From 31feb26e75585dd314c6bd14730534481b099c30 Mon Sep 17 00:00:00 2001 From: bnbailey-psl Date: Tue, 11 Feb 2025 20:21:54 -0800 Subject: [PATCH] [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 Co-authored-by: Ethan Frehner --- core/CMakeLists.txt | 37 +- core/CMake_project.txt | 45 +- core/include/Context.h | 13 + core/include/global.h | 4 + core/src/Context.cpp | 34 + core/src/Context_fileIO.cpp | 4 +- core/src/global.cpp | 2 +- doc/CHANGELOG | 30 +- doc/Doxyfile | 8 +- doc/UserGuide.dox | 34 +- doc/header.html | 2 +- doc/html/Helios_logo_small.png | Bin 29595 -> 29264 bytes doc/html/PSL_logo_compact.png | Bin 22219 -> 21823 bytes doc/html/_a_p_i.html | 123 +- doc/html/_aerial_li_d_a_r_8cpp.html | 37 +- doc/html/_aerial_li_d_a_r_8cpp_source.html | 371 +- doc/html/_aerial_li_d_a_r_8cu.html | 37 +- doc/html/_aerial_li_d_a_r_8cu_source.html | 93 +- doc/html/_aerial_li_d_a_r_8h.html | 37 +- doc/html/_aerial_li_d_a_r_8h.js | 6 + doc/html/_aerial_li_d_a_r_8h_source.html | 335 +- doc/html/_aerial_li_d_a_r_doc.html | 37 +- doc/html/_assets_8cpp.html | 37 +- doc/html/_assets_8cpp_source.html | 132 +- doc/html/_assets_8h_source.html | 39 +- doc/html/_b_l_conductance_doc.html | 37 +- ...boundary_layer_conductance_model_8cpp.html | 37 +- ...y_layer_conductance_model_8cpp_source.html | 92 +- .../_boundary_layer_conductance_model_8h.html | 37 +- .../_boundary_layer_conductance_model_8h.js | 4 + ...ary_layer_conductance_model_8h_source.html | 85 +- doc/html/_c_lion_i_d_e.html | 32 +- doc/html/_camera_calibration_8cpp.html | 37 +- doc/html/_camera_calibration_8cpp_source.html | 149 +- doc/html/_camera_calibration_8h.html | 37 +- doc/html/_camera_calibration_8h.js | 5 + doc/html/_camera_calibration_8h_source.html | 128 +- doc/html/_canopy_generator_8cpp.html | 37 +- doc/html/_canopy_generator_8cpp.js | 9 + doc/html/_canopy_generator_8cpp_source.html | 207 +- doc/html/_canopy_generator_8h.html | 37 +- doc/html/_canopy_generator_8h.js | 25 + doc/html/_canopy_generator_8h_source.html | 877 +- doc/html/_canopy_generator_doc.html | 48 +- doc/html/_carbohydrate_model_8cpp.html | 95 +- doc/html/_carbohydrate_model_8cpp_source.html | 843 +- doc/html/_choosing_c_u_d_a.html | 32 +- doc/html/_context_8cpp.html | 39 +- doc/html/_context_8cpp_source.html | 9416 +++++++++-------- doc/html/_context_8h.html | 37 +- doc/html/_context_8h.js | 42 + doc/html/_context_8h_source.html | 5005 ++++----- doc/html/_context__data_8cpp.html | 39 +- doc/html/_context__data_8cpp_source.html | 88 +- doc/html/_context__file_i_o_8cpp.html | 39 +- doc/html/_context__file_i_o_8cpp_source.html | 168 +- doc/html/_convert_p_l_y.html | 32 +- doc/html/_dependent_software.html | 32 +- doc/html/_dummy.html | 32 +- doc/html/_dummy_model_8cpp.html | 37 +- doc/html/_dummy_model_8cpp_source.html | 45 +- doc/html/_dummy_model_8h.html | 37 +- doc/html/_dummy_model_8h.js | 4 + doc/html/_dummy_model_8h_source.html | 55 +- doc/html/_energy_balance_doc.html | 55 +- doc/html/_energy_balance_model_8cpp.html | 37 +- .../_energy_balance_model_8cpp_source.html | 97 +- doc/html/_energy_balance_model_8cu.html | 39 +- .../_energy_balance_model_8cu_source.html | 140 +- doc/html/_energy_balance_model_8h.html | 37 +- doc/html/_energy_balance_model_8h.js | 4 + doc/html/_energy_balance_model_8h_source.html | 117 +- doc/html/_i_o.html | 50 +- doc/html/_input_output_8cpp.html | 37 +- doc/html/_input_output_8cpp_source.html | 64 +- doc/html/_leaf_optics_8cpp.html | 37 +- doc/html/_leaf_optics_8cpp_source.html | 113 +- doc/html/_leaf_optics_8h.html | 37 +- doc/html/_leaf_optics_8h.js | 5 + doc/html/_leaf_optics_8h_source.html | 90 +- doc/html/_li_d_a_r_8cpp.html | 37 +- doc/html/_li_d_a_r_8cpp_source.html | 102 +- doc/html/_li_d_a_r_8cu.html | 37 +- doc/html/_li_d_a_r_8cu_source.html | 189 +- doc/html/_li_d_a_r_8h.html | 37 +- doc/html/_li_d_a_r_8h.js | 9 + doc/html/_li_d_a_r_8h_source.html | 758 +- doc/html/_li_d_a_r_doc.html | 45 +- doc/html/_making_masks.html | 32 +- doc/html/_overview.html | 32 +- doc/html/_p_c_g_p_u_timeout.html | 32 +- doc/html/_photosynthesis_doc.html | 47 +- doc/html/_photosynthesis_model_8cpp.html | 37 +- .../_photosynthesis_model_8cpp_source.html | 134 +- doc/html/_photosynthesis_model_8h.html | 37 +- doc/html/_photosynthesis_model_8h.js | 7 + doc/html/_photosynthesis_model_8h_source.html | 139 +- doc/html/_plant_architecture_8cpp.html | 39 +- doc/html/_plant_architecture_8cpp.js | 5 + doc/html/_plant_architecture_8cpp_source.html | 5921 ++++++----- doc/html/_plant_architecture_8h.html | 39 +- doc/html/_plant_architecture_8h.js | 16 + doc/html/_plant_architecture_8h_source.html | 1354 +-- doc/html/_plant_architecture_doc.html | 67 +- doc/html/_plant_library_8cpp.html | 37 +- doc/html/_plant_library_8cpp_source.html | 5660 +++++----- doc/html/_plug_ins.html | 32 +- doc/html/_plug_ins.js | 320 + doc/html/_plugins.html | 32 +- doc/html/_radiation_doc.html | 62 +- doc/html/_radiation_model_8cpp.html | 41 +- doc/html/_radiation_model_8cpp_source.html | 8073 +++++++------- doc/html/_radiation_model_8h.html | 41 +- doc/html/_radiation_model_8h.js | 15 + doc/html/_radiation_model_8h_source.html | 802 +- doc/html/_ray_tracing_8cu_8h.html | 37 +- doc/html/_ray_tracing_8cu_8h.js | 8 + doc/html/_ray_tracing_8cu_8h_source.html | 63 +- doc/html/_solar_position_8cpp.html | 37 +- doc/html/_solar_position_8cpp_source.html | 94 +- doc/html/_solar_position_8h.html | 37 +- doc/html/_solar_position_8h.js | 4 + doc/html/_solar_position_8h_source.html | 103 +- doc/html/_solar_position_doc.html | 52 +- .../_stomatal_conductance_model_8cpp.html | 37 +- ...tomatal_conductance_model_8cpp_source.html | 165 +- doc/html/_stomatal_conductance_model_8h.html | 37 +- doc/html/_stomatal_conductance_model_8h.js | 9 + ..._stomatal_conductance_model_8h_source.html | 177 +- doc/html/_stomatal_doc.html | 37 +- doc/html/_synthetic_annotation_8cpp.html | 37 +- .../_synthetic_annotation_8cpp_source.html | 129 +- doc/html/_synthetic_annotation_8h.html | 37 +- doc/html/_synthetic_annotation_8h.js | 4 + doc/html/_synthetic_annotation_8h_source.html | 69 +- doc/html/_tutorials.html | 32 +- doc/html/_tutorials.js | 44 + doc/html/_visualizer_8cpp.html | 79 +- doc/html/_visualizer_8cpp.js | 10 + doc/html/_visualizer_8cpp_source.html | 4441 ++++---- doc/html/_visualizer_8h.html | 45 +- doc/html/_visualizer_8h.js | 14 + doc/html/_visualizer_8h_source.html | 559 +- doc/html/_visualizer_doc.html | 83 +- doc/html/_voxel_intersection_8cpp.html | 37 +- doc/html/_voxel_intersection_8cpp_source.html | 649 +- doc/html/_voxel_intersection_8cu.html | 43 +- doc/html/_voxel_intersection_8cu_source.html | 64 +- doc/html/_voxel_intersection_8h.html | 37 +- doc/html/_voxel_intersection_8h.js | 4 + doc/html/_voxel_intersection_8h_source.html | 85 +- doc/html/_voxel_intersection_doc.html | 37 +- doc/html/_weber_penn_doc.html | 37 +- doc/html/_weber_penn_tree_8cpp.html | 37 +- doc/html/_weber_penn_tree_8cpp_source.html | 135 +- doc/html/_weber_penn_tree_8h.html | 37 +- doc/html/_weber_penn_tree_8h.js | 5 + doc/html/_weber_penn_tree_8h_source.html | 121 +- ...eriallidar_2include_2random_8h_source.html | 37 +- doc/html/aeriallidar_2src_2file_i_o_8cpp.html | 37 +- ...eriallidar_2src_2file_i_o_8cpp_source.html | 46 +- doc/html/annotated.html | 30 +- doc/html/annotated_dup.js | 103 + doc/html/bean_8cpp_source.html | 48 +- ..._c_make_c_x_x_compiler_id_8cpp_source.html | 992 ++ doc/html/class_aerial_li_d_a_rcloud.html | 33 +- doc/html/class_aerial_li_d_a_rcloud.js | 72 + doc/html/class_b_l_conductance_model.html | 33 +- doc/html/class_b_l_conductance_model.js | 12 + doc/html/class_canopy_generator.html | 39 +- doc/html/class_canopy_generator.js | 52 + doc/html/class_dummy_model.html | 33 +- doc/html/class_dummy_model.js | 5 + doc/html/class_energy_balance_model.html | 33 +- doc/html/class_energy_balance_model.js | 16 + doc/html/class_glyph.html | 33 +- doc/html/class_hit_table.html | 61 +- doc/html/class_leaf_optics.html | 35 +- doc/html/class_leaf_optics.js | 11 + doc/html/class_li_d_a_rcloud.html | 86 +- doc/html/class_li_d_a_rcloud.js | 117 + doc/html/class_photosynthesis_model.html | 35 +- doc/html/class_photosynthesis_model.js | 23 + doc/html/class_plant_architecture.html | 487 +- doc/html/class_plant_architecture.js | 56 + doc/html/class_radiation_model.html | 105 +- doc/html/class_radiation_model.js | 102 + doc/html/class_solar_position.html | 35 +- doc/html/class_solar_position.js | 22 + .../class_stomatal_conductance_model.html | 35 +- doc/html/class_stomatal_conductance_model.js | 30 + doc/html/class_synthetic_annotation.html | 35 +- doc/html/class_synthetic_annotation.js | 12 + doc/html/class_visualizer.html | 93 +- doc/html/class_visualizer.js | 106 + doc/html/class_voxel_intersection.html | 33 +- doc/html/class_voxel_intersection.js | 16 + doc/html/class_weber_penn_tree.html | 33 +- doc/html/class_weber_penn_tree.js | 20 + doc/html/classes.html | 30 +- doc/html/classhelios_1_1_box.html | 55 +- doc/html/classhelios_1_1_box.js | 10 + doc/html/classhelios_1_1_compound_object.html | 39 +- doc/html/classhelios_1_1_compound_object.js | 68 + doc/html/classhelios_1_1_cone.html | 67 +- doc/html/classhelios_1_1_cone.js | 16 + doc/html/classhelios_1_1_context.html | 283 +- doc/html/classhelios_1_1_context.js | 546 + doc/html/classhelios_1_1_disk.html | 53 +- doc/html/classhelios_1_1_disk.js | 9 + doc/html/classhelios_1_1_polymesh.html | 47 +- doc/html/classhelios_1_1_polymesh.js | 6 + doc/html/classhelios_1_1_sphere.html | 39 +- doc/html/classhelios_1_1_sphere.js | 10 + doc/html/classhelios_1_1_texture.html | 39 +- doc/html/classhelios_1_1_texture.js | 9 + doc/html/classhelios_1_1_tile.html | 39 +- doc/html/classhelios_1_1_tile.js | 12 + doc/html/classhelios_1_1_tube.html | 71 +- doc/html/classhelios_1_1_tube.js | 20 + doc/html/classhelios_1_1_x_m_lparser.html | 83 +- doc/html/clipboard.js | 4 +- ..._c_make_c_x_x_compiler_id_8cpp_source.html | 992 ++ doc/html/context_globaldata.html | 37 +- doc/html/context_primdata.html | 37 +- doc/html/context_primitives.html | 37 +- doc/html/context_selftest.html | 37 +- doc/html/context_vectors.html | 37 +- doc/html/core_2src_2self_test_8cpp.html | 39 +- .../core_2src_2self_test_8cpp_source.html | 126 +- .../dir_000a2e4fe776603f09c56917fe929269.html | 37 +- .../dir_000a2e4fe776603f09c56917fe929269.js | 5 + .../dir_01af3122a6d2fc081d545f111575c8ac.html | 37 +- .../dir_0581b1fc91af6cc2594fe789a424270d.html | 37 +- .../dir_09ba98b3b490a60de71fb62d89fe47cd.html | 37 +- .../dir_09ba98b3b490a60de71fb62d89fe47cd.js | 4 + .../dir_0b377c449e87c33e20eed98f7cc3a6cc.html | 37 +- .../dir_0b377c449e87c33e20eed98f7cc3a6cc.js | 4 + .../dir_0ed0e5ef04d2b4b7edd36da5802052a6.html | 37 +- .../dir_10651e710c37b90bb60afaa4d2c6a975.html | 37 +- .../dir_10651e710c37b90bb60afaa4d2c6a975.js | 5 + .../dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.html | 129 + .../dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.js | 4 + .../dir_1736472fec890ec3b25c5f707a1ad41b.html | 37 +- .../dir_1736472fec890ec3b25c5f707a1ad41b.js | 9 + .../dir_1b48a9a5d33ab4b7862a4538757abad5.html | 37 +- .../dir_1b48a9a5d33ab4b7862a4538757abad5.js | 4 + .../dir_1c54673618a694dbf6d60994b9e4cd26.html | 37 +- .../dir_1c54673618a694dbf6d60994b9e4cd26.js | 5 + .../dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html | 37 +- .../dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.js | 9 + .../dir_24d671cfcbc5d5238a6bd565a49d198f.html | 37 +- .../dir_24d671cfcbc5d5238a6bd565a49d198f.js | 6 + .../dir_2dbe15cacd8389cc56dad1ecef740014.html | 37 +- .../dir_2dbe15cacd8389cc56dad1ecef740014.js | 5 + .../dir_311a8078924eda44cf0bc3884606fa36.html | 37 +- .../dir_311a8078924eda44cf0bc3884606fa36.js | 5 + .../dir_324b51d306f9962e8d7b85b82cd2c869.html | 37 +- .../dir_3771cc92d713de3e5272f9ad4d0b1912.html | 37 +- .../dir_3771cc92d713de3e5272f9ad4d0b1912.js | 4 + .../dir_38c8d24aef3972a7f87b834274e76e31.html | 37 +- .../dir_38c8d24aef3972a7f87b834274e76e31.js | 19 + .../dir_3b948ba013618d5b0560477725ec43e1.html | 37 +- .../dir_3b948ba013618d5b0560477725ec43e1.js | 5 + .../dir_3d4da5c581737ecd0f864ccf0711fd92.html | 37 +- .../dir_3d6a603070d279a42ac417e5c8a6aba1.html | 37 +- .../dir_3d6a603070d279a42ac417e5c8a6aba1.js | 4 + .../dir_40ea2a4aa4adfc7dc77aa13d0834001b.html | 37 +- .../dir_40ea2a4aa4adfc7dc77aa13d0834001b.js | 7 + .../dir_418637634c2136ee3716f84b17e3fdeb.html | 37 +- .../dir_418637634c2136ee3716f84b17e3fdeb.js | 4 + .../dir_4270bfced15e0e73154b13468c7c9ad9.html | 37 +- .../dir_4270bfced15e0e73154b13468c7c9ad9.js | 7 + .../dir_4821d91ccf02e9e7895ac63900918c57.html | 123 + .../dir_4821d91ccf02e9e7895ac63900918c57.js | 4 + .../dir_4942485e7dfd848fb997bfbb4ff4feb4.html | 37 +- .../dir_4942485e7dfd848fb997bfbb4ff4feb4.js | 5 + .../dir_4bc526d9ea56fd6bbf4f8bb7e1833918.html | 123 + .../dir_4bc526d9ea56fd6bbf4f8bb7e1833918.js | 4 + .../dir_4ccbab8385dcba906f6a2cce80a3b511.html | 37 +- .../dir_4ccbab8385dcba906f6a2cce80a3b511.js | 4 + .../dir_51eab06546c34d501c6cf953a16a9cc5.html | 37 +- .../dir_51eab06546c34d501c6cf953a16a9cc5.js | 4 + .../dir_53e799243804d32eb30709605e43a53b.html | 37 +- .../dir_53e799243804d32eb30709605e43a53b.js | 5 + .../dir_562cb346de9113a49164a1513c42aa1c.html | 37 +- .../dir_562cb346de9113a49164a1513c42aa1c.js | 4 + .../dir_577e0cdb3e2614f5a260ea490887b143.html | 37 +- .../dir_577e0cdb3e2614f5a260ea490887b143.js | 4 + .../dir_58badfc9ced8151ac5118cd2e12bebf1.html | 37 +- .../dir_58badfc9ced8151ac5118cd2e12bebf1.js | 11 + .../dir_594f7d9c1b5f727f933fa022588b0b7d.html | 37 +- .../dir_594f7d9c1b5f727f933fa022588b0b7d.js | 4 + .../dir_59c6a555a98729b3f6a8f77608cc74a4.html | 37 +- .../dir_59c6a555a98729b3f6a8f77608cc74a4.js | 4 + .../dir_615177bc4a60bdbaf2db637460677b64.html | 37 +- .../dir_615177bc4a60bdbaf2db637460677b64.js | 5 + .../dir_6252300d35bf0f8a4d6b5ccb98672957.html | 37 +- .../dir_6252300d35bf0f8a4d6b5ccb98672957.js | 4 + .../dir_6576ef5c45e1ae696f88b82c16a4c6c0.html | 37 +- .../dir_676c0954ed84853013df50d94356577b.html | 37 +- .../dir_676c0954ed84853013df50d94356577b.js | 5 + .../dir_67ef339cfff2cfda5a7b1755578ee854.html | 37 +- .../dir_67ef339cfff2cfda5a7b1755578ee854.js | 4 + .../dir_6d823072f66bbcb32b0d3acc588685b0.html | 37 +- .../dir_6d823072f66bbcb32b0d3acc588685b0.js | 5 + .../dir_7b776a486e9f6b66ded8f2e7f8d3acb3.html | 129 + .../dir_7b776a486e9f6b66ded8f2e7f8d3acb3.js | 4 + .../dir_7b945ff507247f5bd903b50b5c416c04.html | 37 +- .../dir_7b945ff507247f5bd903b50b5c416c04.js | 4 + .../dir_7f186228a2612084b0fc24dff2e535bf.html | 37 +- .../dir_7f186228a2612084b0fc24dff2e535bf.js | 7 + .../dir_8a62bca5fa5119ede20b35462196f194.html | 37 +- .../dir_8a62bca5fa5119ede20b35462196f194.js | 4 + .../dir_8add51f561986f34dfac90d296d2ac1f.html | 37 +- .../dir_9018c8dc5d181eb1cb047286a97fa87b.html | 37 +- .../dir_9018c8dc5d181eb1cb047286a97fa87b.js | 4 + .../dir_90fd98a0ba30abf7a6068a44995d2d6b.html | 37 +- .../dir_90fd98a0ba30abf7a6068a44995d2d6b.js | 8 + .../dir_98f1c86a7f536ff9d6c61df9d8c64baa.html | 37 +- .../dir_98f1c86a7f536ff9d6c61df9d8c64baa.js | 5 + .../dir_9a3b5787d2329f793333f6962c777986.html | 37 +- .../dir_9a3b5787d2329f793333f6962c777986.js | 5 + .../dir_9a6cc15fde559dad335c1dc145a826ea.html | 37 +- .../dir_a2b45ea1295f1e42b26af05f3b546a5b.html | 37 +- .../dir_a2b45ea1295f1e42b26af05f3b546a5b.js | 5 + .../dir_a4ee10e64f839049093220f98040855a.html | 37 +- .../dir_a4ee10e64f839049093220f98040855a.js | 5 + .../dir_a604905e97bad612ecdda55ac09d6396.html | 37 +- .../dir_a604905e97bad612ecdda55ac09d6396.js | 4 + .../dir_a8babb820ec20ecec6aebc09dbfb576c.html | 37 +- .../dir_a8babb820ec20ecec6aebc09dbfb576c.js | 6 + .../dir_b81f286eb903e0c3ba53b620487c01ae.html | 37 +- .../dir_b867f472847a1f099af0eb422541f49e.html | 37 +- .../dir_b867f472847a1f099af0eb422541f49e.js | 5 + .../dir_bc56ed6b0b97565306d951dc61815da9.html | 37 +- .../dir_bc56ed6b0b97565306d951dc61815da9.js | 5 + .../dir_c2e785b0428381d295aba3d86e865907.html | 37 +- .../dir_d11e5a89bd40b12607fdeb823ca30c1a.html | 37 +- .../dir_d11e5a89bd40b12607fdeb823ca30c1a.js | 4 + .../dir_d1ae8b435665c605bb4d6dbecb12be83.html | 123 + .../dir_d1ae8b435665c605bb4d6dbecb12be83.js | 4 + .../dir_d346877beec799c6cac1a2fc56d1c290.html | 37 +- .../dir_d346877beec799c6cac1a2fc56d1c290.js | 4 + .../dir_d39c4dd70ac914a319fbf3979f3cb0cd.html | 37 +- .../dir_d684e7c998fb76edbfb655ffd4cf6611.html | 37 +- .../dir_d6ff66ea9f957e81b4485948f070bc7c.html | 37 +- .../dir_d6ff66ea9f957e81b4485948f070bc7c.js | 4 + .../dir_daed1286feb5181d9374e50e34ff739d.html | 37 +- .../dir_daed1286feb5181d9374e50e34ff739d.js | 5 + .../dir_e68e8157741866f444e17edd764ebbae.html | 37 +- .../dir_e68e8157741866f444e17edd764ebbae.js | 4 + .../dir_e725f6d562ac5b3216da834679296cd3.html | 37 +- .../dir_e771e57a540d4f14ef5ec2c81b56a7b6.html | 37 +- .../dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html | 37 +- .../dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.js | 6 + .../dir_ee14773baee519b082f78b85b263aa48.html | 37 +- .../dir_ee14773baee519b082f78b85b263aa48.js | 5 + .../dir_f34af3b1f7257ff6e74b73055c589954.html | 129 + .../dir_f34af3b1f7257ff6e74b73055c589954.js | 4 + .../dir_f54e10c7807847345da870f7da42cdf0.html | 37 +- .../dir_f54e10c7807847345da870f7da42cdf0.js | 5 + .../dir_f93a58e1b1064abf3e9af98b74e2f5d5.html | 37 +- .../dir_f93a58e1b1064abf3e9af98b74e2f5d5.js | 5 + .../dir_fceca22ca0920a3e9321d273c935ca85.html | 37 +- .../dir_fceca22ca0920a3e9321d273c935ca85.js | 4 + .../dir_ff579404bf421b82abd301ebf28d9c70.html | 129 + .../dir_ff579404bf421b82abd301ebf28d9c70.js | 4 + .../dir_ffb82276458c900659fd697987337356.html | 123 + .../dir_ffb82276458c900659fd697987337356.js | 4 + doc/html/doxygen-awesome-darkmode-toggle.js | 157 + doc/html/doxygen.css | 18 +- doc/html/doxygen_crawl.html | 741 +- doc/html/files.html | 62 +- doc/html/files_dup.js | 6 + doc/html/form_0.png | Bin 4853 -> 4853 bytes doc/html/form_1.png | Bin 514 -> 514 bytes doc/html/form_10.png | Bin 650 -> 650 bytes doc/html/form_100.png | Bin 3048 -> 3048 bytes doc/html/form_101.png | Bin 509 -> 509 bytes doc/html/form_102.png | Bin 2802 -> 2802 bytes doc/html/form_103.png | Bin 413 -> 413 bytes doc/html/form_104.png | Bin 3714 -> 3714 bytes doc/html/form_105.png | Bin 1602 -> 1602 bytes doc/html/form_106.png | Bin 898 -> 898 bytes doc/html/form_107.png | Bin 455 -> 455 bytes doc/html/form_108.png | Bin 1879 -> 1879 bytes doc/html/form_109.png | Bin 5278 -> 5278 bytes doc/html/form_11.png | Bin 587 -> 587 bytes doc/html/form_110.png | Bin 2597 -> 2597 bytes doc/html/form_111.png | Bin 15040 -> 15040 bytes doc/html/form_112.png | Bin 341 -> 341 bytes doc/html/form_113.png | Bin 749 -> 749 bytes doc/html/form_114.png | Bin 1504 -> 1504 bytes doc/html/form_115.png | Bin 847 -> 847 bytes doc/html/form_116.png | Bin 1554 -> 1554 bytes doc/html/form_117.png | Bin 656 -> 656 bytes doc/html/form_118.png | Bin 856 -> 856 bytes doc/html/form_119.png | Bin 830 -> 830 bytes doc/html/form_12.png | Bin 2830 -> 2830 bytes doc/html/form_120.png | Bin 1289 -> 1289 bytes doc/html/form_121.png | Bin 525 -> 525 bytes doc/html/form_122.png | Bin 972 -> 972 bytes doc/html/form_123.png | Bin 1652 -> 1652 bytes doc/html/form_124.png | Bin 24408 -> 24408 bytes doc/html/form_125.png | Bin 698 -> 698 bytes doc/html/form_126.png | Bin 1339 -> 1339 bytes doc/html/form_127.png | Bin 1135 -> 1135 bytes doc/html/form_128.png | Bin 1194 -> 1194 bytes doc/html/form_129.png | Bin 1010 -> 1010 bytes doc/html/form_13.png | Bin 651 -> 651 bytes doc/html/form_130.png | Bin 1538 -> 1538 bytes doc/html/form_131.png | Bin 1525 -> 1525 bytes doc/html/form_132.png | Bin 1570 -> 1570 bytes doc/html/form_133.png | Bin 1407 -> 1407 bytes doc/html/form_134.png | Bin 1400 -> 1400 bytes doc/html/form_135.png | Bin 1435 -> 1435 bytes doc/html/form_136.png | Bin 1368 -> 1368 bytes doc/html/form_137.png | Bin 1333 -> 1333 bytes doc/html/form_138.png | Bin 1389 -> 1389 bytes doc/html/form_139.png | Bin 2203 -> 2203 bytes doc/html/form_14.png | Bin 1100 -> 1100 bytes doc/html/form_140.png | Bin 2550 -> 2550 bytes doc/html/form_141.png | Bin 869 -> 869 bytes doc/html/form_142.png | Bin 1122 -> 1122 bytes doc/html/form_143.png | Bin 1890 -> 1890 bytes doc/html/form_144.png | Bin 921 -> 921 bytes doc/html/form_145.png | Bin 8096 -> 8096 bytes doc/html/form_146.png | Bin 857 -> 857 bytes doc/html/form_147.png | Bin 877 -> 877 bytes doc/html/form_148.png | Bin 438 -> 438 bytes doc/html/form_149.png | Bin 713 -> 713 bytes doc/html/form_15.png | Bin 2094 -> 2094 bytes doc/html/form_150.png | Bin 3794 -> 3794 bytes doc/html/form_151.png | Bin 696 -> 696 bytes doc/html/form_152.png | Bin 3161 -> 3161 bytes doc/html/form_153.png | Bin 2843 -> 2843 bytes doc/html/form_154.png | Bin 392 -> 392 bytes doc/html/form_155.png | Bin 1066 -> 1066 bytes doc/html/form_156.png | Bin 662 -> 662 bytes doc/html/form_157.png | Bin 571 -> 571 bytes doc/html/form_158.png | Bin 825 -> 825 bytes doc/html/form_159.png | Bin 443 -> 443 bytes doc/html/form_16.png | Bin 1156 -> 1156 bytes doc/html/form_160.png | Bin 695 -> 695 bytes doc/html/form_161.png | Bin 739 -> 739 bytes doc/html/form_162.png | Bin 504 -> 504 bytes doc/html/form_163.png | Bin 372 -> 372 bytes doc/html/form_164.png | Bin 2855 -> 2855 bytes doc/html/form_165.png | Bin 687 -> 687 bytes doc/html/form_166.png | Bin 604 -> 604 bytes doc/html/form_167.png | Bin 445 -> 445 bytes doc/html/form_168.png | Bin 1187 -> 1187 bytes doc/html/form_169.png | Bin 776 -> 776 bytes doc/html/form_17.png | Bin 943 -> 943 bytes doc/html/form_170.png | Bin 4415 -> 4415 bytes doc/html/form_171.png | Bin 894 -> 894 bytes doc/html/form_172.png | Bin 392 -> 392 bytes doc/html/form_173.png | Bin 3267 -> 3267 bytes doc/html/form_174.png | Bin 572 -> 572 bytes doc/html/form_175.png | Bin 1285 -> 1285 bytes doc/html/form_176.png | Bin 885 -> 885 bytes doc/html/form_177.png | Bin 1073 -> 1073 bytes doc/html/form_178.png | Bin 844 -> 844 bytes doc/html/form_179.png | Bin 645 -> 645 bytes doc/html/form_18.png | Bin 863 -> 863 bytes doc/html/form_180.png | Bin 3130 -> 3130 bytes doc/html/form_181.png | Bin 2458 -> 2458 bytes doc/html/form_182.png | Bin 3489 -> 3489 bytes doc/html/form_183.png | Bin 640 -> 640 bytes doc/html/form_184.png | Bin 913 -> 913 bytes doc/html/form_185.png | Bin 460 -> 460 bytes doc/html/form_186.png | Bin 582 -> 582 bytes doc/html/form_187.png | Bin 616 -> 616 bytes doc/html/form_188.png | Bin 4855 -> 4855 bytes doc/html/form_189.png | Bin 813 -> 813 bytes doc/html/form_19.png | Bin 489 -> 489 bytes doc/html/form_190.png | Bin 642 -> 642 bytes doc/html/form_191.png | Bin 2900 -> 2900 bytes doc/html/form_192.png | Bin 9369 -> 9369 bytes doc/html/form_193.png | Bin 8372 -> 8372 bytes doc/html/form_194.png | Bin 2073 -> 2073 bytes doc/html/form_195.png | Bin 3532 -> 3532 bytes doc/html/form_196.png | Bin 3728 -> 3728 bytes doc/html/form_197.png | Bin 4574 -> 4574 bytes doc/html/form_198.png | Bin 5223 -> 5223 bytes doc/html/form_199.png | Bin 870 -> 870 bytes doc/html/form_2.png | Bin 703 -> 703 bytes doc/html/form_20.png | Bin 499 -> 499 bytes doc/html/form_200.png | Bin 620 -> 620 bytes doc/html/form_201.png | Bin 1288 -> 1288 bytes doc/html/form_202.png | Bin 1371 -> 1371 bytes doc/html/form_203.png | Bin 3957 -> 3957 bytes doc/html/form_204.png | Bin 427 -> 427 bytes doc/html/form_205.png | Bin 1655 -> 1655 bytes doc/html/form_206.png | Bin 1804 -> 1804 bytes doc/html/form_207.png | Bin 1258 -> 1258 bytes doc/html/form_208.png | Bin 1054 -> 1054 bytes doc/html/form_209.png | Bin 2351 -> 2351 bytes doc/html/form_21.png | Bin 397 -> 397 bytes doc/html/form_210.png | Bin 4151 -> 4151 bytes doc/html/form_211.png | Bin 1585 -> 1585 bytes doc/html/form_212.png | Bin 3401 -> 3401 bytes doc/html/form_213.png | Bin 1836 -> 1836 bytes doc/html/form_214.png | Bin 1078 -> 1078 bytes doc/html/form_215.png | Bin 598 -> 598 bytes doc/html/form_216.png | Bin 2883 -> 2883 bytes doc/html/form_217.png | Bin 674 -> 674 bytes doc/html/form_218.png | Bin 765 -> 765 bytes doc/html/form_219.png | Bin 492 -> 492 bytes doc/html/form_22.png | Bin 769 -> 769 bytes doc/html/form_220.png | Bin 1940 -> 1940 bytes doc/html/form_221.png | Bin 732 -> 732 bytes doc/html/form_222.png | Bin 1160 -> 1160 bytes doc/html/form_223.png | Bin 2776 -> 2776 bytes doc/html/form_224.png | Bin 1363 -> 1363 bytes doc/html/form_225.png | Bin 3879 -> 3879 bytes doc/html/form_226.png | Bin 1421 -> 1421 bytes doc/html/form_227.png | Bin 1345 -> 1345 bytes doc/html/form_228.png | Bin 620 -> 620 bytes doc/html/form_229.png | Bin 684 -> 684 bytes doc/html/form_23.png | Bin 400 -> 400 bytes doc/html/form_230.png | Bin 4687 -> 4687 bytes doc/html/form_231.png | Bin 630 -> 630 bytes doc/html/form_232.png | Bin 659 -> 659 bytes doc/html/form_233.png | Bin 2557 -> 2557 bytes doc/html/form_234.png | Bin 5560 -> 5560 bytes doc/html/form_235.png | Bin 910 -> 910 bytes doc/html/form_236.png | Bin 975 -> 975 bytes doc/html/form_237.png | Bin 518 -> 518 bytes doc/html/form_238.png | Bin 1147 -> 1147 bytes doc/html/form_239.png | Bin 4961 -> 4961 bytes doc/html/form_24.png | Bin 2648 -> 2648 bytes doc/html/form_240.png | Bin 1403 -> 1403 bytes doc/html/form_241.png | Bin 447 -> 447 bytes doc/html/form_242.png | Bin 725 -> 725 bytes doc/html/form_243.png | Bin 555 -> 555 bytes doc/html/form_244.png | Bin 467 -> 467 bytes doc/html/form_245.png | Bin 701 -> 701 bytes doc/html/form_246.png | Bin 1929 -> 1929 bytes doc/html/form_247.png | Bin 352 -> 352 bytes doc/html/form_248.png | Bin 1008 -> 1008 bytes doc/html/form_249.png | Bin 1011 -> 1011 bytes doc/html/form_25.png | Bin 503 -> 503 bytes doc/html/form_250.png | Bin 567 -> 567 bytes doc/html/form_251.png | Bin 3321 -> 3321 bytes doc/html/form_252.png | Bin 858 -> 858 bytes doc/html/form_253.png | Bin 850 -> 850 bytes doc/html/form_254.png | Bin 907 -> 907 bytes doc/html/form_255.png | Bin 930 -> 930 bytes doc/html/form_256.png | Bin 583 -> 583 bytes doc/html/form_257.png | Bin 2657 -> 2657 bytes doc/html/form_258.png | Bin 2427 -> 2427 bytes doc/html/form_259.png | Bin 1027 -> 1027 bytes doc/html/form_26.png | Bin 598 -> 598 bytes doc/html/form_260.png | Bin 1104 -> 1104 bytes doc/html/form_261.png | Bin 1444 -> 1444 bytes doc/html/form_262.png | Bin 1414 -> 1414 bytes doc/html/form_263.png | Bin 637 -> 637 bytes doc/html/form_264.png | Bin 1214 -> 1214 bytes doc/html/form_27.png | Bin 578 -> 578 bytes doc/html/form_28.png | Bin 786 -> 786 bytes doc/html/form_29.png | Bin 932 -> 932 bytes doc/html/form_3.png | Bin 962 -> 962 bytes doc/html/form_30.png | Bin 1329 -> 1329 bytes doc/html/form_31.png | Bin 8716 -> 8716 bytes doc/html/form_32.png | Bin 1302 -> 1302 bytes doc/html/form_33.png | Bin 9893 -> 9893 bytes doc/html/form_34.png | Bin 587 -> 587 bytes doc/html/form_35.png | Bin 386 -> 386 bytes doc/html/form_36.png | Bin 594 -> 594 bytes doc/html/form_37.png | Bin 679 -> 679 bytes doc/html/form_38.png | Bin 695 -> 695 bytes doc/html/form_39.png | Bin 2670 -> 2670 bytes doc/html/form_4.png | Bin 548 -> 548 bytes doc/html/form_40.png | Bin 464 -> 464 bytes doc/html/form_41.png | Bin 545 -> 545 bytes doc/html/form_42.png | Bin 874 -> 874 bytes doc/html/form_43.png | Bin 606 -> 606 bytes doc/html/form_44.png | Bin 4713 -> 4713 bytes doc/html/form_45.png | Bin 3928 -> 3928 bytes doc/html/form_46.png | Bin 4858 -> 4858 bytes doc/html/form_47.png | Bin 2935 -> 2935 bytes doc/html/form_48.png | Bin 1684 -> 1684 bytes doc/html/form_49.png | Bin 1987 -> 1987 bytes doc/html/form_5.png | Bin 716 -> 716 bytes doc/html/form_50.png | Bin 1067 -> 1067 bytes doc/html/form_51.png | Bin 1001 -> 1001 bytes doc/html/form_52.png | Bin 956 -> 956 bytes doc/html/form_53.png | Bin 650 -> 650 bytes doc/html/form_54.png | Bin 1085 -> 1085 bytes doc/html/form_55.png | Bin 650 -> 650 bytes doc/html/form_56.png | Bin 2856 -> 2856 bytes doc/html/form_57.png | Bin 466 -> 466 bytes doc/html/form_58.png | Bin 1952 -> 1952 bytes doc/html/form_59.png | Bin 1413 -> 1413 bytes doc/html/form_6.png | Bin 613 -> 613 bytes doc/html/form_60.png | Bin 9940 -> 9940 bytes doc/html/form_61.png | Bin 580 -> 580 bytes doc/html/form_62.png | Bin 644 -> 644 bytes doc/html/form_63.png | Bin 731 -> 731 bytes doc/html/form_64.png | Bin 1084 -> 1084 bytes doc/html/form_65.png | Bin 573 -> 573 bytes doc/html/form_66.png | Bin 460 -> 460 bytes doc/html/form_67.png | Bin 889 -> 889 bytes doc/html/form_68.png | Bin 718 -> 718 bytes doc/html/form_69.png | Bin 1196 -> 1196 bytes doc/html/form_7.png | Bin 6422 -> 6422 bytes doc/html/form_70.png | Bin 904 -> 904 bytes doc/html/form_71.png | Bin 569 -> 569 bytes doc/html/form_72.png | Bin 439 -> 439 bytes doc/html/form_73.png | Bin 1845 -> 1845 bytes doc/html/form_74.png | Bin 447 -> 447 bytes doc/html/form_75.png | Bin 1012 -> 1012 bytes doc/html/form_76.png | Bin 1095 -> 1095 bytes doc/html/form_77.png | Bin 1079 -> 1079 bytes doc/html/form_78.png | Bin 5708 -> 5708 bytes doc/html/form_79.png | Bin 1150 -> 1150 bytes doc/html/form_8.png | Bin 3172 -> 3172 bytes doc/html/form_80.png | Bin 2932 -> 2932 bytes doc/html/form_81.png | Bin 779 -> 779 bytes doc/html/form_82.png | Bin 1014 -> 1014 bytes doc/html/form_83.png | Bin 745 -> 745 bytes doc/html/form_84.png | Bin 11207 -> 11207 bytes doc/html/form_85.png | Bin 528 -> 528 bytes doc/html/form_86.png | Bin 680 -> 680 bytes doc/html/form_87.png | Bin 713 -> 713 bytes doc/html/form_88.png | Bin 680 -> 680 bytes doc/html/form_89.png | Bin 713 -> 713 bytes doc/html/form_9.png | Bin 629 -> 629 bytes doc/html/form_90.png | Bin 880 -> 880 bytes doc/html/form_91.png | Bin 1051 -> 1051 bytes doc/html/form_92.png | Bin 607 -> 607 bytes doc/html/form_93.png | Bin 698 -> 698 bytes doc/html/form_94.png | Bin 443 -> 443 bytes doc/html/form_95.png | Bin 452 -> 452 bytes doc/html/form_96.png | Bin 646 -> 646 bytes doc/html/form_97.png | Bin 331 -> 331 bytes doc/html/form_98.png | Bin 4453 -> 4453 bytes doc/html/form_99.png | Bin 3143 -> 3143 bytes doc/html/formula.repository | 28 +- doc/html/functions.html | 30 +- doc/html/functions_b.html | 30 +- doc/html/functions_c.html | 30 +- doc/html/functions_d.html | 30 +- doc/html/functions_dup.js | 29 + doc/html/functions_e.html | 31 +- doc/html/functions_enum.html | 30 +- doc/html/functions_eval.html | 30 +- doc/html/functions_f.html | 30 +- doc/html/functions_func.html | 30 +- doc/html/functions_func.js | 27 + doc/html/functions_func_b.html | 30 +- doc/html/functions_func_c.html | 30 +- doc/html/functions_func_d.html | 30 +- doc/html/functions_func_e.html | 31 +- doc/html/functions_func_f.html | 30 +- doc/html/functions_func_g.html | 35 +- doc/html/functions_func_h.html | 30 +- doc/html/functions_func_i.html | 30 +- doc/html/functions_func_j.html | 30 +- doc/html/functions_func_l.html | 30 +- doc/html/functions_func_m.html | 30 +- doc/html/functions_func_n.html | 30 +- doc/html/functions_func_o.html | 30 +- doc/html/functions_func_p.html | 31 +- doc/html/functions_func_q.html | 30 +- doc/html/functions_func_r.html | 30 +- doc/html/functions_func_s.html | 30 +- doc/html/functions_func_t.html | 30 +- doc/html/functions_func_u.html | 30 +- doc/html/functions_func_v.html | 30 +- doc/html/functions_func_w.html | 31 +- doc/html/functions_func_x.html | 30 +- doc/html/functions_func_~.html | 30 +- doc/html/functions_g.html | 35 +- doc/html/functions_h.html | 30 +- doc/html/functions_i.html | 30 +- doc/html/functions_j.html | 30 +- doc/html/functions_l.html | 30 +- doc/html/functions_m.html | 30 +- doc/html/functions_n.html | 30 +- doc/html/functions_o.html | 30 +- doc/html/functions_p.html | 31 +- doc/html/functions_q.html | 30 +- doc/html/functions_r.html | 30 +- doc/html/functions_rela.html | 30 +- doc/html/functions_s.html | 30 +- doc/html/functions_t.html | 30 +- doc/html/functions_u.html | 30 +- doc/html/functions_v.html | 30 +- doc/html/functions_vars.html | 30 +- doc/html/functions_vars.js | 25 + doc/html/functions_vars_b.html | 30 +- doc/html/functions_vars_c.html | 30 +- doc/html/functions_vars_d.html | 30 +- doc/html/functions_vars_e.html | 30 +- doc/html/functions_vars_f.html | 30 +- doc/html/functions_vars_g.html | 30 +- doc/html/functions_vars_h.html | 30 +- doc/html/functions_vars_l.html | 30 +- doc/html/functions_vars_m.html | 30 +- doc/html/functions_vars_n.html | 30 +- doc/html/functions_vars_o.html | 30 +- doc/html/functions_vars_p.html | 30 +- doc/html/functions_vars_r.html | 30 +- doc/html/functions_vars_s.html | 30 +- doc/html/functions_vars_t.html | 30 +- doc/html/functions_vars_u.html | 30 +- doc/html/functions_vars_v.html | 30 +- doc/html/functions_vars_w.html | 30 +- doc/html/functions_vars_x.html | 30 +- doc/html/functions_vars_y.html | 30 +- doc/html/functions_vars_z.html | 30 +- doc/html/functions_w.html | 31 +- doc/html/functions_x.html | 30 +- doc/html/functions_y.html | 30 +- doc/html/functions_z.html | 30 +- doc/html/functions_~.html | 30 +- doc/html/global_8cpp.html | 37 +- doc/html/global_8cpp.js | 4 + doc/html/global_8cpp_source.html | 115 +- doc/html/global_8h.html | 53 +- doc/html/global_8h.js | 137 + doc/html/global_8h_source.html | 988 +- doc/html/globals.html | 30 +- doc/html/globals_enum.html | 30 +- doc/html/globals_func.html | 30 +- doc/html/grapevine_8cpp.html | 37 +- doc/html/grapevine_8cpp_source.html | 215 +- doc/html/group__compoundobjects.html | 140 +- doc/html/group__functions.html | 46 +- doc/html/group__primitives.html | 30 +- doc/html/group__timeseries.html | 30 +- doc/html/group__vectors.html | 56 +- doc/html/helios__vector__types_8h.html | 77 +- doc/html/helios__vector__types_8h.js | 38 + doc/html/helios__vector__types_8h_source.html | 643 +- doc/html/hierarchy.html | 30 +- doc/html/hierarchy.js | 105 + doc/html/index.html | 43 +- .../lidar_2include_2random_8h_source.html | 37 +- doc/html/lidar_2src_2file_i_o_8cpp.html | 37 +- .../lidar_2src_2file_i_o_8cpp_source.html | 721 +- doc/html/main_8cpp_source.html | 49 +- doc/html/navtree.js | 483 + doc/html/navtreedata.js | 191 + doc/html/navtreeindex0.js | 253 + doc/html/navtreeindex1.js | 253 + doc/html/navtreeindex2.js | 253 + doc/html/navtreeindex3.js | 253 + doc/html/navtreeindex4.js | 253 + doc/html/navtreeindex5.js | 253 + doc/html/navtreeindex6.js | 253 + doc/html/navtreeindex7.js | 253 + doc/html/navtreeindex8.js | 253 + doc/html/navtreeindex9.js | 208 + doc/html/pages.html | 30 +- .../plugins_2lidar_2src_2self_test_8cpp.html | 37 +- ...ns_2lidar_2src_2self_test_8cpp_source.html | 64 +- ...lantarchitecture_2src_2self_test_8cpp.html | 37 +- ...hitecture_2src_2self_test_8cpp_source.html | 46 +- ...ugins_2radiation_2src_2self_test_8cpp.html | 37 +- ...radiation_2src_2self_test_8cpp_source.html | 109 +- ...rposition_2src_2self_test_8cpp_source.html | 66 +- doc/html/primitive_intersection_8cu.html | 37 +- doc/html/primitive_intersection_8cu.js | 15 + .../primitive_intersection_8cu_source.html | 74 +- .../radiation_2include_2random_8h_source.html | 37 +- doc/html/radiation__beers_law.html | 37 +- doc/html/radiation_basics.html | 37 +- doc/html/ray_generation_8cu.html | 37 +- doc/html/ray_generation_8cu_source.html | 52 +- doc/html/ray_hit_8cu.html | 118 +- doc/html/ray_hit_8cu_source.html | 1196 ++- doc/html/s__hull__pro_8h_source.html | 74 +- doc/html/search/all_10.js | 2 +- doc/html/search/all_17.js | 2 +- doc/html/search/all_18.js | 3 +- doc/html/search/all_1e.js | 101 +- doc/html/search/all_1f.js | 29 +- doc/html/search/all_2.js | 7 +- doc/html/search/all_3.js | 11 +- doc/html/search/all_c.js | 45 +- doc/html/search/all_d.js | 9 +- doc/html/search/all_f.js | 545 +- doc/html/search/functions_15.js | 15 +- doc/html/search/functions_4.js | 5 +- doc/html/search/functions_6.js | 455 +- doc/html/search/functions_e.js | 3 +- doc/html/search/pages_10.js | 13 +- doc/html/search/pages_11.js | 9 +- doc/html/search/pages_12.js | 8 +- doc/html/search/pages_13.js | 16 +- doc/html/search/pages_14.js | 15 +- doc/html/search/pages_15.js | 9 +- doc/html/search/pages_16.js | 27 +- doc/html/search/pages_17.js | 26 +- doc/html/search/pages_18.js | 12 +- doc/html/search/pages_19.js | 14 +- doc/html/search/pages_1a.js | 9 - doc/html/search/pages_2.js | 3 +- doc/html/search/pages_3.js | 2 +- doc/html/search/pages_4.js | 2 +- doc/html/search/pages_5.js | 2 +- doc/html/search/pages_6.js | 2 +- doc/html/search/pages_7.js | 9 +- doc/html/search/pages_8.js | 13 +- doc/html/search/pages_9.js | 15 +- doc/html/search/pages_a.js | 15 +- doc/html/search/pages_b.js | 7 +- doc/html/search/pages_c.js | 7 +- doc/html/search/pages_d.js | 12 +- doc/html/search/pages_e.js | 10 +- doc/html/search/pages_f.js | 12 +- doc/html/search/related_0.js | 2 +- doc/html/search/searchdata.js | 2 +- doc/html/sorghum_8cpp_source.html | 275 +- doc/html/sponsors.jpg | Bin 63422 -> 0 bytes doc/html/strawberry_8cpp_source.html | 54 +- doc/html/struct_aerial_hit_point.html | 37 +- doc/html/struct_aerial_scan_metadata.html | 33 +- doc/html/struct_aerial_scan_metadata.js | 11 + doc/html/struct_axis_rotation.html | 43 +- doc/html/struct_b_b_lcoefficients.html | 35 +- doc/html/struct_b_bcoefficients.html | 35 +- doc/html/struct_b_m_fcoefficients.html | 35 +- doc/html/struct_b_w_bcoefficients.html | 35 +- doc/html/struct_base_canopy_parameters.html | 39 +- doc/html/struct_base_canopy_parameters.js | 10 + .../struct_base_grape_vine_parameters.html | 37 +- doc/html/struct_base_grape_vine_parameters.js | 50 + doc/html/struct_bean_parameters.html | 37 +- doc/html/struct_bean_parameters.js | 23 + doc/html/struct_camera_calibration.html | 35 +- doc/html/struct_camera_calibration.js | 17 + ...ation_1_1_gradient_descent_parameters.html | 37 +- doc/html/struct_camera_properties.html | 43 +- doc/html/struct_camera_properties.js | 8 + doc/html/struct_colormap.html | 49 +- ...ruct_conical_crowns_canopy_parameters.html | 37 +- ...struct_conical_crowns_canopy_parameters.js | 19 + doc/html/struct_dupex.html | 43 +- .../struct_empirical_model_coefficients.html | 35 +- .../struct_farquhar_model_coefficients.html | 61 +- doc/html/struct_floral_bud.html | 33 +- .../struct_goblet_grapevine_parameters.html | 37 +- .../struct_goblet_grapevine_parameters.js | 8 + doc/html/struct_grid_cell.html | 35 +- doc/html/struct_hit_point.html | 37 +- .../struct_homogeneous_canopy_parameters.html | 37 +- .../struct_homogeneous_canopy_parameters.js | 17 + doc/html/struct_leaf_optics_properties.html | 37 +- doc/html/struct_leaf_prototype.html | 43 +- doc/html/struct_leaf_prototype.js | 21 + doc/html/struct_m_o_p_tcoefficients.html | 35 +- doc/html/struct_per_ray_data.html | 33 +- doc/html/struct_per_ray_data.js | 10 + ...hetic_temperature_response_parameters.html | 43 +- doc/html/struct_phytomer.html | 94 +- doc/html/struct_phytomer.js | 11 + doc/html/struct_phytomer_parameters.html | 41 +- doc/html/struct_phytomer_parameters.js | 7 + doc/html/struct_plant_instance.html | 100 +- doc/html/struct_radiation_band.html | 35 +- doc/html/struct_radiation_band.js | 17 + doc/html/struct_radiation_camera.html | 35 +- doc/html/struct_radiation_source.html | 43 +- doc/html/struct_radiation_source.js | 16 + doc/html/struct_random_parameter__float.html | 55 +- doc/html/struct_random_parameter__float.js | 6 + doc/html/struct_random_parameter__int.html | 49 +- doc/html/struct_scan_metadata.html | 39 +- doc/html/struct_scan_metadata.js | 18 + doc/html/struct_shader.html | 61 +- doc/html/struct_shader.js | 16 + doc/html/struct_shoot.html | 302 +- doc/html/struct_shoot.js | 8 + doc/html/struct_shoot_parameters.html | 55 +- doc/html/struct_shoot_parameters.js | 6 + doc/html/struct_shx.html | 43 +- .../struct_sorghum_canopy_parameters.html | 37 +- doc/html/struct_sorghum_canopy_parameters.js | 69 + ...ct_spherical_crowns_canopy_parameters.html | 37 +- ...ruct_spherical_crowns_canopy_parameters.js | 18 + .../struct_split_grapevine_parameters.html | 37 +- doc/html/struct_split_grapevine_parameters.js | 14 + doc/html/struct_strawberry_parameters.html | 37 +- doc/html/struct_strawberry_parameters.js | 23 + doc/html/struct_tomato_parameters.html | 37 +- doc/html/struct_tomato_parameters.js | 20 + doc/html/struct_triad.html | 43 +- doc/html/struct_triangulation.html | 37 +- ...truct_unilateral_grapevine_parameters.html | 37 +- .../struct_unilateral_grapevine_parameters.js | 8 + .../struct_v_s_p_grapevine_parameters.html | 37 +- doc/html/struct_v_s_p_grapevine_parameters.js | 8 + doc/html/struct_vegetative_bud.html | 33 +- doc/html/struct_walnut_canopy_parameters.html | 37 +- doc/html/struct_walnut_canopy_parameters.js | 22 + .../struct_weber_penn_tree_parameters.html | 33 +- ...struct_white_spruce_canopy_parameters.html | 37 +- .../struct_white_spruce_canopy_parameters.js | 25 + doc/html/structhelios_1_1_date.html | 51 +- doc/html/structhelios_1_1_date.js | 14 + doc/html/structhelios_1_1_global_data.html | 37 +- doc/html/structhelios_1_1_location.html | 47 +- doc/html/structhelios_1_1_location.js | 11 + doc/html/structhelios_1_1_r_g_b_acolor.html | 59 +- doc/html/structhelios_1_1_r_g_b_acolor.js | 15 + doc/html/structhelios_1_1_r_g_bcolor.html | 61 +- doc/html/structhelios_1_1_r_g_bcolor.js | 15 + .../structhelios_1_1_spherical_coord.html | 51 +- doc/html/structhelios_1_1_spherical_coord.js | 14 + doc/html/structhelios_1_1_time.html | 49 +- doc/html/structhelios_1_1_time.js | 12 + doc/html/structhelios_1_1_timer.html | 55 +- doc/html/structhelios_1_1_timer.js | 6 + doc/html/structhelios_1_1int2.html | 61 +- doc/html/structhelios_1_1int2.js | 17 + doc/html/structhelios_1_1int3.html | 61 +- doc/html/structhelios_1_1int3.js | 18 + doc/html/structhelios_1_1int4.html | 61 +- doc/html/structhelios_1_1int4.js | 19 + doc/html/structhelios_1_1vec2.html | 75 +- doc/html/structhelios_1_1vec2.js | 24 + doc/html/structhelios_1_1vec3.html | 75 +- doc/html/structhelios_1_1vec3.js | 25 + doc/html/structhelios_1_1vec4.html | 75 +- doc/html/structhelios_1_1vec4.js | 26 + doc/html/structjpg__error__mgr.html | 33 +- doc/html/structmy__error__mgr.html | 33 +- doc/html/tomato_8cpp_source.html | 51 +- doc/html/usergroup0.html | 30 +- doc/html/visualizer_basics.html | 37 +- doc/html/visualizer_pdata.html | 37 +- doc/html/walnut_8cpp_source.html | 58 +- doc/html/whitespruce_8cpp_source.html | 59 +- doc/images/Helios_logo_small.png | Bin 29595 -> 29264 bytes doc/images/PSL_logo_compact.png | Bin 22219 -> 21823 bytes plugins/lidar/include/LiDAR.h | 7 + plugins/lidar/src/fileIO.cpp | 74 +- .../assets/textures/GroundCherryLeaf.png | Bin 0 -> 626978 bytes .../doc/PlantArchitecture.dox | 4 +- .../include/PlantArchitecture.h | 67 +- .../src/CarbohydrateModel.cpp | 237 +- .../src/PlantArchitecture.cpp | 195 +- .../plantarchitecture/src/PlantLibrary.cpp | 189 +- plugins/radiation/CMakeLists.txt | 30 +- plugins/radiation/include/RadiationModel.h | 17 +- .../leaf_surface_spectral_library.xml | 4312 +++++++- plugins/radiation/src/RadiationModel.cpp | 235 +- plugins/radiation/src/rayHit.cu | 72 +- plugins/radiation/src/selfTest.cpp | 4 +- plugins/visualizer/src/Visualizer.cpp | 3 +- samples/context_selftest/main.cpp | 11 + samples/plantarchitecture_selftest/main.cpp | 1 - samples/tutorial11/main.cpp | 2 +- 958 files changed, 53322 insertions(+), 33365 deletions(-) create mode 100644 doc/html/_aerial_li_d_a_r_8h.js create mode 100644 doc/html/_boundary_layer_conductance_model_8h.js create mode 100644 doc/html/_camera_calibration_8h.js create mode 100644 doc/html/_canopy_generator_8cpp.js create mode 100644 doc/html/_canopy_generator_8h.js create mode 100644 doc/html/_context_8h.js create mode 100644 doc/html/_dummy_model_8h.js create mode 100644 doc/html/_energy_balance_model_8h.js create mode 100644 doc/html/_leaf_optics_8h.js create mode 100644 doc/html/_li_d_a_r_8h.js create mode 100644 doc/html/_photosynthesis_model_8h.js create mode 100644 doc/html/_plant_architecture_8cpp.js create mode 100644 doc/html/_plant_architecture_8h.js create mode 100644 doc/html/_plug_ins.js create mode 100644 doc/html/_radiation_model_8h.js create mode 100644 doc/html/_ray_tracing_8cu_8h.js create mode 100644 doc/html/_solar_position_8h.js create mode 100644 doc/html/_stomatal_conductance_model_8h.js create mode 100644 doc/html/_synthetic_annotation_8h.js create mode 100644 doc/html/_tutorials.js create mode 100644 doc/html/_visualizer_8cpp.js create mode 100644 doc/html/_visualizer_8h.js create mode 100644 doc/html/_voxel_intersection_8h.js create mode 100644 doc/html/_weber_penn_tree_8h.js create mode 100644 doc/html/annotated_dup.js create mode 100644 doc/html/build_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html create mode 100644 doc/html/class_aerial_li_d_a_rcloud.js create mode 100644 doc/html/class_b_l_conductance_model.js create mode 100644 doc/html/class_canopy_generator.js create mode 100644 doc/html/class_dummy_model.js create mode 100644 doc/html/class_energy_balance_model.js create mode 100644 doc/html/class_leaf_optics.js create mode 100644 doc/html/class_li_d_a_rcloud.js create mode 100644 doc/html/class_photosynthesis_model.js create mode 100644 doc/html/class_plant_architecture.js create mode 100644 doc/html/class_radiation_model.js create mode 100644 doc/html/class_solar_position.js create mode 100644 doc/html/class_stomatal_conductance_model.js create mode 100644 doc/html/class_synthetic_annotation.js create mode 100644 doc/html/class_visualizer.js create mode 100644 doc/html/class_voxel_intersection.js create mode 100644 doc/html/class_weber_penn_tree.js create mode 100644 doc/html/classhelios_1_1_box.js create mode 100644 doc/html/classhelios_1_1_compound_object.js create mode 100644 doc/html/classhelios_1_1_cone.js create mode 100644 doc/html/classhelios_1_1_context.js create mode 100644 doc/html/classhelios_1_1_disk.js create mode 100644 doc/html/classhelios_1_1_polymesh.js create mode 100644 doc/html/classhelios_1_1_sphere.js create mode 100644 doc/html/classhelios_1_1_texture.js create mode 100644 doc/html/classhelios_1_1_tile.js create mode 100644 doc/html/classhelios_1_1_tube.js create mode 100644 doc/html/cmake-build-release_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html create mode 100644 doc/html/dir_000a2e4fe776603f09c56917fe929269.js create mode 100644 doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.js create mode 100644 doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.js create mode 100644 doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.js create mode 100644 doc/html/dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.html create mode 100644 doc/html/dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.js create mode 100644 doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.js create mode 100644 doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.js create mode 100644 doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.js create mode 100644 doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.js create mode 100644 doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.js create mode 100644 doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.js create mode 100644 doc/html/dir_311a8078924eda44cf0bc3884606fa36.js create mode 100644 doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.js create mode 100644 doc/html/dir_38c8d24aef3972a7f87b834274e76e31.js create mode 100644 doc/html/dir_3b948ba013618d5b0560477725ec43e1.js create mode 100644 doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.js create mode 100644 doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.js create mode 100644 doc/html/dir_418637634c2136ee3716f84b17e3fdeb.js create mode 100644 doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.js create mode 100644 doc/html/dir_4821d91ccf02e9e7895ac63900918c57.html create mode 100644 doc/html/dir_4821d91ccf02e9e7895ac63900918c57.js create mode 100644 doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.js create mode 100644 doc/html/dir_4bc526d9ea56fd6bbf4f8bb7e1833918.html create mode 100644 doc/html/dir_4bc526d9ea56fd6bbf4f8bb7e1833918.js create mode 100644 doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.js create mode 100644 doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.js create mode 100644 doc/html/dir_53e799243804d32eb30709605e43a53b.js create mode 100644 doc/html/dir_562cb346de9113a49164a1513c42aa1c.js create mode 100644 doc/html/dir_577e0cdb3e2614f5a260ea490887b143.js create mode 100644 doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.js create mode 100644 doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.js create mode 100644 doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.js create mode 100644 doc/html/dir_615177bc4a60bdbaf2db637460677b64.js create mode 100644 doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.js create mode 100644 doc/html/dir_676c0954ed84853013df50d94356577b.js create mode 100644 doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.js create mode 100644 doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.js create mode 100644 doc/html/dir_7b776a486e9f6b66ded8f2e7f8d3acb3.html create mode 100644 doc/html/dir_7b776a486e9f6b66ded8f2e7f8d3acb3.js create mode 100644 doc/html/dir_7b945ff507247f5bd903b50b5c416c04.js create mode 100644 doc/html/dir_7f186228a2612084b0fc24dff2e535bf.js create mode 100644 doc/html/dir_8a62bca5fa5119ede20b35462196f194.js create mode 100644 doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.js create mode 100644 doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.js create mode 100644 doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.js create mode 100644 doc/html/dir_9a3b5787d2329f793333f6962c777986.js create mode 100644 doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.js create mode 100644 doc/html/dir_a4ee10e64f839049093220f98040855a.js create mode 100644 doc/html/dir_a604905e97bad612ecdda55ac09d6396.js create mode 100644 doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.js create mode 100644 doc/html/dir_b867f472847a1f099af0eb422541f49e.js create mode 100644 doc/html/dir_bc56ed6b0b97565306d951dc61815da9.js create mode 100644 doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.js create mode 100644 doc/html/dir_d1ae8b435665c605bb4d6dbecb12be83.html create mode 100644 doc/html/dir_d1ae8b435665c605bb4d6dbecb12be83.js create mode 100644 doc/html/dir_d346877beec799c6cac1a2fc56d1c290.js create mode 100644 doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.js create mode 100644 doc/html/dir_daed1286feb5181d9374e50e34ff739d.js create mode 100644 doc/html/dir_e68e8157741866f444e17edd764ebbae.js create mode 100644 doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.js create mode 100644 doc/html/dir_ee14773baee519b082f78b85b263aa48.js create mode 100644 doc/html/dir_f34af3b1f7257ff6e74b73055c589954.html create mode 100644 doc/html/dir_f34af3b1f7257ff6e74b73055c589954.js create mode 100644 doc/html/dir_f54e10c7807847345da870f7da42cdf0.js create mode 100644 doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.js create mode 100644 doc/html/dir_fceca22ca0920a3e9321d273c935ca85.js create mode 100644 doc/html/dir_ff579404bf421b82abd301ebf28d9c70.html create mode 100644 doc/html/dir_ff579404bf421b82abd301ebf28d9c70.js create mode 100644 doc/html/dir_ffb82276458c900659fd697987337356.html create mode 100644 doc/html/dir_ffb82276458c900659fd697987337356.js create mode 100644 doc/html/doxygen-awesome-darkmode-toggle.js create mode 100644 doc/html/files_dup.js create mode 100644 doc/html/functions_dup.js create mode 100644 doc/html/functions_func.js create mode 100644 doc/html/functions_vars.js create mode 100644 doc/html/global_8cpp.js create mode 100644 doc/html/global_8h.js create mode 100644 doc/html/helios__vector__types_8h.js create mode 100644 doc/html/hierarchy.js create mode 100644 doc/html/navtree.js create mode 100644 doc/html/navtreedata.js create mode 100644 doc/html/navtreeindex0.js create mode 100644 doc/html/navtreeindex1.js create mode 100644 doc/html/navtreeindex2.js create mode 100644 doc/html/navtreeindex3.js create mode 100644 doc/html/navtreeindex4.js create mode 100644 doc/html/navtreeindex5.js create mode 100644 doc/html/navtreeindex6.js create mode 100644 doc/html/navtreeindex7.js create mode 100644 doc/html/navtreeindex8.js create mode 100644 doc/html/navtreeindex9.js create mode 100644 doc/html/primitive_intersection_8cu.js delete mode 100644 doc/html/search/pages_1a.js delete mode 100644 doc/html/sponsors.jpg create mode 100644 doc/html/struct_aerial_scan_metadata.js create mode 100644 doc/html/struct_base_canopy_parameters.js create mode 100644 doc/html/struct_base_grape_vine_parameters.js create mode 100644 doc/html/struct_bean_parameters.js create mode 100644 doc/html/struct_camera_calibration.js create mode 100644 doc/html/struct_camera_properties.js create mode 100644 doc/html/struct_conical_crowns_canopy_parameters.js create mode 100644 doc/html/struct_goblet_grapevine_parameters.js create mode 100644 doc/html/struct_homogeneous_canopy_parameters.js create mode 100644 doc/html/struct_leaf_prototype.js create mode 100644 doc/html/struct_per_ray_data.js create mode 100644 doc/html/struct_phytomer.js create mode 100644 doc/html/struct_phytomer_parameters.js create mode 100644 doc/html/struct_radiation_band.js create mode 100644 doc/html/struct_radiation_source.js create mode 100644 doc/html/struct_random_parameter__float.js create mode 100644 doc/html/struct_scan_metadata.js create mode 100644 doc/html/struct_shader.js create mode 100644 doc/html/struct_shoot.js create mode 100644 doc/html/struct_shoot_parameters.js create mode 100644 doc/html/struct_sorghum_canopy_parameters.js create mode 100644 doc/html/struct_spherical_crowns_canopy_parameters.js create mode 100644 doc/html/struct_split_grapevine_parameters.js create mode 100644 doc/html/struct_strawberry_parameters.js create mode 100644 doc/html/struct_tomato_parameters.js create mode 100644 doc/html/struct_unilateral_grapevine_parameters.js create mode 100644 doc/html/struct_v_s_p_grapevine_parameters.js create mode 100644 doc/html/struct_walnut_canopy_parameters.js create mode 100644 doc/html/struct_white_spruce_canopy_parameters.js create mode 100644 doc/html/structhelios_1_1_date.js create mode 100644 doc/html/structhelios_1_1_location.js create mode 100644 doc/html/structhelios_1_1_r_g_b_acolor.js create mode 100644 doc/html/structhelios_1_1_r_g_bcolor.js create mode 100644 doc/html/structhelios_1_1_spherical_coord.js create mode 100644 doc/html/structhelios_1_1_time.js create mode 100644 doc/html/structhelios_1_1_timer.js create mode 100644 doc/html/structhelios_1_1int2.js create mode 100644 doc/html/structhelios_1_1int3.js create mode 100644 doc/html/structhelios_1_1int4.js create mode 100644 doc/html/structhelios_1_1vec2.js create mode 100644 doc/html/structhelios_1_1vec3.js create mode 100644 doc/html/structhelios_1_1vec4.js create mode 100644 plugins/plantarchitecture/assets/textures/GroundCherryLeaf.png diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index bc4f2ba09..ca70d39c5 100755 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -2,30 +2,43 @@ cmake_minimum_required(VERSION 3.15) project(helios) -include_directories(include) - if(NOT DEFINED CMAKE_SUPPRESS_DEVELOPER_WARNINGS) set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS 1 CACHE INTERNAL "No dev warnings") endif() -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 ) - +# Defining Helios Context source files to be built +set(HELIOS_SOURCES + src/Context.cpp + src/Context_fileIO.cpp + src/Context_data.cpp + src/global.cpp + src/selfTest.cpp + src/pugixml.cpp +) +add_library(helios STATIC ${HELIOS_SOURCES}) + +# Defining Helios Context include files +target_include_directories(helios + PUBLIC + $ + $ +) + +# External libraries include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/lib/zlib") -add_subdirectory( "${CMAKE_CURRENT_SOURCE_DIR}/lib/zlib" "${CMAKE_BINARY_DIR}/lib/zlib" ) -target_link_libraries( zlibstatic ) +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/lib/zlib" "${CMAKE_BINARY_DIR}/lib/zlib") include_directories( "${CMAKE_CURRENT_SOURCE_DIR}/lib/libpng") -add_subdirectory( "${CMAKE_CURRENT_SOURCE_DIR}/lib/libpng" "${CMAKE_BINARY_DIR}/lib/libpng" ) +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/lib/libpng" "${CMAKE_BINARY_DIR}/lib/libpng") add_dependencies( png_static zlibstatic ) -target_link_libraries( helios png_static ) - include_directories("${CMAKE_BINARY_DIR}/lib/libjpeg-9a;${CMAKE_CURRENT_SOURCE_DIR}/lib/libjpeg-9a") -add_subdirectory("lib/libjpeg-9a" "${CMAKE_BINARY_DIR}/lib/libjpeg-9a" ) -target_link_libraries( helios jpeg ) +add_subdirectory("${CMAKE_CURRENT_SOURCE_DIR}/lib/libjpeg-9a" "${CMAKE_BINARY_DIR}/lib/libjpeg-9a") + +target_link_libraries( helios PRIVATE png_static jpeg ) #note that zlib is already linked by libpng file( COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/images" DESTINATION "${CMAKE_BINARY_DIR}/lib/" ) file( COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/models" DESTINATION "${CMAKE_BINARY_DIR}/lib/" ) file( COPY "${CMAKE_CURRENT_SOURCE_DIR}/lib/testdata" DESTINATION "${CMAKE_BINARY_DIR}/lib/" ) -set( PLUGIN_INCLUDE_PATHS ${CMAKE_CURRENT_SOURCE_DIR}/include; PARENT_SCOPE ) +set( PLUGIN_INCLUDE_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/include;" PARENT_SCOPE ) diff --git a/core/CMake_project.txt b/core/CMake_project.txt index e7e17878a..2f966beb1 100644 --- a/core/CMake_project.txt +++ b/core/CMake_project.txt @@ -1,7 +1,10 @@ +option(ENABLE_OPENMP "Enable building with OpenMP" OFF) + +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_EXTENSIONS OFF) + if ( WIN32 ) - SET(CMAKE_C_COMPILER_ID "MSVC") - SET(CMAKE_CXX_COMPILER_ID "MSVC") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /std:c++latest") string(REGEX REPLACE "/MD*" "/MT" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") string(REGEX REPLACE "/MD*" "/MT" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") string(REGEX REPLACE "/W[0-4]" "/W1" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}") @@ -13,15 +16,7 @@ if ( WIN32 ) set( CMAKE_RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}" ) set( CMAKE_LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}/lib" ) set( CMAKE_ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} "${CMAKE_BINARY_DIR}/lib" ) - endforeach( OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES ) -else() - SET(CMAKE_C_COMPILER_ID "GNU") - SET(CMAKE_CXX_COMPILER_ID "GNU") - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") - if( CMAKE_BUILD_TYPE STREQUAL Debug ) - SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g" ) - SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") - endif() + endforeach(OUTPUTCONFIG) endif() if( CMAKE_BUILD_TYPE STREQUAL Debug ) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DHELIOS_DEBUG" ) @@ -49,9 +44,31 @@ foreach(PLUGIN ${PLUGINS}) endif() add_subdirectory( "${BASE_DIRECTORY}/plugins/${PLUGIN}" "${PROJECT_BINARY_DIR}/plugins/${PLUGIN}" ) target_link_libraries( ${EXECUTABLE_NAME} ${PLUGIN} ) - target_link_libraries( ${PLUGIN} helios ) + if( NOT APPLE ) + target_link_libraries( ${PLUGIN} helios ) + endif() endforeach(PLUGIN) include_directories( "${PLUGIN_INCLUDE_PATHS};${CMAKE_CURRENT_SOURCE_DIRECTORY}" ) +if( ENABLE_OPENMP ) + find_package(OpenMP) + if (OpenMP_CXX_FOUND) + message( "-- Enabling experimental OpenMP support" ) + target_link_libraries(${EXECUTABLE_NAME} OpenMP::OpenMP_CXX) + target_compile_definitions(${EXECUTABLE_NAME} PRIVATE USE_OPENMP) + if ( WIN32 ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp") + else() + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") + endif() + else() + if(CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") + message(WARNING "You are using Apple Clang compiler, which does not support OpenMP. The program will compile without OpenMP support.") + else() + message(WARNING "OpenMP not found! The program will compile without OpenMP support.") + endif() + endif() +endif() + enable_testing() -add_test(Test0,"${EXECUTABLE_NAME}" "0") \ No newline at end of file +add_test(NAME Test0 COMMAND ${EXECUTABLE_NAME} 0) \ No newline at end of file diff --git a/core/include/Context.h b/core/include/Context.h index f5874a418..09d8eefd3 100755 --- a/core/include/Context.h +++ b/core/include/Context.h @@ -735,6 +735,12 @@ class Tube : public CompoundObject { */ void setTubeNodes( const std::vector &node_xyz ); + //! Remove a portion of the tube downstream of a specified node + /** + * \param[in] node_index Index of the tube segment node beyond which will be removed + */ + void pruneTubeNodes( uint node_index ); + protected: std::vector nodes; @@ -4793,6 +4799,13 @@ class Context{ */ void scaleTubeLength( uint ObjID, float scale_factor ); + //! Remove a portion of the tube downstream of a specified node + /** + * \param[in] ObjID object ID of the Tube object + * \param[in] node_index Index of the tube segment node beyond which will be removed + */ + void pruneTubeNodes( uint ObjID, uint node_index ); + //! Set tube vertex coordinates at each segment node /** * \param[in] ObjID object ID of the Tube object diff --git a/core/include/global.h b/core/include/global.h index ed9021dca..286c939f8 100755 --- a/core/include/global.h +++ b/core/include/global.h @@ -53,6 +53,10 @@ constexpr float PI_F = 3.14159265358979323846f; #include #include +#ifdef USE_OPENMP +#include +#endif + typedef unsigned int uint; #include "helios_vector_types.h" diff --git a/core/src/Context.cpp b/core/src/Context.cpp index 6367b5c28..4c6142803 100755 --- a/core/src/Context.cpp +++ b/core/src/Context.cpp @@ -3913,6 +3913,33 @@ void Tube::setTubeNodes( const std::vector &node_xyz ){ } +void Tube::pruneTubeNodes( uint node_index ){ + + if( node_index >= nodes.size() ){ + helios_runtime_error("ERROR (Tube::pruneTubeNodes): Node index of " + std::to_string(node_index) + " is out of bounds."); + } + + if( node_index == 0 ){ + context->deleteObject(this->OID); + return; + } + + nodes.erase( nodes.begin() + node_index, nodes.end() ); + triangle_vertices.erase( triangle_vertices.begin() + node_index, triangle_vertices.end() ); + radius.erase( radius.begin() + node_index, radius.end() ); + colors.erase( colors.begin() + node_index, colors.end() ); + + int ii=0; + for (int i = node_index; i < nodes.size() - 1; i++) { + for(int j=0; j < subdiv; j++ ) { + context->deletePrimitive(UUIDs.at(ii)); + context->deletePrimitive(UUIDs.at(ii+1)); + ii += 2; + } + } + +} + void Tube::updateTriangleVertices(){ vec3 v0, v1, v2; @@ -8212,6 +8239,13 @@ void Context::scaleTubeLength( uint ObjID, float scale_factor ){ dynamic_cast(objects.at(ObjID))->scaleTubeLength(scale_factor); } +void Context::pruneTubeNodes( uint ObjID, uint node_index ){ + if( objects.find(ObjID) == objects.end() ) { + helios_runtime_error("ERROR (Context::pruneTubeNodes): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context."); + } + dynamic_cast(objects.at(ObjID))->pruneTubeNodes(node_index); +} + void Context::setTubeNodes( uint ObjID, const std::vector &node_xyz ){ if( objects.find(ObjID) == objects.end() ) { helios_runtime_error("ERROR (Context::setTubeNodes): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context."); diff --git a/core/src/Context_fileIO.cpp b/core/src/Context_fileIO.cpp index 53c7018e7..0890ee169 100644 --- a/core/src/Context_fileIO.cpp +++ b/core/src/Context_fileIO.cpp @@ -4142,10 +4142,10 @@ void Context::writeOBJ( const std::string &filename, const std::vector &UU // - it would make more sense to write patches as quads rather than two triangles if( UUIDs.empty() ){ - std::cout << "WARNING (Context::writeOBJ): No primitives found to write - OBJ file will not be written." << std::endl; + std::cout << "WARNING (Context::writeOBJ): No primitives found to write - OBJ file " << filename << " will not be written." << std::endl; return; }else if( filename.empty() ){ - std::cout << "WARNING (Context::writeOBJ): Filename was empty - OBJ file will not be written." << std::endl; + std::cout << "WARNING (Context::writeOBJ): Filename was empty - OBJ file " << filename << " will not be written." << std::endl; return; } diff --git a/core/src/global.cpp b/core/src/global.cpp index 7107dad61..3b7ee4c80 100755 --- a/core/src/global.cpp +++ b/core/src/global.cpp @@ -3051,7 +3051,7 @@ float helios::interp1( const std::vector &points, float x ) { //If the caller's X value is less than the smallest X value in the table, //we can't interpolate. - if (iter == points.cbegin() and x <= points.cbegin()->x) { + if (iter == points.cbegin() && x <= points.cbegin()->x) { return points.cbegin()->y; } diff --git a/doc/CHANGELOG b/doc/CHANGELOG index 88774f353..9951bf5ff 100644 --- a/doc/CHANGELOG +++ b/doc/CHANGELOG @@ -2023,4 +2023,32 @@ The radiation model has been re-designed, with the following primary additions: - Added mouse-based camera controls in the interactive visualizer. Credit to Sean Banks for this update. *Plant Architecture* -- 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. \ No newline at end of file +- 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. + +[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. \ No newline at end of file diff --git a/doc/Doxyfile b/doc/Doxyfile index f5f1e31d6..185a39d90 100755 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1298,7 +1298,7 @@ HTML_EXTRA_STYLESHEET = # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_FILES = +HTML_EXTRA_FILES = /Users/bnbailey/Dropbox/Helios/doc/assets/doxygen-awesome-darkmode-toggle.js # The HTML_COLORSTYLE tag can be used to specify if the generated HTML output # should be rendered with a dark or light theme. @@ -1611,7 +1611,7 @@ DISABLE_INDEX = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = NO +GENERATE_TREEVIEW = YES # When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the # FULL_SIDEBAR option determines if the side bar is limited to only the treeview @@ -1623,7 +1623,7 @@ GENERATE_TREEVIEW = NO # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. -FULL_SIDEBAR = NO +FULL_SIDEBAR = YES # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that # doxygen will group on one line in the generated HTML documentation. @@ -1702,7 +1702,7 @@ USE_MATHJAX = NO # The default value is: MathJax_2. # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_VERSION = MathJax_2 +MATHJAX_VERSION = MathJax_3 # When MathJax is enabled you can set the default output format to be used for # the MathJax output. For more details about the output format see MathJax diff --git a/doc/UserGuide.dox b/doc/UserGuide.dox index b8ef1ad7e..c0ba8f137 100755 --- a/doc/UserGuide.dox +++ b/doc/UserGuide.dox @@ -1,4 +1,4 @@ -/*! \mainpage Helios Documentation v1.3.26 +/*! \mainpage Helios Documentation


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





+





- \image html doc/images/PSL_logo_compact.png +
+ \image html doc/images/PSL_logo_compact.png +
+



@@ -348,7 +352,7 @@ $ git pull 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. - ~~~~~~ + ``` # Helios standard CMakeLists.txt file version 1.9 cmake_minimum_required(VERSION 3.15) project(helios) @@ -369,21 +373,21 @@ $ git pull #-------- DO NOT MODIFY ---------# include( "${BASE_DIRECTORY}/core/CMake_project.txt" ) - ~~~~~~ + ``` 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". 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: - ~~~~~~ + ``` $ cmake .. - ~~~~~~ + ``` 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: - ~~~~~~ + ``` $ cmake -DCMAKE_BUILD_TYPE='Release' .. - ~~~~~~ + ``` The code can then be compiled by issuing the 'make' command from the build directory, which will produce an executable in the build directory. @@ -459,20 +463,20 @@ $ git pull In order to use the Context, the following header must be included: - ~~~~~~{.cpp} + ~~~ #include "Context.h" - ~~~~~~ + ~~~ The context is typically created within the main function: - ~~~~~~{.cpp} + ~~~ #include "Context.h" using namespace helios; int main(){ Context context; } - ~~~~~~ + ~~~ The Context is usually passed to plugins (see \ref Plugins), which gives them access to geometry and data. @@ -1621,7 +1625,7 @@ $ git pull \section XMLread Reading XML Files - 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. + 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. ~~~~~~{.cpp} #include "Context.h" using namespace helios; @@ -1752,7 +1756,7 @@ $ git pull \section Export 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 \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. + 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. An XML file can be written as follows: diff --git a/doc/header.html b/doc/header.html index b4e095298..22c9882e9 100644 --- a/doc/header.html +++ b/doc/header.html @@ -40,7 +40,7 @@ Logo -
 v1.3.26 +
 v1.3.27
diff --git a/doc/html/Helios_logo_small.png b/doc/html/Helios_logo_small.png index 65732fadffbde053928fd08dac15285a500d7862..92ab7db459e035fc96c7372a076316b143a6d005 100644 GIT binary patch delta 28389 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%0Ajq9Rmgb_v(KyE|Y&N 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 diff --git a/doc/html/PSL_logo_compact.png b/doc/html/PSL_logo_compact.png index a693f784c8e84b03761d68bb5350464e2edd1f76..22ecf064a8013f33c63db44bca22c3babdd40815 100644 GIT binary patch literal 21823 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 literal 22219 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 Logo -

 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
User/API Guide
@@ -356,7 +366,7 @@

int main(){
Context context;
}
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888

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

Vector Types

@@ -440,8 +450,7 @@

RGB::goldenrod(0.855,0.647,0.126)

Note that the above colors can be directly passed to make_RGBAcolor to specify an alpha (transparency) value:

-
RGBAcolor red_trans = make_RGBAcolor( RGB::red, 0.5 );
-
R-G-B-A color vector.
+
RGBAcolor red_trans = make_RGBAcolor( RGB::red, 0.5 );

Coordinate System

Helios uses a right-handed Cartesian coordinate system. (x,y,z) coordinates are typically specified using the 'vec3' data structure (see Vector Types).
@@ -524,26 +533,29 @@

Context context;
-
vec3 center = make_vec3(0,0,1);
-
vec2 size = make_vec2(1,1);
+
vec3 center = make_vec3(0,0,1);
+
vec2 size = make_vec2(1,1);
uint UUID; //universal unique identifier
UUID = context.addPatch( center, size );
}
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.

This will add the Patch shown below, with the default orientation of horizontal. (Note that the addition of the checkerboard ground and the 'Visualizer' plugin is needed to replicate this image, which is not shown in the example code.)

Patch geometric primitive.

The patch can also be rotated by adding the optional SphericalCoord argument:

-
vec3 center = make_vec3(0,0,1);
-
vec2 size = make_vec2(1,1);
-
SphericalCoord rotation = make_SphericalCoord(0.25*M_PI,0.5*M_PI);
+
vec3 center = make_vec3(0,0,1);
+
vec2 size = make_vec2(1,1);
+
SphericalCoord rotation = make_SphericalCoord(0.25*M_PI,0.5*M_PI);
context.addPatch( center, size, rotation );
+
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
Vector of spherical coordinates (elevation,azimuth)

This will first rotate the patch by 0.25 $\pi$ rad about the x-axis such that its normal is pointing toward the +y direction, THEN it will apply a clockwise azimuthal rotation of 0.5 $\pi$ rad such that its normal is pointing in the +x direction (which will be its final orientation). Note that in order to have more control over rotations, it is recommended to use the Primitive::rotate() function (see "Primitive Transformations" section below).

@@ -556,9 +568,9 @@

Context context;
-
vec3 v0 = make_vec3(-0.5,-0.5,1);
-
vec3 v1 = make_vec3(0.5,-0.5,1);
-
vec3 v2 = make_vec3(0,0.5,1);
+
vec3 v0 = make_vec3(-0.5,-0.5,1);
+
vec3 v1 = make_vec3(0.5,-0.5,1);
+
vec3 v2 = make_vec3(0,0.5,1);
uint UUID; //universal unique identifier
UUID = context.addTriangle( v0, v1, v2, RGB::red );
@@ -585,8 +597,8 @@

Context context;
-
vec3 center = make_vec3(0,0,1);
-
vec3 size = make_vec3(1,1,1);
+
vec3 center = make_vec3(0,0,1);
+
vec3 size = make_vec3(1,1,1);
uint UUID; //universal unique identifier
UUID = context.addVoxel( center, size, 0, RGB::red );
@@ -599,8 +611,8 @@

Voxel geometric primitive.

The voxel can also be rotated by adding the optional SphericalCoord argument:

-
vec3 center = make_vec3(0,0,1);
-
vec3 size = make_vec3(1,1,1);
+
vec3 center = make_vec3(0,0,1);
+
vec3 size = make_vec3(1,1,1);
rotation = 0.25*M_PI;
context.addVoxel( center, size, rotation, RGB::red );

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

// Add 'Patch' primitive
vec3 center(0,0,1);
-
vec2 size = make_vec2(1,1);
+
vec2 size = make_vec2(1,1);
uint UUID = context.addPatch( center, size );
// Apply translation
@@ -734,23 +746,24 @@

Context context;
// Add 'Patch' primitive
-
vec3 center = make_vec3(0,0,1);
-
vec2 size = make_vec2(1,1);
-
uint UUID = context.addPatch( center, size, nullrotation, RGB::red );
+
vec3 center = make_vec3(0,0,1);
+
vec2 size = make_vec2(1,1);
+
uint UUID = context.addPatch( center, size, nullrotation, RGB::red );
// Get Patch size
vec2 SIZE = getPatchSize( UUID );
}
+
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57

Texture Mapping

Images can be overlaid on patches and triangles through a process called texture mapping. There are typically two reasons for doing this. One is simply for visualization purposes, as it easily allows for complex coloring of a surface by coloring a surface according to an image. The other is to create a more complex shape by removing a portion of the primitive surface according to the transparency channel of an image. Each of these cases are described in detail below.

Coloring Primitives by Texture Map

Patches: To color a Patch based on an image, simply pass the path to a PNG or JPEG image to the appropriate argument of the addPatch() command. Note that the path should either be absolute, or relative to the directory where the executable will be run (typically the ‘build’ directory).

-
vec3 center = make_vec3(0,0,1);
-
vec2 size = make_vec2(2.5,1);
-
SphericalCoord rotation = make_SphericalCoord(0,0);
+
vec3 center = make_vec3(0,0,1);
+
vec2 size = make_vec2(2.5,1);
+
context.addPatch( center, size, rotation, "PSL_logo_white.png");


@@ -781,10 +794,10 @@

Context context;
// Add 'Patch' primitive with transparency mask
-
vec3 center = make_vec3(0,0,1);
-
vec2 size = make_vec2(1,1);
+
vec3 center = make_vec3(0,0,1);
+
vec2 size = make_vec2(1,1);
-
uint UUID = context.addPatch( center, size, make_SphericalCoord(0,0), "GrapeLeaf.png" );
+
uint UUID = context.addPatch( center, size, make_SphericalCoord(0,0), "GrapeLeaf.png" );
}

@@ -801,16 +814,16 @@

// Add 'Patch' primitive with transparency mask
// We will add a patch at the origin and with unit size, and copy it multiple times
-
vec3 center = make_vec3(0,0,0);
-
vec2 size = make_vec2(1,1);
+
vec3 center = make_vec3(0,0,0);
+
vec2 size = make_vec2(1,1);
-
uint UUID = context.addPatch( center, size, make_SphericalCoord(0,0), "GrapeLeaf.png" );
+
uint UUID = context.addPatch( center, size, make_SphericalCoord(0,0), "GrapeLeaf.png" );
for( int i=0; i<10; i++ ){
uint UUID_copy = context.copyPrimitive(UUID);
-
vec3 position = make_vec3( i*3, 0, 0 );
+
vec3 position = make_vec3( i*3, 0, 0 );
context.translatePrimitive( position );
@@ -1005,7 +1018,7 @@

Similar to individual primitives, objects have functions to perform transformations on the entire object in unison. These functions are member functions of the helios::CompoundObject class. As with primitives, you can use the identifier to an object to get its pointer, from which you can access member functions.

uint objID; //unique identifier to object
-
objID = context.addTileObject( center, size, rotation, make_int2(2,2) );
+
objID = context.addTileObject( center, size, rotation, make_int2(2,2) );
CompoundObject* object = context.getObjectPointer(objID);
@@ -1013,7 +1026,8 @@

float getArea() const
Calculate the total one-sided surface area of the Compound Object.
Definition Context.cpp:2285
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
+
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4577
+
int2 make_int2(int x, int y)
Make an int2 vector from two ints.

or a shorthand would be

uint objID; //object identifier
float area = context.getObjectPointer(objID)->getArea();
@@ -1219,14 +1233,15 @@

std::vector<float> A;
A.push_back(2.3);
A.push_back(9.2);
-
context.setPrimitiveData(UUID,"somedataA",HELIOS_TYPE_FLOAT,A.size(),&A[0]);
+
context.setPrimitiveData(UUID,"somedataA",HELIOS_TYPE_FLOAT,A.size(),&A[0]);
float B[2];
B[0] = 2.3;
B[1] = 9.2;
-
context.setPrimitiveData(UUID,"somedataB",HELIOS_TYPE_FLOAT,2,&B[0]);
+
context.setPrimitiveData(UUID,"somedataB",HELIOS_TYPE_FLOAT,2,&B[0]);
}
+
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47

Getting Primitive Data Values

If primitive data is a scalar value, it can be retrieved for a given primitive via the Context using the getPrimitiveData function:

@@ -1293,7 +1308,7 @@

}
HeliosDataType
Data types.
Definition Context.h:41
uint getPrimitiveDataSize(uint UUID, const char *label) const
Get the size/length of primitive data.
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.

Global Data

@@ -1314,24 +1329,24 @@

Date date;
Time time;
-
date = make_Date( 2, 1, 2000 ); // 2 Jan. 2000
+
date = make_Date( 2, 1, 2000 ); // 2 Jan. 2000
-
time = make_Time( 13, 00, 00 ); // 13:00:00
+
time = make_Time( 13, 00, 00 ); // 13:00:00
context.addTimeseriesData( "temperature", 301.23, date, time ); // index #0
-
time = make_Time( 13, 15, 00 ); // 13:15:00
+
time = make_Time( 13, 15, 00 ); // 13:15:00
context.addTimeseriesData( "temperature", 301.92, date, time ); // index #1
-
time = make_Time( 13, 30, 00 ); // 13:30:00
+
time = make_Time( 13, 30, 00 ); // 13:30:00
context.addTimeseriesData( "temperature", 302.56, date, time ); // index #2
-
time = make_Time( 13, 45, 00 ); // 13:45:00
+
time = make_Time( 13, 45, 00 ); // 13:45:00
context.addTimeseriesData( "temperature", 303.05, date, time ); // index #3
float T;
T = context.queryTimeseriesData( "temperature", 1 ); // Here, T = 301.92
-
time = make_Time( 13, 15, 00 );
+
time = make_Time( 13, 15, 00 );
T = context.queryTimeseriesData( "temperature", date, time ); // Also here, T = 301.92
for( uint i=0; i<context.getTimeseriesLength("temperature"); i++ ){
@@ -1344,6 +1359,8 @@

uint getTimeseriesLength(const char *label) const
Get the length of timeseries data.
Definition Context.cpp:2014
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:1894
void addTimeseriesData(const char *label, float value, const Date &date, const Time &time)
Add a data point to timeseries of data.
Definition Context.cpp:1823
+
Time make_Time(int hour, int minute)
Make a Time vector.
+
Date make_Date(int day, int month, int year)
Make a Date vector.
int second
Second of minute.
@@ -1354,10 +1371,12 @@

uint N = context.getTimeseriesLength( "temperature" );

- - + + diff --git a/doc/html/_aerial_li_d_a_r_8cpp.html b/doc/html/_aerial_li_d_a_r_8cpp.html index 668a22ef9..e52db7243 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
AerialLiDAR.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file AerialLiDAR.cpp.

- - + + 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 c982a3b01..e7c876303 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
AerialLiDAR.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "AerialLiDAR.h"
17
18using namespace std;
@@ -182,7 +189,7 @@
83 LAD_exact = float(Nleaves.x*Nleaves.y*Nleaves.z)*L*L/(boxsize.x*boxsize.y*boxsize.z);
84
85 flag = true;
-
86 AerialLiDARcloud lidar_1;
+
86 AerialLiDARcloud lidar_1;
87 lidar_1.disableMessages();
88
89 lidar_1.syntheticScan( &context_1, "plugins/aeriallidar/xml/synthetic_aerial_test.xml" );
@@ -253,7 +260,7 @@
154
155 LAD_exact = float(Nleaves.x*Nleaves.y*Nleaves.z)*L*L/(boxsize.x*boxsize.y*boxsize.z);
156
-
157 AerialLiDARcloud lidar_2;
+
157 AerialLiDARcloud lidar_2;
158 lidar_2.disableMessages();
159
160 lidar_2.syntheticScan( &context_2, "plugins/aeriallidar/xml/synthetic_aerial_test.xml" );
@@ -305,7 +312,7 @@
206
207 context_3.addPatch( make_vec3(0.5*boxsize.x,0.5*boxsize.y,zground), make_vec2( boxsize.x, boxsize.y ) );
208
-
209 AerialLiDARcloud lidar_3;
+
209 AerialLiDARcloud lidar_3;
210 lidar_3.disableMessages();
211
212 lidar_3.syntheticScan( &context_3, "plugins/aeriallidar/xml/synthetic_aerial_test.xml" );
@@ -672,16 +679,16 @@
521 cerr << "ERROR (setHitGridCell): Hit point index out of bounds. Tried to set hit #" << index << " but scan only has " << hits.size() << " hits." << endl;
522 exit(EXIT_FAILURE);
523 }
-
524 if( ijk.x>=gridresolution.x ){
-
525 cerr << "ERROR (setHitGridCell): Grid index in x-direction was specified as " << ijk.x << ", which is larger than the maximum value based on the grid dimension of " << gridresolution.x-1 << "." << std::endl;
+
524 if( ijk.x>=gridresolution.x ){
+
525 cerr << "ERROR (setHitGridCell): Grid index in x-direction was specified as " << ijk.x << ", which is larger than the maximum value based on the grid dimension of " << gridresolution.x-1 << "." << std::endl;
526 exit(EXIT_FAILURE);
527 }
-
528 if( ijk.y>=gridresolution.y ){
-
529 cerr << "ERROR (setHitGridCell): Grid index in y-direction was specified as " << ijk.y << ", which is larger than the maximum value based on the grid dimension of " << gridresolution.y-1 << "." << std::endl;
+
528 if( ijk.y>=gridresolution.y ){
+
529 cerr << "ERROR (setHitGridCell): Grid index in y-direction was specified as " << ijk.y << ", which is larger than the maximum value based on the grid dimension of " << gridresolution.y-1 << "." << std::endl;
530 exit(EXIT_FAILURE);
531 }
-
532 if( ijk.z>=gridresolution.z ){
-
533 cerr << "ERROR (setHitGridCell): Grid index in x-direction was specified as " << ijk.z << ", which is larger than the maximum value based on the grid dimension of " << gridresolution.z-1 << "." << std::endl;
+
532 if( ijk.z>=gridresolution.z ){
+
533 cerr << "ERROR (setHitGridCell): Grid index in x-direction was specified as " << ijk.z << ", which is larger than the maximum value based on the grid dimension of " << gridresolution.z-1 << "." << std::endl;
534 exit(EXIT_FAILURE);
535 }
536
@@ -720,7 +727,7 @@
565 return;
566 }
567
-
568 int Ngrid = gridresolution.x*gridresolution.y*gridresolution.z;
+
568 int Ngrid = gridresolution.x*gridresolution.y*gridresolution.z;
569
570 //-- hit points --//
571 float minval = 1e9;
@@ -784,7 +791,7 @@
627 return;
628 }
629
-
630 int Ngrid = gridresolution.x*gridresolution.y*gridresolution.z;
+
630 int Ngrid = gridresolution.x*gridresolution.y*gridresolution.z;
631
632 float minval = 1e9;
633 float maxval = -1e9;
@@ -876,22 +883,22 @@
717
-
718 if( index<0 || index>=gridresolution.x*gridresolution.y*gridresolution.z ){
+
718 if( index<0 || index>=gridresolution.x*gridresolution.y*gridresolution.z ){
719 return make_int3(-1,-1,-1);
720 }else{
721
-
722 int k=floor(double(index)/double(gridresolution.x)/double(gridresolution.y));
-
723 int j=floor((double(index)-double(k)*double(gridresolution.x)*double(gridresolution.y))/double(gridresolution.x));
-
724 int i=index-k*gridresolution.x*gridresolution.y-j*gridresolution.x;
+
722 int k=floor(double(index)/double(gridresolution.x)/double(gridresolution.y));
+
723 int j=floor((double(index)-double(k)*double(gridresolution.x)*double(gridresolution.y))/double(gridresolution.x));
+
724 int i=index-k*gridresolution.x*gridresolution.y-j*gridresolution.x;
725
-
726 if( i>=0 && i<gridresolution.x && j>=0 && j<gridresolution.y && k>=0 && k<gridresolution.z ){
+
726 if( i>=0 && i<gridresolution.x && j>=0 && j<gridresolution.y && k>=0 && k<gridresolution.z ){
727 }else{
-
728 printf("resolution: %d x %d x %d\n",gridresolution.x,gridresolution.y,gridresolution.z);
+
728 printf("resolution: %d x %d x %d\n",gridresolution.x,gridresolution.y,gridresolution.z);
729 printf("index: %d\n",index);
730 printf("ijk: (%d,%d,%d)\n",i,j,k);
731 }
732
-
733 assert( i>=0 && i<gridresolution.x && j>=0 && j<gridresolution.y && k>=0 && k<gridresolution.z );
+
733 assert( i>=0 && i<gridresolution.x && j>=0 && j<gridresolution.y && k>=0 && k<gridresolution.z );
734
735 return make_int3(i,j,k);
736
@@ -903,9 +910,9 @@
742
-
743 int index = ijk.z*gridresolution.x*gridresolution.y+ijk.y*gridresolution.y+ijk.x;
+
743 int index = ijk.z*gridresolution.x*gridresolution.y+ijk.y*gridresolution.y+ijk.x;
744
-
745 if( index<0 || index>=gridresolution.x*gridresolution.y*gridresolution.z ){
+
745 if( index<0 || index>=gridresolution.x*gridresolution.y*gridresolution.z ){
746 return -1;
747 }else{
748 return index;
@@ -947,12 +954,12 @@
776
-
777 float x = -0.5*gridextent.x+(float(ijk.x)+0.5f)*gridextent.x/float(gridresolution.x);
-
778 float y = -0.5*gridextent.y+(float(ijk.y)+0.5f)*gridextent.y/float(gridresolution.y);
+
777 float x = -0.5*gridextent.x+(float(ijk.x)+0.5f)*gridextent.x/float(gridresolution.x);
+
778 float y = -0.5*gridextent.y+(float(ijk.y)+0.5f)*gridextent.y/float(gridresolution.y);
779
-
780 vec2 xy = rotatePoint2D( make_vec2(x,y), gridrotation ) + make_vec2(gridcenter.x,gridcenter.y);
+
780 vec2 xy = rotatePoint2D( make_vec2(x,y), gridrotation ) + make_vec2(gridcenter.x,gridcenter.y);
781
-
782 float z = gridcenter.z-0.5*gridextent.z+(float(ijk.z)+0.5f)*gridextent.z/float(gridresolution.z);
+
782 float z = gridcenter.z-0.5*gridextent.z+(float(ijk.z)+0.5f)*gridextent.z/float(gridresolution.z);
783
784 if( groundheightcomputed ){
785
@@ -968,7 +975,7 @@
795
-
796 return make_vec3( gridextent.x/float(gridresolution.x), gridextent.y/float(gridresolution.y), gridextent.z/float(gridresolution.z) );
+
796 return make_vec3( gridextent.x/float(gridresolution.x), gridextent.y/float(gridresolution.y), gridextent.z/float(gridresolution.z) );
797
798}
@@ -978,27 +985,27 @@
802void AerialLiDARcloud::setCellLeafArea( const float area, const int3 ijk ){
803
-
804 if( ijk.x<0 || ijk.x>=gridresolution.x ){
-
805 cerr << "ERROR (setCellLeafArea): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
804 if( ijk.x<0 || ijk.x>=gridresolution.x ){
+
805 cerr << "ERROR (setCellLeafArea): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
806 exit(EXIT_FAILURE);
807 }
-
808 if( ijk.y<0 || ijk.y>=gridresolution.y ){
-
809 cerr << "ERROR (setCellLeafArea): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
808 if( ijk.y<0 || ijk.y>=gridresolution.y ){
+
809 cerr << "ERROR (setCellLeafArea): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
810 exit(EXIT_FAILURE);
811 }
-
812 if( ijk.z<0 || ijk.z>=gridresolution.z ){
-
813 cerr << "ERROR (setCellLeafArea): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
+
812 if( ijk.z<0 || ijk.z>=gridresolution.z ){
+
813 cerr << "ERROR (setCellLeafArea): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
814 exit(EXIT_FAILURE);
815 }
816
-
817 if( leaf_area.size()!=gridresolution.z ){
-
818 leaf_area.resize(gridresolution.z);
+
817 if( leaf_area.size()!=gridresolution.z ){
+
818 leaf_area.resize(gridresolution.z);
819 }
-
820 if( leaf_area.at(ijk.z).size()!=gridresolution.y ){
-
821 leaf_area.at(ijk.z).resize(gridresolution.y);
+
820 if( leaf_area.at(ijk.z).size()!=gridresolution.y ){
+
821 leaf_area.at(ijk.z).resize(gridresolution.y);
822 }
-
823 if( leaf_area.at(ijk.z).at(ijk.y).size()!=gridresolution.x ){
-
824 leaf_area.at(ijk.z).at(ijk.y).resize(gridresolution.x);
+
823 if( leaf_area.at(ijk.z).at(ijk.y).size()!=gridresolution.x ){
+
824 leaf_area.at(ijk.z).at(ijk.y).resize(gridresolution.x);
825 }
826
827 leaf_area.at(ijk.z).at(ijk.y).at(ijk.x) = area;
@@ -1009,21 +1016,21 @@
832
-
833 if( leaf_area.size()!=gridresolution.z ){
+
833 if( leaf_area.size()!=gridresolution.z ){
834 cerr << "ERROR (getCellLeafArea): Leaf area calculations have not been run yet. You must first call the function calculateLeafAreaGPU()." << std::endl;
835 exit(EXIT_FAILURE);
836 }
837
-
838 if( ijk.x<0 || ijk.x>=gridresolution.x ){
-
839 cerr << "ERROR (getCellLeafArea): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
838 if( ijk.x<0 || ijk.x>=gridresolution.x ){
+
839 cerr << "ERROR (getCellLeafArea): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
840 exit(EXIT_FAILURE);
841 }
-
842 if( ijk.y<0 || ijk.y>=gridresolution.y ){
-
843 cerr << "ERROR (getCellLeafArea): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
842 if( ijk.y<0 || ijk.y>=gridresolution.y ){
+
843 cerr << "ERROR (getCellLeafArea): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
844 exit(EXIT_FAILURE);
845 }
-
846 if( ijk.z<0 || ijk.z>=gridresolution.z ){
-
847 cerr << "ERROR (getCellLeafArea): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
+
846 if( ijk.z<0 || ijk.z>=gridresolution.z ){
+
847 cerr << "ERROR (getCellLeafArea): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
848 exit(EXIT_FAILURE);
849 }
850
@@ -1035,25 +1042,25 @@
856
-
857 if( leaf_area.size()!=gridresolution.z ){
+
857 if( leaf_area.size()!=gridresolution.z ){
858 cerr << "ERROR (getCellLeafAreaDensity): Leaf area calculations have not been run yet. You must first call the function calculateLeafAreaGPU()." << std::endl;
859 exit(EXIT_FAILURE);
860 }
861
-
862 if( ijk.x<0 || ijk.x>=gridresolution.x ){
-
863 cerr << "ERROR (getCellLeafAreaDensity): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
862 if( ijk.x<0 || ijk.x>=gridresolution.x ){
+
863 cerr << "ERROR (getCellLeafAreaDensity): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
864 exit(EXIT_FAILURE);
865 }
-
866 if( ijk.y<0 || ijk.y>=gridresolution.y ){
-
867 cerr << "ERROR (getCellLeafAreaDensity): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
866 if( ijk.y<0 || ijk.y>=gridresolution.y ){
+
867 cerr << "ERROR (getCellLeafAreaDensity): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
868 exit(EXIT_FAILURE);
869 }
-
870 if( ijk.z<0 || ijk.z>=gridresolution.z ){
-
871 cerr << "ERROR (getCellLeafAreaDensity): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
+
870 if( ijk.z<0 || ijk.z>=gridresolution.z ){
+
871 cerr << "ERROR (getCellLeafAreaDensity): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
872 exit(EXIT_FAILURE);
873 }
874
-
875 vec3 gridsize( gridextent.x/float(gridresolution.x), gridextent.y/float(gridresolution.y), gridextent.z/float(gridresolution.z) );
+
875 vec3 gridsize( gridextent.x/float(gridresolution.x), gridextent.y/float(gridresolution.y), gridextent.z/float(gridresolution.z) );
876
877 return leaf_area.at(ijk.z).at(ijk.y).at(ijk.x)/(gridsize.x*gridsize.y*gridsize.z);
878
@@ -1063,27 +1070,27 @@
881void AerialLiDARcloud::setCellTransmissionProbability( const int P_denom, const int P_trans, const int3 ijk ){
882
-
883 if( ijk.x<0 || ijk.x>=gridresolution.x ){
-
884 cerr << "ERROR (setCellTransmissionProbability): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
883 if( ijk.x<0 || ijk.x>=gridresolution.x ){
+
884 cerr << "ERROR (setCellTransmissionProbability): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
885 exit(EXIT_FAILURE);
886 }
-
887 if( ijk.y<0 || ijk.y>=gridresolution.y ){
-
888 cerr << "ERROR (setCellTransmissionProbability): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
887 if( ijk.y<0 || ijk.y>=gridresolution.y ){
+
888 cerr << "ERROR (setCellTransmissionProbability): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
889 exit(EXIT_FAILURE);
890 }
-
891 if( ijk.z<0 || ijk.z>=gridresolution.z ){
-
892 cerr << "ERROR (setCellTransmissionProbability): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
+
891 if( ijk.z<0 || ijk.z>=gridresolution.z ){
+
892 cerr << "ERROR (setCellTransmissionProbability): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
893 exit(EXIT_FAILURE);
894 }
895
-
896 if( P_counts.size()!=gridresolution.z ){
-
897 P_counts.resize(gridresolution.z);
+
896 if( P_counts.size()!=gridresolution.z ){
+
897 P_counts.resize(gridresolution.z);
898 }
-
899 if( P_counts.at(ijk.z).size()!=gridresolution.y ){
-
900 P_counts.at(ijk.z).resize(gridresolution.y);
+
899 if( P_counts.at(ijk.z).size()!=gridresolution.y ){
+
900 P_counts.at(ijk.z).resize(gridresolution.y);
901 }
-
902 if( P_counts.at(ijk.z).at(ijk.y).size()!=gridresolution.x ){
-
903 P_counts.at(ijk.z).at(ijk.y).resize(gridresolution.x);
+
902 if( P_counts.at(ijk.z).at(ijk.y).size()!=gridresolution.x ){
+
903 P_counts.at(ijk.z).at(ijk.y).resize(gridresolution.x);
904 }
905
906 P_counts.at(ijk.z).at(ijk.y).at(ijk.x) = make_int2(P_denom,P_trans);
@@ -1094,21 +1101,21 @@
910void AerialLiDARcloud::getCellTransmissionProbability( const int3 ijk, int& P_denom, int& P_trans ) const{
911
-
912 if( P_counts.size()!=gridresolution.z ){
+
912 if( P_counts.size()!=gridresolution.z ){
913 cerr << "ERROR (getCellTransmissionProbability): Leaf area calculations have not been run yet. You must first call the function calculateLeafAreaGPU()." << std::endl;
914 exit(EXIT_FAILURE);
915 }
916
-
917 if( ijk.x<0 || ijk.x>=gridresolution.x ){
-
918 cerr << "ERROR (getCellTransmissionProbabilit): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
917 if( ijk.x<0 || ijk.x>=gridresolution.x ){
+
918 cerr << "ERROR (getCellTransmissionProbabilit): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
919 exit(EXIT_FAILURE);
920 }
-
921 if( ijk.y<0 || ijk.y>=gridresolution.y ){
-
922 cerr << "ERROR (getCellTransmissionProbabilit): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
921 if( ijk.y<0 || ijk.y>=gridresolution.y ){
+
922 cerr << "ERROR (getCellTransmissionProbabilit): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
923 exit(EXIT_FAILURE);
924 }
-
925 if( ijk.z<0 || ijk.z>=gridresolution.z ){
-
926 cerr << "ERROR (getCellTransmissionProbabilit): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
+
925 if( ijk.z<0 || ijk.z>=gridresolution.z ){
+
926 cerr << "ERROR (getCellTransmissionProbabilit): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
927 exit(EXIT_FAILURE);
928 }
929
@@ -1122,27 +1129,27 @@
936void AerialLiDARcloud::setCellRbar( const float rbar, const int3 ijk ){
937
-
938 if( ijk.x<0 || ijk.x>=gridresolution.x ){
-
939 cerr << "ERROR (setCellRbar): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
938 if( ijk.x<0 || ijk.x>=gridresolution.x ){
+
939 cerr << "ERROR (setCellRbar): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
940 exit(EXIT_FAILURE);
941 }
-
942 if( ijk.y<0 || ijk.y>=gridresolution.y ){
-
943 cerr << "ERROR (setCellRbar): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
942 if( ijk.y<0 || ijk.y>=gridresolution.y ){
+
943 cerr << "ERROR (setCellRbar): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
944 exit(EXIT_FAILURE);
945 }
-
946 if( ijk.z<0 || ijk.z>=gridresolution.z ){
-
947 cerr << "ERROR (setCellRbar): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
+
946 if( ijk.z<0 || ijk.z>=gridresolution.z ){
+
947 cerr << "ERROR (setCellRbar): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
948 exit(EXIT_FAILURE);
949 }
950
-
951 if( r_bar.size()!=gridresolution.z ){
-
952 r_bar.resize(gridresolution.z);
+
951 if( r_bar.size()!=gridresolution.z ){
+
952 r_bar.resize(gridresolution.z);
953 }
-
954 if( r_bar.at(ijk.z).size()!=gridresolution.y ){
-
955 r_bar.at(ijk.z).resize(gridresolution.y);
+
954 if( r_bar.at(ijk.z).size()!=gridresolution.y ){
+
955 r_bar.at(ijk.z).resize(gridresolution.y);
956 }
-
957 if( r_bar.at(ijk.z).at(ijk.y).size()!=gridresolution.x ){
-
958 r_bar.at(ijk.z).at(ijk.y).resize(gridresolution.x);
+
957 if( r_bar.at(ijk.z).at(ijk.y).size()!=gridresolution.x ){
+
958 r_bar.at(ijk.z).at(ijk.y).resize(gridresolution.x);
959 }
960
961 r_bar.at(ijk.z).at(ijk.y).at(ijk.x) = rbar;
@@ -1153,21 +1160,21 @@
965float AerialLiDARcloud::getCellRbar( const int3 ijk ) const{
966
-
967 if( r_bar.size()!=gridresolution.z ){
+
967 if( r_bar.size()!=gridresolution.z ){
968 cerr << "ERROR (getCellRbar): Leaf area calculations have not been run yet. You must first call the function calculateLeafAreaGPU()." << std::endl;
969 exit(EXIT_FAILURE);
970 }
971
-
972 if( ijk.x<0 || ijk.x>=gridresolution.x ){
-
973 cerr << "ERROR (getCellRbar): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
972 if( ijk.x<0 || ijk.x>=gridresolution.x ){
+
973 cerr << "ERROR (getCellRbar): Cell index in x-direction of " << ijk.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
974 exit(EXIT_FAILURE);
975 }
-
976 if( ijk.y<0 || ijk.y>=gridresolution.y ){
-
977 cerr << "ERROR (getCellRbar): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
976 if( ijk.y<0 || ijk.y>=gridresolution.y ){
+
977 cerr << "ERROR (getCellRbar): Cell index in y-direction of " << ijk.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
978 exit(EXIT_FAILURE);
979 }
-
980 if( ijk.z<0 || ijk.z>=gridresolution.z ){
-
981 cerr << "ERROR (getCellRbar): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
+
980 if( ijk.z<0 || ijk.z>=gridresolution.z ){
+
981 cerr << "ERROR (getCellRbar): Cell index in z-direction of " << ijk.z << " is outside the allowable range of 0 to " << gridresolution.z-1 << std::endl;
982 exit(EXIT_FAILURE);
983 }
984
@@ -1243,7 +1250,7 @@
1053 inliers.resize(N,0);
1054 for( int p=0; p<N; p++ ){
1055
-
1056 helios::vec3 point = hits.at(p);
+
1056 helios::vec3 point = hits.at(p);
1057
1058 float zplane = -(bestModel.x*point.x+bestModel.y*point.y+bestModel.w)/bestModel.z;
1059 float zerr = fabs( zplane - point.z );
@@ -1561,20 +1568,20 @@
1369void AerialLiDARcloud::setCellVegetationHeight( const float height, const int2 ij ){
1370
-
1371 if( ij.x<0 || ij.x>=gridresolution.x ){
-
1372 cerr << "ERROR (setCellVegetationHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
1371 if( ij.x<0 || ij.x>=gridresolution.x ){
+
1372 cerr << "ERROR (setCellVegetationHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
1373 exit(EXIT_FAILURE);
1374 }
-
1375 if( ij.y<0 || ij.y>=gridresolution.y ){
-
1376 cerr << "ERROR (setCellVegetationHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
1375 if( ij.y<0 || ij.y>=gridresolution.y ){
+
1376 cerr << "ERROR (setCellVegetationHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
1377 exit(EXIT_FAILURE);
1378 }
1379
-
1380 if( vegetation_height.size()!=gridresolution.y ){
-
1381 vegetation_height.resize(gridresolution.y);
+
1380 if( vegetation_height.size()!=gridresolution.y ){
+
1381 vegetation_height.resize(gridresolution.y);
1382 }
-
1383 if( vegetation_height.at(ij.y).size()!=gridresolution.x ){
-
1384 vegetation_height.at(ij.y).resize(gridresolution.x);
+
1383 if( vegetation_height.at(ij.y).size()!=gridresolution.x ){
+
1384 vegetation_height.at(ij.y).resize(gridresolution.x);
1385 }
1386
1387 vegetation_height.at(ij.y).at(ij.x) = height;
@@ -1585,17 +1592,17 @@
1392
-
1393 if( vegetation_height.size()!=gridresolution.y ){
+
1393 if( vegetation_height.size()!=gridresolution.y ){
1394 cerr << "ERROR (getCellVegetationHeight): Height calculations have not been run yet. You must first call the function generateHeightModel()." << std::endl;
1395 exit(EXIT_FAILURE);
1396 }
1397
-
1398 if( ij.x<0 || ij.x>=gridresolution.x ){
-
1399 cerr << "ERROR (getCellVegetationHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
1398 if( ij.x<0 || ij.x>=gridresolution.x ){
+
1399 cerr << "ERROR (getCellVegetationHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
1400 exit(EXIT_FAILURE);
1401 }
-
1402 if( ij.y<0 || ij.y>=gridresolution.y ){
-
1403 cerr << "ERROR (getCellVegetationHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
1402 if( ij.y<0 || ij.y>=gridresolution.y ){
+
1403 cerr << "ERROR (getCellVegetationHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
1404 exit(EXIT_FAILURE);
1405 }
1406
@@ -1607,20 +1614,20 @@
1411void AerialLiDARcloud::setCellMaximumHitHeight( const float height, const int2 ij ){
1412
-
1413 if( ij.x<0 || ij.x>=gridresolution.x ){
-
1414 cerr << "ERROR (setCellMaximumHitHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
1413 if( ij.x<0 || ij.x>=gridresolution.x ){
+
1414 cerr << "ERROR (setCellMaximumHitHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
1415 exit(EXIT_FAILURE);
1416 }
-
1417 if( ij.y<0 || ij.y>=gridresolution.y ){
-
1418 cerr << "ERROR (setCellMaximumHitHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
1417 if( ij.y<0 || ij.y>=gridresolution.y ){
+
1418 cerr << "ERROR (setCellMaximumHitHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
1419 exit(EXIT_FAILURE);
1420 }
1421
-
1422 if( maxhit_height.size()!=gridresolution.y ){
-
1423 maxhit_height.resize(gridresolution.y);
+
1422 if( maxhit_height.size()!=gridresolution.y ){
+
1423 maxhit_height.resize(gridresolution.y);
1424 }
-
1425 if( maxhit_height.at(ij.y).size()!=gridresolution.x ){
-
1426 maxhit_height.at(ij.y).resize(gridresolution.x);
+
1425 if( maxhit_height.at(ij.y).size()!=gridresolution.x ){
+
1426 maxhit_height.at(ij.y).resize(gridresolution.x);
1427 }
1428
1429 maxhit_height.at(ij.y).at(ij.x) = height;
@@ -1631,17 +1638,17 @@
1434
-
1435 if( maxhit_height.size()!=gridresolution.y ){
+
1435 if( maxhit_height.size()!=gridresolution.y ){
1436 cerr << "ERROR (getCellMaximumHitHeight): Height calculations have not been run yet. You must first call the function generateHeightModel()." << std::endl;
1437 exit(EXIT_FAILURE);
1438 }
1439
-
1440 if( ij.x<0 || ij.x>=gridresolution.x ){
-
1441 cerr << "ERROR (getCellMaximumHitHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
1440 if( ij.x<0 || ij.x>=gridresolution.x ){
+
1441 cerr << "ERROR (getCellMaximumHitHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
1442 exit(EXIT_FAILURE);
1443 }
-
1444 if( ij.y<0 || ij.y>=gridresolution.y ){
-
1445 cerr << "ERROR (getCellMaximumHitHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
1444 if( ij.y<0 || ij.y>=gridresolution.y ){
+
1445 cerr << "ERROR (getCellMaximumHitHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
1446 exit(EXIT_FAILURE);
1447 }
1448
@@ -1653,20 +1660,20 @@
1453void AerialLiDARcloud::setCellGroundHeight( const float height, const int2 ij ){
1454
-
1455 if( ij.x<0 || ij.x>=gridresolution.x ){
-
1456 cerr << "ERROR (setCellGroundHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
1455 if( ij.x<0 || ij.x>=gridresolution.x ){
+
1456 cerr << "ERROR (setCellGroundHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
1457 exit(EXIT_FAILURE);
1458 }
-
1459 if( ij.y<0 || ij.y>=gridresolution.y ){
-
1460 cerr << "ERROR (setCellGroundHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
1459 if( ij.y<0 || ij.y>=gridresolution.y ){
+
1460 cerr << "ERROR (setCellGroundHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
1461 exit(EXIT_FAILURE);
1462 }
1463
-
1464 if( ground_height.size()!=gridresolution.y ){
-
1465 ground_height.resize(gridresolution.y);
+
1464 if( ground_height.size()!=gridresolution.y ){
+
1465 ground_height.resize(gridresolution.y);
1466 }
-
1467 if( ground_height.at(ij.y).size()!=gridresolution.x ){
-
1468 ground_height.at(ij.y).resize(gridresolution.x);
+
1467 if( ground_height.at(ij.y).size()!=gridresolution.x ){
+
1468 ground_height.at(ij.y).resize(gridresolution.x);
1469 }
1470
1471 ground_height.at(ij.y).at(ij.x) = height;
@@ -1677,17 +1684,17 @@
1476
-
1477 if( ground_height.size()!=gridresolution.y ){
+
1477 if( ground_height.size()!=gridresolution.y ){
1478 cerr << "ERROR (getCellGroundHeight): Height calculations have not been run yet. You must first call the function generateHeightModel()." << std::endl;
1479 exit(EXIT_FAILURE);
1480 }
1481
-
1482 if( ij.x<0 || ij.x>=gridresolution.x ){
-
1483 cerr << "ERROR (getCellGroundHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
1482 if( ij.x<0 || ij.x>=gridresolution.x ){
+
1483 cerr << "ERROR (getCellGroundHeight): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
1484 exit(EXIT_FAILURE);
1485 }
-
1486 if( ij.y<0 || ij.y>=gridresolution.y ){
-
1487 cerr << "ERROR (getCellGroundHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
1486 if( ij.y<0 || ij.y>=gridresolution.y ){
+
1487 cerr << "ERROR (getCellGroundHeight): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
1488 exit(EXIT_FAILURE);
1489 }
1490
@@ -1712,11 +1719,11 @@
1508
1509 for( int r=0; r<Nhits; r++ ){
1510
-
1511 int3 ijk = getHitGridCell(r);
+
1511 int3 ijk = getHitGridCell(r);
1512
-
1513 int2 ij(ijk.x,ijk.y);
+
1513 int2 ij(ijk.x,ijk.y);
1514
-
1515 if( ij.x>=0 && ij.x<gridresolution.x && ij.y>=0 && ij.y<gridresolution.y ){
+
1515 if( ij.x>=0 && ij.x<gridresolution.x && ij.y>=0 && ij.y<gridresolution.y ){
1516
1517 float ground_flag = getHitData(r,"ground_flag");
1518 if( ground_flag==1 ){
@@ -1728,8 +1735,8 @@
1524
1525 }
1526
-
1527 for( int j=0; j<gridresolution.y; j++ ){
-
1528 for( int i=0; i<gridresolution.x; i++ ){
+
1527 for( int j=0; j<gridresolution.y; j++ ){
+
1528 for( int i=0; i<gridresolution.x; i++ ){
1529
1530 float fcover;
1531 if( total_hits.at(j).at(i)>0 ){
@@ -1751,20 +1758,20 @@
1547void AerialLiDARcloud::setCellCoverFraction( const float fcover, const int2 ij ){
1548
-
1549 if( ij.x<0 || ij.x>=gridresolution.x ){
-
1550 cerr << "ERROR (setCellCoverFraction): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
1549 if( ij.x<0 || ij.x>=gridresolution.x ){
+
1550 cerr << "ERROR (setCellCoverFraction): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
1551 exit(EXIT_FAILURE);
1552 }
-
1553 if( ij.y<0 || ij.y>=gridresolution.y ){
-
1554 cerr << "ERROR (setCellCoverFraction): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
1553 if( ij.y<0 || ij.y>=gridresolution.y ){
+
1554 cerr << "ERROR (setCellCoverFraction): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
1555 exit(EXIT_FAILURE);
1556 }
1557
-
1558 if( cover_fraction.size()!=gridresolution.y ){
-
1559 cover_fraction.resize(gridresolution.y);
+
1558 if( cover_fraction.size()!=gridresolution.y ){
+
1559 cover_fraction.resize(gridresolution.y);
1560 }
-
1561 if( cover_fraction.at(ij.y).size()!=gridresolution.x ){
-
1562 cover_fraction.at(ij.y).resize(gridresolution.x);
+
1561 if( cover_fraction.at(ij.y).size()!=gridresolution.x ){
+
1562 cover_fraction.at(ij.y).resize(gridresolution.x);
1563 }
1564
1565 cover_fraction.at(ij.y).at(ij.x) = fcover;
@@ -1775,17 +1782,17 @@
1570
-
1571 if( cover_fraction.size()!=gridresolution.y ){
+
1571 if( cover_fraction.size()!=gridresolution.y ){
1572 cerr << "ERROR (getCellCoverFraction): Cover fraction calculations have not been run yet. You must first call the function calculateCoverFraction()." << std::endl;
1573 exit(EXIT_FAILURE);
1574 }
1575
-
1576 if( ij.x<0 || ij.x>=gridresolution.x ){
-
1577 cerr << "ERROR (getCellCoverFraction): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
+
1576 if( ij.x<0 || ij.x>=gridresolution.x ){
+
1577 cerr << "ERROR (getCellCoverFraction): Cell index in x-direction of " << ij.x << " is outside the allowable range of 0 to " << gridresolution.x-1 << std::endl;
1578 exit(EXIT_FAILURE);
1579 }
-
1580 if( ij.y<0 || ij.y>=gridresolution.y ){
-
1581 cerr << "ERROR (getCellCoverFraction): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
+
1580 if( ij.y<0 || ij.y>=gridresolution.y ){
+
1581 cerr << "ERROR (getCellCoverFraction): Cell index in y-direction of " << ij.y << " is outside the allowable range of 0 to " << gridresolution.y-1 << std::endl;
1582 exit(EXIT_FAILURE);
1583 }
1584
@@ -1833,22 +1840,22 @@
1624
1625 //inverse rotate the point to a coordinate system centered at bottom left of grid
1626 vec2 XY = make_vec2(hit_xyz.x,hit_xyz.y);
-
1627 XY = (XY-make_vec2(gridcenter.x,gridcenter.y));
-
1628 XY = rotatePoint2D( XY, -gridrotation )+make_vec2(0.5*gridextent.x, 0.5*gridextent.y);
+
1627 XY = (XY-make_vec2(gridcenter.x,gridcenter.y));
+
1628 XY = rotatePoint2D( XY, -gridrotation )+make_vec2(0.5*gridextent.x, 0.5*gridextent.y);
1629
-
1630 int cx = floor(XY.x/(gridextent.x/float(gridresolution.x)));
-
1631 int cy = floor(XY.y/(gridextent.y/float(gridresolution.y)));
+
1630 int cx = floor(XY.x/(gridextent.x/float(gridresolution.x)));
+
1631 int cy = floor(XY.y/(gridextent.y/float(gridresolution.y)));
1632
-
1633 int cz = floor( (hit_xyz.z-gridcenter.z+0.5*gridextent.z)/(gridextent.z/float(gridresolution.z)));
+
1633 int cz = floor( (hit_xyz.z-gridcenter.z+0.5*gridextent.z)/(gridextent.z/float(gridresolution.z)));
1634
-
1635 if( cz<0 || cz>=gridresolution.z ){
+
1635 if( cz<0 || cz>=gridresolution.z ){
1636 cz = -1;
1637 }
1638
-
1639 if( cx<0 || cx>=gridresolution.x ){
+
1639 if( cx<0 || cx>=gridresolution.x ){
1640 cx = -1;
1641 cy = -1;
-
1642 }else if( cy<0 || cy>=gridresolution.y ){
+
1642 }else if( cy<0 || cy>=gridresolution.y ){
1643 cx = -1;
1644 cy = -1;
1645 }
@@ -1863,7 +1870,6 @@
1654}
-
Primary class for aerial LiDAR scan.
Definition AerialLiDAR.h:88
float getCellMaximumHitHeight(const helios::int2 ij) const
Get the height of the highest hit point at the (x,y) location of this gridcell.
float getScanDensity(const uint scanID) const
Get the scan point density in points/m^2.
void syntheticScan(helios::Context *context, const char *xml_file)
Run a discrete return synthetic LiDAR scan based on scan parameters given in an XML file.
@@ -1877,7 +1883,7 @@
void addHitsToVisualizer(Visualizer *visualizer, const uint pointsize) const
Add all hit points to the visualizer plug-in, and color them by their r-g-b color.
int selfTest(void)
Self-test (unit test) function.
helios::vec3 getHitXYZ(uint index) const
Get (x,y,z) coordinate of hit point by index.
-
int gridijk2index(const helios::int3 ijk) const
Use a grid cell's local index in the x-, y-, and z-directions to retrieve the cells' global index (ra...
+
int gridijk2index(const helios::int3 ijk) const
Use a grid cell's local index in the x-, y-, and z-directions to retrieve the cells' global index (ra...
float getCellGroundHeight(const helios::int2 ij) const
Get the height of the ground at the (x,y) location of this gridcell.
float getScanBeamDivergence(const uint scanID) const
Divergence angle of the laser beam in radians.
void setCellCoverFraction(const float cover_fraction, const helios::int2 ij)
Set the ground cover fraction at the (x,y) location of this gridcell.
@@ -1920,11 +1926,11 @@
void generateHeightModel(const int maxIter, const float threshDist_ground, const float inlierRatio_ground, const float threshDist_vegetation, const float inlierRatio_vegetation)
Determine the ground and vegetation height for each x-y grid cell. Inputs to this function are parame...
void addGridToVisualizer(Visualizer *visualizer) const
Add all grid cells to the visualizer plug-in.
Class for visualization of simulation results.
Definition Visualizer.h:275
-
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
+
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
void addPoint(const helios::vec3 &position, const helios::RGBcolor &color, uint pointsize, CoordinateSystem coordFlag)
Add a point by giving its coordinates and size.
void addVoxelByCenter(const helios::vec3 &center, const helios::vec3 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a voxel by giving the coordinates of its center.
-
Colormap getCurrentColormap() const
Get the current colormap used in Colorbar/visualization.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Colormap getCurrentColormap() const
Get the current colormap used in Colorbar/visualization.
+
Stores the state associated with simulation.
Definition Context.h:1888
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
float randu()
Random number from a uniform distribution between 0 and 1.
Definition global.cpp:223
@@ -1952,30 +1958,33 @@
R-G-B-A color vector.
R-G-B color vector.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
-
Vector of four elements of type 'float'.
+
Vector of four elements of type 'float'.
float y
Second element in vector.
float w
Fourth element in vector.
float z
Third element in vector.
float x
First element in vector.
- -
+ + diff --git a/doc/html/_aerial_li_d_a_r_8cu.html b/doc/html/_aerial_li_d_a_r_8cu.html index 7890275be..77964457d 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
AerialLiDAR.cu File Reference
@@ -116,10 +122,13 @@

Definition in file AerialLiDAR.cu.

- -
+ + 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 3311997b7..2765d32b2 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
AerialLiDAR.cu
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "AerialLiDAR.cuh"
17#include "AerialLiDAR.h"
18
@@ -750,7 +757,7 @@
651 loadXML(xml_file);
652 }
653
-
654 AerialLiDARcloud synthscan;
+
654 AerialLiDARcloud synthscan;
655
656 if( !printmessages ){
657 synthscan.disableMessages();
@@ -792,7 +799,7 @@
693 //figure out how many patches
694 size_t Npatches = 0;
695 for( int p=0; p<UUIDs_all.size(); p++ ){
-
696 if( context->getPrimitiveType(UUIDs_all.at(p)) == helios::PRIMITIVE_TYPE_PATCH ){
+
696 if( context->getPrimitiveType(UUIDs_all.at(p)) == helios::PRIMITIVE_TYPE_PATCH ){
697 Npatches++;
698 }
699 }
@@ -804,7 +811,7 @@
705 c=0;
706 for( int p=0; p<UUIDs_all.size(); p++ ){
707 uint UUID = UUIDs_all.at(p);
-
708 if( context->getPrimitiveType(UUID) == helios::PRIMITIVE_TYPE_PATCH ){
+
708 if( context->getPrimitiveType(UUID) == helios::PRIMITIVE_TYPE_PATCH ){
709 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUID);
710 patch_vertex[4*c] = vec3tofloat3(verts.at(0));
711 patch_vertex[4*c+1] = vec3tofloat3(verts.at(1));
@@ -857,7 +864,7 @@
758 //figure out how many triangles
759 size_t Ntriangles = 0;
760 for( int p=0; p<UUIDs_all.size(); p++ ){
-
761 if( context->getPrimitiveType(UUIDs_all.at(p)) == helios::PRIMITIVE_TYPE_TRIANGLE ){
+
761 if( context->getPrimitiveType(UUIDs_all.at(p)) == helios::PRIMITIVE_TYPE_TRIANGLE ){
762 Ntriangles++;
763 }
764 }
@@ -869,7 +876,7 @@
770 c=0;
771 for( int p=0; p<UUIDs_all.size(); p++ ){
772 uint UUID = UUIDs_all.at(p);
-
773 if( context->getPrimitiveType(UUID) == helios::PRIMITIVE_TYPE_TRIANGLE ){
+
774 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUID);
775 tri_vertex[3*c] = vec3tofloat3(verts.at(0));
776 tri_vertex[3*c+1] = vec3tofloat3(verts.at(1));
@@ -991,12 +998,12 @@
892 float y = center.y - 0.5*extent.y + context->randu()*extent.y;
893 float z = center.z;
894
-
895 rayorigin.at(i) = helios::make_vec3(x,y,z);
+
895 rayorigin.at(i) = helios::make_vec3(x,y,z);
896
897 float theta = -0.5f*M_PI+0.5f*coneangle*context->randu();
898 float phi = 2.f*M_PI*context->randu();
899
-
900 raydir.at(i) = helios::sphere2cart(helios::make_SphericalCoord(theta,phi));
+
900 raydir.at(i) = helios::sphere2cart(helios::make_SphericalCoord(theta,phi));
901
902 }
903
@@ -1187,8 +1194,8 @@
1088 data["timestamp"] = r;
1089 data["intensity"] = t_hit.at(hit).at(1);
1090
-
1091 helios::vec3 dir = helios::make_vec3(direction[r].x,direction[r].y,direction[r].z);
-
1092 helios::vec3 o = helios::make_vec3(origin[r].x,origin[r].y,origin[r].z);
+
1091 helios::vec3 dir = helios::make_vec3(direction[r].x,direction[r].y,direction[r].z);
+
1092 helios::vec3 o = helios::make_vec3(origin[r].x,origin[r].y,origin[r].z);
1093 helios::vec3 p = o+dir*t_hit.at(hit).at(0);
1094 addHitPoint( s, p, helios::cart2sphere(dir), helios::RGB::red, data );
1095
@@ -1567,7 +1574,7 @@
1465
1466 float3 raydir = d_sphere2cart( 1.f, 0.5*M_PI-0.5*beam_divergence*rnd(seed), 2.f*M_PI*rnd(seed) );
1467
-
1468 float zenith = acos_safe( d_raydir[idx].z/sqrt(d_raydir[idx].x*d_raydir[idx].x+d_raydir[idx].y*d_raydir[idx].y+d_raydir[idx].z*d_raydir[idx].z) );
+
1468 float zenith = acos_safe( d_raydir[idx].z/sqrt(d_raydir[idx].x*d_raydir[idx].x+d_raydir[idx].y*d_raydir[idx].y+d_raydir[idx].z*d_raydir[idx].z) );
1469 float azimuth = atan2_2pi( d_raydir[idx].x, d_raydir[idx].y );
1470 raydir = d_rotatePoint( raydir, zenith, 0.5*M_PI-azimuth );
1471
@@ -1664,7 +1671,7 @@
1562
1563 float3 raydir = d_sphere2cart( 1.f, 0.5*M_PI-0.5*beam_divergence*rnd(seed), 2.f*M_PI*rnd(seed) );
1564
-
1565 float zenith = acos_safe( d_raydir[idx].z/sqrt(d_raydir[idx].x*d_raydir[idx].x+d_raydir[idx].y*d_raydir[idx].y+d_raydir[idx].z*d_raydir[idx].z) );
+
1565 float zenith = acos_safe( d_raydir[idx].z/sqrt(d_raydir[idx].x*d_raydir[idx].x+d_raydir[idx].y*d_raydir[idx].y+d_raydir[idx].z*d_raydir[idx].z) );
1566 float azimuth = atan2_2pi( d_raydir[idx].x, d_raydir[idx].y );
1567 raydir = d_rotatePoint( raydir, zenith, 0.5*M_PI-azimuth );
1568
@@ -1745,8 +1752,9 @@
1643
1644}
+
@ PRIMITIVE_TYPE_PATCH
< Rectangular primitive
Definition Context.h:33
+
@ PRIMITIVE_TYPE_TRIANGLE
< Triangular primitive
Definition Context.h:35
__device__ float3 d_rotatePoint(const float3 &position, const float &theta, const float &phi)
-
Primary class for aerial LiDAR scan.
Definition AerialLiDAR.h:88
float getScanDensity(const uint scanID) const
Get the scan point density in points/m^2.
void syntheticScan(helios::Context *context, const char *xml_file)
Run a discrete return synthetic LiDAR scan based on scan parameters given in an XML file.
float getScanConeAngle(const uint scanID) const
Get the scan cone angle in degrees.
@@ -1771,48 +1779,53 @@
void calculateSyntheticLeafArea(helios::Context *context)
Calculate the surface area of all primitives in the context.
void calculateHitGridCell()
Determine the grid cell in which each hit point resides for the whole point cloud *‍/.
helios::SphericalCoord getHitRaydir(const uint index) const
Get ray direction of hit point in the scan based on its index.
+
AerialLiDARcloud(void)
Aerial LiDAR point cloud constructor.
helios::vec2 getScanExtent(const uint scanID) const
Get the (x,y) extent of scan surface.
helios::vec3 getGridCenter(void) const
Get the (x,y,z) coordinate of the grid center.
helios::int3 gridindex2ijk(const int index) const
Use a global index of a grid cell (ranging from 0 to Ncells-1) to retrieve the local index in the x-,...
float getScanBeamExitDiameter(const uint scanID) const
Get the diameter of the laser beam at exit from the instrument.
helios::int3 getGridResolution(void) const
Get the total number of cells in the grid.
void enableMessages(void)
Enable all print messages to the screen.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7159
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7175
-
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7179
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
-
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7167
+
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7186
+
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7202
+
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7206
+
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:7011
+
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7194
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:2046
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7187
-
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:7122
+
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7214
+
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:7149
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
float atan2_2pi(float y, float x)
Four quadrant arc tangent between 0 and 2*pi.
Definition global.cpp:584
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
-
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
int2 make_int2(int x, int y)
Make an int2 vector from two ints.
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
vec3 cross(const vec3 &a, const vec3 &b)
Cross product of two vec3 vectors.
-
Vector of two elements of type 'int'.
+
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/_aerial_li_d_a_r_8h.html b/doc/html/_aerial_li_d_a_r_8h.html index 6356b35cf..1d8defae7 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -131,10 +137,13 @@

Definition in file AerialLiDAR.h.

- -
+ + diff --git a/doc/html/_aerial_li_d_a_r_8h.js b/doc/html/_aerial_li_d_a_r_8h.js new file mode 100644 index 000000000..2133d71c1 --- /dev/null +++ b/doc/html/_aerial_li_d_a_r_8h.js @@ -0,0 +1,6 @@ +var _aerial_li_d_a_r_8h = +[ + [ "AerialScanMetadata", "struct_aerial_scan_metadata.html", "struct_aerial_scan_metadata" ], + [ "AerialHitPoint", "struct_aerial_hit_point.html", null ], + [ "AerialLiDARcloud", "class_aerial_li_d_a_rcloud.html", "class_aerial_li_d_a_rcloud" ] +]; \ No newline at end of file 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 f191c169e..c57d9e16c 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
AerialLiDAR.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
16
17#ifndef HELIOS_AERIALLIDAR
18#define HELIOS_AERIALLIDAR
19
20#include "Context.h"
21#include "Visualizer.h"
-
22
-
24
+
22
+
24
- -
27
-
29
+ +
27
+
29
34 AerialScanMetadata( const helios::vec3 __center, const helios::vec2 __extent, const float __coneangle, const float __scandensity, const float __exitDiameter, const float __beamDivergence );
-
35
+
35
37 std::size_t Nrays;
38
-
41
+
41
-
44
+
44
46 float coneangle;
-
47
+
47
-
50
-
52
+
50
+
52
-
54
-
56
+
54
+
56
60
61};
-
62
+
62
- +
64struct AerialHitPoint{
65 helios::vec3 position;
66 helios::SphericalCoord direction;
67 helios::RGBcolor color;
68 std::map<std::string, float> data;
69 helios::int3 gridcell;
70 int scanID;
-
71 AerialHitPoint(void){
-
72 position = helios::make_vec3(0,0,0);
-
73 direction = helios::make_SphericalCoord(0,0);
+
71 AerialHitPoint(void){
+
72 position = helios::make_vec3(0,0,0);
+
73 direction = helios::make_SphericalCoord(0,0);
74 color = helios::RGB::red;
-
75 gridcell = helios::make_int3(-2,-2,-2);
+
75 gridcell = helios::make_int3(-2,-2,-2);
76 scanID = -1;
77 }
-
78 AerialHitPoint( int __scanID, helios::vec3 __position, helios::SphericalCoord __direction, helios::int2 __row_column, helios::RGBcolor __color, std::map<std::string, float> __data ){
+
78 AerialHitPoint( int __scanID, helios::vec3 __position, helios::SphericalCoord __direction, helios::int2 __row_column, helios::RGBcolor __color, std::map<std::string, float> __data ){
79 scanID = __scanID;
80 position = __position;
81 direction = __direction;
@@ -161,12 +168,12 @@
84 }
85};
-
86
+
86
- +
89 private:
-
90
-
92
+
90
+
92
100 helios::vec4 RANSAC( const int maxIter, const float threshDist, const float inlierRatio, const std::vector<helios::vec3>& hits, std::vector<bool>& inliers );
101
102 std::vector<AerialScanMetadata> scans;
@@ -176,7 +183,7 @@
107 bool printmessages;
108
109 // --- grid --- //
-
110
+
110
112 bool hitgridcellcomputed;
113
114 helios::vec3 gridcenter;
@@ -206,217 +213,217 @@
138 helios::vec2 rotatePoint2D( const helios::vec2 point, const float theta ) const;
139
140 public:
-
141
+
141
143 AerialLiDARcloud( void );
-
144
+
144
146 ~AerialLiDARcloud( void );
-
147
+
147
149 int selfTest( void );
-
150
+
150
152 void disableMessages( void );
-
153
+
153
155 void enableMessages( void );
156
157 // ------- SCANS -------- //
-
158
+
158
160 uint getScanCount( void );
-
161
-
163
+
161
+
163
166 void addScan( const AerialScanMetadata newscan );
-
167
-
169
+
167
+
169
174 void addHitPoint( const uint scanID, const helios::vec3 hit_xyz, const helios::vec3 ray_origin );
175
-
177
+
177
182 void addHitPoint( const uint scanID, const helios::vec3 hit_xyz, const helios::SphericalCoord direction );
-
183
-
185
+
183
+
185
192 void addHitPoint( const uint scanID, const helios::vec3 hit_xyz, const helios::SphericalCoord direction, const helios::RGBcolor color );
-
193
-
195
+
193
+
195
201 void addHitPoint( const uint scanID, const helios::vec3 hit_xyz, const helios::SphericalCoord direction, const std::map<std::string, float> data );
202
-
204
+
204
211 void addHitPoint( const uint scanID, const helios::vec3 hit_xyz, const helios::SphericalCoord direction, const helios::RGBcolor color, const std::map<std::string, float> data );
-
212
-
214
+
212
+
214
217 void deleteHitPoint( const uint index );
-
218
+
218
220 uint getHitCount( void ) const;
221
-
223
+
223
226 helios::vec3 getScanCenter( const uint scanID ) const;
-
227
-
229
+
227
+
229
232 helios::vec2 getScanExtent( const uint scanID ) const;
-
233
-
235
+
233
+
235
238 float getScanConeAngle( const uint scanID ) const;
-
239
+
239
241 float getScanDensity( const uint scanID ) const;
-
242
-
244
+
242
+
244
248 float getScanBeamExitDiameter( const uint scanID ) const;
-
249
-
251
+
249
+
251
255 float getScanBeamDivergence( const uint scanID ) const;
-
256
-
258
+
256
+
258
261 helios::vec3 getHitXYZ( uint index ) const;
-
262
-
264
+
262
+
264
267 helios::SphericalCoord getHitRaydir( const uint index ) const;
-
268
-
270
+
268
+
270
275 float getHitData( const uint index, const char* label ) const;
-
276
-
278
+
276
+
278
282 void setHitData( const uint index, const char* label, const float value );
-
283
-
285
+
283
+
285
289 bool doesHitDataExist( const uint index, const char* label ) const;
290
-
292
+
292
293 helios::RGBcolor getHitColor( const uint index ) const;
-
294
-
296
+
294
+
296
299 int getHitScanID( const uint index ) const;
300
-
302
+
302
307 helios::int3 getHitGridCell( const uint index ) const;
-
308
-
310
+
308
+
310
314 void setHitGridCell( const uint index, const helios::int3 ijk );
315
316 void coordinateShift( const helios::vec3 shift );
317
318 // ------- FILE I/O --------- //
-
319
-
321
+
319
+
321
323 void loadXML( const char* filename );
324
326 void readContextXML( void );
-
327
-
329
+
327
+
329
332 void exportPointCloud( const char* filename );
333
334 // ------- VISUALIZER --------- //
335
-
337
+
337
341 void addHitsToVisualizer( Visualizer* visualizer, const uint pointsize ) const;
342
-
344
+
344
349 void addHitsToVisualizer( Visualizer* visualizer, const uint pointsize, const char* color_value ) const;
-
350
-
352
+
350
+
352
355 void addGridToVisualizer( Visualizer* visualizer ) const;
-
356
-
358
+
356
+
358
362 void getHitBoundingBox( helios::vec3& boxmin, helios::vec3& boxmax ) const;
-
363
-
365
+
363
+
365
368 void distanceFilter( const float maxdistance );
369
-
371
+
371
375 void reflectanceFilter( const float minreflectance );
-
376
-
378
+
376
+
378
384 void scalarFilter( const char* scalar_field, const float threshold, const char* comparator );
385
386 // -------- GRID ----------- //
-
387
-
389
+
387
+
389
392 helios::int3 gridindex2ijk( const int index ) const;
-
393
-
395
+
393
+
395
398 int gridijk2index( const helios::int3 ijk ) const;
-
399
+
399
401 helios::vec3 getGridCenter( void ) const;
-
402
+
402
404 helios::vec3 getGridExtent( void ) const;
405
407 helios::int3 getGridResolution( void ) const;
-
408
+
408
410 float getGridRotation() const;
-
411
-
413
+
411
+
413
416 helios::vec3 getCellCenter( const helios::int3 ijk ) const;
-
417
+
417
-
420
-
422
+
420
+
422
426
427 // ------- SYNTHETIC SCAN ------ //
-
428
-
430
+
428
+
430
434 void syntheticScan( helios::Context* context, const char* xml_file );
-
435
-
437
+
435
+
437
444 void syntheticScan( helios::Context* context, const char* xml_file, const int rays_per_pulse, const float pulse_distance_threshold );
-
445
-
447
+
445
+
447
451
452 // -------- LEAF AREA -------- //
-
453
-
455
+
453
+
455
460 void setCellLeafArea( const float area, const helios::int3 ijk );
-
461
-
463
+
461
+
463
466 float getCellLeafArea( const helios::int3 ijk ) const;
-
467
-
469
+
467
+
469
472 float getCellLeafAreaDensity( const helios::int3 ijk ) const;
-
473
-
475
+
473
+
475
480 void setCellTransmissionProbability( const int P_denom, const int P_trans, const helios::int3 ijk );
-
481
-
483
+
481
+
483
488 void getCellTransmissionProbability( const helios::int3 ijk, int& P_denom, int& P_trans ) const;
-
489
-
491
+
489
+
491
495 void setCellRbar( const float r_bar, const helios::int3 ijk );
-
496
-
498
+
496
+
498
501 float getCellRbar( const helios::int3 ijk ) const;
-
502
-
504
+
502
+
504
507 void calculateLeafAreaGPU( const float Gtheta );
-
508
-
510
+
508
+
510
514 void calculateLeafAreaGPU( const float Gtheta, const int minVoxelHits );
515
516 // -------- HEIGHT MODEL -------- //
517
-
519
+
519
526 void generateHeightModel( const int maxIter, const float threshDist_ground, const float inlierRatio_ground, const float threshDist_vegetation, const float inlierRatio_vegetation );
-
527
-
529
+
527
+
529
533 void setCellVegetationHeight( const float height, const helios::int2 ij );
-
534
-
536
+
534
+
536
540 float getCellVegetationHeight( const helios::int2 ij )const;
-
541
-
543
+
541
+
543
547 void setCellMaximumHitHeight( const float height, const helios::int2 ij );
-
548
-
550
+
548
+
550
554 float getCellMaximumHitHeight( const helios::int2 ij ) const;
-
555
-
557
+
555
+
557
561 void setCellGroundHeight( const float height, const helios::int2 ij );
-
562
-
564
+
562
+
564
568 float getCellGroundHeight( const helios::int2 ij ) const;
569
570 //Run calculations for ground cover fraction
571 void calculateCoverFraction( void );
-
572
-
574
+
572
+
574
578 void setCellCoverFraction( const float cover_fraction, const helios::int2 ij );
-
579
-
581
+
579
+
581
585 float getCellCoverFraction( const helios::int2 ij ) const;
586
587};
@@ -426,7 +433,6 @@
590#endif
-
Primary class for aerial LiDAR scan.
Definition AerialLiDAR.h:88
float getCellMaximumHitHeight(const helios::int2 ij) const
Get the height of the highest hit point at the (x,y) location of this gridcell.
float getScanDensity(const uint scanID) const
Get the scan point density in points/m^2.
void syntheticScan(helios::Context *context, const char *xml_file)
Run a discrete return synthetic LiDAR scan based on scan parameters given in an XML file.
@@ -441,7 +447,7 @@
void addHitsToVisualizer(Visualizer *visualizer, const uint pointsize) const
Add all hit points to the visualizer plug-in, and color them by their r-g-b color.
int selfTest(void)
Self-test (unit test) function.
helios::vec3 getHitXYZ(uint index) const
Get (x,y,z) coordinate of hit point by index.
-
int gridijk2index(const helios::int3 ijk) const
Use a grid cell's local index in the x-, y-, and z-directions to retrieve the cells' global index (ra...
+
int gridijk2index(const helios::int3 ijk) const
Use a grid cell's local index in the x-, y-, and z-directions to retrieve the cells' global index (ra...
float getCellGroundHeight(const helios::int2 ij) const
Get the height of the ground at the (x,y) location of this gridcell.
float getScanBeamDivergence(const uint scanID) const
Divergence angle of the laser beam in radians.
void setCellCoverFraction(const float cover_fraction, const helios::int2 ij)
Set the ground cover fraction at the (x,y) location of this gridcell.
@@ -490,8 +496,10 @@
void generateHeightModel(const int maxIter, const float threshDist_ground, const float inlierRatio_ground, const float threshDist_vegetation, const float inlierRatio_vegetation)
Determine the ground and vegetation height for each x-y grid cell. Inputs to this function are parame...
void addGridToVisualizer(Visualizer *visualizer) const
Add all grid cells to the visualizer plug-in.
Class for visualization of simulation results.
Definition Visualizer.h:275
-
Stores the state associated with simulation.
Definition Context.h:1882
-
Structure containing metadata for an aerial hit point.
Definition AerialLiDAR.h:64
+
Stores the state associated with simulation.
Definition Context.h:1888
+
int3 make_int3(int X, int Y, int Z)
Make an int3 vector from three ints.
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
+
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
Structure containing metadata for an aerial scan.
Definition AerialLiDAR.h:26
std::size_t Nrays
Number of laser pulses in scan.
Definition AerialLiDAR.h:37
helios::vec2 extent
(x,y) size/extent of scan surface
Definition AerialLiDAR.h:43
@@ -503,16 +511,19 @@
float scandensity
Scan density in points/m^2.
Definition AerialLiDAR.h:49
R-G-B color vector.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of two elements of type 'int'.
-
Vector of three elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
-
Vector of four elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
+
Vector of four elements of type 'float'.
- -
+ + diff --git a/doc/html/_aerial_li_d_a_r_doc.html b/doc/html/_aerial_li_d_a_r_doc.html index 57218f947..32348c6b7 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Aerial LiDAR Point Cloud Plugin Documentation
@@ -327,10 +333,13 @@

- -
+ + diff --git a/doc/html/_assets_8cpp.html b/doc/html/_assets_8cpp.html index af59c576b..51cb0af2d 100644 --- a/doc/html/_assets_8cpp.html +++ b/doc/html/_assets_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -2043,10 +2049,13 @@

+ + diff --git a/doc/html/_assets_8cpp_source.html b/doc/html/_assets_8cpp_source.html index 8aac2d56b..453965853 100644 --- a/doc/html/_assets_8cpp_source.html +++ b/doc/html/_assets_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Assets.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "PlantArchitecture.h"
17
18using namespace helios;
@@ -116,7 +123,7 @@
24 if ( !std::filesystem::exists( prototype_parameters->OBJ_model_file ) ) {
25 helios_runtime_error("ERROR (PlantArchitecture): Leaf prototype OBJ file " + prototype_parameters->OBJ_model_file + " does not exist.");
26 }
-
27 return context_ptr->addPolymeshObject( context_ptr->loadOBJ( prototype_parameters->OBJ_model_file.c_str(), prototype_parameters->leaf_offset, 0,nullrotation, RGB::black, "ZUP", true ) );
+
27 return context_ptr->addPolymeshObject( context_ptr->loadOBJ( prototype_parameters->OBJ_model_file.c_str(), prototype_parameters->leaf_offset, 0,nullrotation, RGB::black, "ZUP", true ) );
28 }
29
30 std::string leaf_texture;
@@ -180,7 +187,7 @@
88
89 if( prototype_parameters->longitudinal_curvature.val() != 0.0f && i>0 ){
90 dtheta -= atan(4.f*prototype_parameters->longitudinal_curvature.val()*powf(x,3)*dx);
-
91 vertices.at(j).at(i) = rotatePointAboutLine( vertices.at(j).at(i), nullorigin, make_vec3(0,1,0), dtheta );
+
91 vertices.at(j).at(i) = rotatePointAboutLine( vertices.at(j).at(i), nullorigin, make_vec3(0,1,0), dtheta );
92 }
93
94 if( prototype_parameters->leaf_buckle_angle.val()>0 ) {
@@ -220,7 +227,7 @@
128 context_ptr->translatePrimitive( UUIDs, prototype_parameters->leaf_offset );
129
130 if( prototype_parameters->build_petiolule ){
-
131 std::vector<uint> UUIDs_petiolule = context_ptr->loadOBJ("plugins/plantarchitecture/assets/obj/PetiolulePrototype.obj", make_vec3(0,0,0), 0, nullrotation, RGB::black, "ZUP", true);
+
131 std::vector<uint> UUIDs_petiolule = context_ptr->loadOBJ("plugins/plantarchitecture/assets/obj/PetiolulePrototype.obj", make_vec3(0,0,0), 0, nullrotation, RGB::black, "ZUP", true);
132 context_ptr->translatePrimitive(UUIDs, make_vec3(0.07,0,0.005) );
133 UUIDs.insert(UUIDs.end(), UUIDs_petiolule.begin(), UUIDs_petiolule.end());
134 }
@@ -240,13 +247,13 @@
148}
149
150uint AlmondFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
151 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondHull.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
151 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondHull.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
152 uint objID = context_ptr->addPolymeshObject( UUIDs );
153 return objID;
154}
155
156uint AlmondFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
157 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
157 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
158 uint objID = context_ptr->addPolymeshObject( UUIDs );
159 return objID;
160}
@@ -274,13 +281,13 @@
182}
183
184uint AppleFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
185 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AppleFruit.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
185 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AppleFruit.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
186 uint objID = context_ptr->addPolymeshObject( UUIDs );
187 return objID;
188}
189
190uint AppleFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
191 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
191 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
192 uint objID = context_ptr->addPolymeshObject( UUIDs );
193 return objID;
194}
@@ -409,7 +416,7 @@
317}
318
319uint CowpeaLeafPrototype_unifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index ){
-
320 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_unifoliate.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
320 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_unifoliate.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
321
322 uint objID = context_ptr->addPolymeshObject( UUIDs );
323 return objID;
@@ -418,18 +425,18 @@
326uint CowpeaLeafPrototype_trifoliate_OBJ(helios::Context* context_ptr, uint subdivisions, int compound_leaf_index ){
327 std::vector<uint> UUIDs;
328 if( compound_leaf_index<0 ){
-
329 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_left_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
329 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_left_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
330 }else if( compound_leaf_index==0 ){
-
331 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_tip_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
331 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_tip_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
332 }else{
-
333 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_right_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
+
333 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaLeaf_right_highres.obj", make_vec3(0.,0,0), 0, nullrotation, RGB::black, "ZUP", true );
334 }
335 uint objID = context_ptr->addPolymeshObject( UUIDs );
336 return objID;
337}
338
339uint CowpeaFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
340 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaPod.obj", make_vec3(0.,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
+
340 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaPod.obj", make_vec3(0.,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
341 uint objID = context_ptr->addPolymeshObject( UUIDs );
342 return objID;
343}
@@ -437,9 +444,9 @@
345uint CowpeaFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
346 std::vector<uint> UUIDs;
347 if( flower_is_open ){
-
348 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaFlower_open_yellow.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
348 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaFlower_open_yellow.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
349 }else{
-
350 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaFlower_closed_yellow.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
350 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/CowpeaFlower_closed_yellow.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
351 }
352 uint objID = context_ptr->addPolymeshObject( UUIDs );
353 return objID;
@@ -591,14 +598,14 @@
499
500uint MaizeTasselPrototype( helios::Context* context_ptr, uint subdivisions ){
501
-
502 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/MaizeTassel.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
502 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/MaizeTassel.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
503 return context_ptr->addPolymeshObject( UUIDs );
504
505}
506
507uint MaizeEarPrototype( helios::Context* context_ptr, uint subdivisions ){
508
-
509 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/MaizeEar.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
509 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/MaizeEar.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
510 return context_ptr->addPolymeshObject( UUIDs );
511
512}
@@ -636,8 +643,8 @@
544
545uint OliveLeafPrototype( helios::Context* context_ptr, LeafPrototype *prototype_parameters, int compound_leaf_index ){
546
-
547 std::vector<uint> UUIDs_upper = context_ptr->addTile(make_vec3(0.5,0,0), make_vec2(1,0.2), nullrotation, make_int2(prototype_parameters->subdivisions,prototype_parameters->subdivisions), "plugins/plantarchitecture/assets/textures/OliveLeaf_upper.png");
-
548 std::vector<uint> UUIDs_lower = context_ptr->addTile(make_vec3(0.5,0,-1e-4), make_vec2(1,0.2), nullrotation, make_int2(prototype_parameters->subdivisions,prototype_parameters->subdivisions), "plugins/plantarchitecture/assets/textures/OliveLeaf_lower.png");
+
547 std::vector<uint> UUIDs_upper = context_ptr->addTile(make_vec3(0.5,0,0), make_vec2(1,0.2), nullrotation, make_int2(prototype_parameters->subdivisions,prototype_parameters->subdivisions), "plugins/plantarchitecture/assets/textures/OliveLeaf_upper.png");
+
548 std::vector<uint> UUIDs_lower = context_ptr->addTile(make_vec3(0.5,0,-1e-4), make_vec2(1,0.2), nullrotation, make_int2(prototype_parameters->subdivisions,prototype_parameters->subdivisions), "plugins/plantarchitecture/assets/textures/OliveLeaf_lower.png");
549 context_ptr->rotatePrimitive( UUIDs_lower, M_PI, "x" );
550
551 UUIDs_upper.insert(UUIDs_upper.end(), UUIDs_lower.begin(), UUIDs_lower.end());
@@ -646,7 +653,7 @@
554}
555
556uint OliveFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
557 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/OliveFruit.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
557 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/OliveFruit.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
558 uint objID = context_ptr->addPolymeshObject( UUIDs );
559 std::vector<uint> UUIDs_fruit = context_ptr->filterPrimitivesByData( context_ptr->getObjectPrimitiveUUIDs(objID), "object_label", "fruit");
560 context_ptr->setPrimitiveColor( UUIDs_fruit, make_RGBcolor(0.65,0.7,0.4)); //green
@@ -654,7 +661,7 @@
562}
563
564uint OliveFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
565 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/OliveFlower_open.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
565 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/OliveFlower_open.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
566 uint objID = context_ptr->addPolymeshObject( UUIDs );
567 return objID;
568}
@@ -674,13 +681,13 @@
582}
583
584uint PistachioFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
585 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/PistachioNut.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
585 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/PistachioNut.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
586 uint objID = context_ptr->addPolymeshObject( UUIDs );
587 return objID;
588}
589
590uint PistachioFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
591 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/OliveFlower_open.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
591 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/OliveFlower_open.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
592 uint objID = context_ptr->addPolymeshObject( UUIDs );
593 return objID;
594}
@@ -706,18 +713,18 @@
614}
615
616uint PuncturevineFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
617 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/PuncturevineFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
617 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/PuncturevineFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
618 uint objID = context_ptr->addPolymeshObject( UUIDs );
619 return objID;
620}
621
622uint RedbudFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
623 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RedbudFlower_open.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
623 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RedbudFlower_open.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
624 return context_ptr->addPolymeshObject( UUIDs );
625}
626
627uint RedbudFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
628 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RedbudPod.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
628 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RedbudPod.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
629 return context_ptr->addPolymeshObject( UUIDs );
630}
631
@@ -741,7 +748,7 @@
649}
650
651uint RiceSpikePrototype( helios::Context* context_ptr, uint subdivisions ){
-
652 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RiceGrain.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
652 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/RiceGrain.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
653 uint objID = context_ptr->addPolymeshObject( UUIDs );
654 return objID;
655}
@@ -875,7 +882,7 @@
783}
784
785uint SoybeanFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
786 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/SoybeanPod.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
786 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/SoybeanPod.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
787 uint objID = context_ptr->addPolymeshObject( UUIDs );
788 return objID;
789}
@@ -883,9 +890,9 @@
791uint SoybeanFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
792 std::vector<uint> UUIDs;
793 if( flower_is_open ){
-
794 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/SoybeanFlower_open_white.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
794 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/SoybeanFlower_open_white.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
795 }else{
-
796 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanFlower_closed_white.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
796 UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/BeanFlower_closed_white.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
797 }
798 uint objID = context_ptr->addPolymeshObject( UUIDs );
799 return objID;
@@ -910,25 +917,25 @@
818}
819
820uint StrawberryFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
821 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/StrawberryFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
821 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/StrawberryFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
822 uint objID = context_ptr->addPolymeshObject( UUIDs );
823 return objID;
824}
825
826uint StrawberryFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
827 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/StrawberryFruit.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
827 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/StrawberryFruit.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
828 uint objID = context_ptr->addPolymeshObject( UUIDs );
829 return objID;
830}
831
832uint TomatoFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
833 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/TomatoFruit.obj", make_vec3(0.,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
+
833 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/TomatoFruit.obj", make_vec3(0.,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
834 uint objID = context_ptr->addPolymeshObject( UUIDs );
835 return objID;
836}
837
838uint TomatoFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
839 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/TomatoFlower.obj", make_vec3(0.0,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
+
839 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/TomatoFlower.obj", make_vec3(0.0,0,0), 0.75,nullrotation, RGB::black, "ZUP", true );
840 uint objID = context_ptr->addPolymeshObject( UUIDs );
841 return objID;
842}
@@ -950,13 +957,13 @@
858}
859
860uint WalnutFruitPrototype( helios::Context* context_ptr, uint subdivisions ){
-
861 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/WalnutHull.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
861 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/WalnutHull.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
862 uint objID = context_ptr->addPolymeshObject( UUIDs );
863 return objID;
864}
865
866uint WalnutFlowerPrototype( helios::Context* context_ptr, uint subdivisions, bool flower_is_open ){
-
867 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
867 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/AlmondFlower.obj", make_vec3(0.0,0,0), 0,nullrotation, RGB::black, "ZUP", true );
868 uint objID = context_ptr->addPolymeshObject( UUIDs );
869 return objID;
870}
@@ -976,7 +983,7 @@
884}
885
886uint WheatSpikePrototype( helios::Context* context_ptr, uint subdivisions ){
-
887 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/WheatSpike.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
+
887 std::vector<uint> UUIDs = context_ptr->loadOBJ( "plugins/plantarchitecture/assets/obj/WheatSpike.obj", make_vec3(0.,0,0), 0,nullrotation, RGB::black, "ZUP", true );
888 uint objID = context_ptr->addPolymeshObject( UUIDs );
889 return objID;
890}
@@ -992,8 +999,8 @@
900
901}
-
Stores the state associated with simulation.
Definition Context.h:1882
-
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7139
+
Stores the state associated with simulation.
Definition Context.h:1888
+
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7166
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
void rotateObject(uint ObjID, float rotation_radians, const char *rotation_axis_xyz)
Rotate a single compound object about the x, y, or z axis.
Definition Context.cpp:2847
@@ -1007,11 +1014,13 @@
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:1512
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
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
-
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:4728
-
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition Context.cpp:5399
-
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5646
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
+
vec3 nullorigin
Default null vec3 that gives the origin (0,0,0)
Definition global.cpp:58
+
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
+
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:4755
+
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition Context.cpp:5426
+
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5673
+
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5957
+
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5836
float randu()
Random number from a uniform distribution between 0 and 1.
Definition global.cpp:223
float min(const std::vector< float > &vect)
Minimum value of a vector of floats.
Definition global.cpp:1100
float deg2rad(float deg)
Convert degrees to radians.
Definition global.cpp:576
@@ -1037,16 +1046,19 @@
std::string OBJ_model_file
OBJ model file to load for the leaf.
RandomParameter_float longitudinal_curvature
Leaf curvature factor along the longitudinal/length (x-direction). (+curves upward,...
R-G-B color vector.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/_assets_8h_source.html b/doc/html/_assets_8h_source.html index 94cc86ff6..8c0e855aa 100644 --- a/doc/html/_assets_8h_source.html +++ b/doc/html/_assets_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Assets.h
@@ -194,13 +200,16 @@
88
89
90#endif //HELIOS_ASSETS_H
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
- -
+ + diff --git a/doc/html/_b_l_conductance_doc.html b/doc/html/_b_l_conductance_doc.html index 7c0b34d6f..d39cac715 100644 --- a/doc/html/_b_l_conductance_doc.html +++ b/doc/html/_b_l_conductance_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Boundary-Layer Conductance Model Plugin Documentation
@@ -297,10 +303,13 @@

- -
+ + diff --git a/doc/html/_boundary_layer_conductance_model_8cpp.html b/doc/html/_boundary_layer_conductance_model_8cpp.html index c20f9c89e..c3f197939 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
BoundaryLayerConductanceModel.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file BoundaryLayerConductanceModel.cpp.

- -
+ + diff --git a/doc/html/_boundary_layer_conductance_model_8cpp_source.html b/doc/html/_boundary_layer_conductance_model_8cpp_source.html index fa1976891..0020a3764 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
BoundaryLayerConductanceModel.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
17
18using namespace helios;
@@ -150,7 +157,7 @@
55 context_1.setPrimitiveData( UUID_1, "temperature", TL );
56 context_1.setPrimitiveData( UUID_1, "wind_speed", U );
57
-
58 BLConductanceModel blc_1(&context_1);
+
58 BLConductanceModel blc_1(&context_1);
59 blc_1.disableMessages();
60
61 blc_1.setBoundaryLayerModel( UUID_1.at(0), "Polhausen" );
@@ -193,7 +200,7 @@
93
94void BLConductanceModel::setBoundaryLayerModel( const char* gH_model ){
-
95 std::vector<uint> UUIDs = context->getAllUUIDs();
+
95 std::vector<uint> UUIDs = context->getAllUUIDs();
96 setBoundaryLayerModel(UUIDs,gH_model);
97}
@@ -233,7 +240,7 @@
128
-
129 run( context->getAllUUIDs() );
+
129 run( context->getAllUUIDs() );
130
131}
@@ -244,55 +251,55 @@
135 for( uint UUID : UUIDs ){
136
137 float U;
-
138 if( context->doesPrimitiveDataExist( UUID, "wind_speed" ) ){
-
139 context->getPrimitiveData( UUID, "wind_speed", U );
+
138 if( context->doesPrimitiveDataExist( UUID, "wind_speed" ) ){
+
139 context->getPrimitiveData( UUID, "wind_speed", U );
140 }else{
141 U = wind_speed_default;
142 }
143
144 float Ta;
-
145 if( context->doesPrimitiveDataExist( UUID, "air_temperature" ) ){
-
146 context->getPrimitiveData( UUID, "air_temperature", Ta );
+
145 if( context->doesPrimitiveDataExist( UUID, "air_temperature" ) ){
+
146 context->getPrimitiveData( UUID, "air_temperature", Ta );
147 }else{
148 Ta = air_temperature_default;
149 }
150
151 float T;
-
152 if( context->doesPrimitiveDataExist( UUID, "temperature" ) ){
-
153 context->getPrimitiveData( UUID, "temperature", T );
+
152 if( context->doesPrimitiveDataExist( UUID, "temperature" ) ){
+
153 context->getPrimitiveData( UUID, "temperature", T );
154 }else{
155 T = surface_temperature_default;
156 }
157
158 float L;
-
159 if( context->doesPrimitiveDataExist( UUID, "object_length") ) {
-
160 context->getPrimitiveData(UUID, "object_length", L);
+
159 if( context->doesPrimitiveDataExist( UUID, "object_length") ) {
+
160 context->getPrimitiveData(UUID, "object_length", L);
161 if (L == 0) {
-
162 L = sqrt(context->getPrimitiveArea(UUID));
+
162 L = sqrt(context->getPrimitiveArea(UUID));
163 }
-
164 }else if( context->getPrimitiveParentObjectID(UUID)>0 ){
-
165 uint objID = context->getPrimitiveParentObjectID(UUID);
-
166 L = sqrt(context->getObjectArea(objID));
+
164 }else if( context->getPrimitiveParentObjectID(UUID)>0 ){
+
165 uint objID = context->getPrimitiveParentObjectID(UUID);
+
166 L = sqrt(context->getObjectArea(objID));
167 }else{
-
168 L = sqrt(context->getPrimitiveArea(UUID));
+
168 L = sqrt(context->getPrimitiveArea(UUID));
169 }
170
171 //Number of primitive faces
172 char Nsides = 2; //default is 2
-
173 if( context->doesPrimitiveDataExist(UUID,"twosided_flag") && context->getPrimitiveDataType(UUID,"twosided_flag")==HELIOS_TYPE_UINT ){
+
173 if( context->doesPrimitiveDataExist(UUID,"twosided_flag") && context->getPrimitiveDataType(UUID,"twosided_flag")==HELIOS_TYPE_UINT ){
174 uint flag;
-
175 context->getPrimitiveData(UUID,"twosided_flag",flag);
+
175 context->getPrimitiveData(UUID,"twosided_flag",flag);
176 if( flag==0 ){
177 Nsides=1;
178 }
179 }
180
-
181 vec3 norm = context->getPrimitiveNormal(UUID);
+
181 vec3 norm = context->getPrimitiveNormal(UUID);
182 float inclination = cart2sphere( norm ).zenith;
183
184 float gH = calculateBoundaryLayerConductance( boundarylayer_model[UUID], U, L, Nsides, inclination, T, Ta );
185
-
186 context->setPrimitiveData( UUID, "boundarylayer_conductance", gH );
+
186 context->setPrimitiveData( UUID, "boundarylayer_conductance", gH );
187
188 }
189
@@ -381,22 +388,14 @@
271}
@ HELIOS_TYPE_UINT
unsigned integer data type
Definition Context.h:45
-
Boundary-layer conductance model class.
void disableMessages()
Disable standard output from this plug-in.
void setBoundaryLayerModel(const char *gH_model)
Set the boundary-layer conductance model to be used for all primitives in the Context.
void run()
Run boundary-layer conductance calculations for all primitives in the Context.
BLConductanceModel(helios::Context *context)
Constructor.
void enableMessages()
Enable standard output from this plug-in (default)
-
Stores the state associated with simulation.
Definition Context.h:1882
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
Stores the state associated with simulation.
Definition Context.h:1888
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
-
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7017
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
-
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition Context.cpp:7920
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7104
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212
@@ -404,12 +403,15 @@
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
const float & zenith
Zenithal angle (radians)
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_boundary_layer_conductance_model_8h.html b/doc/html/_boundary_layer_conductance_model_8h.html index 6551ce1b3..945c90120 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -124,10 +130,13 @@

Definition in file BoundaryLayerConductanceModel.h.

- - + + diff --git a/doc/html/_boundary_layer_conductance_model_8h.js b/doc/html/_boundary_layer_conductance_model_8h.js new file mode 100644 index 000000000..966eea9e9 --- /dev/null +++ b/doc/html/_boundary_layer_conductance_model_8h.js @@ -0,0 +1,4 @@ +var _boundary_layer_conductance_model_8h = +[ + [ "BLConductanceModel", "class_b_l_conductance_model.html", "class_b_l_conductance_model" ] +]; \ No newline at end of file diff --git a/doc/html/_boundary_layer_conductance_model_8h_source.html b/doc/html/_boundary_layer_conductance_model_8h_source.html index 95c3f3965..ac8c327bb 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
BoundaryLayerConductanceModel.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef BOUNDARYLAYERCONDUCTANCEMODEL
17#define BOUNDARYLAYERCONDUCTANCEMODEL
18
19#include "Context.h"
-
20
-
22
+
20
+
22
- +
24public:
-
25
-
27
+
25
+
27
-
31
-
33
+
31
+
33
36 int selfTest();
-
37
+
37
39 void enableMessages();
-
40
+
40
42 void disableMessages();
-
43
-
45
+
43
+
45
48 void setBoundaryLayerModel( const char* gH_model );
-
49
-
51
+
49
+
51
55 void setBoundaryLayerModel( uint UUID, const char* gH_model );
-
56
-
58
+
56
+
58
62 void setBoundaryLayerModel(const std::vector<uint> &UUIDs, const char* gH_model );
-
63
+
63
65 void run();
-
66
+
66
68 void run(const std::vector<uint> &UUIDs );
69
70private:
-
71
+
71
73 helios::Context* context;
-
74
+
74
76 float wind_speed_default;
-
77
+
77
79 float air_temperature_default;
-
80
+
80
82 float surface_temperature_default;
83
84 bool message_flag;
@@ -159,19 +166,21 @@
91
92#endif
-
Boundary-layer conductance model class.
void disableMessages()
Disable standard output from this plug-in.
void setBoundaryLayerModel(const char *gH_model)
Set the boundary-layer conductance model to be used for all primitives in the Context.
void run()
Run boundary-layer conductance calculations for all primitives in the Context.
BLConductanceModel(helios::Context *context)
Constructor.
void enableMessages()
Enable standard output from this plug-in (default)
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
- -
+ + diff --git a/doc/html/_c_lion_i_d_e.html b/doc/html/_c_lion_i_d_e.html index 3f31fd3e4..1f0276321 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Using the CLion IDE with Helios
@@ -124,10 +134,12 @@

In order to enable this feature, go to the Preferences, then navigate to "Editor->General->Appearance" and tick the box for "Render documentation comments".

- - + + diff --git a/doc/html/_camera_calibration_8cpp.html b/doc/html/_camera_calibration_8cpp.html index cd080e137..56cb63a9c 100644 --- a/doc/html/_camera_calibration_8cpp.html +++ b/doc/html/_camera_calibration_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
@@ -157,10 +163,13 @@

+ + diff --git a/doc/html/_camera_calibration_8cpp_source.html b/doc/html/_camera_calibration_8cpp_source.html index fb1cd01d5..59a074065 100644 --- a/doc/html/_camera_calibration_8cpp_source.html +++ b/doc/html/_camera_calibration_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
CameraCalibration.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "CameraCalibration.h"
17
18using namespace helios;
@@ -138,19 +145,19 @@
45 float xp = 0-patchsize*(float(boardsidesize.x)-1)/2+patchsize*float(inpr);
46 float yp = 0-patchsize*(float(boardsidesize.y)-1)/2+patchsize*float(inpc);
47
-
48 uint UUID = context->addPatch(make_vec3(xp,yp,0),patchfullsize,nullrotation,binarycolor);
+
48 uint UUID = context->addPatch(make_vec3(xp,yp,0),patchfullsize,nullrotation,binarycolor);
49
50 if (bw==1){
51 UUIDs_white.push_back(UUID);
-
52 context->setPrimitiveData( UUID, "reflectivity_spectrum", "white");
+
52 context->setPrimitiveData( UUID, "reflectivity_spectrum", "white");
53 }
54 else{
55 UUIDs_black.push_back(UUID);
-
56 context->setPrimitiveData( UUID, "reflectivity_spectrum", "");
+
56 context->setPrimitiveData( UUID, "reflectivity_spectrum", "");
57 }
58
-
59 context->setPrimitiveData(UUID, "transmissivity_spectrum", "");
-
60 context->setPrimitiveData(UUID, "twosided_flag", uint(0));
+
59 context->setPrimitiveData(UUID, "transmissivity_spectrum", "");
+
60 context->setPrimitiveData(UUID, "twosided_flag", uint(0));
61 UUIDs.push_back(UUID);
62 }
63 }
@@ -159,11 +166,11 @@
66 whitespectra.at(i).x=301+i;
67 whitespectra.at(i).y=1;
68 }
-
69 context->setGlobalData("white",HELIOS_TYPE_VEC2,whitespectra.size(),&whitespectra[0]);
-
70 context->rotatePrimitive(UUIDs,rotationrad.x, make_vec3(1,0,0));
-
71 context->rotatePrimitive(UUIDs,rotationrad.y, make_vec3(0,1,0));
-
72 context->rotatePrimitive(UUIDs,rotationrad.z, make_vec3(0,0,1));
-
73 context->translatePrimitive(UUIDs,centrelocation);
+
69 context->setGlobalData("white",HELIOS_TYPE_VEC2,whitespectra.size(),&whitespectra[0]);
+
70 context->rotatePrimitive(UUIDs,rotationrad.x, make_vec3(1,0,0));
+
71 context->rotatePrimitive(UUIDs,rotationrad.y, make_vec3(0,1,0));
+
72 context->rotatePrimitive(UUIDs,rotationrad.z, make_vec3(0,0,1));
+
73 context->translatePrimitive(UUIDs,centrelocation);
74 return UUIDs;
75}
@@ -206,28 +213,28 @@
109 if( irow>=colorassignment.size() || icolumn>=colorassignment.at(irow).size() ){
110 helios_runtime_error("ERROR (CameraCalibration::addColorboard): Dimensions of color assignment array are not consistent. This should be a square matrix.");
111 }
-
112 UUID = context->addPatch(make_vec3(xp, yp, centrelocation.z), make_vec2(patchsize, patchsize), nullrotation, colorassignment.at(irow).at(icolumn));
+
112 UUID = context->addPatch(make_vec3(xp, yp, centrelocation.z), make_vec2(patchsize, patchsize), nullrotation, colorassignment.at(irow).at(icolumn));
113 }else{
-
114 UUID = context->addPatch(make_vec3(xp, yp, centrelocation.z), make_vec2(patchsize, patchsize), nullrotation);
+
114 UUID = context->addPatch(make_vec3(xp, yp, centrelocation.z), make_vec2(patchsize, patchsize), nullrotation);
115 }
-
116 context->setPrimitiveData(UUID, "twosided_flag", uint(0));
+
116 context->setPrimitiveData(UUID, "twosided_flag", uint(0));
117 UUIDs.push_back(UUID);
118
119 if( !spectrumassignment.empty() ){
120 if( irow>=spectrumassignment.size() || icolumn>=spectrumassignment.at(irow).size() ){
121 helios_runtime_error("ERROR (CameraCalibration::addColorboard): Dimensions of spectrum assignment array are not consistent. This should be a square matrix.");
-
122 }else if( !context->doesGlobalDataExist(spectrumassignment.at(irow).at(icolumn).c_str()) ){
+
122 }else if( !context->doesGlobalDataExist(spectrumassignment.at(irow).at(icolumn).c_str()) ){
123 helios_runtime_error("ERROR (CameraCalibration::addColorboard): Spectrum assignment label of """ + spectrumassignment.at(irow).at(icolumn) + """ does not exist in global data.");
124 }
-
125 context->setPrimitiveData( UUID, "reflectivity_spectrum", spectrumassignment.at(irow).at(icolumn));
+
125 context->setPrimitiveData( UUID, "reflectivity_spectrum", spectrumassignment.at(irow).at(icolumn));
126 }
127
128 }
129 }
130
-
131 context->rotatePrimitive(UUIDs,rotationrad.x, "x"); //rotate color board
-
132 context->rotatePrimitive(UUIDs,rotationrad.y, "y");
-
133 context->rotatePrimitive(UUIDs,rotationrad.z, "z");
+
131 context->rotatePrimitive(UUIDs,rotationrad.x, "x"); //rotate color board
+
132 context->rotatePrimitive(UUIDs,rotationrad.y, "y");
+
133 context->rotatePrimitive(UUIDs,rotationrad.z, "z");
134 UUIDs_colorboard = UUIDs;
135 return UUIDs;
136
@@ -251,11 +258,11 @@
152std::vector<uint> CameraCalibration::addDefaultColorboard(const helios::vec3 &centrelocation, float patchsize, const helios::vec3 &rotationrad) {
153
154 if (!UUIDs_colorboard.empty()){
-
155 context->deletePrimitive(UUIDs_colorboard);
+
155 context->deletePrimitive(UUIDs_colorboard);
156 std::cout << "WARNING (CameraCalibration::addDefaultColorboard): Existing colorboard has been cleared in order to add default colorboard."<< std::endl;
157 }
158
-
159 context->loadXML( "plugins/radiation/spectral_data/color_board/DGK_DKK_colorboard.xml", true);
+
159 context->loadXML( "plugins/radiation/spectral_data/color_board/DGK_DKK_colorboard.xml", true);
160
161 std::vector<uint> UUIDs = CameraCalibration::addColorboard(centrelocation, patchsize, rotationrad, colorassignment_default, spectrumassignment_default);
162
@@ -410,7 +417,7 @@
303 std::vector<std::vector<helios::vec2>> cameraresponsespectra;
304 for (std::string cameraresponselabel:camerareponselabels){
305 std::vector<vec2> cameraresponsespectrum;
-
306 context->getGlobalData(cameraresponselabel.c_str(),cameraresponsespectrum);
+
306 context->getGlobalData(cameraresponselabel.c_str(),cameraresponsespectrum);
307 cameraresponsespectra.push_back(cameraresponsespectrum);
308 }
309
@@ -459,7 +466,7 @@
352 }
353 calibratedcameraspectra[camerareponselabels.at(iband)].back().y = expandedcameraspectra.at(iband).back() * camerarescales.at(iband);
354 std::string calibratedlabel = label+ "_" + camerareponselabels.at(iband);
-
355 context->setGlobalData(calibratedlabel.c_str(),HELIOS_TYPE_VEC2,calibratedcameraspectra.at(camerareponselabels.at(iband)).size(),
+
355 context->setGlobalData(calibratedlabel.c_str(),HELIOS_TYPE_VEC2,calibratedcameraspectra.at(camerareponselabels.at(iband)).size(),
356 &calibratedcameraspectra.at(camerareponselabels.at(iband))[0]);
357 }
358
@@ -481,7 +488,7 @@
372 for (int ispec = 0; ispec < cameraresponsespectrum.size(); ispec ++){
373 cameraresponsespectrum.at(ispec).y= cameraresponsespectrum.at(ispec).y * scale;
374 }
-
375 context->setGlobalData(calibratedlabel.c_str(),HELIOS_TYPE_VEC2,cameraresponsespectrum.size(),&cameraresponsespectrum[0]);
+
375 context->setGlobalData(calibratedlabel.c_str(),HELIOS_TYPE_VEC2,cameraresponsespectrum.size(),&cameraresponsespectrum[0]);
376 CameraCalibration::writeSpectralXMLfile(calibratedlabel + ".xml", "", calibratedlabel, &cameraresponsespectrum);
377 }
378}
@@ -508,7 +515,7 @@
397 std::string global_data_label = "camera_" + cameralabel + "_" + bandlabels.at(ib);
398 std::vector<float> cameradata;
399
-
400 context->getGlobalData(global_data_label.c_str(), cameradata);
+
400 context->getGlobalData(global_data_label.c_str(), cameradata);
401
402 std::vector<float> distorted_cameradata(camerareoslutionR.x * camerareoslutionR.y, 0);
403
@@ -537,7 +544,7 @@
426 }
427 }
428 }
-
429 context->setGlobalData(global_data_label.c_str(), HELIOS_TYPE_FLOAT, distorted_cameradata.size(), &distorted_cameradata[0]);
+
429 context->setGlobalData(global_data_label.c_str(), HELIOS_TYPE_FLOAT, distorted_cameradata.size(), &distorted_cameradata[0]);
430 }
431
432}
@@ -594,9 +601,9 @@
481 // Extract and check source spectra from global data
482 std::map<std::string, std::vector<vec2>> Source_spectra;
483 for (const std::string& sourcelable:sourcelabels){
-
484 if (context->doesGlobalDataExist(sourcelable.c_str())){
+
484 if (context->doesGlobalDataExist(sourcelable.c_str())){
485 std::vector<vec2> Source_spectrum;
-
486 context->getGlobalData(sourcelable.c_str(), Source_spectrum);
+
486 context->getGlobalData(sourcelable.c_str(), Source_spectrum);
487 Source_spectra.emplace(sourcelable, Source_spectrum);
488 wavelengthboundary(wavelengthrange.x, wavelengthrange.y, Source_spectrum);
489 }
@@ -607,9 +614,9 @@
494 // Extract and check camera spectra from global data
495 std::map<std::string, std::vector<vec2>> Camera_spectra;
496 for (const std::string& cameralabel:cameralabels){
-
497 if (context->doesGlobalDataExist(cameralabel.c_str())) {
+
497 if (context->doesGlobalDataExist(cameralabel.c_str())) {
498 std::vector<vec2> Camera_spectrum;
-
499 context->getGlobalData(cameralabel.c_str(), Camera_spectrum);
+
499 context->getGlobalData(cameralabel.c_str(), Camera_spectrum);
500 Camera_spectra.emplace(cameralabel, Camera_spectrum);
501 wavelengthboundary(wavelengthrange.x, wavelengthrange.y, Camera_spectrum);
502 }
@@ -621,9 +628,9 @@
508 std::map<std::string, std::vector<vec2>> Object_spectra;
509 if (!objectlabels.empty()){
510 for (const std::string& objectlable:objectlabels){
-
511 if (context->doesGlobalDataExist(objectlable.c_str())) {
+
511 if (context->doesGlobalDataExist(objectlable.c_str())) {
512 std::vector<vec2> Object_spectrum;
-
513 context->getGlobalData(objectlable.c_str(), Object_spectrum);
+
513 context->getGlobalData(objectlable.c_str(), Object_spectrum);
514 Object_spectra.emplace(objectlable, Object_spectrum);
515 wavelengthboundary(wavelengthrange.x, wavelengthrange.y, Object_spectrum);
516 }
@@ -632,32 +639,32 @@
519 }
520
521 // Check if object spectra in global data has been added to UUIDs but are not in the provided object labels;
-
522 std::vector<uint> exist_UUIDs = context->getAllUUIDs();
+
522 std::vector<uint> exist_UUIDs = context->getAllUUIDs();
523 for (uint UUID:exist_UUIDs){
-
524 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum")) {
+
524 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum")) {
525 std::string spectralreflectivitylabel;
-
526 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectralreflectivitylabel);
-
527 if (context->doesGlobalDataExist(spectralreflectivitylabel.c_str())) {
+
526 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectralreflectivitylabel);
+
527 if (context->doesGlobalDataExist(spectralreflectivitylabel.c_str())) {
528 if (std::find(objectlabels.begin(), objectlabels.end(), spectralreflectivitylabel) == objectlabels.end()) {
529 objectlabels.push_back(spectralreflectivitylabel);
530// std::cout << "WARNING: Spectrum (" << spectralreflectivitylabel << ") has been added to UUID (" << UUID << ") but is not in the provided object spectral labels" << std::endl;
531 std::vector<vec2> Object_spectrum;
-
532 context->getGlobalData(spectralreflectivitylabel.c_str(), Object_spectrum);
+
532 context->getGlobalData(spectralreflectivitylabel.c_str(), Object_spectrum);
533 Object_spectra.emplace(spectralreflectivitylabel, Object_spectrum);
534 wavelengthboundary(wavelengthrange.x, wavelengthrange.y, Object_spectrum);
535 }
536 }
537 }
538
-
539 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum")) {
+
539 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum")) {
540 std::string spectraltransmissivitylabel;
-
541 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectraltransmissivitylabel);
-
542 if (context->doesGlobalDataExist(spectraltransmissivitylabel.c_str())) {
+
541 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectraltransmissivitylabel);
+
542 if (context->doesGlobalDataExist(spectraltransmissivitylabel.c_str())) {
543 if (std::find(objectlabels.begin(), objectlabels.end(), spectraltransmissivitylabel) == objectlabels.end()) {
544 objectlabels.push_back(spectraltransmissivitylabel);
545 std::cout << "WARNING: Spectrum (" << spectraltransmissivitylabel << ") has been added to UUID (" << UUID << ") but is not in the provided object labels" << std::endl;
546 std::vector<vec2> Object_spectrum;
-
547 context->getGlobalData(spectraltransmissivitylabel.c_str(), Object_spectrum);
+
547 context->getGlobalData(spectraltransmissivitylabel.c_str(), Object_spectrum);
548 Object_spectra.emplace(spectraltransmissivitylabel, Object_spectrum);
549 wavelengthboundary(wavelengthrange.x, wavelengthrange.y, Object_spectrum);
550 }
@@ -683,7 +690,7 @@
570 std::vector<vec2> cal_spectrum;
571 for (auto ispectralvalue:target_spectrum){
572 if(ispectralvalue.x>wavelengthrange.y){
-
573 context->setGlobalData(spectrumpair.first.c_str(), HELIOS_TYPE_VEC2, cal_spectrum.size(), &cal_spectrum[0]);
+
573 context->setGlobalData(spectrumpair.first.c_str(), HELIOS_TYPE_VEC2, cal_spectrum.size(), &cal_spectrum[0]);
574 break;
575 }
576 if(ispectralvalue.x>=wavelengthrange.x){
@@ -699,7 +706,7 @@
586 std::vector<float> wavelengths;
587 for (auto ispectralvalue:target_spectrum){
588 if(ispectralvalue.x>wavelengthrange.y || ispectralvalue.x == target_spectrum.back().x){
-
589 context->setGlobalData("wavelengths", HELIOS_TYPE_FLOAT, wavelengths.size(), &wavelengths[0]);
+
589 context->setGlobalData("wavelengths", HELIOS_TYPE_FLOAT, wavelengths.size(), &wavelengths[0]);
590 break;
591 }
592 if(ispectralvalue.x>=wavelengthrange.x){
@@ -716,7 +723,7 @@
601
602 std::vector<uint> camera_UUIDs;
603 std::string global_UUID_label = "camera_" + cameralabel + "_pixel_UUID";
-
604 context->getGlobalData(global_UUID_label.c_str(), camera_UUIDs);
+
604 context->getGlobalData(global_UUID_label.c_str(), camera_UUIDs);
605
606 float dotsimreal = 0;
607 float dotsimsim = 0;
@@ -724,7 +731,7 @@
609
610 std::vector<float> camera_data;
611 std::string global_data_label = "camera_" + cameralabel + "_" + bandlabels.at(ib);
-
612 context->getGlobalData(global_data_label.c_str(), camera_data);
+
612 context->getGlobalData(global_data_label.c_str(), camera_data);
613
614 for (int icu = 0; icu<UUIDs_colorboard.size(); icu++){
615
@@ -780,7 +787,7 @@
663 rotatelf_sc.at(1) += 2 * M_PI;
664 }
665 vec3 iposlf = make_vec3(poslf.at(0),poslf.at(1),poslf.at(2));
-
666 iCUUIDs.push_back(context->addPatch(iposlf,vec2(widthlengthlf,widthlengthlf), make_SphericalCoord(float(0.5*M_PI+rotatelf_sc.at(0)), rotatelf_sc.at(1))));
+
666 iCUUIDs.push_back(context->addPatch(iposlf,vec2(widthlengthlf,widthlengthlf), make_SphericalCoord(float(0.5*M_PI+rotatelf_sc.at(0)), rotatelf_sc.at(1))));
667 }
668 inputFile.close();
669 return iCUUIDs;
@@ -790,23 +797,14 @@
@ HELIOS_TYPE_VEC2
helios::vec2 data type
Definition Context.h:51
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
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:1406
-
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:1536
-
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
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:1763
-
void setGlobalData(const char *label, const int &data)
Add global data value (int)
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
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:3022
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
float sum(const std::vector< float > &vect)
Sum of a vector of floats.
Definition global.cpp:1069
-
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212
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.
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
@@ -825,21 +823,24 @@
std::vector< uint > addColorboard(const helios::vec3 &centrelocation, float patchsize, const helios::vec3 &rotationrad, const std::vector< std::vector< helios::RGBcolor > > &colorassignment={}, const std::vector< std::vector< std::string > > &spectrumassignment={})
Add color board geometry into context.
std::vector< uint > readROMCCanopy()
Read ROMC canopy file (Used for self test).
R-G-B color vector.
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/_camera_calibration_8h.html b/doc/html/_camera_calibration_8h.html index 8349978dc..7b9c03aba 100644 --- a/doc/html/_camera_calibration_8h.html +++ b/doc/html/_camera_calibration_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
@@ -127,10 +133,13 @@

Definition in file CameraCalibration.h.

- - + + diff --git a/doc/html/_camera_calibration_8h.js b/doc/html/_camera_calibration_8h.js new file mode 100644 index 000000000..96382e8d5 --- /dev/null +++ b/doc/html/_camera_calibration_8h.js @@ -0,0 +1,5 @@ +var _camera_calibration_8h = +[ + [ "CameraCalibration", "struct_camera_calibration.html", "struct_camera_calibration" ], + [ "CameraCalibration::GradientDescentParameters", "struct_camera_calibration_1_1_gradient_descent_parameters.html", null ] +]; \ No newline at end of file diff --git a/doc/html/_camera_calibration_8h_source.html b/doc/html/_camera_calibration_8h_source.html index a9575ed5e..14d4f5c69 100644 --- a/doc/html/_camera_calibration_8h_source.html +++ b/doc/html/_camera_calibration_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
CameraCalibration.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef HELIOS_CAMERACALIBRATION_H
17#define HELIOS_CAMERACALIBRATION_H
18#include "Context.h"
-
19
+
19
- -
22 explicit CameraCalibration(helios::Context *context);
-
23
-
25
+
21struct CameraCalibration{
+
22 explicit CameraCalibration(helios::Context *context);
+
23
+
25
32 std::vector<uint> addCheckerboard(const helios::int2 &boardsidesize, const float &patchsize, const helios::vec3 &centrelocation,
33 const helios::vec3 &rotationrad, bool firstblack = true);
34
-
35
-
37
+
35
+
37
41 std::vector<uint> addDefaultCheckerboard(const helios::vec3 &centrelocation,
42 const helios::vec3 &rotationrad);
-
43
-
45
+
43
+
45
52 std::vector<uint> addColorboard(const helios::vec3 &centrelocation, float patchsize, const helios::vec3 &rotationrad, const std::vector<std::vector<helios::RGBcolor>> &colorassignment = {}, const std::vector<std::vector<std::string>> &spectrumassignment = {});
-
53
-
55
+
53
+
55
60// void setColorboardReflectivity(const uint &UUID, const std::string &filename, const std::string &labelname);
-
61
-
63
-
69 std::vector<uint> addDefaultColorboard(const helios::vec3 &centrelocation, float patchsize = 0.5, const helios::vec3 &rotationrad = helios::make_vec3(0,0,0));
+
61
+
63
+
69 std::vector<uint> addDefaultColorboard(const helios::vec3 &centrelocation, float patchsize = 0.5, const helios::vec3 &rotationrad = helios::make_vec3(0,0,0));
70
71 std::vector<uint> getColorBoardUUIDs();
-
72
-
74
+
72
+
74
80 bool writeSpectralXMLfile(const std::string &filename, const std::string &note, const std::string &label, std::vector<helios::vec2> *spectrum);
-
81
-
83
+
81
+
83
88 bool loadXMLlabeldata(const std::string &filename, const std::string &labelname,std::vector<helios::vec2> &spectraldata);
-
89
-
91
+
89
+
91
98 float GradientDescent(std::vector<std::vector<float>> *expandedcameraspectra, const std::vector<std::vector<float>> &expandedconstinput,
99 const float &learningrate, const std::vector<std::vector<float>> &truevalues);
-
100
-
102
+
100
+
102
111 std::vector<float> updateCameraResponseSpectra(const std::vector<std::string>& camerareponselabels, const std::string &label,
112 const std::map<uint,std::vector<helios::vec2>>& simulatedinputspectra,
113 const std::vector<std::vector<float>> &truevalues);
-
114
+
114
- +
116 struct GradientDescentParameters
117 {
118 float learningrate=0.000001;
119 int maxiteration = 500;
120 float minloss = 0.01;
121 std::vector<float> camerarescales = {1,1,1};
-
122 GradientDescentParameters() = default;
+
122 GradientDescentParameters() = default;
123 };
124
125 GradientDescentParameters responseupdateparameters;
-
126
-
128
+
126
+
128
136 void preprocessSpectra(const std::vector<std::string>& sourcelabels, const std::vector<std::string>& cameralabels,
137 std::vector<std::string>& objectlabels, helios::vec2 &wavelengthrange, const std::string& targetlabel="");
-
138
-
140
+
138
+
140
148 void distortImage(const std::string& cameralabel, const std::vector<std::string>& bandlabels, const helios::vec2 &focalxy,
149 std::vector<double> &distCoeffs, helios::int2 camerareoslution);
-
150
-
152
+
150
+
152
158 float getCameraResponseScale(const std::string &cameralabel, const helios::int2 cameraresolution, const std::vector<std::string> &bandlabels,
159 const std::vector<std::vector<float>> &truevalues);
160
161 std::map<std::string,std::map<std::string, std::vector<helios::vec2>>> processedspectra;
-
162
-
164
+
162
+
164
167 std::vector<uint> readROMCCanopy();
-
168
-
170
+
168
+
170
175 void writeCalibratedCameraResponses(const std::vector<std::string>& camerareponselabels, const std::string &calibratemark, float scale);
176
177// void resetCameraResponses(std::string camerareponselabels, float scale);
@@ -188,16 +195,16 @@
181 std::map<std::string, std::vector<helios::vec2>> calibratedcameraspectra;
182
183 helios::Context *context;
-
184
-
186
+
184
+
186
191 std::vector<float> expandSpectrum(const std::vector<helios::vec2>& targetspectrum, float scale);
-
192
+
192
194 std::vector<uint> UUIDs_colorboard;
195
196 std::vector<uint> UUIDs_black;
197
198 std::vector<uint> UUIDs_white;
-
199
+
199
201 helios::RGBcolor white_01 = helios::make_RGBcolor(1.f,1.f,1.f);
202 helios::RGBcolor lightgray_02 = helios::make_RGBcolor(0.8,0.8,0.8);
203 helios::RGBcolor mediumlightgray_03 = helios::make_RGBcolor(0.6,0.6,0.6);
@@ -232,10 +239,10 @@
231
232#endif //HELIOS_CAMERACALIBRATION_H
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor vector.
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
Parameter struct for gradient descent.
-
Camera calibration structure used for camera calibration tasks.
bool loadXMLlabeldata(const std::string &filename, const std::string &labelname, std::vector< helios::vec2 > &spectraldata)
Load XML file and save data in spectral vectors containing both wavelengths and spectral values.
void writeCalibratedCameraResponses(const std::vector< std::string > &camerareponselabels, const std::string &calibratemark, float scale)
Write calibrated camera response spectra.
float getCameraResponseScale(const std::string &cameralabel, const helios::int2 cameraresolution, const std::vector< std::string > &bandlabels, const std::vector< std::vector< float > > &truevalues)
Get camera spectral response scale.
@@ -250,14 +257,17 @@
std::vector< uint > addColorboard(const helios::vec3 &centrelocation, float patchsize, const helios::vec3 &rotationrad, const std::vector< std::vector< helios::RGBcolor > > &colorassignment={}, const std::vector< std::vector< std::string > > &spectrumassignment={})
Add color board geometry into context.
std::vector< uint > readROMCCanopy()
Read ROMC canopy file (Used for self test).
R-G-B color vector.
-
Vector of two elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_canopy_generator_8cpp.html b/doc/html/_canopy_generator_8cpp.html index 0e579dfc1..febcc62b3 100644 --- a/doc/html/_canopy_generator_8cpp.html +++ b/doc/html/_canopy_generator_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -351,10 +357,13 @@

+ + diff --git a/doc/html/_canopy_generator_8cpp.js b/doc/html/_canopy_generator_8cpp.js new file mode 100644 index 000000000..2381b4794 --- /dev/null +++ b/doc/html/_canopy_generator_8cpp.js @@ -0,0 +1,9 @@ +var _canopy_generator_8cpp = +[ + [ "evaluateCDFresid", "_canopy_generator_8cpp.html#a22e592a9de7a15c01e7c87d077fdde2a", null ], + [ "getVariation", "_canopy_generator_8cpp.html#aa0b21a2d6b9506b33d05047716d671e0", null ], + [ "getVariation", "_canopy_generator_8cpp.html#a9f90ba8fe8a074a822424ff748579f25", null ], + [ "getVariation", "_canopy_generator_8cpp.html#a6cdee9cb4984f78c818e46eb2a5b62e6", null ], + [ "interpolateTube", "_canopy_generator_8cpp.html#a3d09d2e054283f9202ad662a2c131018", null ], + [ "interpolateTube", "_canopy_generator_8cpp.html#a2d10c56b3c11e46ebfd346ce37f38612", null ] +]; \ No newline at end of file diff --git a/doc/html/_canopy_generator_8cpp_source.html b/doc/html/_canopy_generator_8cpp_source.html index f2169e956..a6cef41a7 100644 --- a/doc/html/_canopy_generator_8cpp_source.html +++ b/doc/html/_canopy_generator_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
CanopyGenerator.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "CanopyGenerator.h"
17#include "pugixml.hpp"
18
19using namespace helios;
-
20
+
20
22static float nullvalue_f = 99999;
24static int nullvalue_i = 99999;
26static std::string nullvalue_s = "99999";
@@ -122,7 +129,7 @@
32
- +
34 readParametersFromXML(canopy_node);
35}
@@ -144,7 +151,7 @@
50
70
@@ -238,7 +245,7 @@
134
156
@@ -346,7 +353,7 @@
232
256
@@ -462,7 +469,7 @@
338
387
@@ -753,7 +760,7 @@
619
653
@@ -813,7 +820,7 @@
669
712
@@ -897,7 +904,7 @@
743
777
@@ -957,7 +964,7 @@
793
825
@@ -1015,7 +1022,7 @@
841
879
@@ -1159,7 +1166,7 @@
975
1003
-
1004TomatoParameters::TomatoParameters(const pugi::xml_node canopy_node) : TomatoParameters(){
+
1004TomatoParameters::TomatoParameters(const pugi::xml_node canopy_node) : TomatoParameters(){
1005 readParametersFromXML(canopy_node);
1006}
@@ -1274,7 +1281,7 @@
1080
1114
- +
1116 readParametersFromXML(canopy_node);
1117}
@@ -1404,7 +1411,7 @@
1200
1232
@@ -1523,7 +1530,7 @@
1309
1441
@@ -1991,7 +1998,7 @@
1767
1801
-
1802BeanParameters::BeanParameters(const pugi::xml_node canopy_node) : BeanParameters(){
+
1802BeanParameters::BeanParameters(const pugi::xml_node canopy_node) : BeanParameters(){
1803 readParametersFromXML(canopy_node);
1804}
@@ -2150,7 +2157,7 @@
1912
1913 std::cout << "Generating default homogeneous canopy..." << std::flush;
1914
-
1915 CanopyGenerator canopygenerator_0(&context_test);
+
1915 CanopyGenerator canopygenerator_0(&context_test);
1916 canopygenerator_0.disableMessages();
1918 canopygenerator_0.buildCanopy(params_0);
@@ -2160,7 +2167,7 @@
1922
1923 std::cout << "Generating default spherical crowns canopy..." << std::flush;
1924
-
1925 CanopyGenerator canopygenerator_1(&context_test);
+
1925 CanopyGenerator canopygenerator_1(&context_test);
1926 canopygenerator_1.disableMessages();
1928 canopygenerator_1.buildCanopy(params_1);
@@ -2170,7 +2177,7 @@
1932
1933 std::cout << "Generating default VSP grapevine canopy..." << std::flush;
1934
-
1935 CanopyGenerator canopygenerator_2(&context_test);
+
1935 CanopyGenerator canopygenerator_2(&context_test);
1936 canopygenerator_2.disableMessages();
1937 VSPGrapevineParameters params_2;
1938 params_2.grape_radius = 0;
@@ -2181,7 +2188,7 @@
1943
1944 std::cout << "Generating default split trellis grapevine canopy..." << std::flush;
1945
-
1946 CanopyGenerator canopygenerator_3(&context_test);
+
1946 CanopyGenerator canopygenerator_3(&context_test);
1947 canopygenerator_3.disableMessages();
1948 SplitGrapevineParameters params_3;
1949 params_3.grape_radius = 0;
@@ -2192,7 +2199,7 @@
1954
1955 std::cout << "Generating default unilateral trellis grapevine canopy..." << std::flush;
1956
-
1957 CanopyGenerator canopygenerator_4(&context_test);
+
1957 CanopyGenerator canopygenerator_4(&context_test);
1958 canopygenerator_4.disableMessages();
1960 params_4.grape_radius = 0;
@@ -2203,7 +2210,7 @@
1965
1966 std::cout << "Generating default goblet trellis grapevine canopy..." << std::flush;
1967
-
1968 CanopyGenerator canopygenerator_5(&context_test);
+
1968 CanopyGenerator canopygenerator_5(&context_test);
1969 canopygenerator_5.disableMessages();
1971 params_5.grape_radius = 0;
@@ -2214,7 +2221,7 @@
1976
1977 std::cout << "Generating default strawberry canopy..." << std::flush;
1978
-
1979 CanopyGenerator canopygenerator_7(&context_test);
+
1979 CanopyGenerator canopygenerator_7(&context_test);
1980 canopygenerator_7.disableMessages();
1981 StrawberryParameters params_7;
1982 canopygenerator_7.buildCanopy(params_7);
@@ -2224,7 +2231,7 @@
1986
1987 std::cout << "Generating default walnut tree canopy (minus nuts)..." << std::flush;
1988
-
1989 CanopyGenerator canopygenerator_8(&context_test);
+
1989 CanopyGenerator canopygenerator_8(&context_test);
1990 canopygenerator_8.disableMessages();
1991 WalnutCanopyParameters params_8;
1992 params_8.fruit_radius = 0.f;
@@ -2235,7 +2242,7 @@
1997
1998 std::cout << "Generating default sorghum plant canopy..." << std::flush;
1999
-
2000 CanopyGenerator canopygenerator_9(&context_test);
+
2000 CanopyGenerator canopygenerator_9(&context_test);
2001 canopygenerator_9.disableMessages();
2002 SorghumCanopyParameters params_9;
2003 canopygenerator_9.buildCanopy(params_9);
@@ -2245,7 +2252,7 @@
2007
2008 std::cout << "Generating homogeneous canopy with randomly deleted primitives..." << std::flush;
2009
-
2010 CanopyGenerator canopygenerator_6(&context_test);
+
2010 CanopyGenerator canopygenerator_6(&context_test);
2011 canopygenerator_6.disableMessages();
2013 canopygenerator_6.buildCanopy(params_6);
@@ -2563,7 +2570,7 @@
2317 center = rotatePointAboutLine( center, ground_origin, make_vec3(0,0,1), ground_rotation );
2318 }
2319
-
2320 UUIDs = context->addTile( center, dx_tile, make_SphericalCoord(0,-ground_rotation), texture_subpatches, ground_texture_file );
+
2320 UUIDs = context->addTile( center, dx_tile, make_SphericalCoord(0,-ground_rotation), texture_subpatches, ground_texture_file );
2321
2322 UUID_ground.insert( UUID_ground.begin(), UUIDs.begin(), UUIDs.end() );
2323
@@ -2612,9 +2619,9 @@
2362
2363 uint ID0;
2364 if( params.leaf_texture_file.empty() ){
-
2365 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_color );
+
2365 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_color );
2366 }else{
-
2367 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
+
2367 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
2368 }
2369
2370 for( int i=0; i<Nleaves; i++ ){
@@ -2638,18 +2645,18 @@
2388
2389 SphericalCoord rotation( 1.f, sampleLeafPDF(params.leaf_angle_distribution.c_str()), 2.f*float(M_PI)*rp );
2390
-
2391 uint ID = context->copyObject(ID0);
-
2392 context->getObjectPointer(ID)->rotate(-rotation.elevation,"y");
-
2393 context->getObjectPointer(ID)->rotate(rotation.azimuth,"z");
-
2394 context->getObjectPointer(ID)->translate(position);
+
2391 uint ID = context->copyObject(ID0);
+
2392 context->getObjectPointer(ID)->rotate(-rotation.elevation,"y");
+
2393 context->getObjectPointer(ID)->rotate(rotation.azimuth,"z");
+
2394 context->getObjectPointer(ID)->translate(position);
2395
-
2396 std::vector<uint> UUID = context->getObjectPointer(ID)->getPrimitiveUUIDs();
+
2396 std::vector<uint> UUID = context->getObjectPointer(ID)->getPrimitiveUUIDs();
2397
2398 UUID_leaf.front().push_back(UUID);
2399
2400 }
2401
-
2402 context->deleteObject(ID0);
+
2402 context->deleteObject(ID0);
2403
2404
2405 if( printmessages ){
@@ -2695,9 +2702,9 @@
2443
2444 uint ID0;
2445 if( params.leaf_texture_file.empty() ){
-
2446 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_color );
+
2446 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_color );
2447 }else{
-
2448 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
+
2448 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
2449 }
2450
2451 uint plant_ID = 0;
@@ -2735,12 +2742,12 @@
2483 float theta = sampleLeafPDF(params.leaf_angle_distribution.c_str());
2484 float phi = 2.f*float(M_PI)*unif_distribution(generator);
2485
-
2486 uint ID = context->copyObject(ID0);
-
2487 context->getObjectPointer(ID)->rotate(-theta,"y");
-
2488 context->getObjectPointer(ID)->rotate(phi,"z");
-
2489 context->getObjectPointer(ID)->translate(center+position);
+
2486 uint ID = context->copyObject(ID0);
+
2487 context->getObjectPointer(ID)->rotate(-theta,"y");
+
2488 context->getObjectPointer(ID)->rotate(phi,"z");
+
2489 context->getObjectPointer(ID)->translate(center+position);
2490
-
2491 std::vector<uint> UUID = context->getObjectPointer(ID)->getPrimitiveUUIDs();
+
2491 std::vector<uint> UUID = context->getObjectPointer(ID)->getPrimitiveUUIDs();
2492
2493 UUID_leaf.at(plant_ID).push_back(UUID);
2494
@@ -2754,7 +2761,7 @@
2502 }
2503 }
2504
-
2505 context->deleteObject(ID0);
+
2505 context->deleteObject(ID0);
2506
2507 if( printmessages ){
2508 std::cout << "done." << std::endl;
@@ -2799,9 +2806,9 @@
2545
2546 uint ID0;
2547 if( params.leaf_texture_file.empty() ){
-
2548 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_color );
+
2548 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_color );
2549 }else{
-
2550 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
+
2550 ID0 = context->addTileObject( make_vec3(0,0,0), params.leaf_size, make_SphericalCoord(0,0), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
2551 }
2552
2553 uint plant_ID = 0;
@@ -2839,12 +2846,12 @@
2585 float theta = sampleLeafPDF(params.leaf_angle_distribution.c_str());
2586 float phi = 2.f*float(M_PI)*unif_distribution(generator);
2587
-
2588 uint ID = context->copyObject(ID0);
-
2589 context->getObjectPointer(ID)->rotate(-theta,"y");
-
2590 context->getObjectPointer(ID)->rotate(phi,"z");
-
2591 context->getObjectPointer(ID)->translate(center+position);
+
2588 uint ID = context->copyObject(ID0);
+
2589 context->getObjectPointer(ID)->rotate(-theta,"y");
+
2590 context->getObjectPointer(ID)->rotate(phi,"z");
+
2591 context->getObjectPointer(ID)->translate(center+position);
2592
-
2593 std::vector<uint> UUID = context->getObjectPointer(ID)->getPrimitiveUUIDs();
+
2593 std::vector<uint> UUID = context->getObjectPointer(ID)->getPrimitiveUUIDs();
2594
2595 UUID_leaf.at(plant_ID).push_back(UUID);
2596
@@ -2858,7 +2865,7 @@
2604 }
2605 }
2606
-
2607 context->deleteObject(ID0);
+
2607 context->deleteObject(ID0);
2608
2609 if( printmessages ){
2610 std::cout << "done." << std::endl;
@@ -2889,7 +2896,7 @@
2633 for( int i=0; i<params.plant_count.x; i++ ){
2634
2635 if( params.missing_plant_probability > 0 ){
-
2636 float random_draw = context->randu();
+
2636 float random_draw = context->randu();
2637 if( random_draw <= params.missing_plant_probability ){
2638 // Don't add the plant
2639 continue;
@@ -2933,7 +2940,7 @@
2675 for( int i=0; i<params.plant_count.x; i++ ){
2676
2677 if( params.missing_plant_probability > 0 ){
-
2678 float random_draw = context->randu();
+
2678 float random_draw = context->randu();
2679 if( random_draw <= params.missing_plant_probability ){
2680 // Don't add the plant
2681 continue;
@@ -2977,7 +2984,7 @@
2717 for( int i=0; i<params.plant_count.x; i++ ){
2718
2719 if( params.missing_plant_probability > 0 ){
-
2720 float random_draw = context->randu();
+
2720 float random_draw = context->randu();
2721 if( random_draw <= params.missing_plant_probability ){
2722 // Don't add the plant
2723 continue;
@@ -3021,7 +3028,7 @@
2759 for( int i=0; i<params.plant_count.x; i++ ){
2760
2761 if( params.missing_plant_probability > 0 ){
-
2762 float random_draw = context->randu();
+
2762 float random_draw = context->randu();
2763 if( random_draw <= params.missing_plant_probability ){
2764 // Don't add the plant
2765 continue;
@@ -3365,7 +3372,7 @@
3084
3085void CanopyGenerator::cleanDeletedUUIDs( std::vector<uint> &UUIDs ){
3086 for( int p=UUIDs.size()-1; p>=0; p-- ){
-
3087 if( !context->doesPrimitiveExist(UUIDs.at(p)) ){
+
3087 if( !context->doesPrimitiveExist(UUIDs.at(p)) ){
3088 std::swap( UUIDs.at(p), UUIDs.back() );
3089 UUIDs.pop_back();
3090 }
@@ -3481,7 +3488,7 @@
3183
3184 for( uint i : UUID_ground){
3185
-
3186 if( context->doesPrimitiveExist(i) ){
+
3186 if( context->doesPrimitiveExist(i) ){
3187 UUID.push_back(i);
3188 }
3189
@@ -3736,16 +3743,9 @@
void createElementLabels()
Create primitive data that explicitly labels all primitives according to the plant element they corre...
int selfTest()
Unit testing routine.
uint walnut(const WalnutCanopyParameters &params, const helios::vec3 &origin)
Function to add an individual walnut tree.
Definition walnut.cpp:333
-
void rotate(float rotation_radians, const char *rotation_axis_xyz_string)
Method to rotate a Compound Object about the x-, y-, or z-axis.
Definition Context.cpp:2377
-
void translate(const helios::vec3 &shift)
Method to translate/shift a Compound Object.
Definition Context.cpp:2353
-
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
-
Stores the state associated with simulation.
Definition Context.h:1882
-
uint copyObject(uint ObjID)
Make a copy of a Compound Objects from the context.
Definition Context.cpp:2642
+
Stores the state associated with simulation.
Definition Context.h:1888
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
-
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
-
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
void deleteObject(uint ObjID)
Delete a single Compound Object from the context.
Definition Context.cpp:2609
bool doesPrimitiveExist(uint UUID) const
Check if primitive exists for a given UUID.
Definition Context.cpp:1659
Texture map data structure.
Definition Context.h:67
float getSolidFraction() const
Get the solid fraction of the texture transparency channel (if it exists)
Definition Context.cpp:145
@@ -3758,8 +3758,6 @@
std::string XMLloadstring(pugi::xml_node node, const char *field)
Function to load and convert a field in a pugi XML node into a string.
Definition global.cpp:2842
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:2872
helios::int2 XMLloadint2(pugi::xml_node node, const char *field)
Function to load and convert a field in a pugi XML node into a vec2.
Definition global.cpp:2902
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
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:1943
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
int2 make_int2(int x, int y)
Make an int2 vector from two ints.
@@ -3767,12 +3765,10 @@
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor vector.
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
-
Base struct class for Canopy parameters.
helios::vec3 canopy_origin
Cartesian (x,y,z) coordinate of the bottom center point of the canopy (i.e., specifying z=0 places th...
BaseCanopyParameters()
Default constructor.
void readParametersFromXML(const pugi::xml_node canopy_node)
Sets canopy parameters from the given XML node.
float canopy_rotation
Azimuthal rotation of the canopy about the canopy origin. Note that if canopy_rotation is not equal t...
-
float plant_spacing
Spacing between adjacent plants along the row direction.
float shoot_radius_spread
Spread value for the shoot radius. With any new canopy or plant generation, the shoot radius would be...
float missing_plant_probability
Probability for a plant to be missing.
@@ -3847,7 +3843,7 @@
helios::RGBcolor leaf_color
Leaf color if no texture map file is provided.
std::string leaf_texture_file
Path to texture map file for leaves. If left empty, no texture will be used.
float crown_height
Height of the conical crowns.
-
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
+
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
void buildCanopy(CanopyGenerator &canopy_generator) override
Makes the given Canopy generator build a canopy of our type with our parameters.
std::string canopy_configuration
Specifies whether to use a uniformly spaced canopy (canopy_configuration="uniform") or a randomly arr...
helios::vec2 leaf_size
Length of leaf in x- and y- directions (prior to rotation)
@@ -3946,7 +3942,7 @@
std::string leaf_texture_file
Path to texture map file for leaves. If left empty, no texture will be used.
helios::RGBcolor leaf_color
Leaf color if no texture map file is provided.
helios::int2 plant_count
Number of crowns/plants in the x- and y-directions.
-
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
+
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
SphericalCrownsCanopyParameters()
Default constructor.
helios::int2 leaf_subdivisions
Number of sub-division segments per leaf.
std::string leaf_angle_distribution
Leaf angle distribution - one of "spherical", "uniform", "erectophile", "planophile",...
@@ -4038,7 +4034,7 @@
void readParametersFromXML(const pugi::xml_node canopy_node)
Sets canopy parameters from the given XML node.
void buildCanopy(CanopyGenerator &canopy_generator) override
Makes the given Canopy generator build a canopy of our type with our parameters.
std::string wood_texture_file
Path to texture map file for trunks/branches.
-
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
+
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
float needle_length
Length of needles.
float trunk_height
Distance between the ground and top of trunks.
float level_spacing
Vertical spacing between branching levels.
@@ -4062,21 +4058,24 @@
Vector of spherical coordinates (elevation,azimuth)
const float & elevation
Elevation angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- - + + diff --git a/doc/html/_canopy_generator_8h.html b/doc/html/_canopy_generator_8h.html index 1d1c75d5c..fd323ea1e 100644 --- a/doc/html/_canopy_generator_8h.html +++ b/doc/html/_canopy_generator_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
Data Structures | @@ -401,10 +407,13 @@

+ + diff --git a/doc/html/_canopy_generator_8h.js b/doc/html/_canopy_generator_8h.js new file mode 100644 index 000000000..b2cb180e9 --- /dev/null +++ b/doc/html/_canopy_generator_8h.js @@ -0,0 +1,25 @@ +var _canopy_generator_8h = +[ + [ "BaseCanopyParameters", "struct_base_canopy_parameters.html", "struct_base_canopy_parameters" ], + [ "HomogeneousCanopyParameters", "struct_homogeneous_canopy_parameters.html", "struct_homogeneous_canopy_parameters" ], + [ "SphericalCrownsCanopyParameters", "struct_spherical_crowns_canopy_parameters.html", "struct_spherical_crowns_canopy_parameters" ], + [ "ConicalCrownsCanopyParameters", "struct_conical_crowns_canopy_parameters.html", "struct_conical_crowns_canopy_parameters" ], + [ "BaseGrapeVineParameters", "struct_base_grape_vine_parameters.html", "struct_base_grape_vine_parameters" ], + [ "VSPGrapevineParameters", "struct_v_s_p_grapevine_parameters.html", "struct_v_s_p_grapevine_parameters" ], + [ "SplitGrapevineParameters", "struct_split_grapevine_parameters.html", "struct_split_grapevine_parameters" ], + [ "UnilateralGrapevineParameters", "struct_unilateral_grapevine_parameters.html", "struct_unilateral_grapevine_parameters" ], + [ "GobletGrapevineParameters", "struct_goblet_grapevine_parameters.html", "struct_goblet_grapevine_parameters" ], + [ "WhiteSpruceCanopyParameters", "struct_white_spruce_canopy_parameters.html", "struct_white_spruce_canopy_parameters" ], + [ "TomatoParameters", "struct_tomato_parameters.html", "struct_tomato_parameters" ], + [ "StrawberryParameters", "struct_strawberry_parameters.html", "struct_strawberry_parameters" ], + [ "WalnutCanopyParameters", "struct_walnut_canopy_parameters.html", "struct_walnut_canopy_parameters" ], + [ "SorghumCanopyParameters", "struct_sorghum_canopy_parameters.html", "struct_sorghum_canopy_parameters" ], + [ "BeanParameters", "struct_bean_parameters.html", "struct_bean_parameters" ], + [ "CanopyGenerator", "class_canopy_generator.html", "class_canopy_generator" ], + [ "evaluateCDFresid", "_canopy_generator_8h.html#a22e592a9de7a15c01e7c87d077fdde2a", null ], + [ "getVariation", "_canopy_generator_8h.html#accfb46da54c7b0e83878a1331bbc94d1", null ], + [ "getVariation", "_canopy_generator_8h.html#aa3a6e1a26b799f4a2006703314499fed", null ], + [ "getVariation", "_canopy_generator_8h.html#a6cdee9cb4984f78c818e46eb2a5b62e6", null ], + [ "interpolateTube", "_canopy_generator_8h.html#a3d09d2e054283f9202ad662a2c131018", null ], + [ "interpolateTube", "_canopy_generator_8h.html#a339d165bb0c396a75ce255fbe16a20d4", null ] +]; \ No newline at end of file diff --git a/doc/html/_canopy_generator_8h_source.html b/doc/html/_canopy_generator_8h_source.html index 19d1d5ad5..779b35489 100644 --- a/doc/html/_canopy_generator_8h_source.html +++ b/doc/html/_canopy_generator_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
CanopyGenerator.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef CANOPY_GENERATOR
17#define CANOPY_GENERATOR
18
@@ -112,270 +119,270 @@
20#include <random>
21
22class CanopyGenerator;
-
23
+
23
- -
26
+ +
26
-
29
+
29
33 BaseCanopyParameters(const pugi::xml_node canopy_node);
34
-
35 virtual ~BaseCanopyParameters() = default;
-
36
-
38
+
35 virtual ~BaseCanopyParameters() = default;
+
36
+
38
41 void readParametersFromXML(const pugi::xml_node canopy_node);
-
42
+
42
44 virtual void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) = 0;
-
45
+
45
47 virtual void buildCanopy(CanopyGenerator& canopy_generator) = 0;
-
48
+
48
-
51
+
51
54
55};
-
56
+
56
- -
59
+ +
59
-
62
+
62
66 HomogeneousCanopyParameters(const pugi::xml_node canopy_node);
-
67
-
69
+
67
+
69
72 void readParametersFromXML(const pugi::xml_node canopy_node);
-
73
+
73
75 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
76
+
76
78 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
79
+
79
-
82
+
82
-
85
+
85
87 std::string leaf_texture_file;
-
88
+
88
-
91
+
91
-
94
+
94
-
97
+
97
-
100
+
100
-
103
+
103
105 std::vector<float> leaf_angle_PDF;
-
106
+
106
108 std::string buffer;
109
110};
-
111
+
111
- -
114
+ +
114
-
117
+
117
121 SphericalCrownsCanopyParameters(const pugi::xml_node canopy_node);
-
122
-
124
+
122
+
124
127 void readParametersFromXML(const pugi::xml_node canopy_node);
-
128
+
128
130 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
131
+
131
133 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
134
+
134
-
137
+
137
-
140
+
140
142 std::string leaf_texture_file;
-
143
+
143
-
146
+
146
-
149
+
149
-
152
+
152
-
155
+
155
158
-
161
+
161
-
164
+
164
166 std::vector<float> leaf_angle_PDF;
167
168};
-
169
+
169
- -
172
+ +
172
-
175
+
175
179 ConicalCrownsCanopyParameters(const pugi::xml_node canopy_node);
-
180
-
182
+
180
+
182
185 void readParametersFromXML(const pugi::xml_node canopy_node);
-
186
+
186
188 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
189
+
189
191 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
192
+
192
-
195
+
195
-
198
+
198
200 std::string leaf_texture_file;
-
201
+
201
-
204
+
204
-
207
+
207
-
210
+
210
-
213
+
213
-
216
+
216
-
219
+
219
-
222
+
222
-
225
+
225
227 std::vector<float> leaf_angle_PDF;
228
229};
230
- -
232
+ +
232
-
235
+
235
239 BaseGrapeVineParameters(const pugi::xml_node canopy_node);
240
-
241 virtual ~BaseGrapeVineParameters() = default;
-
242
-
244
+
241 virtual ~BaseGrapeVineParameters() = default;
+
242
+
244
247 void readParametersFromXML(const pugi::xml_node canopy_node);
-
248
+
248
250 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
251
+
251
253 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
254
+
254
-
259
+
259
-
262
+
262
264 std::string leaf_texture_file;
-
265
+
265
267 std::string wood_texture_file;
-
268
+
268
-
273
+
273
-
276
-
278
+
276
+
278
282
-
287
+
287
-
292
+
292
-
297
+
297
-
302
+
302
-
307
+
307
-
312
+
312
-
317
+
317
-
322
+
322
-
327
+
327
-
332
+
332
-
337
+
337
-
340
+
340
-
345
+
345
-
350
+
350
-
355
+
355
-
358
+
358
-
363
+
363
365 std::vector<float> leaf_angle_PDF;
-
366
+
366
369
370};
-
371
+
371
- -
374
+ +
374
-
377
+
377
381 VSPGrapevineParameters(const pugi::xml_node canopy_node);
-
382
-
384
+
382
+
384
387 void readParametersFromXML(const pugi::xml_node canopy_node);
-
388
+
388
390 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
391
+
391
393 void buildCanopy(CanopyGenerator& canopy_generator) override;
394
395};
-
396
+
396
- -
399
+ +
399
-
402
+
402
406 SplitGrapevineParameters(const pugi::xml_node canopy_node);
-
407
-
409
+
407
+
409
412 void readParametersFromXML(const pugi::xml_node canopy_node);
-
413
+
413
415 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
416
+
416
418 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
419
+
419
-
424
+
424
429
@@ -384,584 +391,585 @@
434
435};
-
436
+
436
- -
439
+ +
439
-
442
+
442
446 UnilateralGrapevineParameters(const pugi::xml_node canopy_node);
-
447
-
449
+
447
+
449
452 void readParametersFromXML(const pugi::xml_node canopy_node);
-
453
+
453
455 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
456
+
456
458 void buildCanopy(CanopyGenerator& canopy_generator) override;
459
460};
461
-
462
+
462
- -
465
+ +
465
-
468
+
468
472 GobletGrapevineParameters(const pugi::xml_node canopy_node);
-
473
-
475
+
473
+
475
478 void readParametersFromXML(const pugi::xml_node canopy_node);
-
479
+
479
481 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
482
+
482
484 void buildCanopy(CanopyGenerator& canopy_generator) override;
485
486};
-
487
+
487
- -
490
+ +
490
-
493
+
493
497 WhiteSpruceCanopyParameters(const pugi::xml_node canopy_node);
-
498
-
500
+
498
+
500
503 void readParametersFromXML(const pugi::xml_node canopy_node);
-
504
+
504
506 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
507
+
507
509 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
510
+
510
-
513
+
513
-
516
+
516
-
519
+
519
-
522
+
522
524 std::string wood_texture_file;
-
525
+
525
-
528
+
528
-
531
+
531
-
534
+
534
-
537
+
537
-
540
+
540
-
543
+
543
-
546
+
546
-
549
+
549
-
552
+
552
555
-
558
+
558
561
562};
-
563
+
563
- -
566
+ +
566
-
569
+
569
573 TomatoParameters(const pugi::xml_node canopy_node);
-
574
-
576
+
574
+
576
579 void readParametersFromXML(const pugi::xml_node canopy_node);
-
580
+
580
582 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
583
+
583
585 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
586
+
586
-
589
+
589
-
592
+
592
594 std::string leaf_texture_file;
-
595
+
595
-
598
+
598
601
-
604
+
604
-
607
+
607
-
610
+
610
-
613
+
613
-
616
+
616
-
619
+
619
622
623};
-
624
+
624
- -
627
+ +
627
-
630
+
630
634 StrawberryParameters(const pugi::xml_node canopy_node);
-
635
-
637
+
635
+
637
640 void readParametersFromXML(const pugi::xml_node canopy_node);
-
641
+
641
643 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
644
+
644
646 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
647
+
647
-
650
+
650
-
653
+
653
655 std::string leaf_texture_file;
-
656
+
656
-
659
+
659
-
662
+
662
-
665
+
665
668
-
671
+
671
-
674
+
674
-
677
+
677
-
680
+
680
-
683
+
683
-
686
+
686
-
689
+
689
692
693};
-
694
+
694
- -
697
+ +
697
-
700
+
700
704 WalnutCanopyParameters(const pugi::xml_node canopy_node);
-
705
-
707
+
705
+
707
710 void readParametersFromXML(const pugi::xml_node canopy_node);
-
711
+
711
713 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
714
+
714
716 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
717
+
717
-
720
+
720
-
723
+
723
725 std::string leaf_texture_file;
-
726
+
726
728 std::string wood_texture_file;
-
729
+
729
-
732
+
732
-
735
+
735
-
738
+
738
741
742
-
745
+
745
-
748
+
748
-
751
+
751
-
754
+
754
-
757
+
757
760
761};
-
762
+
762
- -
765
+ +
765
-
768
+
768
772 SorghumCanopyParameters(const pugi::xml_node canopy_node);
-
773
-
775
+
773
+
775
778 void readParametersFromXML(const pugi::xml_node canopy_node);
-
779
+
779
781 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
782
+
782
784 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
785
+
785
788
789 // STAGE 1
-
790
+
790
-
793
+
793
-
796
+
796
-
799
+
799
-
802
+
802
-
805
+
805
-
808
+
808
-
811
+
811
-
814
+
814
-
817
+
817
-
820
+
820
823
824 // STAGE 2
-
825
+
825
-
828
+
828
-
831
+
831
-
834
+
834
-
837
+
837
-
840
+
840
-
843
+
843
-
846
+
846
-
849
+
849
-
852
+
852
-
855
+
855
-
858
+
858
-
861
+
861
-
864
+
864
-
867
+
867
870
871 // STAGE 3
-
872
+
872
-
875
+
875
-
878
+
878
-
881
+
881
-
884
+
884
-
887
+
887
-
890
+
890
-
893
+
893
896
897 // STAGE 4
-
898
+
898
-
901
+
901
-
904
+
904
-
907
+
907
-
910
+
910
-
913
+
913
-
916
+
916
-
919
+
919
-
922
+
922
-
925
+
925
-
928
+
928
931
932 // STAGE 5
-
933
+
933
-
936
+
936
-
939
+
939
-
942
+
942
-
945
+
945
-
948
+
948
-
951
+
951
-
954
+
954
-
957
+
957
-
960
+
960
-
963
+
963
-
966
+
966
969
970 // CANOPY
-
973
+
973
-
976
+
976
979
980};
-
981
+
981
- -
984
+ +
984
-
987
+
987
991 BeanParameters(const pugi::xml_node canopy_node);
-
992
-
994
+
992
+
994
997 void readParametersFromXML(const pugi::xml_node canopy_node);
-
998
+
998
1000 void buildPlant(CanopyGenerator& canopy_generator, helios::vec3 origin) override;
-
1001
+
1001
1003 void buildCanopy(CanopyGenerator& canopy_generator) override;
-
1004
+
1004
-
1007
+
1007
-
1010
+
1010
-
1013
+
1013
-
1016
+
1016
-
1019
+
1019
-
1022
+
1022
-
1025
+
1025
-
1028
+
1028
-
1031
+
1031
-
1034
+
1034
-
1037
+
1037
-
1040
+
1040
-
1043
+
1043
-
1046
+
1046
1049
1050};
1051
- +
1053 public:
-
1054
-
1056
+
1054
+
1056
1059 explicit CanopyGenerator( helios::Context* context );
-
1060
+
1060
1062 int selfTest();
-
1063
+
1063
1065 template <typename CanopyType, typename... Args>
1066 void storeCanopyParameters(Args&&... args);
1067
1068 std::vector<std::shared_ptr<BaseCanopyParameters>> getCanopyParametersList();
-
1069
-
1071
+
1069
+
1071
1075 void loadXML( const char* filename, bool build = true );
-
1076
+
1076
1078 void buildCanopies();
-
1079
-
1081
+
1079
+
1081
1084 void buildCanopy( const HomogeneousCanopyParameters &params );
-
1085
-
1087
+
1085
+
1087
1090 void buildCanopy( const SphericalCrownsCanopyParameters &params );
-
1091
-
1093
+
1091
+
1093
1096 void buildCanopy( const ConicalCrownsCanopyParameters &params );
-
1097
-
1099
+
1097
+
1099
1102 void buildCanopy( const VSPGrapevineParameters &params );
-
1103
-
1105
+
1103
+
1105
1108 void buildCanopy( const SplitGrapevineParameters &params );
-
1109
-
1111
+
1109
+
1111
1114 void buildCanopy( const UnilateralGrapevineParameters &params );
-
1115
-
1117
+
1115
+
1117
1120 void buildCanopy( const GobletGrapevineParameters &params );
-
1121
-
1123
+
1121
+
1123
1126 void buildCanopy( const WhiteSpruceCanopyParameters &params );
-
1127
-
1129
+
1127
+
1129
1132 void buildCanopy( const TomatoParameters &params );
-
1133
-
1135
+
1133
+
1135
1138 void buildCanopy( const StrawberryParameters &params );
-
1139
-
1141
+
1139
+
1141
1144 void buildCanopy(const WalnutCanopyParameters &params );
-
1145
-
1147
+
1145
+
1147
1150 void buildCanopy( const SorghumCanopyParameters &params );
-
1151
-
1153
+
1151
+
1153
1156 void buildCanopy( const BeanParameters &params );
-
1157
-
1159
+
1157
+
1159
+
1166
1167 void buildGround( const helios::vec3 &ground_origin, const helios::vec2 &ground_extent, const helios::int2 &texture_subtiles, const helios::int2 &texture_subpatches, const char* ground_texture_file );
-
1168
-
1170
+
1168
+
1170
1178 void buildGround( const helios::vec3 &ground_origin, const helios::vec2 &ground_extent, const helios::int2 &texture_subtiles, const helios::int2 &texture_subpatches, const char* ground_texture_file, float ground_rotation );
1179
-
1181
+
1181
1184 std::vector<uint> getTrunkUUIDs( uint PlantID );
-
1185
+
1185
1187 std::vector<uint> getTrunkUUIDs();
-
1188
-
1190
+
1188
+
1190
1193 std::vector<uint> getBranchUUIDs( uint PlantID );
-
1194
+
1194
1196 std::vector<uint> getBranchUUIDs();
-
1197
-
1199
+
1197
+
1199
1203 std::vector<std::vector<uint> > getLeafUUIDs( uint PlantID );
-
1204
+
1204
1206 std::vector<uint> getLeafUUIDs();
-
1207
-
1209
+
1207
+
1209
1213 std::vector<std::vector<std::vector<uint> > > getFruitUUIDs( uint PlantID );
-
1214
+
1214
1216 std::vector<uint> getFruitUUIDs();
-
1217
+
1217
1219 std::vector<uint> getGroundUUIDs();
-
1220
-
1222
+
1220
+
1222
1225 std::vector<uint> getAllUUIDs( uint PlantID );
-
1226
+
1226
1228 uint getPlantCount();
-
1229
-
1231
+
1229
+
1231
1234 void seedRandomGenerator( uint seed );
-
1235
+
1235
1237 void disableMessages();
-
1238
+
1238
1240 void enableMessages();
1241
1242 //---------- PLANT GEOMETRIES ------------ //
-
1243
-
1245
+
1243
+
1245
1248 void buildIndividualPlants(helios::vec3 position);
-
1249
+
1249
1251 void buildIndividualPlants();
-
1252
-
1254
+
1252
+
1254
1261 std::vector<std::vector<uint> > addGrapeCluster( helios::vec3 position, float grape_rad, float cluster_rad, helios::RGBcolor grape_color, uint grape_subdiv );
-
1262
+
1262
1264
1269uint grapevineVSP(const VSPGrapevineParameters &params, const helios::vec3 &origin );
-
1270
+
1270
1272
1277uint grapevineSplit( const SplitGrapevineParameters &params, const helios::vec3 &origin );
-
1278
+
1278
1280
1285uint grapevineUnilateral( const UnilateralGrapevineParameters &params, const helios::vec3 &origin );
-
1286
+
1286
1288
1293uint grapevineGoblet( const GobletGrapevineParameters &params, const helios::vec3 &origin );
-
1294
+
1294
1296
1301 uint whitespruce( const WhiteSpruceCanopyParameters &params, const helios::vec3 &origin );
-
1302
+
1302
1304
1309 uint tomato( const TomatoParameters &params, const helios::vec3 &origin );
-
1310
+
1310
1312
1317 uint strawberry( const StrawberryParameters &params, const helios::vec3 &origin );
-
1318
+
1318
1320
1325 uint walnut(const WalnutCanopyParameters &params, const helios::vec3 &origin );
-
1326
-
1328
+
1326
+
1328
1333 uint sorghum( const SorghumCanopyParameters &params, const helios::vec3 &origin);
-
1334
-
1336
+
1334
+
1336
1341 uint bean( const BeanParameters &params, const helios::vec3 &origin );
-
1342
+
1342
1344 void createElementLabels();
-
1345
+
1345
1347 void disableElementLabels();
1348
1349 private:
1350
1351 helios::Context* context;
-
1352
+
1352
1354 std::vector<std::shared_ptr<BaseCanopyParameters>> canopy_parameters_list;
-
1355
-
1357
+
1355
+
1357
1360 std::vector<std::vector<uint> > UUID_trunk;
-
1361
-
1363
+
1361
+
1363
1366 std::vector<std::vector<uint> > UUID_branch;
-
1367
-
1369
+
1367
+
1369
1372 std::vector<std::vector<std::vector<uint> > > UUID_leaf;
-
1373
-
1375
+
1373
+
1375
1378 std::vector<std::vector<std::vector<std::vector<uint> > > > UUID_fruit;
-
1379
+
1379
1381 std::vector<uint> UUID_ground;
1382
1383 std::vector<uint> leaf_prototype_global;
@@ -984,23 +992,23 @@
1400
1401};
-
1402
-
1404
+
1402
+
1404
1409float getVariation( float V, std::minstd_rand0& generator, bool positive = false );
-
1410
-
1412
+
1410
+
1412
1417int getVariation( int V, std::minstd_rand0& generator, bool positive = false );
-
1418
-
1420
+
1418
+
1420
1424uint getVariation( uint V, std::minstd_rand0& generator );
-
1425
-
1427
+
1425
+
1427
1431helios::vec3 interpolateTube( const std::vector<helios::vec3> &P, float frac );
-
1432
-
1434
+
1432
+
1434
1438float interpolateTube( const std::vector<float> &P, float frac );
-
1439
-
1441
+
1439
+
1441
1446float evaluateCDFresid(float thetaL, std::vector<float> &ru_v, const void *a_distribution);
1447
1448#endif //CANOPY_GENERATOR
@@ -1040,15 +1048,13 @@
void createElementLabels()
Create primitive data that explicitly labels all primitives according to the plant element they corre...
int selfTest()
Unit testing routine.
uint walnut(const WalnutCanopyParameters &params, const helios::vec3 &origin)
Function to add an individual walnut tree.
Definition walnut.cpp:333
-
Stores the state associated with simulation.
Definition Context.h:1882
-
Base struct class for Canopy parameters.
+
Stores the state associated with simulation.
Definition Context.h:1888
helios::vec3 canopy_origin
Cartesian (x,y,z) coordinate of the bottom center point of the canopy (i.e., specifying z=0 places th...
BaseCanopyParameters()
Default constructor.
virtual void buildCanopy(CanopyGenerator &canopy_generator)=0
Makes the given Canopy generator build a canopy of our type with our parameters.
void readParametersFromXML(const pugi::xml_node canopy_node)
Sets canopy parameters from the given XML node.
float canopy_rotation
Azimuthal rotation of the canopy about the canopy origin. Note that if canopy_rotation is not equal t...
virtual void buildPlant(CanopyGenerator &canopy_generator, helios::vec3 origin)=0
Makes the given Canopy generator build a single plant of our canopy type with our parameters at the g...
-
float plant_spacing
Spacing between adjacent plants along the row direction.
float shoot_radius_spread
Spread value for the shoot radius. With any new canopy or plant generation, the shoot radius would be...
float missing_plant_probability
Probability for a plant to be missing.
@@ -1123,7 +1129,7 @@
helios::RGBcolor leaf_color
Leaf color if no texture map file is provided.
std::string leaf_texture_file
Path to texture map file for leaves. If left empty, no texture will be used.
float crown_height
Height of the conical crowns.
-
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
+
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
void buildCanopy(CanopyGenerator &canopy_generator) override
Makes the given Canopy generator build a canopy of our type with our parameters.
std::string canopy_configuration
Specifies whether to use a uniformly spaced canopy (canopy_configuration="uniform") or a randomly arr...
helios::vec2 leaf_size
Length of leaf in x- and y- directions (prior to rotation)
@@ -1222,7 +1228,7 @@
std::string leaf_texture_file
Path to texture map file for leaves. If left empty, no texture will be used.
helios::RGBcolor leaf_color
Leaf color if no texture map file is provided.
helios::int2 plant_count
Number of crowns/plants in the x- and y-directions.
-
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
+
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
SphericalCrownsCanopyParameters()
Default constructor.
helios::int2 leaf_subdivisions
Number of sub-division segments per leaf.
std::string leaf_angle_distribution
Leaf angle distribution - one of "spherical", "uniform", "erectophile", "planophile",...
@@ -1314,7 +1320,7 @@
void readParametersFromXML(const pugi::xml_node canopy_node)
Sets canopy parameters from the given XML node.
void buildCanopy(CanopyGenerator &canopy_generator) override
Makes the given Canopy generator build a canopy of our type with our parameters.
std::string wood_texture_file
Path to texture map file for trunks/branches.
-
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
+
helios::vec2 plant_spacing
Spacing between adjacent crowns in the x- and y-directions. Note that if canopy_configuration='random...
float needle_length
Length of needles.
float trunk_height
Distance between the ground and top of trunks.
float level_spacing
Vertical spacing between branching levels.
@@ -1331,14 +1337,17 @@
int branches_per_level
Number of primary branches on the bottom level.
std::string canopy_configuration
Specifies whether to use a uniformly spaced canopy (canopy_configuration="uniform") or a randomly arr...
R-G-B color vector.
-
Vector of two elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_canopy_generator_doc.html b/doc/html/_canopy_generator_doc.html index d197a3a06..ccd1ae352 100644 --- a/doc/html/_canopy_generator_doc.html +++ b/doc/html/_canopy_generator_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Canopy Generator Plugin Documentation
@@ -954,10 +960,10 @@

}
-
Stores the state associated with simulation.
Definition Context.h:1882
-
Vector of two elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Stores the state associated with simulation.
Definition Context.h:1888
+
Vector of two elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.

Building an Individual Plant

Maximum flexibility in creating a canopy of plants is achieved by manually adding each individual plant. An example is given below to add a single grapevine plant on VSP trellis at the point (0,0,0).

@@ -1033,9 +1039,10 @@

// Modifying geometric parameters here
parameters.canopy_height = 2.0;
-
parameters.canopy_extent = make_vec2( 10.0, 10.0 );
+
parameters.canopy_extent = make_vec2( 10.0, 10.0 );
canopygenerator.buildCanopy( parameters );
+
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
Parameters defining the homogeneous canopy.

Seeding the Random Number Generator

@@ -1063,10 +1070,13 @@

}

- - + + diff --git a/doc/html/_carbohydrate_model_8cpp.html b/doc/html/_carbohydrate_model_8cpp.html index 9273d9a7f..55c7e674d 100644 --- a/doc/html/_carbohydrate_model_8cpp.html +++ b/doc/html/_carbohydrate_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
@@ -114,15 +120,17 @@ Variables float C_molecular_wt = 12.01   -float rho_w = 675000 +float rho_w = 650000   -float wood_carbon_percentage = .5 +float wood_carbon_percentage = .475   +float shoot_root_ratio = 10 +  float SLA = 1.75e-2   float leaf_carbon_percentage = .4444   -float total_flower_cost = 8.33e-3 +float total_flower_cost = 8.33e-4   float flower_production_cost = total_flower_cost*.69   @@ -147,7 +155,7 @@

Detailed Description

Definitions related to carbohydrate model calculations in the plant architecture plug-in.

-

Copyright (C) 2016-2025 Brian Bailey

+

Copyright (C) 2016-2024 Brian Bailey

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

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

@@ -181,7 +189,7 @@

-

Definition at line 35 of file CarbohydrateModel.cpp.

+

Definition at line 37 of file CarbohydrateModel.cpp.

@@ -197,7 +205,7 @@

-

Definition at line 34 of file CarbohydrateModel.cpp.

+

Definition at line 36 of file CarbohydrateModel.cpp.

@@ -213,7 +221,7 @@

-

Definition at line 44 of file CarbohydrateModel.cpp.

+

Definition at line 46 of file CarbohydrateModel.cpp.

@@ -229,7 +237,7 @@

-

Definition at line 42 of file CarbohydrateModel.cpp.

+

Definition at line 44 of file CarbohydrateModel.cpp.

@@ -245,7 +253,7 @@

-

Definition at line 30 of file CarbohydrateModel.cpp.

+

Definition at line 32 of file CarbohydrateModel.cpp.

@@ -261,7 +269,7 @@

-

Definition at line 45 of file CarbohydrateModel.cpp.

+

Definition at line 47 of file CarbohydrateModel.cpp.

@@ -277,7 +285,7 @@

-

Definition at line 38 of file CarbohydrateModel.cpp.

+

Definition at line 40 of file CarbohydrateModel.cpp.

@@ -293,7 +301,7 @@

-

Definition at line 41 of file CarbohydrateModel.cpp.

+

Definition at line 43 of file CarbohydrateModel.cpp.

@@ -309,7 +317,7 @@

-

Definition at line 39 of file CarbohydrateModel.cpp.

+

Definition at line 41 of file CarbohydrateModel.cpp.

@@ -325,7 +333,7 @@

-

Definition at line 40 of file CarbohydrateModel.cpp.

+

Definition at line 42 of file CarbohydrateModel.cpp.

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

- +
float rho_w = 675000float rho_w = 650000
+ + +

◆ shoot_root_ratio

+ +
+
+ + + + +
float shoot_root_ratio = 10
+
+ +

Definition at line 28 of file CarbohydrateModel.cpp.

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

-

Definition at line 29 of file CarbohydrateModel.cpp.

+

Definition at line 31 of file CarbohydrateModel.cpp.

@@ -384,12 +408,12 @@

- +
float total_flower_cost = 8.33e-3float total_flower_cost = 8.33e-4
@@ -400,7 +424,7 @@

- +
float wood_carbon_percentage = .5float wood_carbon_percentage = .475
+ + diff --git a/doc/html/_carbohydrate_model_8cpp_source.html b/doc/html/_carbohydrate_model_8cpp_source.html index 4f9d0d07d..f9fcb1692 100644 --- a/doc/html/_carbohydrate_model_8cpp_source.html +++ b/doc/html/_carbohydrate_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
CarbohydrateModel.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "PlantArchitecture.h"
17
18using namespace helios;
@@ -114,29 +121,29 @@
22float C_molecular_wt = 12.01; //g C mol^-1
23
24
-
25float rho_w = 675000; //Almond wood density (g m^-3)
-
26float wood_carbon_percentage = .5; //portion of the dry weight of the wood made up by carbon
+
25float rho_w = 650000; //Almond wood density (g m^-3)
+
26float wood_carbon_percentage = .475; //portion of the dry weight of the wood made up by carbon
27
-
28
-
29float SLA = 1.75e-2; //ratio of leaf area to leaf dry mass m^2 / g DW
-
30float leaf_carbon_percentage = .4444; //portion of the dry weight of the leaf made up by carbon
-
31
-
32
-
33float total_flower_cost = 8.33e-3; //mol C flower^-1 (Bustan & Goldschmidt 2002)
-
34float flower_production_cost = total_flower_cost*.69; //mol C flower^-1 (Bustan & Goldschmidt 2002)
-
35float flower_growth_respiration = total_flower_cost*.31; //mol C flower^-1 (Bustan & Goldschmidt 2002)
-
36
-
37
-
38float nut_density = 525000; //g m^-3
-
39float percent_kernel = .27; //portion of the nut made up by the kernel
-
40float percent_shell = .19; //portion of the nut made up by the shell
-
41float percent_hull = .54; //portion of the nut made up by the hull
-
42float kernel_carbon_percentage = .454; //portion of the kernel made up by carbon by dry weight
-
43float shell_carbon_percentage = .470; //portion of the shell made up by caron by dry weight
-
44float hull_carbon_percentage = .494; //portion of the hull made up by carbon by dry weight
-
45float nut_carbon_percentage = percent_kernel*kernel_carbon_percentage + percent_shell*shell_carbon_percentage + percent_hull*hull_carbon_percentage; //overall portion of the nut made up by carbon by dry weight
-
46
-
47
+
28float shoot_root_ratio = 10;
+
29
+
30
+
31float SLA = 1.75e-2; //ratio of leaf area to leaf dry mass m^2 / g DW
+
32float leaf_carbon_percentage = .4444; //portion of the dry weight of the leaf made up by carbon
+
33
+
34
+
35float total_flower_cost = 8.33e-4; //mol C flower^-1 (Bustan & Goldschmidt 2002)
+
36float flower_production_cost = total_flower_cost*.69; //mol C flower^-1 (Bustan & Goldschmidt 2002)
+
37float flower_growth_respiration = total_flower_cost*.31; //mol C flower^-1 (Bustan & Goldschmidt 2002)
+
38
+
39
+
40float nut_density = 525000; //g m^-3
+
41float percent_kernel = .27; //portion of the nut made up by the kernel
+
42float percent_shell = .19; //portion of the nut made up by the shell
+
43float percent_hull = .54; //portion of the nut made up by the hull
+
44float kernel_carbon_percentage = .454; //portion of the kernel made up by carbon by dry weight
+
45float shell_carbon_percentage = .470; //portion of the shell made up by caron by dry weight
+
46float hull_carbon_percentage = .494; //portion of the hull made up by carbon by dry weight
+
47float nut_carbon_percentage = percent_kernel*kernel_carbon_percentage + percent_shell*shell_carbon_percentage + percent_hull*hull_carbon_percentage; //overall portion of the nut made up by carbon by dry weight
48
49
50
@@ -144,355 +151,495 @@
52
53
54
-
55float Phytomer::calculatePhytomerConstructionCosts(){
+
55
56
-
57 //\todo make these values externally settable
-
58 float leaf_construction_cost_base = leaf_carbon_percentage/(C_molecular_wt*SLA); //mol C/m^2
-
59 float internode_construction_cost_base = rho_w * wood_carbon_percentage / C_molecular_wt; // (mol C /m^3)
-
60
-
61 float phytomer_carbon_cost = 0.f; //mol C
+
57float Phytomer::calculatePhytomerConstructionCosts(){
+
58
+
59 //\todo make these values externally settable
+
60 float leaf_construction_cost_base = leaf_carbon_percentage/(C_molecular_wt*SLA); //mol C/m^2
+
61 float internode_construction_cost_base = rho_w * wood_carbon_percentage / C_molecular_wt; // (mol C /m^3)
62
-
63 //leaves (cost per area basis)
-
64 float leaf_area = 0;
-
65 for( const auto &petiole : leaf_objIDs ) {
-
66 for( uint leaf_objID : petiole ) {
-
67 leaf_area += context_ptr->getObjectArea(leaf_objID);
-
68 }
-
69 }
-
70 leaf_area /= current_leaf_scale_factor; //convert to fully-expanded area
-
71 phytomer_carbon_cost += leaf_construction_cost_base*leaf_area;
-
72
-
73 //internode (cost per volume basis)
-
74 float internode_volume = 0;
-
75 uint start_ind = shoot_index.x*phytomer_parameters.internode.length_segments;
-
76 for( int segment = start_ind; segment<start_ind+phytomer_parameters.internode.length_segments; segment++ ){
-
77 internode_volume += context_ptr->getTubeObjectSegmentVolume( parent_shoot_ptr->internode_tube_objID, segment );
-
78 }
-
79 internode_volume /= current_internode_scale_factor; //convert to fully-elongated volume
-
80 phytomer_carbon_cost += internode_construction_cost_base*internode_volume;
-
81
-
82 return phytomer_carbon_cost;
-
83
-
84}
-
85
-
86float Phytomer::calculateFlowerConstructionCosts(const FloralBud &fbud) {
-
87
-
88 //\todo make these values externally settable
-
89 float flower_construction_cost_base = 8.33e-3; //mol C/flower (Bustan & Goldschmidt 2002)
-
90
-
91 float flower_carbon_cost = 0.f; //mol C
-
92
-
93 for( uint flower_objID : fbud.inflorescence_objIDs ) {
-
94 flower_carbon_cost += flower_construction_cost_base;
-
95 }
-
96
-
97 return flower_carbon_cost;
-
98}
-
99
-
100void PlantArchitecture::initializePlantCarbohydratePool(uint plantID, float carbohydrate_concentration_molC_m3 ){
-
101
-
102 if( plant_instances.find(plantID) == plant_instances.end() ){
-
103 helios_runtime_error("ERROR (PlantArchitecture::initializePlantCarbohydratePool): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
104 }else if( carbohydrate_concentration_molC_m3 < 0 ){
-
105 helios_runtime_error("ERROR (PlantArchitecture::initializePlantCarbohydratePool): Carbohydrate concentration must be greater than or equal to zero.");
-
106 }
+
63 float phytomer_carbon_cost = 0.f; //mol C
+
64
+
65 //leaves (cost per area basis)
+
66 float leaf_area = 0;
+
67 for( const auto &petiole : leaf_objIDs ) {
+
68 for( uint leaf_objID : petiole ) {
+
69 leaf_area += context_ptr->getObjectArea(leaf_objID);
+
70 }
+
71 }
+
72 phytomer_carbon_cost += leaf_construction_cost_base*leaf_area;
+
73
+
74 return phytomer_carbon_cost;
+
75
+
76}
+
77
+
78float Phytomer::calculateFlowerConstructionCosts(const FloralBud &fbud) {
+
79
+
80 //\todo make these values externally settable
+
81 float flower_construction_cost_base = 8.33e-3; //mol C/flower (Bustan & Goldschmidt 2002)
+
82
+
83 float flower_carbon_cost = 0.f; //mol C
+
84
+
85 for( uint flower_objID : fbud.inflorescence_objIDs ) {
+
86 flower_carbon_cost += flower_construction_cost_base;
+
87 }
+
88
+
89 return flower_carbon_cost;
+
90}
+
91
+
92void PlantArchitecture::initializeCarbohydratePool(float carbohydrate_concentration_molC_m3){
+
93
+
94 for( auto &plant: plant_instances ) {
+
95
+
96 auto shoot_tree = &plant.second.shoot_tree;
+
97
+
98 for (auto &shoot: *shoot_tree) {
+
99 //calculate shoot volume
+
100 float shoot_volume = shoot->calculateShootInternodeVolume();
+
101 //set carbon pool
+
102 shoot->carbohydrate_pool_molC = shoot_volume * carbohydrate_concentration_molC_m3;
+
103
+
104 }
+
105 }
+
106}
107
-
108 //loop over all shoots
-
109 for( auto &shoot : plant_instances.at(plantID).shoot_tree ) {
-
110 initializeShootCarbohydratePool(plantID, shoot->ID, carbohydrate_concentration_molC_m3);
-
111 }
-
112
-
113}
-
114
-
115void PlantArchitecture::initializeShootCarbohydratePool(uint plantID, uint shootID, float carbohydrate_concentration_molC_m3 ){
-
116
-
117 if( plant_instances.find(plantID) == plant_instances.end() ){
-
118 helios_runtime_error("ERROR (PlantArchitecture::initializeShootCarbohydratePool): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
119 }else if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
-
120 helios_runtime_error("ERROR (PlantArchitecture::initializeShootCarbohydratePool): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
-
121 }else if( carbohydrate_concentration_molC_m3 < 0 ){
-
122 helios_runtime_error("ERROR (PlantArchitecture::initializeShootCarbohydratePool): Carbohydrate concentration must be greater than or equal to zero.");
-
123 }
+
108void PlantArchitecture::initializePlantCarbohydratePool(uint plantID, float carbohydrate_concentration_molC_m3 ){
+
109
+
110 if( plant_instances.find(plantID) == plant_instances.end() ){
+
111 helios_runtime_error("ERROR (PlantArchitecture::initializePlantCarbohydratePool): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
112 }else if( carbohydrate_concentration_molC_m3 < 0 ){
+
113 helios_runtime_error("ERROR (PlantArchitecture::initializePlantCarbohydratePool): Carbohydrate concentration must be greater than or equal to zero.");
+
114 }
+
115
+
116 //loop over all shoots
+
117 for( auto &shoot : plant_instances.at(plantID).shoot_tree ) {
+
118 initializeShootCarbohydratePool(plantID, shoot->ID, carbohydrate_concentration_molC_m3);
+
119 }
+
120
+
121}
+
122
+
123void PlantArchitecture::initializeShootCarbohydratePool(uint plantID, uint shootID, float carbohydrate_concentration_molC_m3 ){
124
-
125 //calculate shoot volume
-
126 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume();
-
127
-
128 //set carbon pool
-
129 plant_instances.at(plantID).shoot_tree.at(shootID)->carbohydrate_pool_molC = shoot_volume * carbohydrate_concentration_molC_m3;
-
130
-
131}
+
125 if( plant_instances.find(plantID) == plant_instances.end() ){
+
126 helios_runtime_error("ERROR (PlantArchitecture::initializeShootCarbohydratePool): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
127 }else if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
128 helios_runtime_error("ERROR (PlantArchitecture::initializeShootCarbohydratePool): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
129 }else if( carbohydrate_concentration_molC_m3 < 0 ){
+
130 helios_runtime_error("ERROR (PlantArchitecture::initializeShootCarbohydratePool): Carbohydrate concentration must be greater than or equal to zero.");
+
131 }
132
-
133void PlantArchitecture::accumulateHourlyLeafPhotosynthesis() {
-
134
-
135 for( auto &plant: plant_instances ){
-
136
-
137 auto shoot_tree = &plant.second.shoot_tree;
+
133 //calculate shoot volume
+
134 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume();
+
135
+
136 //set carbon pool
+
137 plant_instances.at(plantID).shoot_tree.at(shootID)->carbohydrate_pool_molC = shoot_volume * carbohydrate_concentration_molC_m3;
138
-
139 for( auto &shoot: *shoot_tree ){
+
139}
140
-
141 for( auto &phytomer: shoot->phytomers ){
+
141void PlantArchitecture::accumulateHourlyLeafPhotosynthesis() {
142
-
143 for( auto &leaf_objID: flatten(phytomer->leaf_objIDs) ){
-
144 for( uint UUID : context_ptr->getObjectPrimitiveUUIDs(leaf_objID) ){
-
145 float lUUID_area = context_ptr->getPrimitiveArea(UUID);
-
146 float leaf_A;
-
147 context_ptr->getPrimitiveData(UUID,"net_photosynthesis", leaf_A);
-
148 //std::cout<< "leaf photosynthesis mol C: "<< leaf_A<<std::endl;
-
149
-
150 float new_hourly_photo = leaf_A * lUUID_area * 3600*1e-6; //hourly net photosynthesis (mol C) from umol CO2 m-2 sec-1
-
151 //std::cout<< "hourly photosynthesis mol C: "<< new_hourly_photo<<std::endl;
-
152 float current_net_photo;
-
153
-
154 context_ptr->getPrimitiveData(UUID,"cumulative_net_photosynthesis", current_net_photo);
-
155 current_net_photo += new_hourly_photo;
-
156 context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", current_net_photo);
-
157 //std::cout<< "net photo mol C: "<< current_net_photo<<std::endl;
-
158
-
159 }
-
160 }
-
161
-
162 }
-
163
-
164 }
-
165
-
166 }
-
167
-
168
-
169}
+
143 for( auto &plant: plant_instances ){
+
144
+
145 auto shoot_tree = &plant.second.shoot_tree;
+
146
+
147 for( auto &shoot: *shoot_tree ){
+
148
+
149 if(shoot->isdormant) {
+
150 for( auto &phytomer: shoot->phytomers ){
+
151 for( auto &leaf_objID: flatten(phytomer->leaf_objIDs) ) {
+
152 for (uint UUID: context_ptr->getObjectPrimitiveUUIDs(leaf_objID)) {
+
153 context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", 0);
+
154 }
+
155 }
+
156 }
+
157 }else{
+
158 for( auto &phytomer: shoot->phytomers ){
+
159
+
160 for( auto &leaf_objID: flatten(phytomer->leaf_objIDs) ){
+
161 for( uint UUID : context_ptr->getObjectPrimitiveUUIDs(leaf_objID) ){
+
162 float lUUID_area = context_ptr->getPrimitiveArea(UUID);
+
163 float leaf_A;
+
164 context_ptr->getPrimitiveData(UUID,"net_photosynthesis", leaf_A);
+
165 //std::cout<< "leaf photosynthesis mol C: "<< leaf_A<<std::endl;
+
166
+
167 float new_hourly_photo = leaf_A * lUUID_area * 3600*1e-6; //hourly net photosynthesis (mol C) from umol CO2 m-2 sec-1
+
168 //std::cout<< "hourly photosynthesis mol C: "<< new_hourly_photo<<std::endl;
+
169 float current_net_photo;
170
-
171void PlantArchitecture::accumulateShootPhotosynthesis() {
-
172
-
173 uint A_prim_data_missing = 0;
-
174
-
175 for( auto &plant: plant_instances ){
-
176
-
177 auto shoot_tree = &plant.second.shoot_tree;
+
171 context_ptr->getPrimitiveData(UUID,"cumulative_net_photosynthesis", current_net_photo);
+
172 current_net_photo += new_hourly_photo;
+
173 context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", current_net_photo);
+
174 //std::cout<< "net photo mol C: "<< current_net_photo<<std::endl;
+
175
+
176 }
+
177 }
178
-
179 for( auto &shoot: *shoot_tree ){
+
179 }
180
-
181 float net_photosynthesis = 0;
+
181 }
182
-
183 for( auto &phytomer: shoot->phytomers ){
+
183 }
184
-
185 for( auto &leaf_objID: flatten(phytomer->leaf_objIDs) ){
-
186 for( uint UUID : context_ptr->getObjectPrimitiveUUIDs(leaf_objID) ){
-
187 if( context_ptr->doesPrimitiveDataExist(UUID, "cumulative_net_photosynthesis") && context_ptr->getPrimitiveDataType(UUID,"cumulative_net_photosynthesis")==HELIOS_TYPE_FLOAT ){
-
188 float A;
-
189 context_ptr->getPrimitiveData(UUID,"cumulative_net_photosynthesis",A);
-
190 net_photosynthesis += A;
-
191 context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", 0.f);
-
192 }else{
-
193 A_prim_data_missing++;
-
194 context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", 0.f);
-
195 }
-
196 }
-
197 }
-
198
-
199 }
-
200
-
201 shoot->carbohydrate_pool_molC += net_photosynthesis;
-
202
-
203 }
-
204
-
205 }
-
206
-
207 if( A_prim_data_missing>0 ){
-
208 std::cerr << "WARNING (PlantArchitecture::accumulateShootPhotosynthesis): " << A_prim_data_missing << " leaf primitives were missing net_photosynthesis primitive data. Did you run the photosynthesis model?" << std::endl;
-
209 }
-
210
-
211}
-
212
-
213void PlantArchitecture::subtractShootMaintenanceCarbon(float dt ) {
-
214
-
215 //\todo move to externally settable parameter
-
216 float stem_maintainance_respiration_rate = 1.9458e-05 * 1.341641; //mol C respired/mol C in pool/day
-
217 float root_maintainance_respiration_rate = 9.139e-04 * 1.341641; //mol C respired/mol C in pool/day
-
218
-
219 float rho_cw = rho_w * wood_carbon_percentage / C_molecular_wt; //Density of carbon in almond wood (mol C m^-3)
-
220
-
221
-
222 for (auto &plant: plant_instances) {
-
223
-
224 auto shoot_tree = &plant.second.shoot_tree;
-
225
-
226 for (auto &shoot: *shoot_tree) {
-
227 if( context_ptr->doesObjectExist(shoot->internode_tube_objID) ) {
-
228 shoot->carbohydrate_pool_molC -= context_ptr->getTubeObjectVolume(shoot->internode_tube_objID) * rho_cw * stem_maintainance_respiration_rate * dt; //remove shoot maintenance respiration
-
229 shoot->carbohydrate_pool_molC -= context_ptr->getTubeObjectVolume(shoot->internode_tube_objID) * rho_cw * .2 / .76 * root_maintainance_respiration_rate * dt; //remove root maintenance respiration portion
-
230 }
-
231 }
+
185 }
+
186
+
187
+
188}
+
189
+
190void PlantArchitecture::accumulateShootPhotosynthesis() {
+
191
+
192 uint A_prim_data_missing = 0;
+
193
+
194 for( auto &plant: plant_instances ){
+
195
+
196 auto shoot_tree = &plant.second.shoot_tree;
+
197
+
198 for( auto &shoot: *shoot_tree ){
+
199
+
200 float net_photosynthesis = 0;
+
201
+
202 for( auto &phytomer: shoot->phytomers ){
+
203
+
204 for( auto &leaf_objID: flatten(phytomer->leaf_objIDs) ){
+
205 for( uint UUID : context_ptr->getObjectPrimitiveUUIDs(leaf_objID) ){
+
206 if( context_ptr->doesPrimitiveDataExist(UUID, "cumulative_net_photosynthesis") && context_ptr->getPrimitiveDataType(UUID,"cumulative_net_photosynthesis")==HELIOS_TYPE_FLOAT ){
+
207 float A;
+
208 context_ptr->getPrimitiveData(UUID,"cumulative_net_photosynthesis",A);
+
209 net_photosynthesis += A;
+
210 context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", 0.f);
+
211 }else{
+
212 A_prim_data_missing++;
+
213 context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", 0.f);
+
214 }
+
215 }
+
216 }
+
217
+
218 }
+
219
+
220 shoot->carbohydrate_pool_molC += net_photosynthesis;
+
221 //std::cout<< "Net photosynthesis"<< net_photosynthesis<<std::endl;
+
222
+
223 }
+
224
+
225 }
+
226
+
227 if( A_prim_data_missing>0 ){
+
228 std::cerr << "WARNING (PlantArchitecture::accumulateShootPhotosynthesis): " << A_prim_data_missing << " leaf primitives were missing net_photosynthesis primitive data. Did you run the photosynthesis model?" << std::endl;
+
229 }
+
230
+
231}
232
-
233 }
+
233void PlantArchitecture::subtractShootMaintenanceCarbon(float dt ) {
234
-
235}
-
236
-
237void PlantArchitecture::subtractShootGrowthCarbon(){
+
235 //\todo move to externally settable parameter
+
236 float stem_maintainance_respiration_rate = 1.9458e-05; //mol C respired/mol C in pool/day
+
237 float root_maintainance_respiration_rate = 9.139e-06 * 1.341641/shoot_root_ratio; //mol C respired/mol C in pool/day
238
-
239 //\todo move to externally settable parameter
-
240 float rho_cw = rho_w * 0.5 / 12.01; //Density of carbon in almond wood (mol C m^-3)
-
241 float growth_respiration_fraction = 0.28; //Accounting for the growth carbon lost to respiration (assumed 28%)
-
242
+
239 float rho_cw = rho_w * wood_carbon_percentage / C_molecular_wt; //Density of carbon in almond wood (mol C m^-3)
+
240
+
241
+
242 for (auto &plant: plant_instances) {
243
-
244 for( auto &plant: plant_instances ){
+
244 auto shoot_tree = &plant.second.shoot_tree;
245
-
246 uint plantID = plant.first;
-
247 auto shoot_tree = &plant.second.shoot_tree;
-
248
-
249 for( auto &shoot: *shoot_tree ){
-
250 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shoot->ID)->calculateShootInternodeVolume();
-
251
-
252 float shoot_growth_carbon_demand = rho_cw*( shoot_volume - shoot->old_shoot_volume) / (1-growth_respiration_fraction); //Structural carbon + growth respiration required to construct new shoot volume
-
253 shoot->carbohydrate_pool_molC -= shoot_growth_carbon_demand; //Subtract construction carbon + growth respiration from the carbon pool
-
254 shoot->old_shoot_volume = shoot_volume; //Set old volume to the current volume for the next timestep
-
255
-
256 context_ptr->setObjectData( shoot->internode_tube_objID, "carbohydrate_concentration", shoot->carbohydrate_pool_molC / shoot_volume );
-
257
-
258 }
-
259
-
260 }
-
261
-
262}
+
246 for (auto &shoot: *shoot_tree) {
+
247 if( context_ptr->doesObjectExist(shoot->internode_tube_objID) ) {
+
248 if(shoot->isdormant) {
+
249 shoot->carbohydrate_pool_molC -=
+
250 shoot->old_shoot_volume * rho_cw *
+
251 stem_maintainance_respiration_rate * .2 * dt; //remove shoot maintenance respiration
+
252 }else{
+
253 shoot->carbohydrate_pool_molC -=
+
254 shoot->old_shoot_volume * rho_cw *
+
255 stem_maintainance_respiration_rate * dt; //remove shoot maintenance respiration
+
256 //std::cout << "shoot stem maintenance: " << context_ptr->getTubeObjectVolume(shoot->internode_tube_objID) * rho_cw * stem_maintainance_respiration_rate * dt << std::endl;
+
257 shoot->carbohydrate_pool_molC -=
+
258 shoot->old_shoot_volume * rho_cw * .2 / .76 * root_maintainance_respiration_rate * dt; //remove root maintenance respiration portion
+
259 //std::cout << "shoot root maintenance: " << context_ptr->getTubeObjectVolume(shoot->internode_tube_objID) * rho_cw * .2 / .76 * root_maintainance_respiration_rate * dt << std::endl;
+
260 }
+
261 }
+
262 }
263
-
264
-
265float Phytomer::calculateFruitConstructionCosts(const FloralBud &fbud) {
-
266
-
267 //\todo make these values externally settable
-
268 float fruit_construction_cost_base = nut_density*nut_carbon_percentage/C_molecular_wt; //mol C/m^3
+
264 }
+
265
+
266}
+
267
+
268void PlantArchitecture::subtractShootGrowthCarbon(){
269
-
270 float fruit_carbon_cost = 0.f; //mol C
-
271
-
272 //fruit (cost per fruit basis)
-
273 for( uint fruit_objID : fbud.inflorescence_objIDs ) {
-
274 float mature_volume = context_ptr->getPolymeshObjectVolume(fruit_objID)/fbud.current_fruit_scale_factor; //mature fruit volume
-
275 fruit_carbon_cost += fruit_construction_cost_base*(mature_volume)*(fbud.current_fruit_scale_factor - fbud.previous_fruit_scale_factor);
-
276 }
-
277
-
278 return fruit_carbon_cost;
-
279}
-
280
-
281void PlantArchitecture::checkCarbonPool_abortbuds(){
-
282 float carbohydrate_threshold = 10; //mol C/m3
-
283 float day_threshold = 5;
-
284 float storage_conductance = 0.5;
-
285
-
286 //\todo make these values externally settable
-
287 float fruit_construction_cost_base = 29021; //mol C/m^3
-
288
-
289 for( auto &plant: plant_instances ){
+
270 //\todo move to externally settable parameter
+
271 float rho_cw = rho_w * wood_carbon_percentage / C_molecular_wt; //Density of carbon in almond wood (mol C m^-3)
+
272 float growth_respiration_fraction = 0.28; //Accounting for the growth carbon lost to respiration (assumed 28%)
+
273
+
274
+
275 for( auto &plant: plant_instances ){
+
276
+
277 uint plantID = plant.first;
+
278 auto shoot_tree = &plant.second.shoot_tree;
+
279
+
280 for( auto &shoot: *shoot_tree ){
+
281 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shoot->ID)->calculateShootInternodeVolume();
+
282
+
283 float shoot_growth_carbon_demand = rho_cw*( shoot_volume - shoot->old_shoot_volume) * 0.5 * (1+growth_respiration_fraction); //Structural carbon + growth respiration required to construct new shoot volume
+
284 shoot->carbohydrate_pool_molC -= shoot_growth_carbon_demand; //Subtract construction carbon + growth respiration from the carbon pool
+
285 //std::cout<<shoot->old_shoot_volume<<" old shoot volume"<<std::endl;
+
286 shoot->old_shoot_volume = shoot_volume; //Set old volume to the current volume for the next timestep
+
287
+
288 std::cout<<"shoot growth demand: " << shoot_growth_carbon_demand<< std::endl;
+
289 std::cout<<"shoot carbohydrate pool mol C: " << shoot->carbohydrate_pool_molC<< std::endl;
290
-
291 uint plantID = plant.first;
-
292 auto shoot_tree = &plant.second.shoot_tree;
-
293 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
-
294
-
295 for( auto &shoot: *shoot_tree ){
-
296
-
297 uint shootID = shoot->ID;
-
298
-
299 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume();
-
300 float working_carb_pool = shoot->carbohydrate_pool_molC;
-
301 uint parentID = shoot->parent_shoot_ID;
+
291 context_ptr->setObjectData( shoot->internode_tube_objID, "carbohydrate_concentration", shoot->carbohydrate_pool_molC / shoot_volume );
+
292
+
293 std::cout<<"Shoot Carbohydate Concentration (mg/g dry weight): "<<(shoot->carbohydrate_pool_molC*12.01*1000) / (shoot_volume*rho_w)<<std::endl;
+
294 std::cout<<"ID "<<shoot->ID<<std::endl;
+
295
+
296 }
+
297
+
298 }
+
299
+
300}
+
301
302
-
303 if(shoot->carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume){
-
304 if(parentID <1000000){
-
305 shoot_tree_ptr->at(parentID)->carbohydrate_pool_molC += (shoot->carbohydrate_pool_molC - carbohydrate_threshold*shoot_volume)*storage_conductance;
-
306 shoot->carbohydrate_pool_molC -= (shoot->carbohydrate_pool_molC - carbohydrate_threshold*shoot_volume)*storage_conductance;
-
307 shoot->days_with_negative_carbon_balance = 0;
-
308 goto shoot_balanced;
-
309 }else{
-
310 shoot->days_with_negative_carbon_balance = 0;
-
311 goto shoot_balanced;
-
312 }
-
313
-
314
-
315 }else if(shoot->days_with_negative_carbon_balance < day_threshold){
-
316 shoot->days_with_negative_carbon_balance += 1;
-
317 }else if(shoot->days_with_negative_carbon_balance >= day_threshold) {
+
303float Phytomer::calculateFruitConstructionCosts(const FloralBud &fbud) {
+
304
+
305 //\todo make these values externally settable
+
306 float fruit_construction_cost_base = nut_density*nut_carbon_percentage/C_molecular_wt; //mol C/m^3
+
307
+
308 float fruit_carbon_cost = 0.f; //mol C
+
309
+
310 //fruit (cost per fruit basis)
+
311 for( uint fruit_objID : fbud.inflorescence_objIDs ) {
+
312 float mature_volume = context_ptr->getPolymeshObjectVolume(fruit_objID)/fbud.current_fruit_scale_factor; //mature fruit volume
+
313 fruit_carbon_cost += fruit_construction_cost_base*(mature_volume)*(fbud.current_fruit_scale_factor - fbud.previous_fruit_scale_factor);
+
314 }
+
315
+
316 return fruit_carbon_cost;
+
317}
318
-
319 auto phytomers = &shoot->phytomers;
-
320
-
321 bool living_buds = true;
+
319void PlantArchitecture::checkCarbonPool_abortBuds(){
+
320 float carbohydrate_threshold = 75*rho_w/(1000*C_molecular_wt); //mol C/m3
+
321 float day_threshold = 5;
322
-
323 while (living_buds) {
-
324
-
325 living_buds = false;
-
326
-
327 for (auto &phytomer: *phytomers) {
-
328 bool next_phytomer = false;
-
329
-
330
-
331 for (auto &petiole: phytomer->floral_buds) {
-
332 bool next_petiole = false;
+
323 //\todo make these values externally settable
+
324 float fruit_construction_cost_base = 29021; //mol C/m^3
+
325
+
326 for( auto &plant: plant_instances ){
+
327
+
328 uint plantID = plant.first;
+
329 auto shoot_tree = &plant.second.shoot_tree;
+
330 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
331
+
332 for( auto &shoot: *shoot_tree ){
333
-
334 if(next_phytomer){
-
335 break;
-
336 }else{
-
337 for (auto &fbud: petiole) {
-
338
-
339 if (next_petiole){
-
340 break;
-
341 }else{
-
342 if (fbud.state != BUD_DORMANT && fbud.state != BUD_DEAD) {
-
343 for (uint fruit_objID: fbud.inflorescence_objIDs) {
-
344 float mature_volume = context_ptr->getPolymeshObjectVolume(fruit_objID) /
-
345 fbud.current_fruit_scale_factor; //mature fruit volume
-
346 working_carb_pool += fruit_construction_cost_base * (mature_volume) *
-
347 (fbud.current_fruit_scale_factor -
-
348 fbud.previous_fruit_scale_factor);
-
349 }
-
350 phytomer->setFloralBudState(BUD_DEAD, fbud); //Kill a floral bud to eliminate it as a future sink
+
334 uint shootID = shoot->ID;
+
335
+
336 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume();
+
337 float working_carb_pool = shoot->carbohydrate_pool_molC;
+
338 uint parentID = shoot->parent_shoot_ID;
+
339
+
340 if(shoot->carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume){
+
341 if(parentID <1000000){
+
342 shoot->days_with_negative_carbon_balance = 0;
+
343 goto shoot_balanced;
+
344 }
+
345
+
346 }else if(shoot->days_with_negative_carbon_balance < day_threshold){
+
347 shoot->days_with_negative_carbon_balance += 1;
+
348 }else if(shoot->days_with_negative_carbon_balance >= day_threshold) {
+
349
+
350 auto phytomers = &shoot->phytomers;
351
-
352 if (working_carb_pool > carbohydrate_threshold) {
-
353 goto shoot_balanced;
-
354 } //If the amount of carbon you've eliminated by aborting flower buds would have given you a positive carbon balance, move on to the next shoot
+
352 bool living_buds = true;
+
353
+
354 while (living_buds) {
355
-
356 living_buds = true; //There was at least one living bud, so stay in the loop until there aren't any more
-
357 next_petiole = true; //As soon as you've eliminated one bud from a given petiole, move to the next one
-
358 next_phytomer = true; //As soon as you've eliminated one bud from a given phytomer, move to the next one
-
359 }
+
356 living_buds = false;
+
357
+
358 for (auto &phytomer: *phytomers) {
+
359 bool next_phytomer = false;
360
-
361 }
-
362
-
363 }
+
361
+
362 for (auto &petiole: phytomer->floral_buds) {
+
363 bool next_petiole = false;
364
-
365 }
-
366
-
367 }
-
368
-
369 }
-
370
-
371 }
-
372
-
373 }
-
374 shoot_balanced:
-
375 ; //empty statement after the label to avoid a compiler warning
-
376 }
-
377
-
378 }
-
379
-
380}
+
365 if(next_phytomer){
+
366 break;
+
367 }else{
+
368 for (auto &fbud: petiole) {
+
369
+
370 if (next_petiole){
+
371 break;
+
372 }else{
+
373 if (fbud.state != BUD_DORMANT && fbud.state != BUD_DEAD) {
+
374 for (uint fruit_objID: fbud.inflorescence_objIDs) {
+
375 float mature_volume = context_ptr->getPolymeshObjectVolume(fruit_objID) /
+
376 fbud.current_fruit_scale_factor; //mature fruit volume
+
377 working_carb_pool += fruit_construction_cost_base * (mature_volume) *
+
378 (fbud.current_fruit_scale_factor -
+
379 fbud.previous_fruit_scale_factor);
+
380 }
+
381 phytomer->setFloralBudState(BUD_DEAD, fbud); //Kill a floral bud to eliminate it as a future sink
+
382
+
383 if (working_carb_pool > carbohydrate_threshold) {
+
384 goto shoot_balanced;
+
385 } //If the amount of carbon you've eliminated by aborting flower buds would have given you a positive carbon balance, move on to the next shoot
+
386
+
387 living_buds = true; //There was at least one living bud, so stay in the loop until there aren't any more
+
388 next_petiole = true; //As soon as you've eliminated one bud from a given petiole, move to the next one
+
389 next_phytomer = true; //As soon as you've eliminated one bud from a given phytomer, move to the next one
+
390 }
+
391
+
392 }
+
393
+
394 }
+
395
+
396 }
+
397
+
398 }
+
399
+
400 }
+
401
+
402 }
+
403
+
404 }
+
405 shoot_balanced:
+
406 ; //empty statement after the label to avoid a compiler warning
+
407 }
+
408
+
409 }
+
410
+
411}
+
412
+
413
+
414void PlantArchitecture::checkCarbonPool_adjustPhyllochron(){
+
415 float carbohydrate_threshold = 150*rho_w/(1000*C_molecular_wt); //mol C/m3
+
416 float carbohydrate_threshold_low = 50*rho_w/(1000*C_molecular_wt); //mol C/m3
+
417
+
418 for( auto &plant: plant_instances ){
+
419
+
420 uint plantID = plant.first;
+
421 auto shoot_tree = &plant.second.shoot_tree;
+
422 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
423
+
424 for( auto &shoot: *shoot_tree ){
+
425
+
426 uint shootID = shoot->ID;
+
427
+
428 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume();
+
429 float working_carb_pool = shoot->carbohydrate_pool_molC;
+
430 uint parentID = shoot->parent_shoot_ID;
+
431
+
432 if(shoot->carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume){
+
433 if(shoot->phyllochron_instantaneous > shoot->shoot_parameters.phyllochron_min.val() * shoot->phyllochron_recovery){
+
434 shoot->phyllochron_instantaneous = shoot->phyllochron_instantaneous / shoot->phyllochron_recovery;
+
435 }else{
+
436 shoot->phyllochron_instantaneous = shoot->shoot_parameters.phyllochron_min.val();
+
437 }
+
438
+
439 if(shoot->elongation_rate_instantaneous < shoot->shoot_parameters.elongation_rate_max.val() * shoot->elongation_recovery){
+
440 shoot->elongation_rate_instantaneous = shoot->elongation_rate_instantaneous / shoot->elongation_recovery;
+
441 }else{
+
442 shoot->elongation_rate_instantaneous = shoot->shoot_parameters.elongation_rate_max.val();
+
443 }
+
444
+
445 }else if (shoot->carbohydrate_pool_molC < carbohydrate_threshold_low*shoot_volume) {
+
446 shoot->elongation_rate_instantaneous = shoot->shoot_parameters.phyllochron_min.val() * 20;
+
447 shoot->phyllochron_instantaneous = 100;
+
448
+
449 }else{
+
450 if(shoot->phyllochron_instantaneous <= shoot->shoot_parameters.phyllochron_min.val() * 20){
+
451 shoot->phyllochron_instantaneous = shoot->phyllochron_instantaneous * shoot->phyllochron_increase;
+
452 }
+
453 if(shoot->elongation_rate_instantaneous >= shoot->shoot_parameters.elongation_rate_max.val()*0.005){
+
454 shoot->elongation_rate_instantaneous = shoot->elongation_rate_instantaneous * shoot->elongation_decay;
+
455 }
+
456 }
+
457
+
458 }
+
459
+
460 }
+
461
+
462}
+
463
+
464void PlantArchitecture::checkCarbonPool_transferCarbon(){
+
465 float carbohydrate_threshold = 50*rho_w/(1000*C_molecular_wt); //mol C/m3
+
466 float storage_conductance = 0.25;
+
467 float return_conductance = 0.25;
+
468
+
469 for( auto &plant: plant_instances ){
+
470
+
471 uint plantID = plant.first;
+
472 auto shoot_tree = &plant.second.shoot_tree;
+
473 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
474
+
475 for( auto &shoot: *shoot_tree ){
+
476
+
477 uint shootID = shoot->ID;
+
478
+
479 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume();
+
480 uint parentID = shoot->parent_shoot_ID;
+
481
+
482 if(shoot->carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume){
+
483 if(parentID <1000000 ){
+
484 float transfer_mol_C = (shoot->carbohydrate_pool_molC - carbohydrate_threshold * shoot_volume) * storage_conductance;
+
485 shoot_tree_ptr->at(parentID)->carbohydrate_pool_molC +=
+
486 transfer_mol_C;
+
487 shoot->carbohydrate_pool_molC -=
+
488 transfer_mol_C;
+
489
+
490 }
+
491
+
492 }
+
493
+
494 }
+
495
+
496 for( auto &shoot: *shoot_tree ){
+
497 uint shootID = shoot->ID;
+
498 float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume();
+
499 if(shoot->carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume) {
+
500
+
501 float totalChildVolume = shoot->sumChildVolume(0);
+
502 //std::cout<<"child volume: "<<totalChildVolume<<std::endl;
+
503
+
504 for (uint p = 0; p < shoot->phytomers.size(); p++) {
+
505 //call recursively for child shoots
+
506 if (shoot->childIDs.find(p) != shoot->childIDs.end()) {
+
507 for (int child_shoot_ID: shoot->childIDs.at(p)) {
+
508 float child_volume = plant_instances.at(plantID).shoot_tree.at(
+
509 child_shoot_ID)->sumChildVolume(0)+plant_instances.at(plantID).shoot_tree.at(
+
510 child_shoot_ID)->calculateShootInternodeVolume();
+
511 float child_ratio = child_volume / totalChildVolume;
+
512 //std::cout<<"child ratio: "<<child_ratio<<std::endl;
+
513
+
514 float transfer_mol_C = (shoot->carbohydrate_pool_molC - carbohydrate_threshold * shoot_volume)*return_conductance*child_ratio;
+
515
+
516 shoot_tree_ptr->at(child_shoot_ID)->carbohydrate_pool_molC +=
+
517 transfer_mol_C;
+
518 shoot->carbohydrate_pool_molC -=
+
519 transfer_mol_C;
+
520 //std::cout<<"Carb to child: "<<(shoot->carbohydrate_pool_molC - carbohydrate_threshold*shoot_volume)*return_conductance*child_ratio<<std::endl;
+
521 }
+
522 }
+
523
+
524 }
+
525 }
+
526
+
527 }
+
528
+
529 }
+
530
+
531}
-
float getTubeObjectSegmentVolume(uint ObjID, uint segment_index) const
get the volume of a segment within a Tube object
Definition Context.cpp:8176
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
-
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
-
float getTubeObjectVolume(uint ObjID) const
get the volume of a Tube object from the context
Definition Context.cpp:8172
-
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
-
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:2907
-
bool doesObjectExist(uint ObjID) const
Check whether Compound Object exists in the Context.
Definition Context.cpp:2585
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
-
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition Context.cpp:7920
-
float getPolymeshObjectVolume(uint ObjID) const
Get the volume of a Polygon Mesh object from the context.
Definition Context.cpp:8282
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
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:1943
-
helios::int3 shoot_index
.x = index of phytomer along shoot, .y = current number of phytomers on parent shoot,...
-
int x
First element in vector.
- -
+ + diff --git a/doc/html/_choosing_c_u_d_a.html b/doc/html/_choosing_c_u_d_a.html index a5c727c8f..fc96f73d6 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Choosing the right CUDA and OptiX version
@@ -132,10 +142,12 @@

- - + + diff --git a/doc/html/_context_8cpp.html b/doc/html/_context_8cpp.html index 0b4ff15ef..9f0ed30da 100644 --- a/doc/html/_context_8cpp.html +++ b/doc/html/_context_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Context.cpp File Reference
@@ -108,17 +114,20 @@

Go to the source code of this file.

Detailed Description

-

Context declarations.

+

Context declarations.

Copyright (C) 2016-2025 Brian Bailey

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

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

Definition in file Context.cpp.

- - + + diff --git a/doc/html/_context_8cpp_source.html b/doc/html/_context_8cpp_source.html index 12fa1f646..7db729a9b 100644 --- a/doc/html/_context_8cpp_source.html +++ b/doc/html/_context_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Context.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "Context.h"
17
18using namespace helios;
@@ -160,7 +167,7 @@
62 helios_runtime_error("ERROR (Context::addTexture): Texture file " + std::string(texture_file) + " does not exist.");
63 }
64
-
65 Texture text( texture_file );
+
65 Texture text( texture_file );
66 textures[ texture_file ] = text;
67 }
68}
@@ -305,7 +312,7 @@
189
190float Patch::getArea() const{
191
-
192 const vec2 &size = getSize();
+
192 const vec2 &size = getSize();
193
194 return size.x*size.y*solid_fraction;
195
@@ -322,7 +329,7 @@
206
207float Voxel::getArea() const{
208
-
209 const vec3 size(transform[0],transform[5],transform[10]);
+
209 const vec3 size(transform[0],transform[5],transform[10]);
210
211 return 2.f*size.x*size.y+2*size.x*size.z+2*size.y*size.z;
212
@@ -330,7 +337,7 @@
214
215vec3 Patch::getNormal() const{
216
-
217 vec3 normal(transform[2],transform[6],transform[10]);
+
217 vec3 normal(transform[2],transform[6],transform[10]);
218
219 normal.normalize();
220
@@ -340,7 +347,7 @@
224
225vec3 Triangle::getNormal() const{
226 const std::vector<vec3> &vertices = getVertices();
-
227 vec3 norm = cross(vertices.at(1)-vertices.at(0),vertices.at(2)-vertices.at(1));
+
227 vec3 norm = cross(vertices.at(1)-vertices.at(0),vertices.at(2)-vertices.at(1));
228 norm.normalize();
229 return norm;
230}
@@ -351,7 +358,7 @@
235
236std::vector<vec3> Patch::getVertices() const{
237
-
238 vec3 Y[4];
+
238 vec3 Y[4];
239 std::vector<vec3> vertices;
240 vertices.resize(4);
241 Y[0] = make_vec3( -0.5f, -0.5f, 0.f);
@@ -369,7 +376,7 @@
253
254std::vector<vec3> Triangle::getVertices() const{
255
-
256 vec3 Y[3];
+
256 vec3 Y[3];
257 std::vector<vec3> vertices;
258 vertices.resize(3);
259 Y[0] = make_vec3( 0.f, 0.f, 0.f);
@@ -387,7 +394,7 @@
271
272std::vector<vec3> Voxel::getVertices() const{
273
-
274 vec3 Y[8];
+
274 vec3 Y[8];
275 std::vector<vec3> vertices;
276 vertices.resize(8);
277 Y[0] = make_vec3( -0.5f, -0.5f, -0.5f);
@@ -408,18 +415,18 @@
292}
293
294RGBcolor Primitive::getColor() const{
-
295 return make_RGBcolor(color.r,color.g,color.b);
+
295 return make_RGBcolor(color.r,color.g,color.b);
296}
297
298RGBcolor Primitive::getColorRGB() const{
-
299 return make_RGBcolor(color.r,color.g,color.b);
+
299 return make_RGBcolor(color.r,color.g,color.b);
300}
301
302RGBAcolor Primitive::getColorRGBA() const{
303 return color;
304}
305
-
306void Primitive::setColor( const helios::RGBcolor& newcolor ){
+
306void Primitive::setColor( const helios::RGBcolor& newcolor ){
307
308 // if( parent_object_ID!=0 ){
309 // std::cout << "WARNING (Primitive::setColor): Cannot set the color of individual primitives within a compound object. Use the setter function for objects." << std::endl;
@@ -430,7 +437,7 @@
314
315}
316
-
317void Primitive::setColor( const helios::RGBAcolor& newcolor ){
+
317void Primitive::setColor( const helios::RGBAcolor& newcolor ){
318
319 // if( parent_object_ID!=0 ){
320 // std::cout << "WARNING (Primitive::setColor): Cannot set the color of individual primitives within a compound object. Use the setter function for objects." << std::endl;
@@ -503,9 +510,9 @@
387 const std::vector<std::vector<bool> >* alpha = textures.at(texturefile).getTransparencyData();
388 int A = 0;
389 int At = 0;
-
390 const int2 &sz = textures.at(texturefile).getImageResolution();
-
391 int2 uv_min( std::max(0,(int)roundf(uv.at(0).x*float(sz.x))), std::max(0,(int)roundf((1.f-uv.at(2).y)*float(sz.y))) );
-
392 int2 uv_max( std::min(sz.x-1,(int)roundf(uv.at(2).x*float(sz.x))), std::min(sz.y-1,(int)roundf((1.f-uv.at(0).y)*float(sz.y))) );
+
390 const int2 &sz = textures.at(texturefile).getImageResolution();
+
391 int2 uv_min( std::max(0,(int)roundf(uv.at(0).x*float(sz.x))), std::max(0,(int)roundf((1.f-uv.at(2).y)*float(sz.y))) );
+
392 int2 uv_max( std::min(sz.x-1,(int)roundf(uv.at(2).x*float(sz.x))), std::min(sz.y-1,(int)roundf((1.f-uv.at(0).y)*float(sz.y))) );
393 for( int j=uv_min.y; j<uv_max.y; j++ ){
394 for( int i=uv_min.x; i<uv_max.x; i++ ){
395 At += 1;
@@ -529,12 +536,12 @@
413
414 if( textures.at(texturefile).hasTransparencyChannel() ){
415 const std::vector<std::vector<bool> >* alpha = textures.at(texturefile).getTransparencyData();
-
416 const int2 &sz = textures.at(texturefile).getImageResolution();
-
417 int2 uv_min( std::max(0,(int)round(fminf(fminf(uv.at(0).x,uv.at(1).x),uv.at(2).x)*float(sz.x))), std::max(0,(int)round(fmin(fminf(uv.at(0).y,uv.at(1).y),uv.at(2).y)*float(sz.y))) );
-
418 int2 uv_max( std::min(sz.x-1,(int)round(fmaxf(fmaxf(uv.at(0).x,uv.at(1).x),uv.at(2).x)*float(sz.x))), std::min(sz.y-1,(int)round(fmaxf(fmaxf(uv.at(0).y,uv.at(1).y),uv.at(2).y)*float(sz.y))) );
+
416 const int2 &sz = textures.at(texturefile).getImageResolution();
+
417 int2 uv_min( std::max(0,(int)round(fminf(fminf(uv.at(0).x,uv.at(1).x),uv.at(2).x)*float(sz.x))), std::max(0,(int)round(fmin(fminf(uv.at(0).y,uv.at(1).y),uv.at(2).y)*float(sz.y))) );
+
418 int2 uv_max( std::min(sz.x-1,(int)round(fmaxf(fmaxf(uv.at(0).x,uv.at(1).x),uv.at(2).x)*float(sz.x))), std::min(sz.y-1,(int)round(fmaxf(fmaxf(uv.at(0).y,uv.at(1).y),uv.at(2).y)*float(sz.y))) );
419 int A = 0;
420 int At = 0;
-
421 vec2 xy;
+
421 vec2 xy;
422 for( int j=uv_min.y; j<uv_max.y; j++ ){
423 for( int i=uv_min.x; i<uv_max.x; i++ ){
424 xy.x = float(i+0.5)/float(sz.x-1);
@@ -568,11 +575,11 @@
452
453}
454
-
455bool Triangle::edgeFunction(const helios::vec2 &a, const helios::vec2 &b, const helios::vec2 &c){
+
455bool Triangle::edgeFunction(const helios::vec2 &a, const helios::vec2 &b, const helios::vec2 &c){
456 return ((c.y - a.y) * (b.x - a.x)-(c.x - a.x) * (b.y - a.y) >= 0);
457}
458
-
459void Triangle::setVertices(const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 ){
+
459void Triangle::setVertices(const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 ){
460 makeTransformationMatrix(vertex0, vertex1, vertex2);
461}
462
@@ -617,7 +624,7 @@
501 matmult(T,transform,transform);
502}
503
-
504void Primitive::translate( const helios::vec3& shift ){
+
504void Primitive::translate( const helios::vec3& shift ){
505
506 if( parent_object_ID!=0 ){
507 std::cerr << "WARNING (Primitive::translate): Cannot translate individual primitives within a compound object. Use the setter function for objects." << std::endl;
@@ -661,7 +668,7 @@
545
546}
547
-
548void Patch::rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ){
+
548void Patch::rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ){
549
550 if( parent_object_ID!=0 ){
551 std::cerr << "WARNING (Patch::rotate): Cannot rotate individual primitives within a compound object. Use the setter function for objects." << std::endl;
@@ -676,7 +683,7 @@
560 matmult(R,transform,transform);
561}
562
-
563void Patch::rotate(float rotation_radians, const helios::vec3& origin, const helios::vec3& rotation_axis_vector ){
+
563void Patch::rotate(float rotation_radians, const helios::vec3& origin, const helios::vec3& rotation_axis_vector ){
564
565 if( parent_object_ID!=0 ){
566 std::cerr << "WARNING (Patch::rotate): Cannot rotate individual primitives within a compound object. Use the setter function for objects." << std::endl;
@@ -719,7 +726,7 @@
603
604}
605
-
606void Triangle::rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ){
+
606void Triangle::rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ){
607
608 if( parent_object_ID!=0 ){
609 std::cerr << "WARNING (Triangle::rotate): Cannot rotate individual primitives within a compound object. Use the setter function for objects." << std::endl;
@@ -734,7 +741,7 @@
618 matmult(R,transform,transform);
619}
620
-
621void Triangle::rotate(float rotation_radians, const helios::vec3& origin, const helios::vec3& rotation_axis_vector ){
+
621void Triangle::rotate(float rotation_radians, const helios::vec3& origin, const helios::vec3& rotation_axis_vector ){
622
623 if( parent_object_ID!=0 ){
624 std::cerr << "WARNING (Triangle::rotate): Cannot rotate individual primitives within a compound object. Use the setter function for objects." << std::endl;
@@ -765,15 +772,15 @@
649
650}
651
-
652void Voxel::rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ){
+
652void Voxel::rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ){
653 std::cerr << "WARNING (Voxel::rotate) - Voxels can only be rotated about the z-axis. Ignoring this call to rotate()." << std::endl;
654}
655
-
656void Voxel::rotate(float rotation_radians, const helios::vec3& origin, const helios::vec3& rotation_axis_vector ){
+
656void Voxel::rotate(float rotation_radians, const helios::vec3& origin, const helios::vec3& rotation_axis_vector ){
657 std::cerr << "WARNING (Voxel::rotate) - Voxels can only be rotated about the z-axis. Ignoring this call to rotate()." << std::endl;
658}
659
-
660void Triangle::makeTransformationMatrix( const helios::vec3& vert0, const helios::vec3& vert1, const helios::vec3& vert2 ){
+
660void Triangle::makeTransformationMatrix( const helios::vec3& vert0, const helios::vec3& vert1, const helios::vec3& vert2 ){
661
662 //We need to construct the Affine transformation matrix that transforms some generic triangle to a triangle with vertices at vertex0, vertex1, vertex2.
663
@@ -1022,18 +1029,18 @@
906
907}
908
-
909helios::vec2 Patch::getSize() const{
+
909helios::vec2 Patch::getSize() const{
910 const std::vector<vec3> &vertices = getVertices();
911 float l = (vertices.at(1)-vertices.at(0)).magnitude();
912 float w = (vertices.at(3)-vertices.at(0)).magnitude();
913 return make_vec2(l,w);
914}
915
-
916helios::vec3 Patch::getCenter() const{
+
916helios::vec3 Patch::getCenter() const{
917 return make_vec3(transform[3],transform[7],transform[11]);
918}
919
-
920Triangle::Triangle( const helios::vec3& a_vertex0, const helios::vec3& a_vertex1, const helios::vec3& a_vertex2, const helios::RGBAcolor& a_color, uint a_parent_objID, uint a_UUID ){
+
920Triangle::Triangle( const helios::vec3& a_vertex0, const helios::vec3& a_vertex1, const helios::vec3& a_vertex2, const helios::RGBAcolor& a_color, uint a_parent_objID, uint a_UUID ){
921
922 makeTransformationMatrix(a_vertex0,a_vertex1,a_vertex2);
923 color = a_color;
@@ -1046,7 +1053,7 @@
930
931}
932
-
933Triangle::Triangle( const helios::vec3& a_vertex0, const helios::vec3& a_vertex1, const helios::vec3& a_vertex2, const char* a_texturefile, const std::vector<helios::vec2>& a_uv, float solid_fraction, uint a_parent_objID, uint a_UUID ){
+
933Triangle::Triangle( const helios::vec3& a_vertex0, const helios::vec3& a_vertex1, const helios::vec3& a_vertex2, const char* a_texturefile, const std::vector<helios::vec2>& a_uv, float solid_fraction, uint a_parent_objID, uint a_UUID ){
934
935 makeTransformationMatrix(a_vertex0,a_vertex1,a_vertex2);
936 color = make_RGBAcolor(RGB::red,1);
@@ -1061,7 +1068,7 @@
945
946}
947
-
948Triangle::Triangle( const helios::vec3& a_vertex0, const helios::vec3& a_vertex1, const helios::vec3& a_vertex2, const char* a_texturefile, const std::vector<helios::vec2>& a_uv, const std::map<std::string,Texture> &textures, uint a_parent_objID, uint a_UUID ){
+
948Triangle::Triangle( const helios::vec3& a_vertex0, const helios::vec3& a_vertex1, const helios::vec3& a_vertex2, const char* a_texturefile, const std::vector<helios::vec2>& a_uv, const std::map<std::string,Texture> &textures, uint a_parent_objID, uint a_UUID ){
949
950 makeTransformationMatrix(a_vertex0,a_vertex1,a_vertex2);
951 color = make_RGBAcolor(RGB::red,1);
@@ -1084,12 +1091,12 @@
968 helios_runtime_error("ERROR (Context::getVertex): vertex index must be 1, 2, or 3.");
969 }
970
-
971 vec3 Y[3];
+
971 vec3 Y[3];
972 Y[0] = make_vec3( 0.f, 0.f, 0.f);
973 Y[1] = make_vec3( 0.f, 1.f, 0.f);
974 Y[2] = make_vec3( 1.f, 1.f, 0.f);
975
-
976 vec3 vertex;
+
976 vec3 vertex;
977
978 vertex.x = transform[0] * Y[vertex_index].x + transform[1] * Y[vertex_index].y + transform[2] * Y[vertex_index].z + transform[3];
979 vertex.y = transform[4] * Y[vertex_index].x + transform[5] * Y[vertex_index].y + transform[6] * Y[vertex_index].z + transform[7];
@@ -1105,8 +1112,8 @@
989// Y[1] = make_vec3( 0.f, 1.f, 0.f);
990// Y[2] = make_vec3( 1.f/3.f, 1.f, 0.f);
991
-
992 vec3 center0 = make_vec3(1.f/3.f,2.f/3.f,0.f);
-
993 vec3 center;
+
992 vec3 center0 = make_vec3(1.f/3.f,2.f/3.f,0.f);
+
993 vec3 center;
994
995 center.x = transform[0] * center0.x + transform[1] * center0.y + transform[2] * center0.z + transform[3];
996 center.y = transform[4] * center0.x + transform[5] * center0.y + transform[6] * center0.z + transform[7];
@@ -1133,15 +1140,15 @@
1017
1018float Voxel::getVolume(){
1019
-
1020 const vec3 &size = getSize();
+
1020 const vec3 &size = getSize();
1021
1022 return size.x*size.y*size.z;
1023}
1024
1025vec3 Voxel::getCenter() const{
1026
-
1027 vec3 center;
-
1028 vec3 Y;
+
1027 vec3 center;
+
1028 vec3 Y;
1029 Y.x = 0.f;
1030 Y.y = 0.f;
1031 Y.z = 0.f;
@@ -1156,8 +1163,8 @@
1040
1041vec3 Voxel::getSize(){
1042
-
1043 vec3 n0(0,0,0), nx(1,0,0), ny(0,1,0), nz(0,0,1);
-
1044 vec3 n0_T, nx_T, ny_T, nz_T;
+
1043 vec3 n0(0,0,0), nx(1,0,0), ny(0,1,0), nz(0,0,1);
+
1044 vec3 n0_T, nx_T, ny_T, nz_T;
1045
1046 vecmult(transform,n0,n0_T);
1047 vecmult(transform,nx,nx_T);
@@ -1226,27 +1233,27 @@
1102
1103const char* Context::getMonthString() const{
-
1104 if( sim_date.month==1 ){
+
1104 if( sim_date.month==1 ){
1105 return "JAN";
-
1106 }else if( sim_date.month==2 ){
+
1106 }else if( sim_date.month==2 ){
1107 return "FEB";
-
1108 }else if( sim_date.month==3 ){
+
1108 }else if( sim_date.month==3 ){
1109 return "MAR";
-
1110 }else if( sim_date.month==4 ){
+
1110 }else if( sim_date.month==4 ){
1111 return "APR";
-
1112 }else if( sim_date.month==5 ){
+
1112 }else if( sim_date.month==5 ){
1113 return "MAY";
-
1114 }else if( sim_date.month==6 ){
+
1114 }else if( sim_date.month==6 ){
1115 return "JUN";
-
1116 }else if( sim_date.month==7 ){
+
1116 }else if( sim_date.month==7 ){
1117 return "JUL";
-
1118 }else if( sim_date.month==8 ){
+
1118 }else if( sim_date.month==8 ){
1119 return "AUG";
-
1120 }else if( sim_date.month==9 ){
+
1120 }else if( sim_date.month==9 ){
1121 return "SEP";
-
1122 }else if( sim_date.month==10 ){
+
1122 }else if( sim_date.month==10 ){
1123 return "OCT";
-
1124 }else if( sim_date.month==11 ){
+
1124 }else if( sim_date.month==11 ){
1125 return "NOV";
1126 }else{
1127 return "DEC";
@@ -1257,7 +1264,7 @@
1131
-
1133 return JulianDay( sim_date.day, sim_date.month, sim_date.year );
+
1133 return JulianDay( sim_date.day, sim_date.month, sim_date.year );
1134}
1135
@@ -1891,7 +1898,7 @@
1675Patch* Context::getPatchPointer_private(uint UUID ) const{
1676 if( primitives.find(UUID) == primitives.end() ){
1677 helios_runtime_error("ERROR (Context::getPatchPointer_private): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
-
1678 }else if( primitives.at(UUID)->getType()!=PRIMITIVE_TYPE_PATCH ){
+
1678 }else if( primitives.at(UUID)->getType()!=PRIMITIVE_TYPE_PATCH ){
1679 helios_runtime_error("ERROR (Context::getPatchPointer_private): UUID of " + std::to_string(UUID) + " is not a patch.");
1680 }
1681 return dynamic_cast<Patch*>(primitives.at(UUID));
@@ -1922,7 +1929,7 @@
1702Triangle* Context::getTrianglePointer_private(uint UUID ) const{
1703 if( primitives.find(UUID) == primitives.end() ){
1704 helios_runtime_error("ERROR (Context::getTrianglePointer_private): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
-
1705 }else if( primitives.at(UUID)->getType()!=PRIMITIVE_TYPE_TRIANGLE ){
+
1705 }else if( primitives.at(UUID)->getType()!=PRIMITIVE_TYPE_TRIANGLE ){
1706 helios_runtime_error("ERROR (Context::getTrianglePointer_private): UUID of " + std::to_string(UUID) + " is not a triangle.");
1707 }
1708 return dynamic_cast<Triangle*>(primitives.at(UUID));
@@ -1956,7 +1963,7 @@
1732Voxel* Context::getVoxelPointer_private(uint UUID ) const{
1733 if( primitives.find(UUID) == primitives.end() ){
1734 helios_runtime_error("ERROR (Context::getVoxelPointer): UUID of " + std::to_string(UUID) + " does not exist in the Context.");
-
1735 }else if( primitives.at(UUID)->getType()!=PRIMITIVE_TYPE_VOXEL ){
+
1735 }else if( primitives.at(UUID)->getType()!=PRIMITIVE_TYPE_VOXEL ){
1736 helios_runtime_error("ERROR (Context::getVoxelPointer): UUID of " + std::to_string(UUID) + " is not a voxel.");
1737 }
1738 return dynamic_cast<Voxel*>(primitives.at(UUID));
@@ -2562,7 +2569,7 @@
2271
2272 const std::vector<uint> &U = getPrimitiveUUIDs();
2273
-
2274 context->getDomainBoundingBox( U, xbounds, ybounds, zbounds );
+
2274 context->getDomainBoundingBox( U, xbounds, ybounds, zbounds );
2275
2276 vec3 origin;
2277
@@ -2581,8 +2588,8 @@
2288
2289 for( uint UUID : UUIDs){
2290
-
2291 if( context->doesPrimitiveExist( UUID ) ){
-
2292 area += context->getPrimitiveArea(UUID);
+
2291 if( context->doesPrimitiveExist( UUID ) ){
+
2292 area += context->getPrimitiveArea(UUID);
2293 }
2294
2295 }
@@ -2596,8 +2603,8 @@
2302 for( uint UUID : UUIDs){
2303
-
2304 if( context->doesPrimitiveExist( UUID ) ){
-
2305 context->setPrimitiveColor( UUID, a_color );
+
2304 if( context->doesPrimitiveExist( UUID ) ){
+
2305 context->setPrimitiveColor( UUID, a_color );
2306 }
2307
2308 }
@@ -2608,8 +2615,8 @@
2312 for( uint UUID : UUIDs){
2313
-
2314 if( context->doesPrimitiveExist( UUID ) ){
-
2315 context->setPrimitiveColor( UUID, a_color );
+
2314 if( context->doesPrimitiveExist( UUID ) ){
+
2315 context->setPrimitiveColor( UUID, a_color );
2316 }
2317
2318 }
@@ -2620,8 +2627,8 @@
2322 for( uint UUID : UUIDs){
2323
-
2324 if( context->doesPrimitiveExist( UUID ) ){
-
2325 context->overridePrimitiveTextureColor( UUID );
+
2324 if( context->doesPrimitiveExist( UUID ) ){
+
2325 context->overridePrimitiveTextureColor( UUID );
2326 }
2327
2328 }
@@ -2632,8 +2639,8 @@
2332 for( uint UUID : UUIDs){
2333
-
2334 if( context->doesPrimitiveExist( UUID ) ){
-
2335 context->usePrimitiveTextureColor( UUID );
+
2334 if( context->doesPrimitiveExist( UUID ) ){
+
2335 context->usePrimitiveTextureColor( UUID );
2336 }
2337
2338 }
@@ -2670,11 +2677,11 @@
2363
2364 for( uint UUID : UUIDs){
2365
-
2366 if( context->doesPrimitiveExist( UUID ) ){
+
2366 if( context->doesPrimitiveExist( UUID ) ){
2367
-
2368 context->getPrimitiveTransformationMatrix( UUID,T_prim);
+
2368 context->getPrimitiveTransformationMatrix( UUID,T_prim);
2369 matmult(T,T_prim,T_prim);
-
2370 context->setPrimitiveTransformationMatrix( UUID,T_prim);
+
2370 context->setPrimitiveTransformationMatrix( UUID,T_prim);
2371 }
2372
2373 }
@@ -2695,10 +2702,10 @@
2386 matmult(Rz,transform,transform);
2387
2388 for( uint UUID : UUIDs){
-
2389 if( context->doesPrimitiveExist( UUID ) ){
-
2390 context->getPrimitiveTransformationMatrix( UUID,Rz_prim);
+
2389 if( context->doesPrimitiveExist( UUID ) ){
+
2390 context->getPrimitiveTransformationMatrix( UUID,Rz_prim);
2391 matmult(Rz,Rz_prim,Rz_prim);
-
2392 context->setPrimitiveTransformationMatrix( UUID,Rz_prim);
+
2392 context->setPrimitiveTransformationMatrix( UUID,Rz_prim);
2393 }
2394 }
2395 }else if(strcmp(rotation_axis_xyz_string, "y") == 0 ){
@@ -2706,10 +2713,10 @@
2397 makeRotationMatrix(rotation_radians, "y", Ry);
2398 matmult(Ry,transform,transform);
2399 for( uint UUID : UUIDs){
-
2400 if( context->doesPrimitiveExist( UUID ) ){
-
2401 context->getPrimitiveTransformationMatrix( UUID,Ry_prim);
+
2400 if( context->doesPrimitiveExist( UUID ) ){
+
2401 context->getPrimitiveTransformationMatrix( UUID,Ry_prim);
2402 matmult(Ry,Ry_prim,Ry_prim);
-
2403 context->setPrimitiveTransformationMatrix( UUID,Ry_prim);
+
2403 context->setPrimitiveTransformationMatrix( UUID,Ry_prim);
2404 }
2405 }
2406 }else if(strcmp(rotation_axis_xyz_string, "x") == 0 ){
@@ -2717,10 +2724,10 @@
2408 makeRotationMatrix(rotation_radians, "x", Rx);
2409 matmult(Rx,transform,transform);
2410 for( uint UUID : UUIDs){
-
2411 if( context->doesPrimitiveExist( UUID ) ){
-
2412 context->getPrimitiveTransformationMatrix( UUID,Rx_prim);
+
2411 if( context->doesPrimitiveExist( UUID ) ){
+
2412 context->getPrimitiveTransformationMatrix( UUID,Rx_prim);
2413 matmult(Rx,Rx_prim,Rx_prim);
-
2414 context->setPrimitiveTransformationMatrix( UUID,Rx_prim);
+
2414 context->setPrimitiveTransformationMatrix( UUID,Rx_prim);
2415 }
2416 }
2417 }else{
@@ -2743,11 +2750,11 @@
2432
2433 for( uint UUID : UUIDs){
2434
-
2435 if( context->doesPrimitiveExist( UUID ) ){
+
2435 if( context->doesPrimitiveExist( UUID ) ){
2436
-
2437 context->getPrimitiveTransformationMatrix( UUID,R_prim);
+
2437 context->getPrimitiveTransformationMatrix( UUID,R_prim);
2438 matmult(R,R_prim,R_prim);
-
2439 context->setPrimitiveTransformationMatrix( UUID,R_prim);
+
2439 context->setPrimitiveTransformationMatrix( UUID,R_prim);
2440
2441 }
2442
@@ -2769,11 +2776,11 @@
2456
2457 for( uint UUID : UUIDs){
2458
-
2459 if( context->doesPrimitiveExist( UUID ) ){
+
2459 if( context->doesPrimitiveExist( UUID ) ){
2460
-
2461 context->getPrimitiveTransformationMatrix( UUID,R_prim);
+
2461 context->getPrimitiveTransformationMatrix( UUID,R_prim);
2462 matmult(R,R_prim,R_prim);
-
2463 context->setPrimitiveTransformationMatrix( UUID,R_prim);
+
2463 context->setPrimitiveTransformationMatrix( UUID,R_prim);
2464
2465 }
2466
@@ -2783,19 +2790,19 @@
2470
2474
2478
- +
2480
2481 if( scale.x==1.f && scale.y==1.f && scale.z==1.f ){
2482 return;
@@ -2807,11 +2814,11 @@
2488
2489 for( uint UUID : UUIDs) {
2490
-
2491 if (context->doesPrimitiveExist(UUID)) {
+
2491 if (context->doesPrimitiveExist(UUID)) {
2492
-
2493 context->getPrimitiveTransformationMatrix(UUID, T_prim);
+
2493 context->getPrimitiveTransformationMatrix(UUID, T_prim);
2494 matmult(T, T_prim, T_prim);
-
2495 context->setPrimitiveTransformationMatrix(UUID, T_prim);
+
2495 context->setPrimitiveTransformationMatrix(UUID, T_prim);
2496
2497 }
2498
@@ -4071,7 +4078,7 @@
3616 if (fabs(axial_vector * initial_radial) > 0.99f) {
3617 initial_radial = vec3(0.0f, 1.0f, 0.0f); // Avoid parallel vectors
3618 }
-
3619 previous_radial_dir = cross(axial_vector, initial_radial).normalize();
+
3619 previous_radial_dir = cross(axial_vector, initial_radial).normalize();
3620 } else {
3621 if (i == node_count - 1) {
3622 axial_vector = nodes[i] - nodes[i - 1];
@@ -4194,7 +4201,7 @@
3737 if (fabs(axial_vector * initial_radial) > 0.99f) {
3738 initial_radial = vec3(0.0f, 1.0f, 0.0f); // Avoid parallel vectors
3739 }
-
3740 previous_radial_dir = cross(axial_vector, initial_radial).normalize();
+
3740 previous_radial_dir = cross(axial_vector, initial_radial).normalize();
3741 } else {
3742 if (i == node_count - 1) {
3743 axial_vector = nodes[i] - nodes[i - 1];
@@ -4379,1622 +4386,1622 @@
3914}
3915
-
3916void Tube::updateTriangleVertices(){
+
+
3916void Tube::pruneTubeNodes( uint node_index ){
3917
-
3918 vec3 v0, v1, v2;
-
3919
-
3920 int ii=0;
-
3921 for (int i = 0; i < nodes.size() - 1; i++) {
-
3922 for(int j=0; j < subdiv; j++ ) {
-
3923
-
3924 v0 = triangle_vertices.at(i).at(j);
-
3925 v1 = triangle_vertices.at(i + 1).at(j + 1);
-
3926 v2 = triangle_vertices.at(i).at(j + 1);
-
3927 context->setTriangleVertices(UUIDs.at(ii), v0, v1, v2);
-
3928
-
3929 v0 = triangle_vertices.at(i).at(j);
-
3930 v1 = triangle_vertices.at(i + 1).at(j);
-
3931 v2 = triangle_vertices.at(i + 1).at(j + 1);
-
3932
-
3933 context->setTriangleVertices(UUIDs.at(ii+1), v0, v1, v2);
-
3934
-
3935 ii += 2;
-
3936 }
-
3937 }
-
3938
-
3939}
+
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
-
-
3941Box::Box(uint a_OID, const std::vector<uint> &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context) {
+
3941}
+
3942
-
3943 makeIdentityMatrix( transform );
+
3943void Tube::updateTriangleVertices(){
3944
-
3945 OID = a_OID;
- -
3947 UUIDs = a_UUIDs;
-
3948 subdiv = a_subdiv;
-
3949 texturefile = a_texturefile;
-
3950 context = a_context;
-
3951
-
3952}
-
-
3953
-
- -
3955 if( objects.find(ObjID) == objects.end() ){
-
3956 helios_runtime_error("ERROR (Context::getBoxObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
3957 }
-
3958 return dynamic_cast<Box*>(objects.at(ObjID));
-
3959}
-
-
3960
-
- -
3962
-
3963 vec3 n0(0,0,0), nx(1,0,0), ny(0,1,0), nz(0,0,1);
-
3964
-
3965 vec3 n0_T, nx_T, ny_T, nz_T;
-
3966
-
3967 vecmult(transform,n0,n0_T);
-
3968 vecmult(transform,nx,nx_T);
-
3969 vecmult(transform,ny,ny_T);
-
3970 vecmult(transform,nz,nz_T);
+
3945 vec3 v0, v1, v2;
+
3946
+
3947 int ii=0;
+
3948 for (int i = 0; i < nodes.size() - 1; i++) {
+
3949 for(int j=0; j < subdiv; j++ ) {
+
3950
+
3951 v0 = triangle_vertices.at(i).at(j);
+
3952 v1 = triangle_vertices.at(i + 1).at(j + 1);
+
3953 v2 = triangle_vertices.at(i).at(j + 1);
+
3954 context->setTriangleVertices(UUIDs.at(ii), v0, v1, v2);
+
3955
+
3956 v0 = triangle_vertices.at(i).at(j);
+
3957 v1 = triangle_vertices.at(i + 1).at(j);
+
3958 v2 = triangle_vertices.at(i + 1).at(j + 1);
+
3959
+
3960 context->setTriangleVertices(UUIDs.at(ii+1), v0, v1, v2);
+
3961
+
3962 ii += 2;
+
3963 }
+
3964 }
+
3965
+
3966}
+
3967
+
+
3968Box::Box(uint a_OID, const std::vector<uint> &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context) {
+
3969
+
3970 makeIdentityMatrix( transform );
3971
-
3972 float x = (nx_T-n0_T).magnitude();
-
3973 float y = (ny_T-n0_T).magnitude();
-
3974 float z = (nz_T-n0_T).magnitude();
-
3975
-
3976 return make_vec3( x, y, z );
-
3977
-
3978}
-
-
3979
-
- -
3981
-
3982 vec3 center;
-
3983 vec3 Y;
-
3984 Y.x = 0.f;
-
3985 Y.y = 0.f;
-
3986 Y.z = 0.f;
+
3972 OID = a_OID;
+ +
3974 UUIDs = a_UUIDs;
+
3975 subdiv = a_subdiv;
+
3976 texturefile = a_texturefile;
+
3977 context = a_context;
+
3978
+
3979}
+
+
3980
+
+ +
3982 if( objects.find(ObjID) == objects.end() ){
+
3983 helios_runtime_error("ERROR (Context::getBoxObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
3984 }
+
3985 return dynamic_cast<Box*>(objects.at(ObjID));
+
3986}
+
3987
-
3988 center.x = transform[0] * Y.x + transform[1] * Y.y + transform[2] * Y.z + transform[3];
-
3989 center.y = transform[4] * Y.x + transform[5] * Y.y + transform[6] * Y.z + transform[7];
-
3990 center.z = transform[8] * Y.x + transform[9] * Y.y + transform[10] * Y.z + transform[11];
+
+ +
3989
+
3990 vec3 n0(0,0,0), nx(1,0,0), ny(0,1,0), nz(0,0,1);
3991
-
3992 return center;
+
3992 vec3 n0_T, nx_T, ny_T, nz_T;
3993
-
3994}
-
-
3995
-
- -
3997 return subdiv;
-
3998}
-
-
3999
-
- -
4001 subdiv = a_subdiv;
-
4002}
-
-
4003
-
-
4004float Box::getVolume() const{
-
4005 const vec3 &size = getSize();
-
4006 return size.x * size.y * size.z;
-
4007}
-
+
3994 vecmult(transform,n0,n0_T);
+
3995 vecmult(transform,nx,nx_T);
+
3996 vecmult(transform,ny,ny_T);
+
3997 vecmult(transform,nz,nz_T);
+
3998
+
3999 float x = (nx_T-n0_T).magnitude();
+
4000 float y = (ny_T-n0_T).magnitude();
+
4001 float z = (nz_T-n0_T).magnitude();
+
4002
+
4003 return make_vec3( x, y, z );
+
4004
+
4005}
+
+
4006
+
+
4008
-
-
4009Disk::Disk(uint a_OID, const std::vector<uint> &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context) {
-
4010
-
4011 makeIdentityMatrix( transform );
-
4012
-
4013 OID = a_OID;
- -
4015 UUIDs = a_UUIDs;
-
4016 subdiv = a_subdiv;
-
4017 texturefile = a_texturefile;
-
4018 context = a_context;
-
4019
-
4020}
-
-
4021
-
- -
4023 if( objects.find(ObjID) == objects.end() ){
-
4024 helios_runtime_error("ERROR (Context::getDiskObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
4025 }
-
4026 return dynamic_cast<Disk*>(objects.at(ObjID));
-
4027}
-
-
4028
-
- +
4009 vec3 center;
+
4010 vec3 Y;
+
4011 Y.x = 0.f;
+
4012 Y.y = 0.f;
+
4013 Y.z = 0.f;
+
4014
+
4015 center.x = transform[0] * Y.x + transform[1] * Y.y + transform[2] * Y.z + transform[3];
+
4016 center.y = transform[4] * Y.x + transform[5] * Y.y + transform[6] * Y.z + transform[7];
+
4017 center.z = transform[8] * Y.x + transform[9] * Y.y + transform[10] * Y.z + transform[11];
+
4018
+
4019 return center;
+
4020
+
4021}
+
+
4022
+
+ +
4024 return subdiv;
+
4025}
+
+
4026
+
+ +
4028 subdiv = a_subdiv;
+
4029}
+
4030
-
4031 vec3 n0(0,0,0), nx(1,0,0), ny(0,1,0);
-
4032 vec3 n0_T, nx_T, ny_T;
-
4033
-
4034 vecmult(transform,n0,n0_T);
-
4035 vecmult(transform,nx,nx_T);
-
4036 vecmult(transform,ny,ny_T);
+
+
4031float Box::getVolume() const{
+
4032 const vec3 &size = getSize();
+
4033 return size.x * size.y * size.z;
+
4034}
+
+
4035
+
+
4036Disk::Disk(uint a_OID, const std::vector<uint> &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context) {
4037
-
4038 float x = (nx_T-n0_T).magnitude();
-
4039 float y = (ny_T-n0_T).magnitude();
-
4040
-
4041 return make_vec2(x,y);
-
4042
-
4043}
-
-
4044
-
- +
4038 makeIdentityMatrix( transform );
+
4039
+
4040 OID = a_OID;
+ +
4042 UUIDs = a_UUIDs;
+
4043 subdiv = a_subdiv;
+
4044 texturefile = a_texturefile;
+
4045 context = a_context;
4046
-
4047 vec3 center;
-
4048 vec3 Y;
-
4049 Y.x = 0.f;
-
4050 Y.y = 0.f;
-
4051 Y.z = 0.f;
-
4052
-
4053 center.x = transform[0] * Y.x + transform[1] * Y.y + transform[2] * Y.z + transform[3];
-
4054 center.y = transform[4] * Y.x + transform[5] * Y.y + transform[6] * Y.z + transform[7];
-
4055 center.z = transform[8] * Y.x + transform[9] * Y.y + transform[10] * Y.z + transform[11];
-
4056
-
4057 return center;
-
4058
-
4059}
-
+
4047}
+
+
4048
+
+ +
4050 if( objects.find(ObjID) == objects.end() ){
+
4051 helios_runtime_error("ERROR (Context::getDiskObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
4052 }
+
4053 return dynamic_cast<Disk*>(objects.at(ObjID));
+
4054}
+
+
4055
+
+ +
4057
+
4058 vec3 n0(0,0,0), nx(1,0,0), ny(0,1,0);
+
4059 vec3 n0_T, nx_T, ny_T;
4060
-
- -
4062 return subdiv;
-
4063}
-
+
4061 vecmult(transform,n0,n0_T);
+
4062 vecmult(transform,nx,nx_T);
+
4063 vecmult(transform,ny,ny_T);
4064
-
- -
4066 subdiv = a_subdiv;
-
4067}
-
-
4068
-
-
4069Polymesh::Polymesh(uint a_OID, const std::vector<uint> &a_UUIDs, const char *a_texturefile, helios::Context *a_context) {
-
4070
-
4071 makeIdentityMatrix( transform );
-
4072
-
4073 OID = a_OID;
- -
4075 UUIDs = a_UUIDs;
-
4076 texturefile = a_texturefile;
-
4077 context = a_context;
-
4078
-
4079}
-
-
4080
-
- -
4082 if( objects.find(ObjID) == objects.end() ){
-
4083 helios_runtime_error("ERROR (Context::getPolymeshObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
4084 }
-
4085 return dynamic_cast<Polymesh*>(objects.at(ObjID));
+
4065 float x = (nx_T-n0_T).magnitude();
+
4066 float y = (ny_T-n0_T).magnitude();
+
4067
+
4068 return make_vec2(x,y);
+
4069
+
4070}
+
+
4071
+
+ +
4073
+
4074 vec3 center;
+
4075 vec3 Y;
+
4076 Y.x = 0.f;
+
4077 Y.y = 0.f;
+
4078 Y.z = 0.f;
+
4079
+
4080 center.x = transform[0] * Y.x + transform[1] * Y.y + transform[2] * Y.z + transform[3];
+
4081 center.y = transform[4] * Y.x + transform[5] * Y.y + transform[6] * Y.z + transform[7];
+
4082 center.z = transform[8] * Y.x + transform[9] * Y.y + transform[10] * Y.z + transform[11];
+
4083
+
4084 return center;
+
4085
4086}
4087
- -
4089 float volume = 0.f;
-
4090 for (uint UUID : UUIDs ) {
-
4091 if( context->getPrimitiveType(UUID)==PRIMITIVE_TYPE_TRIANGLE ) {
-
4092 const vec3 &v0 = context->getTriangleVertex(UUID, 0);
-
4093 const vec3 &v1 = context->getTriangleVertex(UUID, 1);
-
4094 const vec3 &v2 = context->getTriangleVertex(UUID, 2);
-
4095 volume += (1.f / 6.f) * v0 * cross(v1,v2);
-
4096 }else if ( context->getPrimitiveType(UUID)==PRIMITIVE_TYPE_PATCH ) {
-
4097 const vec3 &v0 = context->getTriangleVertex(UUID, 0);
-
4098 const vec3 &v1 = context->getTriangleVertex(UUID, 1);
-
4099 const vec3 &v2 = context->getTriangleVertex(UUID, 2);
-
4100 const vec3 &v3 = context->getTriangleVertex(UUID, 3);
-
4101 volume += (1.f / 6.f) * v0 * cross(v1,v2) + (1.f / 6.f) * v0 * cross(v2,v3);
-
4102 }
-
4103 }
-
4104 return std::abs(volume);
-
4105}
-
-
4106
-
-
4107Cone::Cone(uint a_OID, const std::vector<uint> &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0,
-
4108 float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context) {
-
4109
-
4110 makeIdentityMatrix( transform );
-
4111
-
4112 OID = a_OID;
- -
4114 UUIDs = a_UUIDs;
-
4115 subdiv = a_subdiv;
-
4116 texturefile = a_texturefile;
-
4117 context = a_context;
-
4118 nodes = {a_node0, a_node1};
-
4119 radii = {a_radius0, a_radius1};
-
4120
-
4121}
-
-
4122
-
-
4123Cone* Context::getConeObjectPointer( const uint ObjID ) const{
-
4124 if( objects.find(ObjID) == objects.end() ){
-
4125 helios_runtime_error("ERROR (Context::getConeObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
4126 }
-
4127 return dynamic_cast<Cone*>(objects.at(ObjID));
-
4128}
-
-
4129
-
-
4130std::vector<helios::vec3> Cone::getNodeCoordinates() const{
-
4131
-
4132 std::vector<vec3> nodes_T;
-
4133 nodes_T.resize( 2 );
-
4134
-
4135 for( int i=0; i<2; i++ ){
-
4136 nodes_T.at(i).x = transform[0] * nodes.at(i).x + transform[1] * nodes.at(i).y + transform[2] * nodes.at(i).z + transform[3];
-
4137 nodes_T.at(i).y = transform[4] * nodes.at(i).x + transform[5] * nodes.at(i).y + transform[6] * nodes.at(i).z + transform[7];
-
4138 nodes_T.at(i).z = transform[8] * nodes.at(i).x + transform[9] * nodes.at(i).y + transform[10] * nodes.at(i).z + transform[11];
-
4139 }
-
4140
-
4141 return nodes_T;
-
4142}
-
-
4143
-
- -
4145
-
4146 if(node_index < 0 || node_index > 1 ){
-
4147 helios_runtime_error("ERROR (Cone::getNodeCoordinate): node number must be 0 or 1.");
-
4148 }
-
4149
-
4150 vec3 node_T;
-
4151
-
4152 node_T.x = transform[0] * nodes.at(node_index).x + transform[1] * nodes.at(node_index).y + transform[2] * nodes.at(node_index).z + transform[3];
-
4153 node_T.y = transform[4] * nodes.at(node_index).x + transform[5] * nodes.at(node_index).y + transform[6] * nodes.at(node_index).z + transform[7];
-
4154 node_T.z = transform[8] * nodes.at(node_index).x + transform[9] * nodes.at(node_index).y + transform[10] * nodes.at(node_index).z + transform[11];
-
4155
-
4156 return node_T;
-
4157}
+ +
4089 return subdiv;
+
4090}
+
+
4091
+
+ +
4093 subdiv = a_subdiv;
+
4094}
+
+
4095
+
+
4096Polymesh::Polymesh(uint a_OID, const std::vector<uint> &a_UUIDs, const char *a_texturefile, helios::Context *a_context) {
+
4097
+
4098 makeIdentityMatrix( transform );
+
4099
+
4100 OID = a_OID;
+ +
4102 UUIDs = a_UUIDs;
+
4103 texturefile = a_texturefile;
+
4104 context = a_context;
+
4105
+
4106}
+
+
4107
+
+ +
4109 if( objects.find(ObjID) == objects.end() ){
+
4110 helios_runtime_error("ERROR (Context::getPolymeshObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
4111 }
+
4112 return dynamic_cast<Polymesh*>(objects.at(ObjID));
+
4113}
+
+
4114
+
+ +
4116 float volume = 0.f;
+
4117 for (uint UUID : UUIDs ) {
+
4118 if( context->getPrimitiveType(UUID)==PRIMITIVE_TYPE_TRIANGLE ) {
+
4119 const vec3 &v0 = context->getTriangleVertex(UUID, 0);
+
4120 const vec3 &v1 = context->getTriangleVertex(UUID, 1);
+
4121 const vec3 &v2 = context->getTriangleVertex(UUID, 2);
+
4122 volume += (1.f / 6.f) * v0 * cross(v1,v2);
+
4123 }else if ( context->getPrimitiveType(UUID)==PRIMITIVE_TYPE_PATCH ) {
+
4124 const vec3 &v0 = context->getTriangleVertex(UUID, 0);
+
4125 const vec3 &v1 = context->getTriangleVertex(UUID, 1);
+
4126 const vec3 &v2 = context->getTriangleVertex(UUID, 2);
+
4127 const vec3 &v3 = context->getTriangleVertex(UUID, 3);
+
4128 volume += (1.f / 6.f) * v0 * cross(v1,v2) + (1.f / 6.f) * v0 * cross(v2,v3);
+
4129 }
+
4130 }
+
4131 return std::abs(volume);
+
4132}
+
+
4133
+
+
4134Cone::Cone(uint a_OID, const std::vector<uint> &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0,
+
4135 float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context) {
+
4136
+
4137 makeIdentityMatrix( transform );
+
4138
+
4139 OID = a_OID;
+ +
4141 UUIDs = a_UUIDs;
+
4142 subdiv = a_subdiv;
+
4143 texturefile = a_texturefile;
+
4144 context = a_context;
+
4145 nodes = {a_node0, a_node1};
+
4146 radii = {a_radius0, a_radius1};
+
4147
+
4148}
+
4149
+
+
4150Cone* Context::getConeObjectPointer( const uint ObjID ) const{
+
4151 if( objects.find(ObjID) == objects.end() ){
+
4152 helios_runtime_error("ERROR (Context::getConeObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
4153 }
+
4154 return dynamic_cast<Cone*>(objects.at(ObjID));
+
4155}
+
+
4156
+
+
4157std::vector<helios::vec3> Cone::getNodeCoordinates() const{
4158
-
-
4159std::vector<float> Cone::getNodeRadii() const{
-
4160 return radii;
-
4161}
-
-
4162
-
-
4163float Cone::getNodeRadius( int node_index ) const{
-
4164 if(node_index < 0 || node_index > 1 ){
-
4165 helios_runtime_error("ERROR (Cone::getNodeRadius): node number must be 0 or 1.");
+
4159 std::vector<vec3> nodes_T;
+
4160 nodes_T.resize( 2 );
+
4161
+
4162 for( int i=0; i<2; i++ ){
+
4163 nodes_T.at(i).x = transform[0] * nodes.at(i).x + transform[1] * nodes.at(i).y + transform[2] * nodes.at(i).z + transform[3];
+
4164 nodes_T.at(i).y = transform[4] * nodes.at(i).x + transform[5] * nodes.at(i).y + transform[6] * nodes.at(i).z + transform[7];
+
4165 nodes_T.at(i).z = transform[8] * nodes.at(i).x + transform[9] * nodes.at(i).y + transform[10] * nodes.at(i).z + transform[11];
4166 }
4167
-
4168 return radii.at(node_index);
+
4168 return nodes_T;
4169}
4170
- -
4172 return subdiv;
-
4173}
-
-
4174
-
-
4175void Cone::setSubdivisionCount( uint a_subdiv ){
-
4176 subdiv = a_subdiv;
-
4177}
-
+ +
4172
+
4173 if(node_index < 0 || node_index > 1 ){
+
4174 helios_runtime_error("ERROR (Cone::getNodeCoordinate): node number must be 0 or 1.");
+
4175 }
+
4176
+
4177 vec3 node_T;
4178
-
- -
4180
-
4181 std::vector<vec3> nodes_T;
-
4182 nodes_T.resize( 2 );
-
4183
-
4184 for( uint i=0; i<2; i++ ){
-
4185 nodes_T.at(i).x = transform[0] * nodes.at(i).x + transform[1] * nodes.at(i).y + transform[2] * nodes.at(i).z + transform[3];
-
4186 nodes_T.at(i).y = transform[4] * nodes.at(i).x + transform[5] * nodes.at(i).y + transform[6] * nodes.at(i).z + transform[7];
-
4187 nodes_T.at(i).z = transform[8] * nodes.at(i).x + transform[9] * nodes.at(i).y + transform[10] * nodes.at(i).z + transform[11];
-
4188 }
+
4179 node_T.x = transform[0] * nodes.at(node_index).x + transform[1] * nodes.at(node_index).y + transform[2] * nodes.at(node_index).z + transform[3];
+
4180 node_T.y = transform[4] * nodes.at(node_index).x + transform[5] * nodes.at(node_index).y + transform[6] * nodes.at(node_index).z + transform[7];
+
4181 node_T.z = transform[8] * nodes.at(node_index).x + transform[9] * nodes.at(node_index).y + transform[10] * nodes.at(node_index).z + transform[11];
+
4182
+
4183 return node_T;
+
4184}
+
+
4185
+
+
4186std::vector<float> Cone::getNodeRadii() const{
+
4187 return radii;
+
4188}
+
4189
-
4190 helios::vec3 axis_unit_vector = helios::make_vec3(nodes_T.at(1).x - nodes_T.at(0).x, nodes_T.at(1).y - nodes_T.at(0).y, nodes_T.at(1).z - nodes_T.at(0).z );
-
4191 float length = powf(powf(axis_unit_vector.x,2) + powf(axis_unit_vector.y,2) + powf(axis_unit_vector.z,2),0.5);
-
4192 axis_unit_vector = axis_unit_vector / length;
-
4193
-
4194 return axis_unit_vector;
-
4195}
-
-
4196
-
-
4197float Cone::getLength() const{
-
4198
-
4199 std::vector<vec3> nodes_T;
-
4200 nodes_T.resize( 2);
+
+
4190float Cone::getNodeRadius( int node_index ) const{
+
4191 if(node_index < 0 || node_index > 1 ){
+
4192 helios_runtime_error("ERROR (Cone::getNodeRadius): node number must be 0 or 1.");
+
4193 }
+
4194
+
4195 return radii.at(node_index);
+
4196}
+
+
4197
+
+ +
4199 return subdiv;
+
4200}
+
4201
-
4202 for( uint i=0; i<2; i++ ){
-
4203 nodes_T.at(i).x = transform[0] * nodes.at(i).x + transform[1] * nodes.at(i).y + transform[2] * nodes.at(i).z + transform[3];
-
4204 nodes_T.at(i).y = transform[4] * nodes.at(i).x + transform[5] * nodes.at(i).y + transform[6] * nodes.at(i).z + transform[7];
-
4205 nodes_T.at(i).z = transform[8] * nodes.at(i).x + transform[9] * nodes.at(i).y + transform[10] * nodes.at(i).z + transform[11];
-
4206 }
+
+
4202void Cone::setSubdivisionCount( uint a_subdiv ){
+
4203 subdiv = a_subdiv;
+
4204}
+
+
4205
+
+
4207
-
4208 float length = powf(powf(nodes_T.at(1).x - nodes_T.at(0).x, 2) + powf(nodes_T.at(1).y - nodes_T.at(0).y, 2) + powf(nodes_T.at(1).z - nodes_T.at(0).z, 2), 0.5);
-
4209 return length;
-
4210}
-
-
4211
-
-
4212void Cone::scaleLength( float S ){
-
4213
-
4214 //get the nodes and radii of the nodes with transformation matrix applied
-
4215 const std::vector<helios::vec3> &nodes_T = context->getConeObjectPointer(OID)->getNodeCoordinates();
-
4216 const std::vector<float> &radii_T = context->getConeObjectPointer(OID)->getNodeRadii();
-
4217
-
4218 // calculate the transformed axis unit vector of the cone
-
4219 vec3 axis_unit_vector = helios::make_vec3(nodes_T.at(1).x - nodes_T.at(0).x, nodes_T.at(1).y - nodes_T.at(0).y, nodes_T.at(1).z - nodes_T.at(0).z );
-
4220 float length = powf(powf(axis_unit_vector.x,2) + powf(axis_unit_vector.y,2) + powf(axis_unit_vector.z,2),0.5);
-
4221 axis_unit_vector = axis_unit_vector / length;
-
4222
-
4223 //translate node 0 back to origin
-
4224 context->getConeObjectPointer(OID)->translate(-1.0*nodes_T.at(0));
+
4208 std::vector<vec3> nodes_T;
+
4209 nodes_T.resize( 2 );
+
4210
+
4211 for( uint i=0; i<2; i++ ){
+
4212 nodes_T.at(i).x = transform[0] * nodes.at(i).x + transform[1] * nodes.at(i).y + transform[2] * nodes.at(i).z + transform[3];
+
4213 nodes_T.at(i).y = transform[4] * nodes.at(i).x + transform[5] * nodes.at(i).y + transform[6] * nodes.at(i).z + transform[7];
+
4214 nodes_T.at(i).z = transform[8] * nodes.at(i).x + transform[9] * nodes.at(i).y + transform[10] * nodes.at(i).z + transform[11];
+
4215 }
+
4216
+
4217 helios::vec3 axis_unit_vector = helios::make_vec3(nodes_T.at(1).x - nodes_T.at(0).x, nodes_T.at(1).y - nodes_T.at(0).y, nodes_T.at(1).z - nodes_T.at(0).z );
+
4218 float length = powf(powf(axis_unit_vector.x,2) + powf(axis_unit_vector.y,2) + powf(axis_unit_vector.z,2),0.5);
+
4219 axis_unit_vector = axis_unit_vector / length;
+
4220
+
4221 return axis_unit_vector;
+
4222}
+
+
4223
+
+
4224float Cone::getLength() const{
4225
-
4226 //rotate the cone to align with z axis
-
4227 helios::vec3 z_axis = make_vec3(0,0,1);
-
4228 //get the axis about which to rotate
-
4229 vec3 ra = cross( z_axis, axis_unit_vector);
-
4230 //get the angle to rotate
-
4231 float dot = axis_unit_vector.x*z_axis.x + axis_unit_vector.y*z_axis.y + axis_unit_vector.z*z_axis.z;
-
4232 float angle = acos_safe(dot);
-
4233
-
4234 //only rotate if the cone is not alread aligned with the z axis (i.e., angle is not zero. If zero, the axis of rotation is 0,0,0 and we end up with problems)
-
4235 if(angle != float(0.0)){
-
4236 context->getConeObjectPointer(OID)->rotate( -1*angle, ra );
-
4237 }
-
4238
-
4239 // scale the cone in the z (length) dimension
-
4240 float T[16], T_prim[16];
-
4241 makeScaleMatrix( make_vec3(1,1,S), T);
-
4242 matmult(T,transform,transform);
-
4243 for( uint UUID : UUIDs){
-
4244 if( context->doesPrimitiveExist( UUID ) ){
-
4245 context->getPrimitiveTransformationMatrix( UUID,T_prim);
-
4246 matmult(T,T_prim,T_prim);
-
4247 context->setPrimitiveTransformationMatrix( UUID,T_prim);
-
4248 }
-
4249 }
-
4250
-
4251 //rotate back
-
4252 if(angle != 0.0){
-
4253 context->getConeObjectPointer(OID)->rotate( angle, ra );
-
4254 }
-
4255
-
4256 // translate back
-
4257 context->getConeObjectPointer(OID)->translate(nodes_T.at(0));
-
4258
-
4259}
+
4226 std::vector<vec3> nodes_T;
+
4227 nodes_T.resize( 2);
+
4228
+
4229 for( uint i=0; i<2; i++ ){
+
4230 nodes_T.at(i).x = transform[0] * nodes.at(i).x + transform[1] * nodes.at(i).y + transform[2] * nodes.at(i).z + transform[3];
+
4231 nodes_T.at(i).y = transform[4] * nodes.at(i).x + transform[5] * nodes.at(i).y + transform[6] * nodes.at(i).z + transform[7];
+
4232 nodes_T.at(i).z = transform[8] * nodes.at(i).x + transform[9] * nodes.at(i).y + transform[10] * nodes.at(i).z + transform[11];
+
4233 }
+
4234
+
4235 float length = powf(powf(nodes_T.at(1).x - nodes_T.at(0).x, 2) + powf(nodes_T.at(1).y - nodes_T.at(0).y, 2) + powf(nodes_T.at(1).z - nodes_T.at(0).z, 2), 0.5);
+
4236 return length;
+
4237}
+
4238
+
+
4239void Cone::scaleLength( float S ){
+
4240
+
4241 //get the nodes and radii of the nodes with transformation matrix applied
+
4242 const std::vector<helios::vec3> &nodes_T = context->getConeObjectPointer(OID)->getNodeCoordinates();
+
4243 const std::vector<float> &radii_T = context->getConeObjectPointer(OID)->getNodeRadii();
+
4244
+
4245 // calculate the transformed axis unit vector of the cone
+
4246 vec3 axis_unit_vector = helios::make_vec3(nodes_T.at(1).x - nodes_T.at(0).x, nodes_T.at(1).y - nodes_T.at(0).y, nodes_T.at(1).z - nodes_T.at(0).z );
+
4247 float length = powf(powf(axis_unit_vector.x,2) + powf(axis_unit_vector.y,2) + powf(axis_unit_vector.z,2),0.5);
+
4248 axis_unit_vector = axis_unit_vector / length;
+
4249
+
4250 //translate node 0 back to origin
+
4251 context->getConeObjectPointer(OID)->translate(-1.0*nodes_T.at(0));
+
4252
+
4253 //rotate the cone to align with z axis
+
4254 helios::vec3 z_axis = make_vec3(0,0,1);
+
4255 //get the axis about which to rotate
+
4256 vec3 ra = cross( z_axis, axis_unit_vector);
+
4257 //get the angle to rotate
+
4258 float dot = axis_unit_vector.x*z_axis.x + axis_unit_vector.y*z_axis.y + axis_unit_vector.z*z_axis.z;
+
4259 float angle = acos_safe(dot);
4260
-
-
4261void Cone::scaleGirth( float S ){
-
4262
-
4263 //get the nodes and radii of the nodes with transformation matrix applied
-
4264 const std::vector<helios::vec3> &nodes_T = context->getConeObjectPointer(OID)->getNodeCoordinates();
-
4265 const std::vector<float> &radii_T = context->getConeObjectPointer(OID)->getNodeRadii();
-
4266
-
4267 // calculate the transformed axis unit vector of the cone
-
4268 vec3 axis_unit_vector = helios::make_vec3(nodes_T.at(1).x - nodes_T.at(0).x, nodes_T.at(1).y - nodes_T.at(0).y, nodes_T.at(1).z - nodes_T.at(0).z );
-
4269 axis_unit_vector.normalize();
-
4270
-
4271 //translate node 0 back to origin
-
4272 context->getConeObjectPointer(OID)->translate(-1.0*nodes_T.at(0));
-
4273 //rotate the cone to align with z axis
-
4274 helios::vec3 z_axis = make_vec3(0,0,1);
-
4275 //get the axis about which to rotate
-
4276 vec3 ra = cross( z_axis, axis_unit_vector);
-
4277 //get the angle to rotate
-
4278 float dot = axis_unit_vector*z_axis;
-
4279 float angle = acos_safe(dot);
-
4280 //only rotate if the cone is not already aligned with the z axis (i.e., angle is not zero. If zero, the axis of rotation is 0,0,0 and we end up with problems)
-
4281 if(angle != float(0.0)){
-
4282 context->getConeObjectPointer(OID)->rotate( -1*angle, ra );
-
4283 }
-
4284
-
4285 // scale the cone in the x and y dimensions
-
4286 context->scaleObject( OID, make_vec3(S,S,1) );
+
4261 //only rotate if the cone is not alread aligned with the z axis (i.e., angle is not zero. If zero, the axis of rotation is 0,0,0 and we end up with problems)
+
4262 if(angle != float(0.0)){
+
4263 context->getConeObjectPointer(OID)->rotate( -1*angle, ra );
+
4264 }
+
4265
+
4266 // scale the cone in the z (length) dimension
+
4267 float T[16], T_prim[16];
+
4268 makeScaleMatrix( make_vec3(1,1,S), T);
+
4269 matmult(T,transform,transform);
+
4270 for( uint UUID : UUIDs){
+
4271 if( context->doesPrimitiveExist( UUID ) ){
+
4272 context->getPrimitiveTransformationMatrix( UUID,T_prim);
+
4273 matmult(T,T_prim,T_prim);
+
4274 context->setPrimitiveTransformationMatrix( UUID,T_prim);
+
4275 }
+
4276 }
+
4277
+
4278 //rotate back
+
4279 if(angle != 0.0){
+
4280 context->getConeObjectPointer(OID)->rotate( angle, ra );
+
4281 }
+
4282
+
4283 // translate back
+
4284 context->getConeObjectPointer(OID)->translate(nodes_T.at(0));
+
4285
+
4286}
+
4287
-
4288
-
4289 //rotate back
-
4290 if(angle != 0.0){
-
4291 context->getConeObjectPointer(OID)->rotate( angle, ra );
-
4292 }
+
+
4288void Cone::scaleGirth( float S ){
+
4289
+
4290 //get the nodes and radii of the nodes with transformation matrix applied
+
4291 const std::vector<helios::vec3> &nodes_T = context->getConeObjectPointer(OID)->getNodeCoordinates();
+
4292 const std::vector<float> &radii_T = context->getConeObjectPointer(OID)->getNodeRadii();
4293
-
4294 // translate back
-
4295 context->getConeObjectPointer(OID)->translate(nodes_T.at(0));
-
4296
-
4297 radii.at(0) *= S;
-
4298 radii.at(1) *= S;
-
4299
-
4300}
-
-
4301
-
-
4302float Cone::getVolume() const{
-
4303 float r0 = getNodeRadius(0);
-
4304 float r1 = getNodeRadius(1);
-
4305 float h = getLength();
-
4306
-
4307 return M_PI * h / 3.f * (r0*r0 + r0*r1 + r1*r1);
-
4308}
-
-
4309
-
-
4310uint Context::addSphereObject(uint Ndivs, const vec3 &center, float radius ){
-
4311 return addSphereObject(Ndivs,center,{radius,radius,radius},{0.f,0.75f,0.f}); //Default color is green
-
4312}
-
-
4313
-
-
4314uint Context::addSphereObject(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color ){
-
4315 return addSphereObject(Ndivs,center,{radius,radius,radius},color);
-
4316}
-
-
4317
-
-
4318uint Context::addSphereObject(uint Ndivs, const vec3 &center, float radius, const char* texturefile ){
-
4319 return addSphereObject(Ndivs,center,{radius,radius,radius},texturefile);
-
4320}
-
-
4321
-
-
4322uint Context::addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius ){
+
4294 // calculate the transformed axis unit vector of the cone
+
4295 vec3 axis_unit_vector = helios::make_vec3(nodes_T.at(1).x - nodes_T.at(0).x, nodes_T.at(1).y - nodes_T.at(0).y, nodes_T.at(1).z - nodes_T.at(0).z );
+
4296 axis_unit_vector.normalize();
+
4297
+
4298 //translate node 0 back to origin
+
4299 context->getConeObjectPointer(OID)->translate(-1.0*nodes_T.at(0));
+
4300 //rotate the cone to align with z axis
+
4301 helios::vec3 z_axis = make_vec3(0,0,1);
+
4302 //get the axis about which to rotate
+
4303 vec3 ra = cross( z_axis, axis_unit_vector);
+
4304 //get the angle to rotate
+
4305 float dot = axis_unit_vector*z_axis;
+
4306 float angle = acos_safe(dot);
+
4307 //only rotate if the cone is not already aligned with the z axis (i.e., angle is not zero. If zero, the axis of rotation is 0,0,0 and we end up with problems)
+
4308 if(angle != float(0.0)){
+
4309 context->getConeObjectPointer(OID)->rotate( -1*angle, ra );
+
4310 }
+
4311
+
4312 // scale the cone in the x and y dimensions
+
4313 context->scaleObject( OID, make_vec3(S,S,1) );
+
4314
+
4315
+
4316 //rotate back
+
4317 if(angle != 0.0){
+
4318 context->getConeObjectPointer(OID)->rotate( angle, ra );
+
4319 }
+
4320
+
4321 // translate back
+
4322 context->getConeObjectPointer(OID)->translate(nodes_T.at(0));
4323
-
4324 return addSphereObject(Ndivs,center,radius,{0.f,0.75f,0.f}); //Default color is green
-
4325
-
4326}
-
-
4327
-
-
4328uint Context::addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const RGBcolor &color ){
-
4329
-
4330 if( radius.x<=0.f || radius.y<=0.f || radius.z<=0.f ){
-
4331 helios_runtime_error("ERROR (Context::addSphereObject): Radius of sphere must be positive.");
-
4332 }
+
4324 radii.at(0) *= S;
+
4325 radii.at(1) *= S;
+
4326
+
4327}
+
+
4328
+
+
4329float Cone::getVolume() const{
+
4330 float r0 = getNodeRadius(0);
+
4331 float r1 = getNodeRadius(1);
+
4332 float h = getLength();
4333
-
4334 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
-
4335
-
4336 float theta;
-
4337 float dtheta=float(M_PI)/float(Ndivs);
-
4338 float dphi=2.0f*float(M_PI)/float(Ndivs);
-
4339
-
4340 vec3 cart;
-
4341
-
4342 //bottom cap
-
4343 for( int j=0; j<Ndivs; j++ ){
+
4334 return M_PI * h / 3.f * (r0*r0 + r0*r1 + r1*r1);
+
4335}
+
+
4336
+
+
4337uint Context::addSphereObject(uint Ndivs, const vec3 &center, float radius ){
+
4338 return addSphereObject(Ndivs,center,{radius,radius,radius},{0.f,0.75f,0.f}); //Default color is green
+
4339}
+
+
4340
+
+
4341uint Context::addSphereObject(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color ){
+
4342 return addSphereObject(Ndivs,center,{radius,radius,radius},color);
+
4343}
+
4344
-
4345 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI), 0 ) );
-
4346 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4347 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+dtheta, float(j)*dphi ) );
-
4348 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4349 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+dtheta, float(j+1)*dphi ) );
-
4350 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4351
-
4352 UUID.push_back( addTriangle(v0,v1,v2,color) );
-
4353
-
4354 }
-
4355
-
4356 //top cap
-
4357 for( int j=0; j<Ndivs; j++ ){
-
4358
-
4359 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI), 0 ) );
-
4360 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4361 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI)-dtheta, float(j)*dphi ) );
-
4362 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4363 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI)-dtheta, float(j+1)*dphi ) );
-
4364 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4365
-
4366 UUID.push_back( addTriangle(v2,v1,v0,color) );
-
4367
-
4368 }
-
4369
-
4370 //middle
-
4371 for( int j=0; j<Ndivs; j++ ){
-
4372 for( int i=1; i<Ndivs-1; i++ ){
-
4373
-
4374 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i)*dtheta, float(j)*dphi ) );
-
4375 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4376 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j)*dphi ) );
-
4377 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4378 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j+1)*dphi ) );
-
4379 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4380 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i)*dtheta, float(j+1)*dphi ) );
-
4381 vec3 v3 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
+
4345uint Context::addSphereObject(uint Ndivs, const vec3 &center, float radius, const char* texturefile ){
+
4346 return addSphereObject(Ndivs,center,{radius,radius,radius},texturefile);
+
4347}
+
+
4348
+
+
4349uint Context::addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius ){
+
4350
+
4351 return addSphereObject(Ndivs,center,radius,{0.f,0.75f,0.f}); //Default color is green
+
4352
+
4353}
+
+
4354
+
+
4355uint Context::addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const RGBcolor &color ){
+
4356
+
4357 if( radius.x<=0.f || radius.y<=0.f || radius.z<=0.f ){
+
4358 helios_runtime_error("ERROR (Context::addSphereObject): Radius of sphere must be positive.");
+
4359 }
+
4360
+
4361 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
+
4362
+
4363 float theta;
+
4364 float dtheta=float(M_PI)/float(Ndivs);
+
4365 float dphi=2.0f*float(M_PI)/float(Ndivs);
+
4366
+
4367 vec3 cart;
+
4368
+
4369 //bottom cap
+
4370 for( int j=0; j<Ndivs; j++ ){
+
4371
+
4372 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI), 0 ) );
+
4373 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4374 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+dtheta, float(j)*dphi ) );
+
4375 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4376 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+dtheta, float(j+1)*dphi ) );
+
4377 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4378
+
4379 UUID.push_back( addTriangle(v0,v1,v2,color) );
+
4380
+
4381 }
4382
-
4383 UUID.push_back( addTriangle(v0,v1,v2,color) );
-
4384 UUID.push_back( addTriangle(v0,v2,v3,color) );
+
4383 //top cap
+
4384 for( int j=0; j<Ndivs; j++ ){
4385
-
4386 }
-
4387 }
-
4388
-
4389 auto* sphere_new = (new Sphere(currentObjectID, UUID, Ndivs, "", this));
-
4390
-
4391 float T[16], transform[16];
-
4392 sphere_new->getTransformationMatrix( transform );
-
4393
-
4394 makeScaleMatrix(radius,T);
-
4395 matmult(T,transform,transform);
+
4386 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI), 0 ) );
+
4387 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4388 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI)-dtheta, float(j)*dphi ) );
+
4389 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4390 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI)-dtheta, float(j+1)*dphi ) );
+
4391 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4392
+
4393 UUID.push_back( addTriangle(v2,v1,v0,color) );
+
4394
+
4395 }
4396
-
4397 makeTranslationMatrix(center,T);
-
4398 matmult(T,transform,transform);
-
4399 sphere_new->setTransformationMatrix( transform );
+
4397 //middle
+
4398 for( int j=0; j<Ndivs; j++ ){
+
4399 for( int i=1; i<Ndivs-1; i++ ){
4400
-
4401 sphere_new->setColor( color );
-
4402
-
4403 for( uint p : UUID){
-
4404 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
4405 }
-
4406
-
4407 objects[currentObjectID] = sphere_new;
-
4408 currentObjectID++;
-
4409 return currentObjectID-1;
-
4410
-
4411}
-
+
4401 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i)*dtheta, float(j)*dphi ) );
+
4402 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4403 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j)*dphi ) );
+
4404 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4405 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j+1)*dphi ) );
+
4406 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4407 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i)*dtheta, float(j+1)*dphi ) );
+
4408 vec3 v3 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4409
+
4410 UUID.push_back( addTriangle(v0,v1,v2,color) );
+
4411 UUID.push_back( addTriangle(v0,v2,v3,color) );
4412
-
-
4413uint Context::addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const char* texturefile ){
-
4414
-
4415 if( !validateTextureFileExtenstion(texturefile) ) {
-
4416 helios_runtime_error("ERROR (Context::addSphereObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
4417 }else if( !doesTextureFileExist(texturefile) ) {
-
4418 helios_runtime_error("ERROR (Context::addSphereObject): Texture file " + std::string(texturefile) + " does not exist.");
-
4419 }else if( radius.x<=0.f || radius.y<=0.f || radius.z<=0.f ){
-
4420 helios_runtime_error("ERROR (Context::addSphereObject): Radius of sphere must be positive.");
-
4421 }
-
4422
-
4423 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
-
4424
-
4425 float theta;
-
4426 float dtheta=float(M_PI)/float(Ndivs);
-
4427 float dphi=2.0f*float(M_PI)/float(Ndivs);
-
4428
-
4429 vec3 cart;
-
4430
-
4431 //bottom cap
-
4432 for( int j=0; j<Ndivs; j++ ){
+
4413 }
+
4414 }
+
4415
+
4416 auto* sphere_new = (new Sphere(currentObjectID, UUID, Ndivs, "", this));
+
4417
+
4418 float T[16], transform[16];
+
4419 sphere_new->getTransformationMatrix( transform );
+
4420
+
4421 makeScaleMatrix(radius,T);
+
4422 matmult(T,transform,transform);
+
4423
+
4424 makeTranslationMatrix(center,T);
+
4425 matmult(T,transform,transform);
+
4426 sphere_new->setTransformationMatrix( transform );
+
4427
+
4428 sphere_new->setColor( color );
+
4429
+
4430 for( uint p : UUID){
+
4431 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
4432 }
4433
-
4434 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI), 0 ) );
-
4435 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4436 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+dtheta, float(j)*dphi ) );
-
4437 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4438 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+dtheta, float(j+1)*dphi ) );
-
4439 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4440
-
4441 vec3 n0 = v0-center;
-
4442 n0.normalize();
-
4443 vec3 n1 = v1-center;
-
4444 n1.normalize();
-
4445 vec3 n2 = v2-center;
-
4446 n2.normalize();
-
4447
-
4448 vec2 uv0 = make_vec2( 1.f - atan2f( sinf((float(j)+0.5f)*dphi), -cosf((float(j)+0.5f)*dphi) )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
-
4449 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
-
4450 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
+
4434 objects[currentObjectID] = sphere_new;
+
4435 currentObjectID++;
+
4436 return currentObjectID-1;
+
4437
+
4438}
+
+
4439
+
+
4440uint Context::addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const char* texturefile ){
+
4441
+
4442 if( !validateTextureFileExtenstion(texturefile) ) {
+
4443 helios_runtime_error("ERROR (Context::addSphereObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
4444 }else if( !doesTextureFileExist(texturefile) ) {
+
4445 helios_runtime_error("ERROR (Context::addSphereObject): Texture file " + std::string(texturefile) + " does not exist.");
+
4446 }else if( radius.x<=0.f || radius.y<=0.f || radius.z<=0.f ){
+
4447 helios_runtime_error("ERROR (Context::addSphereObject): Radius of sphere must be positive.");
+
4448 }
+
4449
+
4450 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
4451
-
4452 if( j==Ndivs-1 ){
-
4453 uv2.x = 1;
-
4454 }
+
4452 float theta;
+
4453 float dtheta=float(M_PI)/float(Ndivs);
+
4454 float dphi=2.0f*float(M_PI)/float(Ndivs);
4455
-
4456 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
+
4456 vec3 cart;
4457
-
4458 }
-
4459
-
4460 //top cap
-
4461 for( int j=0; j<Ndivs; j++ ){
-
4462
-
4463 vec3 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI), 0 ) );
-
4464 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4465 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI)-dtheta, float(j+1)*dphi ) );
-
4466 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4467 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI)-dtheta, float(j)*dphi ) );
-
4468 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);;
-
4469
-
4470 vec3 n0 = v0-center;
-
4471 n0.normalize();
-
4472 vec3 n1 = v1-center;
-
4473 n1.normalize();
-
4474 vec3 n2 = v2-center;
-
4475 n2.normalize();
-
4476
-
4477 vec2 uv0 = make_vec2( 1.f - atan2f( sinf((float(j)+0.5f)*dphi), -cosf((float(j)+0.5f)*dphi) )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
-
4478 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
-
4479 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
-
4480
-
4481 if( j==Ndivs-1 ){
-
4482 uv2.x = 1;
-
4483 }
+
4458 //bottom cap
+
4459 for( int j=0; j<Ndivs; j++ ){
+
4460
+
4461 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI), 0 ) );
+
4462 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4463 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+dtheta, float(j)*dphi ) );
+
4464 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4465 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+dtheta, float(j+1)*dphi ) );
+
4466 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4467
+
4468 vec3 n0 = v0-center;
+
4469 n0.normalize();
+
4470 vec3 n1 = v1-center;
+
4471 n1.normalize();
+
4472 vec3 n2 = v2-center;
+
4473 n2.normalize();
+
4474
+
4475 vec2 uv0 = make_vec2( 1.f - atan2f( sinf((float(j)+0.5f)*dphi), -cosf((float(j)+0.5f)*dphi) )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
+
4476 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
+
4477 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
+
4478
+
4479 if( j==Ndivs-1 ){
+
4480 uv2.x = 1;
+
4481 }
+
4482
+
4483 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
4484
-
4485 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
+
4485 }
4486
-
4487 }
-
4488
-
4489 //middle
-
4490 for( int j=0; j<Ndivs; j++ ){
-
4491 for( int i=1; i<Ndivs-1; i++ ){
-
4492
-
4493 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i)*dtheta, float(j)*dphi ) );
-
4494 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4495 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j)*dphi ) );
-
4496 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4497 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j+1)*dphi ) );
-
4498 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4499 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i)*dtheta, float(j+1)*dphi ) );
-
4500 vec3 v3 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
-
4501
-
4502 vec3 n0 = v0-center;
-
4503 n0.normalize();
-
4504 vec3 n1 = v1-center;
-
4505 n1.normalize();
-
4506 vec3 n2 = v2-center;
-
4507 n2.normalize();
-
4508 vec3 n3 = v3-center;
-
4509 n3.normalize();
-
4510
-
4511 vec2 uv0 = make_vec2( 1.f - atan2f( n0.x, -n0.y )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
-
4512 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
-
4513 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
-
4514 vec2 uv3 = make_vec2( 1.f - atan2f( n3.x, -n3.y )/float(2.f*M_PI) - 0.5f, 1.f - n3.z*0.5f - 0.5f );
+
4487 //top cap
+
4488 for( int j=0; j<Ndivs; j++ ){
+
4489
+
4490 vec3 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI), 0 ) );
+
4491 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4492 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI)-dtheta, float(j+1)*dphi ) );
+
4493 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4494 cart = sphere2cart( make_SphericalCoord(1.f, 0.5f*float(M_PI)-dtheta, float(j)*dphi ) );
+
4495 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);;
+
4496
+
4497 vec3 n0 = v0-center;
+
4498 n0.normalize();
+
4499 vec3 n1 = v1-center;
+
4500 n1.normalize();
+
4501 vec3 n2 = v2-center;
+
4502 n2.normalize();
+
4503
+
4504 vec2 uv0 = make_vec2( 1.f - atan2f( sinf((float(j)+0.5f)*dphi), -cosf((float(j)+0.5f)*dphi) )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
+
4505 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
+
4506 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
+
4507
+
4508 if( j==Ndivs-1 ){
+
4509 uv2.x = 1;
+
4510 }
+
4511
+
4512 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
+
4513
+
4514 }
4515
-
4516 if( j==Ndivs-1 ){
-
4517 uv2.x = 1;
-
4518 uv3.x = 1;
-
4519 }
-
4520
-
4521 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
-
4522 UUID.push_back( addTriangle(v0,v2,v3,texturefile,uv0,uv2,uv3) );
-
4523
-
4524 }
-
4525 }
-
4526
-
4527 auto* sphere_new = (new Sphere(currentObjectID, UUID, Ndivs, texturefile, this));
+
4516 //middle
+
4517 for( int j=0; j<Ndivs; j++ ){
+
4518 for( int i=1; i<Ndivs-1; i++ ){
+
4519
+
4520 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i)*dtheta, float(j)*dphi ) );
+
4521 vec3 v0 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4522 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j)*dphi ) );
+
4523 vec3 v1 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4524 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j+1)*dphi ) );
+
4525 vec3 v2 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
+
4526 cart = sphere2cart( make_SphericalCoord(1.f, -0.5f*float(M_PI)+float(i)*dtheta, float(j+1)*dphi ) );
+
4527 vec3 v3 = center + make_vec3(cart.x*radius.x,cart.y*radius.y,cart.z*radius.z);
4528
-
4529 float T[16], transform[16];
-
4530 sphere_new->getTransformationMatrix( transform );
-
4531
-
4532 makeScaleMatrix(radius,T);
-
4533 matmult(T,transform,transform);
-
4534
-
4535 makeTranslationMatrix(center,T);
-
4536 matmult(T,transform,transform);
-
4537 sphere_new->setTransformationMatrix( transform );
-
4538
-
4539 for( uint p : UUID){
-
4540 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
4541 }
+
4529 vec3 n0 = v0-center;
+
4530 n0.normalize();
+
4531 vec3 n1 = v1-center;
+
4532 n1.normalize();
+
4533 vec3 n2 = v2-center;
+
4534 n2.normalize();
+
4535 vec3 n3 = v3-center;
+
4536 n3.normalize();
+
4537
+
4538 vec2 uv0 = make_vec2( 1.f - atan2f( n0.x, -n0.y )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
+
4539 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
+
4540 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
+
4541 vec2 uv3 = make_vec2( 1.f - atan2f( n3.x, -n3.y )/float(2.f*M_PI) - 0.5f, 1.f - n3.z*0.5f - 0.5f );
4542
-
4543 objects[currentObjectID] = sphere_new;
-
4544 currentObjectID++;
-
4545
-
4546 return currentObjectID-1;
+
4543 if( j==Ndivs-1 ){
+
4544 uv2.x = 1;
+
4545 uv3.x = 1;
+
4546 }
4547
-
4548}
-
-
4549
-
-
4550uint Context::addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv) {
-
4551
-
4552 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
4548 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
+
4549 UUID.push_back( addTriangle(v0,v2,v3,texturefile,uv0,uv2,uv3) );
+
4550
+
4551 }
+
4552 }
4553
-
4554 return addTileObject(center,size,rotation,subdiv,color);
-
4555}
-
-
4556
-
-
4557uint Context::addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color ){
+
4554 auto* sphere_new = (new Sphere(currentObjectID, UUID, Ndivs, texturefile, this));
+
4555
+
4556 float T[16], transform[16];
+
4557 sphere_new->getTransformationMatrix( transform );
4558
-
4559 if( size.x==0 || size.y==0 ){
-
4560 helios_runtime_error("ERROR (Context::addTileObject): Size of tile must be greater than 0.");
-
4561 }else if( subdiv.x<1 || subdiv.y<1 ){
-
4562 helios_runtime_error("ERROR (Context::addTileObject): Number of tile subdivisions must be greater than 0.");
-
4563 }
-
4564
-
4565 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
-
4566
-
4567 vec2 subsize;
-
4568 subsize.x = size.x/float(subdiv.x);
-
4569 subsize.y = size.y/float(subdiv.y);
-
4570
-
4571 vec3 subcenter;
+
4559 makeScaleMatrix(radius,T);
+
4560 matmult(T,transform,transform);
+
4561
+
4562 makeTranslationMatrix(center,T);
+
4563 matmult(T,transform,transform);
+
4564 sphere_new->setTransformationMatrix( transform );
+
4565
+
4566 for( uint p : UUID){
+
4567 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
4568 }
+
4569
+
4570 objects[currentObjectID] = sphere_new;
+
4571 currentObjectID++;
4572
-
4573 for( uint j=0; j<subdiv.y; j++ ){
-
4574 for( uint i=0; i<subdiv.x; i++ ){
-
4575
-
4576 subcenter = make_vec3(-0.5f*size.x+(float(i)+0.5f)*subsize.x,-0.5f*size.y+(float(j)+0.5f)*subsize.y,0.f);
-
4577
-
4578 UUID.push_back( addPatch( subcenter, subsize, make_SphericalCoord(0,0), color ) );
-
4579
-
4580 if( rotation.elevation!=0.f ){
-
4581 getPrimitivePointer_private( UUID.back() )->rotate( -rotation.elevation, "x" );
-
4582 }
-
4583 if( rotation.azimuth!=0.f ){
-
4584 getPrimitivePointer_private( UUID.back() )->rotate( -rotation.azimuth, "z" );
-
4585 }
-
4586 getPrimitivePointer_private( UUID.back() )->translate( center );
-
4587
-
4588 }
-
4589 }
-
4590
-
4591 auto* tile_new = (new Tile(currentObjectID, UUID, subdiv, "", this));
-
4592
-
4593 float T[16], S[16], R[16];
-
4594
-
4595 float transform[16];
-
4596 tile_new->getTransformationMatrix( transform );
+
4573 return currentObjectID-1;
+
4574
+
4575}
+
+
4576
+
+
4577uint Context::addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv) {
+
4578
+
4579 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
4580
+
4581 return addTileObject(center,size,rotation,subdiv,color);
+
4582}
+
+
4583
+
+
4584uint Context::addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color ){
+
4585
+
4586 if( size.x==0 || size.y==0 ){
+
4587 helios_runtime_error("ERROR (Context::addTileObject): Size of tile must be greater than 0.");
+
4588 }else if( subdiv.x<1 || subdiv.y<1 ){
+
4589 helios_runtime_error("ERROR (Context::addTileObject): Number of tile subdivisions must be greater than 0.");
+
4590 }
+
4591
+
4592 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
+
4593
+
4594 vec2 subsize;
+
4595 subsize.x = size.x/float(subdiv.x);
+
4596 subsize.y = size.y/float(subdiv.y);
4597
-
4598 makeScaleMatrix(make_vec3(size.x,size.y,1.f),S);
-
4599 matmult(S,transform,transform);
-
4600
-
4601 makeRotationMatrix( -rotation.elevation,"x",R);
-
4602 matmult(R,transform,transform);
-
4603 makeRotationMatrix( -rotation.azimuth,"z",R);
-
4604 matmult(R,transform,transform);
-
4605
-
4606 makeTranslationMatrix(center,T);
-
4607 matmult(T,transform,transform);
-
4608 tile_new->setTransformationMatrix( transform );
-
4609
-
4610 tile_new->setColor( color );
-
4611
-
4612 for( uint p : UUID){
-
4613 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
4614 }
-
4615
-
4616 objects[currentObjectID] = tile_new;
-
4617 currentObjectID++;
-
4618 return currentObjectID-1;
+
4598 vec3 subcenter;
+
4599
+
4600 for( uint j=0; j<subdiv.y; j++ ){
+
4601 for( uint i=0; i<subdiv.x; i++ ){
+
4602
+
4603 subcenter = make_vec3(-0.5f*size.x+(float(i)+0.5f)*subsize.x,-0.5f*size.y+(float(j)+0.5f)*subsize.y,0.f);
+
4604
+
4605 UUID.push_back( addPatch( subcenter, subsize, make_SphericalCoord(0,0), color ) );
+
4606
+
4607 if( rotation.elevation!=0.f ){
+
4608 getPrimitivePointer_private( UUID.back() )->rotate( -rotation.elevation, "x" );
+
4609 }
+
4610 if( rotation.azimuth!=0.f ){
+
4611 getPrimitivePointer_private( UUID.back() )->rotate( -rotation.azimuth, "z" );
+
4612 }
+
4613 getPrimitivePointer_private( UUID.back() )->translate( center );
+
4614
+
4615 }
+
4616 }
+
4617
+
4618 auto* tile_new = (new Tile(currentObjectID, UUID, subdiv, "", this));
4619
-
4620}
-
+
4620 float T[16], S[16], R[16];
4621
-
-
4622uint Context::addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile ){
-
4623
-
4624 if( !validateTextureFileExtenstion(texturefile) ) {
-
4625 helios_runtime_error("ERROR (Context::addTileObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
4626 }else if( !doesTextureFileExist(texturefile) ) {
-
4627 helios_runtime_error("ERROR (Context::addTileObject): Texture file " + std::string(texturefile) + " does not exist.");
-
4628 }else if( size.x==0 || size.y==0 ){
-
4629 helios_runtime_error("ERROR (Context::addTileObject): Size of tile must be greater than 0.");
-
4630 }else if( subdiv.x<1 || subdiv.y<1 ){
-
4631 helios_runtime_error("ERROR (Context::addTileObject): Number of tile subdivisions must be greater than 0.");
-
4632 }
-
4633
-
4634 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
-
4635
-
4636 vec2 subsize;
-
4637 subsize.x = size.x/float(subdiv.x);
-
4638 subsize.y = size.y/float(subdiv.y);
-
4639
-
4640 vec3 subcenter;
-
4641
-
4642 std::vector<helios::vec2> uv;
-
4643 uv.resize(4);
-
4644 vec2 uv_sub;
-
4645 uv_sub.x = 1.f/float(subdiv.x);
-
4646 uv_sub.y = 1.f/float(subdiv.y);
-
4647
-
4648 addTexture( texturefile );
-
4649 const std::vector<std::vector<bool> >* alpha;
-
4650 if( textures.at(texturefile).hasTransparencyChannel() ){
-
4651 alpha = textures.at(texturefile).getTransparencyData();
-
4652 }
-
4653
-
4654 const int2 &sz = textures.at(texturefile).getImageResolution();
-
4655 if( subdiv.x>=sz.x || subdiv.y>=sz.y ){
-
4656 helios_runtime_error("ERROR (Context::addTileObject): The resolution of the texture image '" + std::string(texturefile) + "' is lower than the number of tile subdivisions. Increase resolution of the texture image.");
-
4657 }
-
4658
-
4659 for( uint j=0; j<subdiv.y; j++ ){
-
4660 for( uint i=0; i<subdiv.x; i++ ){
-
4661
-
4662 subcenter = make_vec3(-0.5f*size.x+(float(i)+0.5f)*subsize.x,-0.5f*size.y+(float(j)+0.5f)*subsize.y,0.f);
-
4663
-
4664 uv.at(0) = make_vec2(float(i)*uv_sub.x,float(j)*uv_sub.y);
-
4665 uv.at(1) = make_vec2(float(i+1)*uv_sub.x,float(j)*uv_sub.y);
-
4666 uv.at(2) = make_vec2(float(i+1)*uv_sub.x,float(j+1)*uv_sub.y);
-
4667 uv.at(3) = make_vec2(float(i)*uv_sub.x,float(j+1)*uv_sub.y);
+
4622 float transform[16];
+
4623 tile_new->getTransformationMatrix( transform );
+
4624
+
4625 makeScaleMatrix(make_vec3(size.x,size.y,1.f),S);
+
4626 matmult(S,transform,transform);
+
4627
+
4628 makeRotationMatrix( -rotation.elevation,"x",R);
+
4629 matmult(R,transform,transform);
+
4630 makeRotationMatrix( -rotation.azimuth,"z",R);
+
4631 matmult(R,transform,transform);
+
4632
+
4633 makeTranslationMatrix(center,T);
+
4634 matmult(T,transform,transform);
+
4635 tile_new->setTransformationMatrix( transform );
+
4636
+
4637 tile_new->setColor( color );
+
4638
+
4639 for( uint p : UUID){
+
4640 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
4641 }
+
4642
+
4643 objects[currentObjectID] = tile_new;
+
4644 currentObjectID++;
+
4645 return currentObjectID-1;
+
4646
+
4647}
+
+
4648
+
+
4649uint Context::addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile ){
+
4650
+
4651 if( !validateTextureFileExtenstion(texturefile) ) {
+
4652 helios_runtime_error("ERROR (Context::addTileObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
4653 }else if( !doesTextureFileExist(texturefile) ) {
+
4654 helios_runtime_error("ERROR (Context::addTileObject): Texture file " + std::string(texturefile) + " does not exist.");
+
4655 }else if( size.x==0 || size.y==0 ){
+
4656 helios_runtime_error("ERROR (Context::addTileObject): Size of tile must be greater than 0.");
+
4657 }else if( subdiv.x<1 || subdiv.y<1 ){
+
4658 helios_runtime_error("ERROR (Context::addTileObject): Number of tile subdivisions must be greater than 0.");
+
4659 }
+
4660
+
4661 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
+
4662
+
4663 vec2 subsize;
+
4664 subsize.x = size.x/float(subdiv.x);
+
4665 subsize.y = size.y/float(subdiv.y);
+
4666
+
4667 vec3 subcenter;
4668
-
4669 auto* patch_new = (new Patch( texturefile, uv, textures, 0, currentUUID ));
-
4670
-
4671 if( patch_new->getSolidFraction()==0 ){
-
4672 delete patch_new;
-
4673 continue;
-
4674 }
-
4675
-
4676 assert( size.x>0.f && size.y>0.f );
-
4677 patch_new->scale( make_vec3(subsize.x,subsize.y,1) );
-
4678
-
4679 patch_new->translate( subcenter );
+
4669 std::vector<helios::vec2> uv;
+
4670 uv.resize(4);
+
4671 vec2 uv_sub;
+
4672 uv_sub.x = 1.f/float(subdiv.x);
+
4673 uv_sub.y = 1.f/float(subdiv.y);
+
4674
+
4675 addTexture( texturefile );
+
4676 const std::vector<std::vector<bool> >* alpha;
+
4677 if( textures.at(texturefile).hasTransparencyChannel() ){
+
4678 alpha = textures.at(texturefile).getTransparencyData();
+
4679 }
4680
-
4681 if( rotation.elevation!=0 ){
-
4682 patch_new->rotate(-rotation.elevation, "x");
-
4683 }
-
4684 if( rotation.azimuth!=0 ){
-
4685 patch_new->rotate(-rotation.azimuth, "z");
-
4686 }
-
4687
-
4688 patch_new->translate( center );
-
4689
-
4690 primitives[currentUUID] = patch_new;
- -
4692 currentUUID++;
-
4693 UUID.push_back(currentUUID-1);
-
4694
+
4681 const int2 &sz = textures.at(texturefile).getImageResolution();
+
4682 if( subdiv.x>=sz.x || subdiv.y>=sz.y ){
+
4683 helios_runtime_error("ERROR (Context::addTileObject): The resolution of the texture image '" + std::string(texturefile) + "' is lower than the number of tile subdivisions. Increase resolution of the texture image.");
+
4684 }
+
4685
+
4686 for( uint j=0; j<subdiv.y; j++ ){
+
4687 for( uint i=0; i<subdiv.x; i++ ){
+
4688
+
4689 subcenter = make_vec3(-0.5f*size.x+(float(i)+0.5f)*subsize.x,-0.5f*size.y+(float(j)+0.5f)*subsize.y,0.f);
+
4690
+
4691 uv.at(0) = make_vec2(float(i)*uv_sub.x,float(j)*uv_sub.y);
+
4692 uv.at(1) = make_vec2(float(i+1)*uv_sub.x,float(j)*uv_sub.y);
+
4693 uv.at(2) = make_vec2(float(i+1)*uv_sub.x,float(j+1)*uv_sub.y);
+
4694 uv.at(3) = make_vec2(float(i)*uv_sub.x,float(j+1)*uv_sub.y);
4695
-
4696 }
-
4697 }
-
4698
-
4699 auto* tile_new = (new Tile(currentObjectID, UUID, subdiv, texturefile, this));
-
4700
-
4701 float T[16], S[16], R[16];
+
4696 auto* patch_new = (new Patch( texturefile, uv, textures, 0, currentUUID ));
+
4697
+
4698 if( patch_new->getSolidFraction()==0 ){
+
4699 delete patch_new;
+
4700 continue;
+
4701 }
4702
-
4703 float transform[16];
-
4704 tile_new->getTransformationMatrix( transform );
+
4703 assert( size.x>0.f && size.y>0.f );
+
4704 patch_new->scale( make_vec3(subsize.x,subsize.y,1) );
4705
-
4706 makeScaleMatrix(make_vec3(size.x,size.y,1.f),S);
-
4707 matmult(S,transform,transform);
-
4708
-
4709 makeRotationMatrix( -rotation.elevation,"x",R);
-
4710 matmult(R,transform,transform);
-
4711 makeRotationMatrix( -rotation.azimuth,"z",R);
-
4712 matmult(R,transform,transform);
-
4713
-
4714 makeTranslationMatrix(center,T);
-
4715 matmult(T,transform,transform);
-
4716 tile_new->setTransformationMatrix( transform );
-
4717
-
4718 for( uint p : UUID){
-
4719 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
4720 }
+
4706 patch_new->translate( subcenter );
+
4707
+
4708 if( rotation.elevation!=0 ){
+
4709 patch_new->rotate(-rotation.elevation, "x");
+
4710 }
+
4711 if( rotation.azimuth!=0 ){
+
4712 patch_new->rotate(-rotation.azimuth, "z");
+
4713 }
+
4714
+
4715 patch_new->translate( center );
+
4716
+
4717 primitives[currentUUID] = patch_new;
+ +
4719 currentUUID++;
+
4720 UUID.push_back(currentUUID-1);
4721
-
4722 objects[currentObjectID] = tile_new;
-
4723 currentObjectID++;
-
4724 return currentObjectID-1;
+
4722
+
4723 }
+
4724 }
4725
-
4726}
-
+
4726 auto* tile_new = (new Tile(currentObjectID, UUID, subdiv, texturefile, this));
4727
-
-
4728uint Context::addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius ){
+
4728 float T[16], S[16], R[16];
4729
-
4730 uint node_count = nodes.size();
-
4731
-
4732 std::vector<RGBcolor> color;
-
4733 color.resize(node_count);
-
4734
-
4735 for( uint i=0; i<node_count; i++ ){
-
4736 color.at(i) = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
-
4737 }
-
4738
-
4739 return addTubeObject(radial_subdivisions, nodes, radius, color);
+
4730 float transform[16];
+
4731 tile_new->getTransformationMatrix( transform );
+
4732
+
4733 makeScaleMatrix(make_vec3(size.x,size.y,1.f),S);
+
4734 matmult(S,transform,transform);
+
4735
+
4736 makeRotationMatrix( -rotation.elevation,"x",R);
+
4737 matmult(R,transform,transform);
+
4738 makeRotationMatrix( -rotation.azimuth,"z",R);
+
4739 matmult(R,transform,transform);
4740
-
4741}
-
-
4742
-
-
4743uint Context::addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color ){
+
4741 makeTranslationMatrix(center,T);
+
4742 matmult(T,transform,transform);
+
4743 tile_new->setTransformationMatrix( transform );
4744
-
4745 const uint node_count = nodes.size();
-
4746
-
4747 if( node_count==0 ){
-
4748 helios_runtime_error("ERROR (Context::addTubeObject): Node and radius arrays are empty.");
-
4749 }else if( node_count!=radius.size() ){
-
4750 helios_runtime_error("ERROR (Context::addTubeObject): Size of `nodes' and `radius' arguments must agree.");
-
4751 }else if( node_count!=color.size() ){
-
4752 helios_runtime_error("ERROR (Context::addTubeObject): Size of `nodes' and `color' arguments must agree.");
-
4753 }
+
4745 for( uint p : UUID){
+
4746 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
4747 }
+
4748
+
4749 objects[currentObjectID] = tile_new;
+
4750 currentObjectID++;
+
4751 return currentObjectID-1;
+
4752
+
4753}
+
4754
-
4755 vec3 axial_vector;
-
4756 std::vector<float> cfact(radial_subdivisions + 1);
-
4757 std::vector<float> sfact(radial_subdivisions + 1);
-
4758 std::vector<std::vector<vec3>> triangle_vertices;
-
4759 resize_vector(triangle_vertices, radial_subdivisions + 1, node_count);
-
4760
-
4761 // Initialize trigonometric factors for circle points
-
4762 for (int j = 0; j < radial_subdivisions + 1; j++) {
-
4763 cfact[j] = cosf(2.f * float(M_PI) * float(j) / float(radial_subdivisions));
-
4764 sfact[j] = sinf(2.f * float(M_PI) * float(j) / float(radial_subdivisions));
-
4765 }
-
4766
-
4767 vec3 initial_radial(1.0f, 0.0f, 0.0f);
-
4768 vec3 previous_axial_vector;
-
4769 vec3 previous_radial_dir;
-
4770
-
4771 for (int i = 0; i < node_count; i++) { // Looping over tube segments
-
4772 if (radius.at(i) < 0) {
-
4773 helios_runtime_error("ERROR (Context::addTubeObject): Radius of tube must be positive.");
-
4774 }
-
4775
-
4776 if (i == 0) {
-
4777 axial_vector = nodes[i + 1] - nodes[i];
-
4778 axial_vector.normalize();
-
4779 if (fabs(axial_vector * initial_radial) > 0.99f) {
-
4780 initial_radial = vec3(0.0f, 1.0f, 0.0f); // Avoid parallel vectors
-
4781 }
-
4782 previous_radial_dir = cross(axial_vector, initial_radial).normalize();
-
4783 } else {
-
4784 if (i == node_count - 1) {
-
4785 axial_vector = nodes[i] - nodes[i - 1];
-
4786 } else {
-
4787 axial_vector = 0.5f * ((nodes[i] - nodes[i - 1]) + (nodes[i + 1] - nodes[i]));
-
4788 }
-
4789 axial_vector.normalize();
-
4790
-
4791 // Calculate radial direction using parallel transport
-
4792 vec3 rotation_axis = cross(previous_axial_vector, axial_vector);
-
4793 if (rotation_axis.magnitude() > 1e-6) {
-
4794 float angle = acos(std::clamp(previous_axial_vector * axial_vector, -1.0f, 1.0f));
-
4795 previous_radial_dir = rotatePointAboutLine(previous_radial_dir, nullorigin, rotation_axis, angle);
-
4796 }
-
4797// else {
-
4798// // Handle the case of nearly parallel vectors
-
4799// // Ensure previous_radial_dir remains orthogonal to axial_vector
-
4800// previous_radial_dir = cross(axial_vector, previous_radial_dir);
-
4801// if (previous_radial_dir.magnitude() < 1e-6) {
-
4802// // If still degenerate, choose another orthogonal direction
-
4803// previous_radial_dir = cross(axial_vector, vec3(1.0f, 0.0f, 0.0f));
-
4804// }
-
4805// previous_radial_dir.normalize();
-
4806// }
-
4807 }
-
4808
-
4809 previous_axial_vector = axial_vector;
-
4810
-
4811 vec3 radial_dir = previous_radial_dir;
-
4812 vec3 orthogonal_dir = cross(radial_dir, axial_vector);
-
4813 orthogonal_dir.normalize();
-
4814
-
4815 for (int j = 0; j < radial_subdivisions + 1; j++) {
-
4816 vec3 normal = cfact[j] * radius[i] * radial_dir + sfact[j] * radius[i] * orthogonal_dir;
-
4817 triangle_vertices[i][j] = nodes[i] + normal;
-
4818 }
-
4819 }
-
4820
-
4821
-
4822 std::vector<uint> UUIDs(2 * (node_count-1) * radial_subdivisions );
-
4823 vec3 v0, v1, v2;
-
4824
-
4825 int ii=0;
-
4826 for(int j=0; j < radial_subdivisions; j++ ) {
-
4827 for (int i = 0; i < node_count - 1; i++) {
-
4828
-
4829 v0 = triangle_vertices[i][j];
-
4830 v1 = triangle_vertices[i + 1][j + 1];
-
4831 v2 = triangle_vertices[i][j + 1];
-
4832
-
4833 UUIDs.at(ii) = addTriangle(v0, v1, v2, color.at(i));
-
4834
-
4835 v0 = triangle_vertices[i][j];
-
4836 v1 = triangle_vertices[i + 1][j];
-
4837 v2 = triangle_vertices[i + 1][j + 1];
-
4838
-
4839 UUIDs.at(ii + 1) = addTriangle(v0, v1, v2, color.at(i));
-
4840
-
4841 ii += 2;
-
4842 }
-
4843 }
-
4844
-
4845 auto* tube_new = (new Tube(currentObjectID, UUIDs, nodes, radius, color, triangle_vertices, radial_subdivisions, "", this));
-
4846
-
4847 for( uint p : UUIDs){
-
4848 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
4849 }
-
4850
-
4851 objects[currentObjectID] = tube_new;
-
4852 currentObjectID++;
-
4853 return currentObjectID-1;
-
4854
-
4855}
-
-
4856
-
-
4857uint Context::addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile ){
-
4858 size_t node_count = nodes.size();
-
4859 std::vector<float> textureuv_ufrac(node_count);
-
4860 for( int i=0; i<node_count; i++ ){
-
4861 textureuv_ufrac.at(i) = float(i)/float(node_count-1);
-
4862 }
-
4863
-
4864 return addTubeObject( radial_subdivisions, nodes, radius, texturefile, textureuv_ufrac );
-
4865}
-
-
4866
-
-
4867uint Context::addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile, const std::vector<float> &textureuv_ufrac) {
-
4868 if (!validateTextureFileExtenstion(texturefile)) {
-
4869 helios_runtime_error("ERROR (Context::addTubeObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
4870 } else if (!doesTextureFileExist(texturefile)) {
-
4871 helios_runtime_error("ERROR (Context::addTubeObject): Texture file " + std::string(texturefile) + " does not exist.");
-
4872 }
+
+
4755uint Context::addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius ){
+
4756
+
4757 uint node_count = nodes.size();
+
4758
+
4759 std::vector<RGBcolor> color;
+
4760 color.resize(node_count);
+
4761
+
4762 for( uint i=0; i<node_count; i++ ){
+
4763 color.at(i) = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
4764 }
+
4765
+
4766 return addTubeObject(radial_subdivisions, nodes, radius, color);
+
4767
+
4768}
+
+
4769
+
+
4770uint Context::addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color ){
+
4771
+
4772 const uint node_count = nodes.size();
+
4773
+
4774 if( node_count==0 ){
+
4775 helios_runtime_error("ERROR (Context::addTubeObject): Node and radius arrays are empty.");
+
4776 }else if( node_count!=radius.size() ){
+
4777 helios_runtime_error("ERROR (Context::addTubeObject): Size of `nodes' and `radius' arguments must agree.");
+
4778 }else if( node_count!=color.size() ){
+
4779 helios_runtime_error("ERROR (Context::addTubeObject): Size of `nodes' and `color' arguments must agree.");
+
4780 }
+
4781
+
4782 vec3 axial_vector;
+
4783 std::vector<float> cfact(radial_subdivisions + 1);
+
4784 std::vector<float> sfact(radial_subdivisions + 1);
+
4785 std::vector<std::vector<vec3>> triangle_vertices;
+
4786 resize_vector(triangle_vertices, radial_subdivisions + 1, node_count);
+
4787
+
4788 // Initialize trigonometric factors for circle points
+
4789 for (int j = 0; j < radial_subdivisions + 1; j++) {
+
4790 cfact[j] = cosf(2.f * float(M_PI) * float(j) / float(radial_subdivisions));
+
4791 sfact[j] = sinf(2.f * float(M_PI) * float(j) / float(radial_subdivisions));
+
4792 }
+
4793
+
4794 vec3 initial_radial(1.0f, 0.0f, 0.0f);
+
4795 vec3 previous_axial_vector;
+
4796 vec3 previous_radial_dir;
+
4797
+
4798 for (int i = 0; i < node_count; i++) { // Looping over tube segments
+
4799 if (radius.at(i) < 0) {
+
4800 helios_runtime_error("ERROR (Context::addTubeObject): Radius of tube must be positive.");
+
4801 }
+
4802
+
4803 if (i == 0) {
+
4804 axial_vector = nodes[i + 1] - nodes[i];
+
4805 axial_vector.normalize();
+
4806 if (fabs(axial_vector * initial_radial) > 0.99f) {
+
4807 initial_radial = vec3(0.0f, 1.0f, 0.0f); // Avoid parallel vectors
+
4808 }
+
4809 previous_radial_dir = cross(axial_vector, initial_radial).normalize();
+
4810 } else {
+
4811 if (i == node_count - 1) {
+
4812 axial_vector = nodes[i] - nodes[i - 1];
+
4813 } else {
+
4814 axial_vector = 0.5f * ((nodes[i] - nodes[i - 1]) + (nodes[i + 1] - nodes[i]));
+
4815 }
+
4816 axial_vector.normalize();
+
4817
+
4818 // Calculate radial direction using parallel transport
+
4819 vec3 rotation_axis = cross(previous_axial_vector, axial_vector);
+
4820 if (rotation_axis.magnitude() > 1e-6) {
+
4821 float angle = acos(std::clamp(previous_axial_vector * axial_vector, -1.0f, 1.0f));
+
4822 previous_radial_dir = rotatePointAboutLine(previous_radial_dir, nullorigin, rotation_axis, angle);
+
4823 }
+
4824// else {
+
4825// // Handle the case of nearly parallel vectors
+
4826// // Ensure previous_radial_dir remains orthogonal to axial_vector
+
4827// previous_radial_dir = cross(axial_vector, previous_radial_dir);
+
4828// if (previous_radial_dir.magnitude() < 1e-6) {
+
4829// // If still degenerate, choose another orthogonal direction
+
4830// previous_radial_dir = cross(axial_vector, vec3(1.0f, 0.0f, 0.0f));
+
4831// }
+
4832// previous_radial_dir.normalize();
+
4833// }
+
4834 }
+
4835
+
4836 previous_axial_vector = axial_vector;
+
4837
+
4838 vec3 radial_dir = previous_radial_dir;
+
4839 vec3 orthogonal_dir = cross(radial_dir, axial_vector);
+
4840 orthogonal_dir.normalize();
+
4841
+
4842 for (int j = 0; j < radial_subdivisions + 1; j++) {
+
4843 vec3 normal = cfact[j] * radius[i] * radial_dir + sfact[j] * radius[i] * orthogonal_dir;
+
4844 triangle_vertices[i][j] = nodes[i] + normal;
+
4845 }
+
4846 }
+
4847
+
4848
+
4849 std::vector<uint> UUIDs(2 * (node_count-1) * radial_subdivisions );
+
4850 vec3 v0, v1, v2;
+
4851
+
4852 int ii=0;
+
4853 for(int j=0; j < radial_subdivisions; j++ ) {
+
4854 for (int i = 0; i < node_count - 1; i++) {
+
4855
+
4856 v0 = triangle_vertices[i][j];
+
4857 v1 = triangle_vertices[i + 1][j + 1];
+
4858 v2 = triangle_vertices[i][j + 1];
+
4859
+
4860 UUIDs.at(ii) = addTriangle(v0, v1, v2, color.at(i));
+
4861
+
4862 v0 = triangle_vertices[i][j];
+
4863 v1 = triangle_vertices[i + 1][j];
+
4864 v2 = triangle_vertices[i + 1][j + 1];
+
4865
+
4866 UUIDs.at(ii + 1) = addTriangle(v0, v1, v2, color.at(i));
+
4867
+
4868 ii += 2;
+
4869 }
+
4870 }
+
4871
+
4872 auto* tube_new = (new Tube(currentObjectID, UUIDs, nodes, radius, color, triangle_vertices, radial_subdivisions, "", this));
4873
-
4874 const uint node_count = nodes.size();
-
4875
-
4876 if (node_count == 0) {
-
4877 helios_runtime_error("ERROR (Context::addTubeObject): Node and radius arrays are empty.");
-
4878 } else if (node_count != radius.size()) {
-
4879 helios_runtime_error("ERROR (Context::addTubeObject): Size of `nodes' and `radius' arguments must agree.");
-
4880 } else if (node_count != textureuv_ufrac.size()) {
-
4881 helios_runtime_error("ERROR (Context::addTubeObject): Size of `nodes' and `textureuv_ufrac' arguments must agree.");
-
4882 }
+
4874 for( uint p : UUIDs){
+
4875 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
4876 }
+
4877
+
4878 objects[currentObjectID] = tube_new;
+
4879 currentObjectID++;
+
4880 return currentObjectID-1;
+
4881
+
4882}
+
4883
-
4884 vec3 axial_vector;
-
4885 std::vector<float> cfact(radial_subdivisions + 1);
-
4886 std::vector<float> sfact(radial_subdivisions + 1);
-
4887 std::vector<std::vector<vec3>> triangle_vertices;
-
4888 resize_vector(triangle_vertices, radial_subdivisions + 1, node_count);
-
4889 std::vector<std::vector<vec2>> uv;
-
4890 resize_vector(uv, radial_subdivisions + 1, node_count);
-
4891
-
4892 // Initialize trigonometric factors for circle points
-
4893 for (int j = 0; j < radial_subdivisions + 1; j++) {
-
4894 cfact[j] = cosf(2.f * float(M_PI) * float(j) / float(radial_subdivisions));
-
4895 sfact[j] = sinf(2.f * float(M_PI) * float(j) / float(radial_subdivisions));
-
4896 }
-
4897
-
4898 vec3 initial_radial(1.0f, 0.0f, 0.0f);
-
4899 vec3 previous_axial_vector;
-
4900 vec3 previous_radial_dir;
-
4901
-
4902 for (int i = 0; i < node_count; i++) { // Looping over tube segments
-
4903 if (radius.at(i) < 0) {
-
4904 helios_runtime_error("ERROR (Context::addTubeObject): Radius of tube must be positive.");
-
4905 }
-
4906
-
4907 if (i == 0) {
-
4908 axial_vector = nodes[i + 1] - nodes[i];
-
4909 axial_vector.normalize();
-
4910 if (fabs(axial_vector * initial_radial) > 0.99f) {
-
4911 initial_radial = vec3(0.0f, 1.0f, 0.0f); // Avoid parallel vectors
-
4912 }
-
4913 previous_radial_dir = cross(axial_vector, initial_radial).normalize();
-
4914 } else {
-
4915 if (i == node_count - 1) {
-
4916 axial_vector = nodes[i] - nodes[i - 1];
-
4917 } else {
-
4918 axial_vector = 0.5f * ((nodes[i] - nodes[i - 1]) + (nodes[i + 1] - nodes[i]));
-
4919 }
-
4920 axial_vector.normalize();
-
4921
-
4922 // Calculate radial direction using parallel transport
-
4923 vec3 rotation_axis = cross(previous_axial_vector, axial_vector);
-
4924 if (rotation_axis.magnitude() > 1e-6) {
-
4925 float angle = acos(std::clamp(previous_axial_vector * axial_vector, -1.0f, 1.0f));
-
4926 previous_radial_dir = rotatePointAboutLine(previous_radial_dir, nullorigin, rotation_axis, angle);
-
4927 }
-
4928// else {
-
4929// // Handle the case of nearly parallel vectors
-
4930// // Ensure previous_radial_dir remains orthogonal to axial_vector
-
4931// previous_radial_dir = cross(axial_vector, previous_radial_dir);
-
4932// if (previous_radial_dir.magnitude() < 1e-6) {
-
4933// // If still degenerate, choose another orthogonal direction
-
4934// previous_radial_dir = cross(axial_vector, vec3(1.0f, 0.0f, 0.0f));
-
4935// }
-
4936// previous_radial_dir.normalize();
-
4937// }
-
4938 }
-
4939
-
4940 previous_axial_vector = axial_vector;
-
4941
-
4942 vec3 radial_dir = previous_radial_dir;
-
4943 vec3 orthogonal_dir = cross(radial_dir, axial_vector);
-
4944 orthogonal_dir.normalize();
-
4945
-
4946 for (int j = 0; j < radial_subdivisions + 1; j++) {
-
4947 vec3 normal = cfact[j] * radius[i] * radial_dir + sfact[j] * radius[i] * orthogonal_dir;
-
4948 triangle_vertices[i][j] = nodes[i] + normal;
-
4949
-
4950 uv[i][j].x = textureuv_ufrac[i];
-
4951 uv[i][j].y = float(j) / float(radial_subdivisions);
-
4952 }
-
4953 }
-
4954
-
4955 std::vector<uint> UUIDs(2 * (node_count - 1) * radial_subdivisions);
-
4956 vec3 v0, v1, v2;
-
4957 vec2 uv0, uv1, uv2;
-
4958
-
4959 int ii = 0;
-
4960 for (int j = 0; j < radial_subdivisions; j++) {
-
4961 for (int i = 0; i < node_count - 1; i++) {
-
4962 v0 = triangle_vertices[i][j];
-
4963 v1 = triangle_vertices[i + 1][j + 1];
-
4964 v2 = triangle_vertices[i][j + 1];
-
4965
-
4966 uv0 = uv[i][j];
-
4967 uv1 = uv[i + 1][j + 1];
-
4968 uv2 = uv[i][j + 1];
-
4969
-
4970 UUIDs.at(ii) = addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
-
4971
-
4972 v0 = triangle_vertices[i][j];
-
4973 v1 = triangle_vertices[i + 1][j];
-
4974 v2 = triangle_vertices[i + 1][j + 1];
-
4975
-
4976 uv0 = uv[i][j];
-
4977 uv1 = uv[i + 1][j];
-
4978 uv2 = uv[i + 1][j + 1];
-
4979
-
4980 UUIDs.at(ii + 1) = addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
+
+
4884uint Context::addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile ){
+
4885 size_t node_count = nodes.size();
+
4886 std::vector<float> textureuv_ufrac(node_count);
+
4887 for( int i=0; i<node_count; i++ ){
+
4888 textureuv_ufrac.at(i) = float(i)/float(node_count-1);
+
4889 }
+
4890
+
4891 return addTubeObject( radial_subdivisions, nodes, radius, texturefile, textureuv_ufrac );
+
4892}
+
+
4893
+
+
4894uint Context::addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile, const std::vector<float> &textureuv_ufrac) {
+
4895 if (!validateTextureFileExtenstion(texturefile)) {
+
4896 helios_runtime_error("ERROR (Context::addTubeObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
4897 } else if (!doesTextureFileExist(texturefile)) {
+
4898 helios_runtime_error("ERROR (Context::addTubeObject): Texture file " + std::string(texturefile) + " does not exist.");
+
4899 }
+
4900
+
4901 const uint node_count = nodes.size();
+
4902
+
4903 if (node_count == 0) {
+
4904 helios_runtime_error("ERROR (Context::addTubeObject): Node and radius arrays are empty.");
+
4905 } else if (node_count != radius.size()) {
+
4906 helios_runtime_error("ERROR (Context::addTubeObject): Size of `nodes' and `radius' arguments must agree.");
+
4907 } else if (node_count != textureuv_ufrac.size()) {
+
4908 helios_runtime_error("ERROR (Context::addTubeObject): Size of `nodes' and `textureuv_ufrac' arguments must agree.");
+
4909 }
+
4910
+
4911 vec3 axial_vector;
+
4912 std::vector<float> cfact(radial_subdivisions + 1);
+
4913 std::vector<float> sfact(radial_subdivisions + 1);
+
4914 std::vector<std::vector<vec3>> triangle_vertices;
+
4915 resize_vector(triangle_vertices, radial_subdivisions + 1, node_count);
+
4916 std::vector<std::vector<vec2>> uv;
+
4917 resize_vector(uv, radial_subdivisions + 1, node_count);
+
4918
+
4919 // Initialize trigonometric factors for circle points
+
4920 for (int j = 0; j < radial_subdivisions + 1; j++) {
+
4921 cfact[j] = cosf(2.f * float(M_PI) * float(j) / float(radial_subdivisions));
+
4922 sfact[j] = sinf(2.f * float(M_PI) * float(j) / float(radial_subdivisions));
+
4923 }
+
4924
+
4925 vec3 initial_radial(1.0f, 0.0f, 0.0f);
+
4926 vec3 previous_axial_vector;
+
4927 vec3 previous_radial_dir;
+
4928
+
4929 for (int i = 0; i < node_count; i++) { // Looping over tube segments
+
4930 if (radius.at(i) < 0) {
+
4931 helios_runtime_error("ERROR (Context::addTubeObject): Radius of tube must be positive.");
+
4932 }
+
4933
+
4934 if (i == 0) {
+
4935 axial_vector = nodes[i + 1] - nodes[i];
+
4936 axial_vector.normalize();
+
4937 if (fabs(axial_vector * initial_radial) > 0.99f) {
+
4938 initial_radial = vec3(0.0f, 1.0f, 0.0f); // Avoid parallel vectors
+
4939 }
+
4940 previous_radial_dir = cross(axial_vector, initial_radial).normalize();
+
4941 } else {
+
4942 if (i == node_count - 1) {
+
4943 axial_vector = nodes[i] - nodes[i - 1];
+
4944 } else {
+
4945 axial_vector = 0.5f * ((nodes[i] - nodes[i - 1]) + (nodes[i + 1] - nodes[i]));
+
4946 }
+
4947 axial_vector.normalize();
+
4948
+
4949 // Calculate radial direction using parallel transport
+
4950 vec3 rotation_axis = cross(previous_axial_vector, axial_vector);
+
4951 if (rotation_axis.magnitude() > 1e-6) {
+
4952 float angle = acos(std::clamp(previous_axial_vector * axial_vector, -1.0f, 1.0f));
+
4953 previous_radial_dir = rotatePointAboutLine(previous_radial_dir, nullorigin, rotation_axis, angle);
+
4954 }
+
4955// else {
+
4956// // Handle the case of nearly parallel vectors
+
4957// // Ensure previous_radial_dir remains orthogonal to axial_vector
+
4958// previous_radial_dir = cross(axial_vector, previous_radial_dir);
+
4959// if (previous_radial_dir.magnitude() < 1e-6) {
+
4960// // If still degenerate, choose another orthogonal direction
+
4961// previous_radial_dir = cross(axial_vector, vec3(1.0f, 0.0f, 0.0f));
+
4962// }
+
4963// previous_radial_dir.normalize();
+
4964// }
+
4965 }
+
4966
+
4967 previous_axial_vector = axial_vector;
+
4968
+
4969 vec3 radial_dir = previous_radial_dir;
+
4970 vec3 orthogonal_dir = cross(radial_dir, axial_vector);
+
4971 orthogonal_dir.normalize();
+
4972
+
4973 for (int j = 0; j < radial_subdivisions + 1; j++) {
+
4974 vec3 normal = cfact[j] * radius[i] * radial_dir + sfact[j] * radius[i] * orthogonal_dir;
+
4975 triangle_vertices[i][j] = nodes[i] + normal;
+
4976
+
4977 uv[i][j].x = textureuv_ufrac[i];
+
4978 uv[i][j].y = float(j) / float(radial_subdivisions);
+
4979 }
+
4980 }
4981
-
4982 ii += 2;
-
4983 }
-
4984 }
+
4982 std::vector<uint> UUIDs(2 * (node_count - 1) * radial_subdivisions);
+
4983 vec3 v0, v1, v2;
+
4984 vec2 uv0, uv1, uv2;
4985
-
4986 std::vector<RGBcolor> colors(nodes.size());
-
4987
-
4988 auto* tube_new = (new Tube(currentObjectID, UUIDs, nodes, radius, colors, triangle_vertices, radial_subdivisions, texturefile, this));
-
4989
-
4990 for (uint p : UUIDs) {
-
4991 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
4992 }
-
4993
-
4994 objects[currentObjectID] = tube_new;
-
4995 currentObjectID++;
+
4986 int ii = 0;
+
4987 for (int j = 0; j < radial_subdivisions; j++) {
+
4988 for (int i = 0; i < node_count - 1; i++) {
+
4989 v0 = triangle_vertices[i][j];
+
4990 v1 = triangle_vertices[i + 1][j + 1];
+
4991 v2 = triangle_vertices[i][j + 1];
+
4992
+
4993 uv0 = uv[i][j];
+
4994 uv1 = uv[i + 1][j + 1];
+
4995 uv2 = uv[i][j + 1];
4996
-
4997 return currentObjectID - 1;
-
4998}
-
-
4999
-
-
5000uint Context::addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv ){
-
5001
-
5002 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
-
5003
-
5004 return addBoxObject(center,size,subdiv,color,false);
-
5005}
-
+
4997 UUIDs.at(ii) = addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
+
4998
+
4999 v0 = triangle_vertices[i][j];
+
5000 v1 = triangle_vertices[i + 1][j];
+
5001 v2 = triangle_vertices[i + 1][j + 1];
+
5002
+
5003 uv0 = uv[i][j];
+
5004 uv1 = uv[i + 1][j];
+
5005 uv2 = uv[i + 1][j + 1];
5006
-
-
5007uint Context::addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color ){
-
5008 return addBoxObject(center,size,subdiv,color,false);
-
5009}
-
-
5010
-
-
5011uint Context::addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile ){
-
5012 return addBoxObject(center,size,subdiv,texturefile,false);
-
5013}
-
+
5007 UUIDs.at(ii + 1) = addTriangle(v0, v1, v2, texturefile, uv0, uv1, uv2);
+
5008
+
5009 ii += 2;
+
5010 }
+
5011 }
+
5012
+
5013 std::vector<RGBcolor> colors(nodes.size());
5014
-
-
5015uint Context::addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals ){
+
5015 auto* tube_new = (new Tube(currentObjectID, UUIDs, nodes, radius, colors, triangle_vertices, radial_subdivisions, texturefile, this));
5016
-
5017 if( size.x<=0 || size.y<=0 || size.z<=0 ){
-
5018 helios_runtime_error("ERROR (Context::addBoxObject): Size of box must be positive.");
-
5019 }else if( subdiv.x<1 || subdiv.y<1 || subdiv.z<1 ){
-
5020 helios_runtime_error("ERROR (Context::addBoxObject): Number of box subdivisions must be positive.");
-
5021 }
-
5022
-
5023 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
-
5024
-
5025 vec3 subsize;
-
5026 subsize.x = size.x/float(subdiv.x);
-
5027 subsize.y = size.y/float(subdiv.y);
-
5028 subsize.z = size.z/float(subdiv.z);
-
5029
-
5030 vec3 subcenter;
-
5031 uint objID;
-
5032 std::vector<uint> U, U_copy;
+
5017 for (uint p : UUIDs) {
+
5018 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
5019 }
+
5020
+
5021 objects[currentObjectID] = tube_new;
+
5022 currentObjectID++;
+
5023
+
5024 return currentObjectID - 1;
+
5025}
+
+
5026
+
+
5027uint Context::addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv ){
+
5028
+
5029 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
5030
+
5031 return addBoxObject(center,size,subdiv,color,false);
+
5032}
+
5033
-
5034 if( reverse_normals ){ //normals point inward
-
5035
-
5036 // x-z faces (vertical)
+
+
5034uint Context::addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color ){
+
5035 return addBoxObject(center,size,subdiv,color,false);
+
5036}
+
5037
-
5038 //right
-
5039 subcenter = center + make_vec3(0,0.5f*size.y,0);
-
5040 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5f*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), color );
-
5041 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5042
-
5043 //left
-
5044 subcenter = center - make_vec3(0,0.5f*size.y,0);
-
5045 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5f*M_PI,0), make_int2(subdiv.x,subdiv.z), color );
-
5046 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5047
-
5048 // y-z faces (vertical)
+
+
5038uint Context::addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile ){
+
5039 return addBoxObject(center,size,subdiv,texturefile,false);
+
5040}
+
+
5041
+
+
5042uint Context::addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals ){
+
5043
+
5044 if( size.x<=0 || size.y<=0 || size.z<=0 ){
+
5045 helios_runtime_error("ERROR (Context::addBoxObject): Size of box must be positive.");
+
5046 }else if( subdiv.x<1 || subdiv.y<1 || subdiv.z<1 ){
+
5047 helios_runtime_error("ERROR (Context::addBoxObject): Number of box subdivisions must be positive.");
+
5048 }
5049
-
5050 //front
-
5051 subcenter = center + make_vec3(0.5f*size.x,0,0);
-
5052 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5f*M_PI,1.5f*M_PI), make_int2(subdiv.y,subdiv.z), color );
-
5053 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5054
-
5055 //back
-
5056 subcenter = center - make_vec3(0.5f*size.x,0,0);
-
5057 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5f*M_PI,0.5f*M_PI), make_int2(subdiv.y,subdiv.z), color );
-
5058 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5059
-
5060 // x-y faces (horizontal)
-
5061
-
5062 //top
-
5063 subcenter = center + make_vec3(0,0,0.5f*size.z);
-
5064 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), color );
-
5065 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5066
-
5067 //bottom
-
5068 subcenter = center - make_vec3(0,0,0.5f*size.z);
-
5069 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), color );
-
5070 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5071
-
5072 }else{ //normals point outward
-
5073
-
5074 // x-z faces (vertical)
-
5075
-
5076 //right
-
5077 subcenter = center + make_vec3(0,0.5f*size.y,0);
-
5078 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5f*M_PI,0), make_int2(subdiv.x,subdiv.z), color );
-
5079 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5080
-
5081 //left
-
5082 subcenter = center - make_vec3(0,0.5f*size.y,0);
-
5083 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5f*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), color );
-
5084 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5085
-
5086 // y-z faces (vertical)
-
5087
-
5088 //front
-
5089 subcenter = center + make_vec3(0.5f*size.x,0,0);
-
5090 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5f*M_PI,0.5f*M_PI), make_int2(subdiv.y,subdiv.z), color );
-
5091 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5092
-
5093 //back
-
5094 subcenter = center - make_vec3(0.5f*size.x,0,0);
-
5095 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5f*M_PI,1.5f*M_PI), make_int2(subdiv.y,subdiv.z), color );
-
5096 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5097
-
5098 // x-y faces (horizontal)
-
5099
-
5100 //top
-
5101 subcenter = center + make_vec3(0,0,0.5f*size.z);
-
5102 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), color );
-
5103 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5104
-
5105 //bottom
-
5106 subcenter = center - make_vec3(0,0,0.5f*size.z);
-
5107 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), color );
-
5108 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5109
-
5110 }
-
5111
-
5112 auto* box_new = (new Box(currentObjectID, UUID, subdiv, "", this));
-
5113
-
5114 float T[16], transform[16];
-
5115 box_new->getTransformationMatrix( transform );
-
5116
-
5117 makeScaleMatrix(size,T);
-
5118 matmult(T,transform,transform);
+
5050 std::vector<uint> UUID; //\todo Resize here and avoid using push_back() below.
+
5051
+
5052 vec3 subsize;
+
5053 subsize.x = size.x/float(subdiv.x);
+
5054 subsize.y = size.y/float(subdiv.y);
+
5055 subsize.z = size.z/float(subdiv.z);
+
5056
+
5057 vec3 subcenter;
+
5058 uint objID;
+
5059 std::vector<uint> U, U_copy;
+
5060
+
5061 if( reverse_normals ){ //normals point inward
+
5062
+
5063 // x-z faces (vertical)
+
5064
+
5065 //right
+
5066 subcenter = center + make_vec3(0,0.5f*size.y,0);
+
5067 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5f*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), color );
+
5068 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5069
+
5070 //left
+
5071 subcenter = center - make_vec3(0,0.5f*size.y,0);
+
5072 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5f*M_PI,0), make_int2(subdiv.x,subdiv.z), color );
+
5073 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5074
+
5075 // y-z faces (vertical)
+
5076
+
5077 //front
+
5078 subcenter = center + make_vec3(0.5f*size.x,0,0);
+
5079 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5f*M_PI,1.5f*M_PI), make_int2(subdiv.y,subdiv.z), color );
+
5080 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5081
+
5082 //back
+
5083 subcenter = center - make_vec3(0.5f*size.x,0,0);
+
5084 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5f*M_PI,0.5f*M_PI), make_int2(subdiv.y,subdiv.z), color );
+
5085 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5086
+
5087 // x-y faces (horizontal)
+
5088
+
5089 //top
+
5090 subcenter = center + make_vec3(0,0,0.5f*size.z);
+
5091 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), color );
+
5092 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5093
+
5094 //bottom
+
5095 subcenter = center - make_vec3(0,0,0.5f*size.z);
+
5096 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), color );
+
5097 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5098
+
5099 }else{ //normals point outward
+
5100
+
5101 // x-z faces (vertical)
+
5102
+
5103 //right
+
5104 subcenter = center + make_vec3(0,0.5f*size.y,0);
+
5105 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5f*M_PI,0), make_int2(subdiv.x,subdiv.z), color );
+
5106 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5107
+
5108 //left
+
5109 subcenter = center - make_vec3(0,0.5f*size.y,0);
+
5110 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5f*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), color );
+
5111 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5112
+
5113 // y-z faces (vertical)
+
5114
+
5115 //front
+
5116 subcenter = center + make_vec3(0.5f*size.x,0,0);
+
5117 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5f*M_PI,0.5f*M_PI), make_int2(subdiv.y,subdiv.z), color );
+
5118 UUID.insert( UUID.end(), U.begin(), U.end() );
5119
-
5120 makeTranslationMatrix(center,T);
-
5121 matmult(T,transform,transform);
-
5122 box_new->setTransformationMatrix( transform );
-
5123
-
5124 box_new->setColor( color );
-
5125
-
5126 for( uint p : UUID){
-
5127 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
5128 }
-
5129
-
5130 objects[currentObjectID] = box_new;
-
5131 currentObjectID++;
-
5132 return currentObjectID-1;
-
5133
-
5134}
-
-
5135
-
-
5136uint Context::addBoxObject(vec3 center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals ){
-
5137
-
5138 if( !validateTextureFileExtenstion(texturefile) ){
-
5139 helios_runtime_error("ERROR (Context::addBoxObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
5140 }else if( !doesTextureFileExist(texturefile) ){
-
5141 helios_runtime_error("ERROR (Context::addBoxObject): Texture file " + std::string(texturefile) + " does not exist.");
-
5142 }
+
5120 //back
+
5121 subcenter = center - make_vec3(0.5f*size.x,0,0);
+
5122 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5f*M_PI,1.5f*M_PI), make_int2(subdiv.y,subdiv.z), color );
+
5123 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5124
+
5125 // x-y faces (horizontal)
+
5126
+
5127 //top
+
5128 subcenter = center + make_vec3(0,0,0.5f*size.z);
+
5129 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), color );
+
5130 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5131
+
5132 //bottom
+
5133 subcenter = center - make_vec3(0,0,0.5f*size.z);
+
5134 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), color );
+
5135 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5136
+
5137 }
+
5138
+
5139 auto* box_new = (new Box(currentObjectID, UUID, subdiv, "", this));
+
5140
+
5141 float T[16], transform[16];
+
5142 box_new->getTransformationMatrix( transform );
5143
-
5144 std::vector<uint> UUID;
-
5145
-
5146 vec3 subsize;
-
5147 subsize.x = size.x/float(subdiv.x);
-
5148 subsize.y = size.y/float(subdiv.y);
-
5149 subsize.z = size.z/float(subdiv.z);
+
5144 makeScaleMatrix(size,T);
+
5145 matmult(T,transform,transform);
+
5146
+
5147 makeTranslationMatrix(center,T);
+
5148 matmult(T,transform,transform);
+
5149 box_new->setTransformationMatrix( transform );
5150
-
5151 vec3 subcenter;
-
5152 uint objID;
-
5153 std::vector<uint> U, U_copy;
-
5154
-
5155 if( reverse_normals ){ //normals point inward
+
5151 box_new->setColor( color );
+
5152
+
5153 for( uint p : UUID){
+
5154 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
5155 }
5156
-
5157 // x-z faces (vertical)
-
5158
-
5159 //right
-
5160 subcenter = center + make_vec3(0,0.5f*size.y,0);
-
5161 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), texturefile );
-
5162 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5163
-
5164 //left
-
5165 subcenter = center - make_vec3(0,0.5f*size.y,0);
-
5166 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), texturefile );
-
5167 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5168
-
5169 // y-z faces (vertical)
+
5157 objects[currentObjectID] = box_new;
+
5158 currentObjectID++;
+
5159 return currentObjectID-1;
+
5160
+
5161}
+
+
5162
+
+
5163uint Context::addBoxObject(vec3 center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals ){
+
5164
+
5165 if( !validateTextureFileExtenstion(texturefile) ){
+
5166 helios_runtime_error("ERROR (Context::addBoxObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
5167 }else if( !doesTextureFileExist(texturefile) ){
+
5168 helios_runtime_error("ERROR (Context::addBoxObject): Texture file " + std::string(texturefile) + " does not exist.");
+
5169 }
5170
-
5171 //front
-
5172 subcenter = center + make_vec3(0.5f*size.x,0,0);
-
5173 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
-
5174 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5175
-
5176 //back
-
5177 subcenter = center - make_vec3(0.5f*size.x,0,0);
-
5178 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
-
5179 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5180
-
5181 // x-y faces (horizontal)
-
5182
-
5183 //top
-
5184 subcenter = center + make_vec3(0,0,0.5f*size.z);
-
5185 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), texturefile );
-
5186 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5187
-
5188 //bottom
-
5189 subcenter = center - make_vec3(0,0,0.5f*size.z);
-
5190 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), texturefile );
-
5191 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5192
-
5193 }else{ //normals point outward
-
5194
-
5195 // x-z faces (vertical)
-
5196
-
5197 //right
-
5198 subcenter = center + make_vec3(0,0.5f*size.y,0);
-
5199 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), texturefile );
-
5200 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5201
-
5202 //left
-
5203 subcenter = center - make_vec3(0,0.5f*size.y,0);
-
5204 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), texturefile );
-
5205 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5206
-
5207 // y-z faces (vertical)
-
5208
-
5209 //front
-
5210 subcenter = center + make_vec3(0.5f*size.x,0,0);
-
5211 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
-
5212 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5213
-
5214 //back
-
5215 subcenter = center - make_vec3(0.5f*size.x,0,0);
-
5216 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
-
5217 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5218
-
5219 // x-y faces (horizontal)
-
5220
-
5221 //top
-
5222 subcenter = center + make_vec3(0,0,0.5f*size.z);
-
5223 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), texturefile );
-
5224 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5225
-
5226 //bottom
-
5227 subcenter = center - make_vec3(0,0,0.5f*size.z);
-
5228 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), texturefile );
-
5229 UUID.insert( UUID.end(), U.begin(), U.end() );
-
5230
-
5231 }
-
5232
-
5233 auto* box_new = (new Box(currentObjectID, UUID, subdiv, texturefile, this));
-
5234
-
5235 float T[16], transform[16];
-
5236 box_new->getTransformationMatrix( transform );
-
5237
-
5238 makeScaleMatrix(size,T);
-
5239 matmult(T,transform,transform);
+
5171 std::vector<uint> UUID;
+
5172
+
5173 vec3 subsize;
+
5174 subsize.x = size.x/float(subdiv.x);
+
5175 subsize.y = size.y/float(subdiv.y);
+
5176 subsize.z = size.z/float(subdiv.z);
+
5177
+
5178 vec3 subcenter;
+
5179 uint objID;
+
5180 std::vector<uint> U, U_copy;
+
5181
+
5182 if( reverse_normals ){ //normals point inward
+
5183
+
5184 // x-z faces (vertical)
+
5185
+
5186 //right
+
5187 subcenter = center + make_vec3(0,0.5f*size.y,0);
+
5188 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), texturefile );
+
5189 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5190
+
5191 //left
+
5192 subcenter = center - make_vec3(0,0.5f*size.y,0);
+
5193 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), texturefile );
+
5194 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5195
+
5196 // y-z faces (vertical)
+
5197
+
5198 //front
+
5199 subcenter = center + make_vec3(0.5f*size.x,0,0);
+
5200 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
+
5201 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5202
+
5203 //back
+
5204 subcenter = center - make_vec3(0.5f*size.x,0,0);
+
5205 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
+
5206 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5207
+
5208 // x-y faces (horizontal)
+
5209
+
5210 //top
+
5211 subcenter = center + make_vec3(0,0,0.5f*size.z);
+
5212 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), texturefile );
+
5213 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5214
+
5215 //bottom
+
5216 subcenter = center - make_vec3(0,0,0.5f*size.z);
+
5217 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), texturefile );
+
5218 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5219
+
5220 }else{ //normals point outward
+
5221
+
5222 // x-z faces (vertical)
+
5223
+
5224 //right
+
5225 subcenter = center + make_vec3(0,0.5f*size.y,0);
+
5226 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), texturefile );
+
5227 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5228
+
5229 //left
+
5230 subcenter = center - make_vec3(0,0.5f*size.y,0);
+
5231 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), texturefile );
+
5232 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5233
+
5234 // y-z faces (vertical)
+
5235
+
5236 //front
+
5237 subcenter = center + make_vec3(0.5f*size.x,0,0);
+
5238 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
+
5239 UUID.insert( UUID.end(), U.begin(), U.end() );
5240
-
5241 makeTranslationMatrix(center,T);
-
5242 matmult(T,transform,transform);
-
5243 box_new->setTransformationMatrix( transform );
-
5244
-
5245 for( uint p : UUID){
-
5246 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
5247 }
-
5248
-
5249 objects[currentObjectID] = box_new;
-
5250 currentObjectID++;
-
5251 return currentObjectID-1;
+
5241 //back
+
5242 subcenter = center - make_vec3(0.5f*size.x,0,0);
+
5243 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
+
5244 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5245
+
5246 // x-y faces (horizontal)
+
5247
+
5248 //top
+
5249 subcenter = center + make_vec3(0,0,0.5f*size.z);
+
5250 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), texturefile );
+
5251 UUID.insert( UUID.end(), U.begin(), U.end() );
5252
-
5253
-
5254}
-
-
5255
-
-
5256uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size ){
-
5257 return addDiskObject(make_int2(Ndivs,1),center,size,make_SphericalCoord(0,0),make_RGBAcolor(1,0,0,1));
-
5258}
-
+
5253 //bottom
+
5254 subcenter = center - make_vec3(0,0,0.5f*size.z);
+
5255 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), texturefile );
+
5256 UUID.insert( UUID.end(), U.begin(), U.end() );
+
5257
+
5258 }
5259
-
-
5260uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation ){
-
5261 return addDiskObject(make_int2(Ndivs,1),center,size,rotation,make_RGBAcolor(1,0,0,1));
-
5262}
-
-
5263
-
-
5264uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBcolor &color ){
-
5265 return addDiskObject(make_int2(Ndivs,1),center,size,rotation,make_RGBAcolor(color,1));
-
5266}
-
+
5260 auto* box_new = (new Box(currentObjectID, UUID, subdiv, texturefile, this));
+
5261
+
5262 float T[16], transform[16];
+
5263 box_new->getTransformationMatrix( transform );
+
5264
+
5265 makeScaleMatrix(size,T);
+
5266 matmult(T,transform,transform);
5267
-
-
5268uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBAcolor &color ){
-
5269 return addDiskObject(make_int2(Ndivs,1),center,size,rotation,color);
-
5270}
-
+
5268 makeTranslationMatrix(center,T);
+
5269 matmult(T,transform,transform);
+
5270 box_new->setTransformationMatrix( transform );
5271
-
-
5272uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const char* texture_file ){
-
5273 return addDiskObject(make_int2(Ndivs,1),center,size,rotation,texture_file);
-
5274}
-
+
5272 for( uint p : UUID){
+
5273 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
5274 }
5275
-
-
5276uint Context::addDiskObject(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBcolor &color ){
-
5277 return addDiskObject(Ndivs,center,size,rotation,make_RGBAcolor(color,1));
-
5278}
-
+
5276 objects[currentObjectID] = box_new;
+
5277 currentObjectID++;
+
5278 return currentObjectID-1;
5279
-
-
5280uint Context::addDiskObject(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBAcolor &color ){
-
5281
-
5282 std::vector<uint> UUID;
-
5283
-
5284 UUID.resize(Ndivs.x+Ndivs.x*(Ndivs.y-1)*2);
-
5285 int i=0;
-
5286 for( int r=0; r < Ndivs.y; r++ ) {
-
5287 for (int t = 0; t < Ndivs.x; t++) {
-
5288
-
5289 float dtheta = 2.f * float(M_PI) / float(Ndivs.x);
-
5290 float theta = dtheta*float(t);
-
5291 float theta_plus = dtheta*float(t+1);
-
5292
-
5293 float rx = size.x/float(Ndivs.y)*float(r);
-
5294 float ry = size.y/float(Ndivs.y)*float(r);
-
5295
-
5296 float rx_plus = size.x/float(Ndivs.y)*float(r+1);
-
5297 float ry_plus = size.y/float(Ndivs.y)*float(r+1);
+
5280
+
5281}
+
+
5282
+
+
5283uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size ){
+
5284 return addDiskObject(make_int2(Ndivs,1),center,size,make_SphericalCoord(0,0),make_RGBAcolor(1,0,0,1));
+
5285}
+
+
5286
+
+
5287uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation ){
+
5288 return addDiskObject(make_int2(Ndivs,1),center,size,rotation,make_RGBAcolor(1,0,0,1));
+
5289}
+
+
5290
+
+
5291uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBcolor &color ){
+
5292 return addDiskObject(make_int2(Ndivs,1),center,size,rotation,make_RGBAcolor(color,1));
+
5293}
+
+
5294
+
+
5295uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBAcolor &color ){
+
5296 return addDiskObject(make_int2(Ndivs,1),center,size,rotation,color);
+
5297}
+
5298
-
5299 if( r==0 ) {
-
5300 UUID.at(i) = addTriangle(make_vec3(0, 0, 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
-
5301 }else{
-
5302 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx * cosf(theta), ry * sinf(theta), 0),make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), color);
-
5303 i++;
-
5304 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
-
5305 }
-
5306 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.elevation, "y");
-
5307 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.azimuth, "z");
-
5308 getPrimitivePointer_private(UUID.at(i))->translate(center);
-
5309
-
5310 i++;
-
5311 }
-
5312 }
-
5313
-
5314 auto* disk_new = (new Disk(currentObjectID, UUID, Ndivs, "", this));
+
+
5299uint Context::addDiskObject(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const char* texture_file ){
+
5300 return addDiskObject(make_int2(Ndivs,1),center,size,rotation,texture_file);
+
5301}
+
+
5302
+
+
5303uint Context::addDiskObject(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBcolor &color ){
+
5304 return addDiskObject(Ndivs,center,size,rotation,make_RGBAcolor(color,1));
+
5305}
+
+
5306
+
+
5307uint Context::addDiskObject(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBAcolor &color ){
+
5308
+
5309 std::vector<uint> UUID;
+
5310
+
5311 UUID.resize(Ndivs.x+Ndivs.x*(Ndivs.y-1)*2);
+
5312 int i=0;
+
5313 for( int r=0; r < Ndivs.y; r++ ) {
+
5314 for (int t = 0; t < Ndivs.x; t++) {
5315
-
5316 float T[16], transform[16];
-
5317 disk_new->getTransformationMatrix( transform );
-
5318
-
5319 makeScaleMatrix(make_vec3(size.x,size.y,1.f),T);
-
5320 matmult(T,transform,transform);
-
5321
-
5322 makeTranslationMatrix(center,T);
-
5323 matmult(T,transform,transform);
-
5324 disk_new->setTransformationMatrix( transform );
+
5316 float dtheta = 2.f * float(M_PI) / float(Ndivs.x);
+
5317 float theta = dtheta*float(t);
+
5318 float theta_plus = dtheta*float(t+1);
+
5319
+
5320 float rx = size.x/float(Ndivs.y)*float(r);
+
5321 float ry = size.y/float(Ndivs.y)*float(r);
+
5322
+
5323 float rx_plus = size.x/float(Ndivs.y)*float(r+1);
+
5324 float ry_plus = size.y/float(Ndivs.y)*float(r+1);
5325
-
5326 disk_new->setColor( color );
-
5327
-
5328 for( uint p : UUID){
-
5329 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
5330 }
-
5331
-
5332 objects[currentObjectID] = disk_new;
-
5333 currentObjectID++;
-
5334 return currentObjectID-1;
-
5335
-
5336}
-
-
5337
-
-
5338uint Context::addDiskObject(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const char* texturefile ){
-
5339
-
5340 if( !validateTextureFileExtenstion(texturefile) ) {
-
5341 helios_runtime_error("ERROR (Context::addDiskObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
5342 }else if( !doesTextureFileExist(texturefile) ){
-
5343 helios_runtime_error("ERROR (Context::addDiskObject): Texture file " + std::string(texturefile) + " does not exist.");
-
5344 }
+
5326 if( r==0 ) {
+
5327 UUID.at(i) = addTriangle(make_vec3(0, 0, 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
+
5328 }else{
+
5329 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx * cosf(theta), ry * sinf(theta), 0),make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), color);
+
5330 i++;
+
5331 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
+
5332 }
+
5333 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.elevation, "y");
+
5334 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.azimuth, "z");
+
5335 getPrimitivePointer_private(UUID.at(i))->translate(center);
+
5336
+
5337 i++;
+
5338 }
+
5339 }
+
5340
+
5341 auto* disk_new = (new Disk(currentObjectID, UUID, Ndivs, "", this));
+
5342
+
5343 float T[16], transform[16];
+
5344 disk_new->getTransformationMatrix( transform );
5345
-
5346 std::vector<uint> UUID;
-
5347
-
5348 UUID.resize(Ndivs.x+Ndivs.x*(Ndivs.y-1)*2);
-
5349 int i=0;
-
5350 for( int r=0; r < Ndivs.y; r++ ) {
-
5351 for (int t = 0; t < Ndivs.x; t++) {
+
5346 makeScaleMatrix(make_vec3(size.x,size.y,1.f),T);
+
5347 matmult(T,transform,transform);
+
5348
+
5349 makeTranslationMatrix(center,T);
+
5350 matmult(T,transform,transform);
+
5351 disk_new->setTransformationMatrix( transform );
5352
-
5353 float dtheta = 2.f * float(M_PI) / float(Ndivs.x);
-
5354 float theta = dtheta*float(t);
-
5355 float theta_plus = dtheta*float(t+1);
-
5356
-
5357 float rx = size.x/float(Ndivs.y)*float(r);
-
5358 float ry = size.y/float(Ndivs.y)*float(r);
-
5359 float rx_plus = size.x/float(Ndivs.y)*float(r+1);
-
5360 float ry_plus = size.y/float(Ndivs.y)*float(r+1);
-
5361
-
5362 if( r==0 ) {
-
5363 UUID.at(i) = addTriangle(make_vec3(0, 0, 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile, make_vec2(0.5, 0.5), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)), make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.y)));
-
5364 }else{
-
5365 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx * cosf(theta), ry * sinf(theta), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), texturefile, make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.x), 0.5f * (1.f + sinf(theta_plus) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx / size.x), 0.5f * (1.f + sinf(theta) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)));
-
5366 i++;
-
5367 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile, make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.x), 0.5f * (1.f + sinf(theta_plus) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)), make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.y)));
-
5368 }
-
5369 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.elevation, "y");
-
5370 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.azimuth, "z");
-
5371 getPrimitivePointer_private(UUID.at(i))->translate(center);
+
5353 disk_new->setColor( color );
+
5354
+
5355 for( uint p : UUID){
+
5356 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
5357 }
+
5358
+
5359 objects[currentObjectID] = disk_new;
+
5360 currentObjectID++;
+
5361 return currentObjectID-1;
+
5362
+
5363}
+
+
5364
+
+
5365uint Context::addDiskObject(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const char* texturefile ){
+
5366
+
5367 if( !validateTextureFileExtenstion(texturefile) ) {
+
5368 helios_runtime_error("ERROR (Context::addDiskObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
5369 }else if( !doesTextureFileExist(texturefile) ){
+
5370 helios_runtime_error("ERROR (Context::addDiskObject): Texture file " + std::string(texturefile) + " does not exist.");
+
5371 }
5372
-
5373 i++;
-
5374 }
-
5375 }
-
5376
-
5377 auto* disk_new = (new Disk(currentObjectID, UUID, Ndivs, texturefile, this));
-
5378
-
5379 float T[16], transform[16];
-
5380 disk_new->getTransformationMatrix( transform );
-
5381
-
5382 makeScaleMatrix(make_vec3(size.x,size.y,1.f),T);
-
5383 matmult(T,transform,transform);
-
5384
-
5385 makeTranslationMatrix(center,T);
-
5386 matmult(T,transform,transform);
-
5387 disk_new->setTransformationMatrix( transform );
+
5373 std::vector<uint> UUID;
+
5374
+
5375 UUID.resize(Ndivs.x+Ndivs.x*(Ndivs.y-1)*2);
+
5376 int i=0;
+
5377 for( int r=0; r < Ndivs.y; r++ ) {
+
5378 for (int t = 0; t < Ndivs.x; t++) {
+
5379
+
5380 float dtheta = 2.f * float(M_PI) / float(Ndivs.x);
+
5381 float theta = dtheta*float(t);
+
5382 float theta_plus = dtheta*float(t+1);
+
5383
+
5384 float rx = size.x/float(Ndivs.y)*float(r);
+
5385 float ry = size.y/float(Ndivs.y)*float(r);
+
5386 float rx_plus = size.x/float(Ndivs.y)*float(r+1);
+
5387 float ry_plus = size.y/float(Ndivs.y)*float(r+1);
5388
-
5389 for( uint p : UUID){
-
5390 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
5391 }
-
5392
-
5393 objects[currentObjectID] = disk_new;
-
5394 currentObjectID++;
-
5395 return currentObjectID-1;
-
5396
-
5397}
-
-
5398
-
-
5399uint Context::addPolymeshObject(const std::vector<uint> &UUIDs ){
-
5400
-
5401 if( UUIDs.empty() ){
-
5402 helios_runtime_error("ERROR (Context::addPolymeshObject): UUIDs array is empty. Cannot create polymesh object.");
-
5403 }else if( !doesPrimitiveExist(UUIDs) ){
-
5404 helios_runtime_error("ERROR (Context::addPolymeshObject): One or more of the provided UUIDs does not exist. Cannot create polymesh object.");
-
5405 }
-
5406
-
5407 auto* polymesh_new = (new Polymesh(currentObjectID, UUIDs, "", this));
+
5389 if( r==0 ) {
+
5390 UUID.at(i) = addTriangle(make_vec3(0, 0, 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile, make_vec2(0.5, 0.5), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)), make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.y)));
+
5391 }else{
+
5392 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx * cosf(theta), ry * sinf(theta), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), texturefile, make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.x), 0.5f * (1.f + sinf(theta_plus) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx / size.x), 0.5f * (1.f + sinf(theta) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)));
+
5393 i++;
+
5394 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile, make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.x), 0.5f * (1.f + sinf(theta_plus) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)), make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.y)));
+
5395 }
+
5396 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.elevation, "y");
+
5397 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.azimuth, "z");
+
5398 getPrimitivePointer_private(UUID.at(i))->translate(center);
+
5399
+
5400 i++;
+
5401 }
+
5402 }
+
5403
+
5404 auto* disk_new = (new Disk(currentObjectID, UUID, Ndivs, texturefile, this));
+
5405
+
5406 float T[16], transform[16];
+
5407 disk_new->getTransformationMatrix( transform );
5408
-
5409 float T[16], transform[16];
-
5410 polymesh_new->getTransformationMatrix( transform );
+
5409 makeScaleMatrix(make_vec3(size.x,size.y,1.f),T);
+
5410 matmult(T,transform,transform);
5411
-
5412 makeTranslationMatrix( getPrimitivePointer_private( UUIDs.front())->getVertices().front(),T);
+
5412 makeTranslationMatrix(center,T);
5413 matmult(T,transform,transform);
-
5414 polymesh_new->setTransformationMatrix( transform );
+
5414 disk_new->setTransformationMatrix( transform );
5415
-
5416 for( uint UUID : UUIDs){
-
5417 getPrimitivePointer_private(UUID)->setParentObjectID(currentObjectID);
+
5416 for( uint p : UUID){
+
5417 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
5418 }
5419
-
5420 objects[currentObjectID] = polymesh_new;
+
5420 objects[currentObjectID] = disk_new;
5421 currentObjectID++;
5422 return currentObjectID-1;
5423
@@ -6002,3113 +6009,3151 @@
5425
-
5426uint Context::addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 ){
+
5426uint Context::addPolymeshObject(const std::vector<uint> &UUIDs ){
5427
-
5428 RGBcolor color;
-
5429 color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
-
5430 return addConeObject(Ndivs, node0, node1, radius0, radius1, color);
-
5431}
-
-
5432
-
-
5433uint Context::addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const RGBcolor &color ){
-
5434
-
5435 const std::vector<helios::vec3> nodes{node0, node1};
-
5436 const std::vector<float> radii{radius0, radius1};
-
5437
-
5438 vec3 vec, convec;
-
5439 std::vector<float> cfact(Ndivs+1);
-
5440 std::vector<float> sfact(Ndivs+1);
-
5441 std::vector<std::vector<vec3> > xyz, normal;
-
5442 xyz.resize(Ndivs+1);
-
5443 normal.resize(Ndivs+1);
-
5444 for( uint j=0; j<Ndivs+1; j++ ){
-
5445 xyz.at(j).resize(2);
-
5446 normal.at(j).resize(2);
-
5447 }
-
5448 vec3 nvec(0.1817f,0.6198f,0.7634f);//random vector to get things going
-
5449
-
5450 for( int j=0; j<Ndivs+1; j++ ){
-
5451 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(Ndivs));
-
5452 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(Ndivs));
-
5453 }
+
5428 if( UUIDs.empty() ){
+
5429 helios_runtime_error("ERROR (Context::addPolymeshObject): UUIDs array is empty. Cannot create polymesh object.");
+
5430 }else if( !doesPrimitiveExist(UUIDs) ){
+
5431 helios_runtime_error("ERROR (Context::addPolymeshObject): One or more of the provided UUIDs does not exist. Cannot create polymesh object.");
+
5432 }
+
5433
+
5434 auto* polymesh_new = (new Polymesh(currentObjectID, UUIDs, "", this));
+
5435
+
5436 float T[16], transform[16];
+
5437 polymesh_new->getTransformationMatrix( transform );
+
5438
+
5439 makeTranslationMatrix( getPrimitivePointer_private( UUIDs.front())->getVertices().front(),T);
+
5440 matmult(T,transform,transform);
+
5441 polymesh_new->setTransformationMatrix( transform );
+
5442
+
5443 for( uint UUID : UUIDs){
+
5444 getPrimitivePointer_private(UUID)->setParentObjectID(currentObjectID);
+
5445 }
+
5446
+
5447 objects[currentObjectID] = polymesh_new;
+
5448 currentObjectID++;
+
5449 return currentObjectID-1;
+
5450
+
5451}
+
+
5452
+
+
5453uint Context::addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 ){
5454
-
5455 for( int i=0; i<2; i++ ){ //looping over cone segments
-
5456
-
5457 if(i==0){
-
5458 vec.x=nodes[i+1].x-nodes[i].x;
-
5459 vec.y=nodes[i+1].y-nodes[i].y;
-
5460 vec.z=nodes[i+1].z-nodes[i].z;
-
5461 }else if(i==1){
-
5462 vec.x=nodes[i].x-nodes[i-1].x;
-
5463 vec.y=nodes[i].y-nodes[i-1].y;
-
5464 vec.z=nodes[i].z-nodes[i-1].z;
-
5465 }
-
5466
-
5467 float norm;
-
5468 convec = cross(nvec,vec);
-
5469 norm=convec.magnitude();
-
5470 convec.x=convec.x/norm;
-
5471 convec.y=convec.y/norm;
-
5472 convec.z=convec.z/norm;
-
5473 nvec = cross(vec,convec);
-
5474 norm=nvec.magnitude();
-
5475 nvec.x=nvec.x/norm;
-
5476 nvec.y=nvec.y/norm;
-
5477 nvec.z=nvec.z/norm;
-
5478
-
5479 for( int j=0; j<Ndivs+1; j++ ){
-
5480 normal[j][i].x=cfact[j]*radii[i]*nvec.x+sfact[j]*radii[i]*convec.x;
-
5481 normal[j][i].y=cfact[j]*radii[i]*nvec.y+sfact[j]*radii[i]*convec.y;
-
5482 normal[j][i].z=cfact[j]*radii[i]*nvec.z+sfact[j]*radii[i]*convec.z;
+
5455 RGBcolor color;
+
5456 color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
5457 return addConeObject(Ndivs, node0, node1, radius0, radius1, color);
+
5458}
+
+
5459
+
+
5460uint Context::addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const RGBcolor &color ){
+
5461
+
5462 const std::vector<helios::vec3> nodes{node0, node1};
+
5463 const std::vector<float> radii{radius0, radius1};
+
5464
+
5465 vec3 vec, convec;
+
5466 std::vector<float> cfact(Ndivs+1);
+
5467 std::vector<float> sfact(Ndivs+1);
+
5468 std::vector<std::vector<vec3> > xyz, normal;
+
5469 xyz.resize(Ndivs+1);
+
5470 normal.resize(Ndivs+1);
+
5471 for( uint j=0; j<Ndivs+1; j++ ){
+
5472 xyz.at(j).resize(2);
+
5473 normal.at(j).resize(2);
+
5474 }
+
5475 vec3 nvec(0.1817f,0.6198f,0.7634f);//random vector to get things going
+
5476
+
5477 for( int j=0; j<Ndivs+1; j++ ){
+
5478 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(Ndivs));
+
5479 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(Ndivs));
+
5480 }
+
5481
+
5482 for( int i=0; i<2; i++ ){ //looping over cone segments
5483
-
5484 xyz[j][i].x=nodes[i].x+normal[j][i].x;
-
5485 xyz[j][i].y=nodes[i].y+normal[j][i].y;
-
5486 xyz[j][i].z=nodes[i].z+normal[j][i].z;
-
5487
-
5488 normal[j][i] = normal[j][i]/radii[i];
-
5489 }
-
5490
-
5491 }
-
5492
-
5493 vec3 v0, v1, v2;
-
5494 std::vector<uint> UUID(2*Ndivs);
-
5495
-
5496 int i=0;
-
5497 for( int j=0; j<Ndivs; j++ ){
-
5498
-
5499 v0 = xyz[j][0];
-
5500 v1 = xyz[j+1][1];
-
5501 v2 = xyz[j+1][0];
-
5502
-
5503 UUID.at(i) = addTriangle( v0, v1, v2, color );
-
5504
-
5505 v0 = xyz[j][0];
-
5506 v1 = xyz[j][1];
-
5507 v2 = xyz[j+1][1];
-
5508
-
5509 UUID.at(i+1) = addTriangle( v0, v1, v2, color );
+
5484 if(i==0){
+
5485 vec.x=nodes[i+1].x-nodes[i].x;
+
5486 vec.y=nodes[i+1].y-nodes[i].y;
+
5487 vec.z=nodes[i+1].z-nodes[i].z;
+
5488 }else if(i==1){
+
5489 vec.x=nodes[i].x-nodes[i-1].x;
+
5490 vec.y=nodes[i].y-nodes[i-1].y;
+
5491 vec.z=nodes[i].z-nodes[i-1].z;
+
5492 }
+
5493
+
5494 float norm;
+
5495 convec = cross(nvec,vec);
+
5496 norm=convec.magnitude();
+
5497 convec.x=convec.x/norm;
+
5498 convec.y=convec.y/norm;
+
5499 convec.z=convec.z/norm;
+
5500 nvec = cross(vec,convec);
+
5501 norm=nvec.magnitude();
+
5502 nvec.x=nvec.x/norm;
+
5503 nvec.y=nvec.y/norm;
+
5504 nvec.z=nvec.z/norm;
+
5505
+
5506 for( int j=0; j<Ndivs+1; j++ ){
+
5507 normal[j][i].x=cfact[j]*radii[i]*nvec.x+sfact[j]*radii[i]*convec.x;
+
5508 normal[j][i].y=cfact[j]*radii[i]*nvec.y+sfact[j]*radii[i]*convec.y;
+
5509 normal[j][i].z=cfact[j]*radii[i]*nvec.z+sfact[j]*radii[i]*convec.z;
5510
-
5511 i+=2;
-
5512 }
-
5513
-
5514 auto* cone_new = (new Cone(currentObjectID, UUID, node0, node1, radius0, radius1, Ndivs, "", this));
-
5515
-
5516 for( uint p : UUID){
-
5517 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
5511 xyz[j][i].x=nodes[i].x+normal[j][i].x;
+
5512 xyz[j][i].y=nodes[i].y+normal[j][i].y;
+
5513 xyz[j][i].z=nodes[i].z+normal[j][i].z;
+
5514
+
5515 normal[j][i] = normal[j][i]/radii[i];
+
5516 }
+
5517
5518 }
5519
-
5520 cone_new->setColor( color );
-
5521
-
5522 objects[currentObjectID] = cone_new;
-
5523 currentObjectID++;
-
5524 return currentObjectID-1;
+
5520 vec3 v0, v1, v2;
+
5521 std::vector<uint> UUID(2*Ndivs);
+
5522
+
5523 int i=0;
+
5524 for( int j=0; j<Ndivs; j++ ){
5525
-
5526}
-
-
5527
-
-
5528uint Context::addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile ){
+
5526 v0 = xyz[j][0];
+
5527 v1 = xyz[j+1][1];
+
5528 v2 = xyz[j+1][0];
5529
-
5530 if( !validateTextureFileExtenstion(texturefile) ) {
-
5531 helios_runtime_error("ERROR (Context::addConeObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
5532 }else if( !doesTextureFileExist(texturefile) ) {
-
5533 helios_runtime_error("ERROR (Context::addConeObject): Texture file " + std::string(texturefile) + " does not exist.");
-
5534 }
+
5530 UUID.at(i) = addTriangle( v0, v1, v2, color );
+
5531
+
5532 v0 = xyz[j][0];
+
5533 v1 = xyz[j][1];
+
5534 v2 = xyz[j+1][1];
5535
-
5536 const std::vector<helios::vec3> nodes{node0, node1};
-
5537 const std::vector<float> radii{radius0, radius1};
-
5538
-
5539 vec3 vec, convec;
-
5540 std::vector<float> cfact(Ndivs+1);
-
5541 std::vector<float> sfact(Ndivs+1);
-
5542 std::vector<std::vector<vec3> > xyz, normal;
-
5543 std::vector<std::vector<vec2> > uv;
-
5544 xyz.resize(Ndivs+1);
-
5545 normal.resize(Ndivs+1);
-
5546 uv.resize(Ndivs+1);
-
5547 for( uint j=0; j<Ndivs+1; j++ ){
-
5548 xyz.at(j).resize(2);
-
5549 normal.at(j).resize(2);
-
5550 uv.at(j).resize(2);
-
5551 }
-
5552 vec3 nvec(0.f,1.f,0.f);
-
5553
-
5554 for( int j=0; j<Ndivs+1; j++ ){
-
5555 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(Ndivs));
-
5556 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(Ndivs));
-
5557 }
-
5558
-
5559 for( int i=0; i<2; i++ ){ //looping over cone segments
-
5560
-
5561 if(i==0){
-
5562 vec.x=nodes[i+1].x-nodes[i].x;
-
5563 vec.y=nodes[i+1].y-nodes[i].y;
-
5564 vec.z=nodes[i+1].z-nodes[i].z;
-
5565 }else if(i==1){
-
5566 vec.x=nodes[i].x-nodes[i-1].x;
-
5567 vec.y=nodes[i].y-nodes[i-1].y;
-
5568 vec.z=nodes[i].z-nodes[i-1].z;
-
5569 }
-
5570
-
5571 float norm;
-
5572 convec = cross(nvec,vec);
-
5573 norm=convec.magnitude();
-
5574 convec.x=convec.x/norm;
-
5575 convec.y=convec.y/norm;
-
5576 convec.z=convec.z/norm;
-
5577 nvec = cross(vec,convec);
-
5578 norm=nvec.magnitude();
-
5579 nvec.x=nvec.x/norm;
-
5580 nvec.y=nvec.y/norm;
-
5581 nvec.z=nvec.z/norm;
-
5582
-
5583 for( int j=0; j<Ndivs+1; j++ ){
-
5584 normal[j][i].x=cfact[j]*radii[i]*nvec.x+sfact[j]*radii[i]*convec.x;
-
5585 normal[j][i].y=cfact[j]*radii[i]*nvec.y+sfact[j]*radii[i]*convec.y;
-
5586 normal[j][i].z=cfact[j]*radii[i]*nvec.z+sfact[j]*radii[i]*convec.z;
+
5536 UUID.at(i+1) = addTriangle( v0, v1, v2, color );
+
5537
+
5538 i+=2;
+
5539 }
+
5540
+
5541 auto* cone_new = (new Cone(currentObjectID, UUID, node0, node1, radius0, radius1, Ndivs, "", this));
+
5542
+
5543 for( uint p : UUID){
+
5544 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
5545 }
+
5546
+
5547 cone_new->setColor( color );
+
5548
+
5549 objects[currentObjectID] = cone_new;
+
5550 currentObjectID++;
+
5551 return currentObjectID-1;
+
5552
+
5553}
+
+
5554
+
+
5555uint Context::addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile ){
+
5556
+
5557 if( !validateTextureFileExtenstion(texturefile) ) {
+
5558 helios_runtime_error("ERROR (Context::addConeObject): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
5559 }else if( !doesTextureFileExist(texturefile) ) {
+
5560 helios_runtime_error("ERROR (Context::addConeObject): Texture file " + std::string(texturefile) + " does not exist.");
+
5561 }
+
5562
+
5563 const std::vector<helios::vec3> nodes{node0, node1};
+
5564 const std::vector<float> radii{radius0, radius1};
+
5565
+
5566 vec3 vec, convec;
+
5567 std::vector<float> cfact(Ndivs+1);
+
5568 std::vector<float> sfact(Ndivs+1);
+
5569 std::vector<std::vector<vec3> > xyz, normal;
+
5570 std::vector<std::vector<vec2> > uv;
+
5571 xyz.resize(Ndivs+1);
+
5572 normal.resize(Ndivs+1);
+
5573 uv.resize(Ndivs+1);
+
5574 for( uint j=0; j<Ndivs+1; j++ ){
+
5575 xyz.at(j).resize(2);
+
5576 normal.at(j).resize(2);
+
5577 uv.at(j).resize(2);
+
5578 }
+
5579 vec3 nvec(0.f,1.f,0.f);
+
5580
+
5581 for( int j=0; j<Ndivs+1; j++ ){
+
5582 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(Ndivs));
+
5583 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(Ndivs));
+
5584 }
+
5585
+
5586 for( int i=0; i<2; i++ ){ //looping over cone segments
5587
-
5588 xyz[j][i].x=nodes[i].x+normal[j][i].x;
-
5589 xyz[j][i].y=nodes[i].y+normal[j][i].y;
-
5590 xyz[j][i].z=nodes[i].z+normal[j][i].z;
-
5591
-
5592 uv[j][i].x = float(i)/float(2-1);
-
5593 uv[j][i].y = float(j)/float(Ndivs);
-
5594
-
5595 normal[j][i] = normal[j][i]/radii[i];
+
5588 if(i==0){
+
5589 vec.x=nodes[i+1].x-nodes[i].x;
+
5590 vec.y=nodes[i+1].y-nodes[i].y;
+
5591 vec.z=nodes[i+1].z-nodes[i].z;
+
5592 }else if(i==1){
+
5593 vec.x=nodes[i].x-nodes[i-1].x;
+
5594 vec.y=nodes[i].y-nodes[i-1].y;
+
5595 vec.z=nodes[i].z-nodes[i-1].z;
5596 }
5597
-
5598 }
-
5599
-
5600 vec3 v0, v1, v2;
-
5601 vec2 uv0, uv1, uv2;
-
5602 std::vector<uint> UUID;
-
5603
-
5604 for( int i=0; i<2-1; i++ ){
-
5605 for( int j=0; j<Ndivs; j++ ){
-
5606
-
5607 v0 = xyz[j][i];
-
5608 v1 = xyz[j+1][i+1];
-
5609 v2 = xyz[j+1][i];
-
5610
-
5611 uv0 = uv[j][i];
-
5612 uv1 = uv[j+1][i+1];
-
5613 uv2 = uv[j+1][i];
+
5598 float norm;
+
5599 convec = cross(nvec,vec);
+
5600 norm=convec.magnitude();
+
5601 convec.x=convec.x/norm;
+
5602 convec.y=convec.y/norm;
+
5603 convec.z=convec.z/norm;
+
5604 nvec = cross(vec,convec);
+
5605 norm=nvec.magnitude();
+
5606 nvec.x=nvec.x/norm;
+
5607 nvec.y=nvec.y/norm;
+
5608 nvec.z=nvec.z/norm;
+
5609
+
5610 for( int j=0; j<Ndivs+1; j++ ){
+
5611 normal[j][i].x=cfact[j]*radii[i]*nvec.x+sfact[j]*radii[i]*convec.x;
+
5612 normal[j][i].y=cfact[j]*radii[i]*nvec.y+sfact[j]*radii[i]*convec.y;
+
5613 normal[j][i].z=cfact[j]*radii[i]*nvec.z+sfact[j]*radii[i]*convec.z;
5614
-
5615 if( (v1-v0).magnitude()>1e-6 && (v2-v0).magnitude()>1e-6 && (v2-v1).magnitude()>1e-6 ){
-
5616 UUID.push_back(addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 ));
-
5617 }
+
5615 xyz[j][i].x=nodes[i].x+normal[j][i].x;
+
5616 xyz[j][i].y=nodes[i].y+normal[j][i].y;
+
5617 xyz[j][i].z=nodes[i].z+normal[j][i].z;
5618
-
5619 v0 = xyz[j][i];
-
5620 v1 = xyz[j][i+1];
-
5621 v2 = xyz[j+1][i+1];
-
5622
-
5623 uv0 = uv[j][i];
-
5624 uv1 = uv[j][i+1];
-
5625 uv2 = uv[j+1][i+1];
+
5619 uv[j][i].x = float(i)/float(2-1);
+
5620 uv[j][i].y = float(j)/float(Ndivs);
+
5621
+
5622 normal[j][i] = normal[j][i]/radii[i];
+
5623 }
+
5624
+
5625 }
5626
-
5627 if( (v1-v0).magnitude()>1e-6 && (v2-v0).magnitude()>1e-6 && (v2-v1).magnitude()>1e-6 ){
-
5628 UUID.push_back(addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 ));
-
5629 }
+
5627 vec3 v0, v1, v2;
+
5628 vec2 uv0, uv1, uv2;
+
5629 std::vector<uint> UUID;
5630
-
5631 }
-
5632 }
+
5631 for( int i=0; i<2-1; i++ ){
+
5632 for( int j=0; j<Ndivs; j++ ){
5633
-
5634 auto* cone_new = (new Cone(currentObjectID, UUID, node0, node1, radius0, radius1, Ndivs, texturefile, this));
-
5635
-
5636 for( uint p : UUID){
-
5637 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
-
5638 }
-
5639
-
5640 objects[currentObjectID] = cone_new;
-
5641 currentObjectID++;
-
5642 return currentObjectID-1;
-
5643
-
5644}
-
+
5634 v0 = xyz[j][i];
+
5635 v1 = xyz[j+1][i+1];
+
5636 v2 = xyz[j+1][i];
+
5637
+
5638 uv0 = uv[j][i];
+
5639 uv1 = uv[j+1][i+1];
+
5640 uv2 = uv[j+1][i];
+
5641
+
5642 if( (v1-v0).magnitude()>1e-6 && (v2-v0).magnitude()>1e-6 && (v2-v1).magnitude()>1e-6 ){
+
5643 UUID.push_back(addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 ));
+
5644 }
5645
-
-
5646std::vector<uint> Context::addSphere(uint Ndivs, const vec3 &center, float radius ){
-
5647
-
5648 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
5646 v0 = xyz[j][i];
+
5647 v1 = xyz[j][i+1];
+
5648 v2 = xyz[j+1][i+1];
5649
-
5650 return addSphere(Ndivs,center,radius,color);
-
5651
-
5652}
-
+
5650 uv0 = uv[j][i];
+
5651 uv1 = uv[j][i+1];
+
5652 uv2 = uv[j+1][i+1];
5653
-
-
5654std::vector<uint> Context::addSphere(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color ){
-
5655
-
5656 std::vector<uint> UUID;
+
5654 if( (v1-v0).magnitude()>1e-6 && (v2-v0).magnitude()>1e-6 && (v2-v1).magnitude()>1e-6 ){
+
5655 UUID.push_back(addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 ));
+
5656 }
5657
-
5658 float theta;
-
5659 float dtheta=M_PI/float(Ndivs);
-
5660 float dphi=2.0f*float(M_PI)/float(Ndivs);
-
5661
-
5662 //bottom cap
-
5663 for( int j=0; j<Ndivs; j++ ){
-
5664
-
5665 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI), 0 ) );
-
5666 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+dtheta, float(j)*dphi ) );
-
5667 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+dtheta, float(j+1)*dphi ) );
-
5668
-
5669 UUID.push_back( addTriangle(v0,v1,v2,color) );
+
5658 }
+
5659 }
+
5660
+
5661 auto* cone_new = (new Cone(currentObjectID, UUID, node0, node1, radius0, radius1, Ndivs, texturefile, this));
+
5662
+
5663 for( uint p : UUID){
+
5664 getPrimitivePointer_private(p)->setParentObjectID(currentObjectID);
+
5665 }
+
5666
+
5667 objects[currentObjectID] = cone_new;
+
5668 currentObjectID++;
+
5669 return currentObjectID-1;
5670
-
5671 }
+
5671}
+
5672
-
5673 //top cap
-
5674 for( int j=0; j<Ndivs; j++ ){
-
5675
-
5676 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI), 0 ) );
-
5677 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI)-dtheta, float(j)*dphi ) );
-
5678 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI)-dtheta, float(j+1)*dphi ) );
-
5679
-
5680 UUID.push_back( addTriangle(v2,v1,v0,color) );
-
5681
-
5682 }
-
5683
-
5684 //middle
-
5685 for( int j=0; j<Ndivs; j++ ){
-
5686 for( int i=1; i<Ndivs-1; i++ ){
-
5687
-
5688 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i)*dtheta, float(j)*dphi ) );
-
5689 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j)*dphi ) );
-
5690 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j+1)*dphi ) );
-
5691 vec3 v3 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i)*dtheta, float(j+1)*dphi ) );
-
5692
-
5693 UUID.push_back( addTriangle(v0,v1,v2,color) );
-
5694 UUID.push_back( addTriangle(v0,v2,v3,color) );
+
+
5673std::vector<uint> Context::addSphere(uint Ndivs, const vec3 &center, float radius ){
+
5674
+
5675 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
5676
+
5677 return addSphere(Ndivs,center,radius,color);
+
5678
+
5679}
+
+
5680
+
+
5681std::vector<uint> Context::addSphere(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color ){
+
5682
+
5683 std::vector<uint> UUID;
+
5684
+
5685 float theta;
+
5686 float dtheta=M_PI/float(Ndivs);
+
5687 float dphi=2.0f*float(M_PI)/float(Ndivs);
+
5688
+
5689 //bottom cap
+
5690 for( int j=0; j<Ndivs; j++ ){
+
5691
+
5692 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI), 0 ) );
+
5693 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+dtheta, float(j)*dphi ) );
+
5694 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+dtheta, float(j+1)*dphi ) );
5695
-
5696 }
-
5697 }
-
5698
-
5699 return UUID;
-
5700
-
5701
-
5702}
-
-
5703
-
-
5704std::vector<uint> Context::addSphere(uint Ndivs, const vec3 &center, float radius, const char* texturefile ){
-
5705
-
5706 if( !validateTextureFileExtenstion(texturefile) ) {
-
5707 helios_runtime_error("ERROR (Context::addSphere): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
5708 }else if( !doesTextureFileExist(texturefile) ) {
-
5709 helios_runtime_error("ERROR (Context::addSphere): Texture file " + std::string(texturefile) + " does not exist.");
-
5710 }
-
5711
-
5712 std::vector<uint> UUID;
-
5713
-
5714 float theta;
-
5715 float dtheta=M_PI/float(Ndivs);
-
5716 float dphi=2.0f*float(M_PI)/float(Ndivs);
-
5717
-
5718 //bottom cap
-
5719 for( int j=0; j<Ndivs; j++ ){
-
5720
-
5721 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI), 0 ) );
-
5722 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+dtheta, float(j)*dphi ) );
-
5723 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+dtheta, float(j+1)*dphi ) );
-
5724
-
5725 vec3 n0 = v0-center;
-
5726 n0.normalize();
-
5727 vec3 n1 = v1-center;
-
5728 n1.normalize();
-
5729 vec3 n2 = v2-center;
-
5730 n2.normalize();
-
5731
-
5732 vec2 uv0 = make_vec2( 1.f - atan2f( sin((float(j)+0.5f)*dphi), -cos((float(j)+0.5f)*dphi) )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
-
5733 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
-
5734 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
-
5735
-
5736 if( j==Ndivs-1 ){
-
5737 uv2.x = 1;
-
5738 }
-
5739
-
5740 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
-
5741
-
5742 }
-
5743
-
5744 //top cap
-
5745 for( int j=0; j<Ndivs; j++ ){
-
5746
-
5747 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI), 0 ) );
-
5748 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI)-dtheta, float(j+1)*dphi ) );
-
5749 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI)-dtheta, float(j)*dphi ) );
-
5750
-
5751 vec3 n0 = v0-center;
-
5752 n0.normalize();
-
5753 vec3 n1 = v1-center;
-
5754 n1.normalize();
-
5755 vec3 n2 = v2-center;
-
5756 n2.normalize();
-
5757
-
5758 vec2 uv0 = make_vec2( 1.f - atan2f( sinf((float(j)+0.5f)*dphi), -cosf((float(j)+0.5f)*dphi) )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
-
5759 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
-
5760 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
-
5761
-
5762 if( j==Ndivs-1 ){
-
5763 uv2.x = 1;
-
5764 }
-
5765
-
5766 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
-
5767
-
5768 }
-
5769
-
5770 //middle
-
5771 for( int j=0; j<Ndivs; j++ ){
-
5772 for( int i=1; i<Ndivs-1; i++ ){
+
5696 UUID.push_back( addTriangle(v0,v1,v2,color) );
+
5697
+
5698 }
+
5699
+
5700 //top cap
+
5701 for( int j=0; j<Ndivs; j++ ){
+
5702
+
5703 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI), 0 ) );
+
5704 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI)-dtheta, float(j)*dphi ) );
+
5705 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI)-dtheta, float(j+1)*dphi ) );
+
5706
+
5707 UUID.push_back( addTriangle(v2,v1,v0,color) );
+
5708
+
5709 }
+
5710
+
5711 //middle
+
5712 for( int j=0; j<Ndivs; j++ ){
+
5713 for( int i=1; i<Ndivs-1; i++ ){
+
5714
+
5715 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i)*dtheta, float(j)*dphi ) );
+
5716 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j)*dphi ) );
+
5717 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j+1)*dphi ) );
+
5718 vec3 v3 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i)*dtheta, float(j+1)*dphi ) );
+
5719
+
5720 UUID.push_back( addTriangle(v0,v1,v2,color) );
+
5721 UUID.push_back( addTriangle(v0,v2,v3,color) );
+
5722
+
5723 }
+
5724 }
+
5725
+
5726 return UUID;
+
5727
+
5728
+
5729}
+
+
5730
+
+
5731std::vector<uint> Context::addSphere(uint Ndivs, const vec3 &center, float radius, const char* texturefile ){
+
5732
+
5733 if( !validateTextureFileExtenstion(texturefile) ) {
+
5734 helios_runtime_error("ERROR (Context::addSphere): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
5735 }else if( !doesTextureFileExist(texturefile) ) {
+
5736 helios_runtime_error("ERROR (Context::addSphere): Texture file " + std::string(texturefile) + " does not exist.");
+
5737 }
+
5738
+
5739 std::vector<uint> UUID;
+
5740
+
5741 float theta;
+
5742 float dtheta=M_PI/float(Ndivs);
+
5743 float dphi=2.0f*float(M_PI)/float(Ndivs);
+
5744
+
5745 //bottom cap
+
5746 for( int j=0; j<Ndivs; j++ ){
+
5747
+
5748 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI), 0 ) );
+
5749 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+dtheta, float(j)*dphi ) );
+
5750 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+dtheta, float(j+1)*dphi ) );
+
5751
+
5752 vec3 n0 = v0-center;
+
5753 n0.normalize();
+
5754 vec3 n1 = v1-center;
+
5755 n1.normalize();
+
5756 vec3 n2 = v2-center;
+
5757 n2.normalize();
+
5758
+
5759 vec2 uv0 = make_vec2( 1.f - atan2f( sin((float(j)+0.5f)*dphi), -cos((float(j)+0.5f)*dphi) )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
+
5760 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
+
5761 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
+
5762
+
5763 if( j==Ndivs-1 ){
+
5764 uv2.x = 1;
+
5765 }
+
5766
+
5767 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
+
5768
+
5769 }
+
5770
+
5771 //top cap
+
5772 for( int j=0; j<Ndivs; j++ ){
5773
-
5774 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i)*dtheta, float(j)*dphi ) );
-
5775 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j)*dphi ) );
-
5776 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j+1)*dphi ) );
-
5777 vec3 v3 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i)*dtheta, float(j+1)*dphi ) );
-
5778
-
5779 vec3 n0 = v0-center;
-
5780 n0.normalize();
-
5781 vec3 n1 = v1-center;
-
5782 n1.normalize();
-
5783 vec3 n2 = v2-center;
-
5784 n2.normalize();
-
5785 vec3 n3 = v3-center;
-
5786 n3.normalize();
-
5787
-
5788 vec2 uv0 = make_vec2( 1.f - atan2f( n0.x, -n0.y )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
-
5789 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
-
5790 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
-
5791 vec2 uv3 = make_vec2( 1.f - atan2f( n3.x, -n3.y )/float(2.f*M_PI) - 0.5f, 1.f - n3.z*0.5f - 0.5f );
+
5774 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI), 0 ) );
+
5775 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI)-dtheta, float(j+1)*dphi ) );
+
5776 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, 0.5f*float(M_PI)-dtheta, float(j)*dphi ) );
+
5777
+
5778 vec3 n0 = v0-center;
+
5779 n0.normalize();
+
5780 vec3 n1 = v1-center;
+
5781 n1.normalize();
+
5782 vec3 n2 = v2-center;
+
5783 n2.normalize();
+
5784
+
5785 vec2 uv0 = make_vec2( 1.f - atan2f( sinf((float(j)+0.5f)*dphi), -cosf((float(j)+0.5f)*dphi) )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
+
5786 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
+
5787 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
+
5788
+
5789 if( j==Ndivs-1 ){
+
5790 uv2.x = 1;
+
5791 }
5792
-
5793 if( j==Ndivs-1 ){
-
5794 uv2.x = 1;
-
5795 uv3.x = 1;
-
5796 }
-
5797
-
5798 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
-
5799 UUID.push_back( addTriangle(v0,v2,v3,texturefile,uv0,uv2,uv3) );
+
5793 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
+
5794
+
5795 }
+
5796
+
5797 //middle
+
5798 for( int j=0; j<Ndivs; j++ ){
+
5799 for( int i=1; i<Ndivs-1; i++ ){
5800
-
5801 }
-
5802 }
-
5803
-
5804 return UUID;
+
5801 vec3 v0 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i)*dtheta, float(j)*dphi ) );
+
5802 vec3 v1 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j)*dphi ) );
+
5803 vec3 v2 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i+1)*dtheta, float(j+1)*dphi ) );
+
5804 vec3 v3 = center + sphere2cart( make_SphericalCoord(radius, -0.5f*float(M_PI)+float(i)*dtheta, float(j+1)*dphi ) );
5805
-
5806
-
5807}
-
-
5808
-
-
5809std::vector<uint> Context::addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv ){
-
5810
-
5811 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
-
5812
-
5813 return addTile(center,size,rotation,subdiv,color);
-
5814}
-
-
5815
-
-
5816std::vector<uint> Context::addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color ){
-
5817
-
5818 std::vector<uint> UUID;
+
5806 vec3 n0 = v0-center;
+
5807 n0.normalize();
+
5808 vec3 n1 = v1-center;
+
5809 n1.normalize();
+
5810 vec3 n2 = v2-center;
+
5811 n2.normalize();
+
5812 vec3 n3 = v3-center;
+
5813 n3.normalize();
+
5814
+
5815 vec2 uv0 = make_vec2( 1.f - atan2f( n0.x, -n0.y )/float(2.f*M_PI) - 0.5f, 1.f - n0.z*0.5f - 0.5f );
+
5816 vec2 uv1 = make_vec2( 1.f - atan2f( n1.x, -n1.y )/float(2.f*M_PI) - 0.5f, 1.f - n1.z*0.5f - 0.5f );
+
5817 vec2 uv2 = make_vec2( 1.f - atan2f( n2.x, -n2.y )/float(2.f*M_PI) - 0.5f, 1.f - n2.z*0.5f - 0.5f );
+
5818 vec2 uv3 = make_vec2( 1.f - atan2f( n3.x, -n3.y )/float(2.f*M_PI) - 0.5f, 1.f - n3.z*0.5f - 0.5f );
5819
-
5820 vec2 subsize;
-
5821 subsize.x = size.x/float(subdiv.x);
-
5822 subsize.y = size.y/float(subdiv.y);
-
5823
-
5824 vec3 subcenter;
-
5825
-
5826 UUID.resize( subdiv.x*subdiv.y );
+
5820 if( j==Ndivs-1 ){
+
5821 uv2.x = 1;
+
5822 uv3.x = 1;
+
5823 }
+
5824
+
5825 UUID.push_back( addTriangle(v0,v1,v2,texturefile,uv0,uv1,uv2) );
+
5826 UUID.push_back( addTriangle(v0,v2,v3,texturefile,uv0,uv2,uv3) );
5827
-
5828 size_t t = 0;
-
5829 for( uint j=0; j<subdiv.y; j++ ){
-
5830 for( uint i=0; i<subdiv.x; i++ ){
-
5831
-
5832 subcenter = make_vec3(-0.5f*size.x+(float(i)+0.5f)*subsize.x,-0.5f*size.y+(float(j)+0.5f)*subsize.y,0);
+
5828 }
+
5829 }
+
5830
+
5831 return UUID;
+
5832
5833
-
5834 UUID[t] = addPatch( subcenter, subsize, make_SphericalCoord(0,0), color );
+
5834}
+
5835
-
5836 if( rotation.elevation!=0.f ){
-
5837 getPrimitivePointer_private( UUID[t] )->rotate( -rotation.elevation, "x" );
-
5838 }
-
5839 if( rotation.azimuth!=0.f ){
-
5840 getPrimitivePointer_private( UUID[t] )->rotate( -rotation.azimuth, "z" );
-
5841 }
-
5842 getPrimitivePointer_private( UUID[t] )->translate( center );
-
5843
-
5844 t++;
-
5845
-
5846 }
-
5847 }
-
5848
-
5849 return UUID;
+
+
5836std::vector<uint> Context::addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv ){
+
5837
+
5838 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
5839
+
5840 return addTile(center,size,rotation,subdiv,color);
+
5841}
+
+
5842
+
+
5843std::vector<uint> Context::addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color ){
+
5844
+
5845 std::vector<uint> UUID;
+
5846
+
5847 vec2 subsize;
+
5848 subsize.x = size.x/float(subdiv.x);
+
5849 subsize.y = size.y/float(subdiv.y);
5850
-
5851}
-
+
5851 vec3 subcenter;
5852
-
-
5853std::vector<uint> Context::addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile ){
+
5853 UUID.resize( subdiv.x*subdiv.y );
5854
-
5855 if( !validateTextureFileExtenstion(texturefile) ) {
-
5856 helios_runtime_error("ERROR (Context::addTile): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
5857 }else if( !doesTextureFileExist(texturefile) ) {
-
5858 helios_runtime_error("ERROR (Context::addTile): Texture file " + std::string(texturefile) + " does not exist.");
-
5859 }
+
5855 size_t t = 0;
+
5856 for( uint j=0; j<subdiv.y; j++ ){
+
5857 for( uint i=0; i<subdiv.x; i++ ){
+
5858
+
5859 subcenter = make_vec3(-0.5f*size.x+(float(i)+0.5f)*subsize.x,-0.5f*size.y+(float(j)+0.5f)*subsize.y,0);
5860
-
5861 std::vector<uint> UUID;
+
5861 UUID[t] = addPatch( subcenter, subsize, make_SphericalCoord(0,0), color );
5862
-
5863 vec2 subsize;
-
5864 subsize.x = size.x/float(subdiv.x);
-
5865 subsize.y = size.y/float(subdiv.y);
-
5866
-
5867 vec3 subcenter;
-
5868
-
5869 std::vector<helios::vec2> uv;
-
5870 uv.resize(4);
-
5871 vec2 uv_sub;
-
5872 uv_sub.x = 1.f/float(subdiv.x);
-
5873 uv_sub.y = 1.f/float(subdiv.y);
-
5874
-
5875 addTexture( texturefile );
-
5876 std::vector<std::vector<bool> > alpha;
-
5877 if( textures.at(texturefile).hasTransparencyChannel() ){
-
5878 alpha = *textures.at(texturefile).getTransparencyData();
-
5879 }
-
5880
-
5881 int2 sz = textures.at(texturefile).getImageResolution();
-
5882 if( subdiv.x>=sz.x || subdiv.y>=sz.y ){
-
5883 helios_runtime_error("ERROR (Context::addTile): The resolution of the texture image '" + std::string(texturefile) + "' is lower than the number of tile subdivisions. Increase resolution of the texture image.");
-
5884 }
-
5885
-
5886 for( uint j=0; j<subdiv.y; j++ ){
-
5887 for( uint i=0; i<subdiv.x; i++ ){
-
5888
-
5889 subcenter = make_vec3(-0.5f*size.x+(float(i)+0.5f)*subsize.x,-0.5f*size.y+(float(j)+0.5f)*subsize.y,0);
-
5890
-
5891 uv[0] = make_vec2(float(i)*uv_sub.x,float(j)*uv_sub.y);
-
5892 uv[1] = make_vec2(float(i+1)*uv_sub.x,float(j)*uv_sub.y);
-
5893 uv[2] = make_vec2(float(i+1)*uv_sub.x,float(j+1)*uv_sub.y);
-
5894 uv[3] = make_vec2(float(i)*uv_sub.x,float(j+1)*uv_sub.y);
+
5863 if( rotation.elevation!=0.f ){
+
5864 getPrimitivePointer_private( UUID[t] )->rotate( -rotation.elevation, "x" );
+
5865 }
+
5866 if( rotation.azimuth!=0.f ){
+
5867 getPrimitivePointer_private( UUID[t] )->rotate( -rotation.azimuth, "z" );
+
5868 }
+
5869 getPrimitivePointer_private( UUID[t] )->translate( center );
+
5870
+
5871 t++;
+
5872
+
5873 }
+
5874 }
+
5875
+
5876 return UUID;
+
5877
+
5878}
+
+
5879
+
+
5880std::vector<uint> Context::addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile ){
+
5881
+
5882 if( !validateTextureFileExtenstion(texturefile) ) {
+
5883 helios_runtime_error("ERROR (Context::addTile): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
5884 }else if( !doesTextureFileExist(texturefile) ) {
+
5885 helios_runtime_error("ERROR (Context::addTile): Texture file " + std::string(texturefile) + " does not exist.");
+
5886 }
+
5887
+
5888 std::vector<uint> UUID;
+
5889
+
5890 vec2 subsize;
+
5891 subsize.x = size.x/float(subdiv.x);
+
5892 subsize.y = size.y/float(subdiv.y);
+
5893
+
5894 vec3 subcenter;
5895
-
5896 auto* patch_new = (new Patch( texturefile, uv, textures, 0, currentUUID ));
-
5897
-
5898 if( patch_new->getSolidFraction()==0 ){
-
5899 delete patch_new;
-
5900 continue;
-
5901 }
-
5902
-
5903 assert( size.x>0.f && size.y>0.f );
-
5904 patch_new->scale( make_vec3(subsize.x,subsize.y,1) );
-
5905
-
5906 patch_new->translate( subcenter );
+
5896 std::vector<helios::vec2> uv;
+
5897 uv.resize(4);
+
5898 vec2 uv_sub;
+
5899 uv_sub.x = 1.f/float(subdiv.x);
+
5900 uv_sub.y = 1.f/float(subdiv.y);
+
5901
+
5902 addTexture( texturefile );
+
5903 std::vector<std::vector<bool> > alpha;
+
5904 if( textures.at(texturefile).hasTransparencyChannel() ){
+
5905 alpha = *textures.at(texturefile).getTransparencyData();
+
5906 }
5907
-
5908 if( rotation.elevation!=0 ){
-
5909 patch_new->rotate(-rotation.elevation, "x");
-
5910 }
-
5911 if( rotation.azimuth!=0 ){
-
5912 patch_new->rotate(-rotation.azimuth, "z");
-
5913 }
-
5914
-
5915 patch_new->translate( center );
-
5916
-
5917 primitives[currentUUID] = patch_new;
- -
5919 currentUUID++;
-
5920 UUID.push_back(currentUUID-1);
-
5921
+
5908 int2 sz = textures.at(texturefile).getImageResolution();
+
5909 if( subdiv.x>=sz.x || subdiv.y>=sz.y ){
+
5910 helios_runtime_error("ERROR (Context::addTile): The resolution of the texture image '" + std::string(texturefile) + "' is lower than the number of tile subdivisions. Increase resolution of the texture image.");
+
5911 }
+
5912
+
5913 for( uint j=0; j<subdiv.y; j++ ){
+
5914 for( uint i=0; i<subdiv.x; i++ ){
+
5915
+
5916 subcenter = make_vec3(-0.5f*size.x+(float(i)+0.5f)*subsize.x,-0.5f*size.y+(float(j)+0.5f)*subsize.y,0);
+
5917
+
5918 uv[0] = make_vec2(float(i)*uv_sub.x,float(j)*uv_sub.y);
+
5919 uv[1] = make_vec2(float(i+1)*uv_sub.x,float(j)*uv_sub.y);
+
5920 uv[2] = make_vec2(float(i+1)*uv_sub.x,float(j+1)*uv_sub.y);
+
5921 uv[3] = make_vec2(float(i)*uv_sub.x,float(j+1)*uv_sub.y);
5922
-
5923 }
-
5924 }
-
5925
-
5926 return UUID;
-
5927
-
5928}
-
+
5923 auto* patch_new = (new Patch( texturefile, uv, textures, 0, currentUUID ));
+
5924
+
5925 if( patch_new->getSolidFraction()==0 ){
+
5926 delete patch_new;
+
5927 continue;
+
5928 }
5929
-
-
5930std::vector<uint> Context::addTube(uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius ){
-
5931
-
5932 uint node_count = nodes.size();
-
5933
-
5934 std::vector<RGBcolor> color;
-
5935 color.resize(node_count);
-
5936
-
5937 for( uint i=0; i<node_count; i++ ){
-
5938 color.at(i) = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
-
5939 }
-
5940
-
5941 return addTube(Ndivs,nodes,radius,color);
-
5942
-
5943}
-
-
5944
-
-
5945std::vector<uint> Context::addTube(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color ){
-
5946
-
5947 const uint node_count = nodes.size();
+
5930 assert( size.x>0.f && size.y>0.f );
+
5931 patch_new->scale( make_vec3(subsize.x,subsize.y,1) );
+
5932
+
5933 patch_new->translate( subcenter );
+
5934
+
5935 if( rotation.elevation!=0 ){
+
5936 patch_new->rotate(-rotation.elevation, "x");
+
5937 }
+
5938 if( rotation.azimuth!=0 ){
+
5939 patch_new->rotate(-rotation.azimuth, "z");
+
5940 }
+
5941
+
5942 patch_new->translate( center );
+
5943
+
5944 primitives[currentUUID] = patch_new;
+ +
5946 currentUUID++;
+
5947 UUID.push_back(currentUUID-1);
5948
-
5949 if( node_count==0 ){
-
5950 helios_runtime_error("ERROR (Context::addTube): Node and radius arrays are empty.");
-
5951 }else if( node_count!=radius.size() ){
-
5952 helios_runtime_error("ERROR (Context::addTube): Size of `nodes' and `radius' arguments must agree.");
-
5953 }else if( node_count!=color.size() ){
-
5954 helios_runtime_error("ERROR (Context::addTube): Size of `nodes' and `color' arguments must agree.");
-
5955 }
+
5949
+
5950 }
+
5951 }
+
5952
+
5953 return UUID;
+
5954
+
5955}
+
5956
-
5957 vec3 vec, convec;
-
5958 std::vector<float> cfact(radial_subdivisions + 1);
-
5959 std::vector<float> sfact(radial_subdivisions + 1);
-
5960 std::vector<std::vector<vec3> > xyz;
-
5961 resize_vector( xyz, node_count, radial_subdivisions + 1 );
-
5962
-
5963 vec3 nvec(0.1817f,0.6198f,0.7634f);//random vector to get things going
-
5964
-
5965 for(int j=0; j < radial_subdivisions + 1; j++ ){
-
5966 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(radial_subdivisions));
-
5967 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(radial_subdivisions));
-
5968 }
+
+
5957std::vector<uint> Context::addTube(uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius ){
+
5958
+
5959 uint node_count = nodes.size();
+
5960
+
5961 std::vector<RGBcolor> color;
+
5962 color.resize(node_count);
+
5963
+
5964 for( uint i=0; i<node_count; i++ ){
+
5965 color.at(i) = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
5966 }
+
5967
+
5968 return addTube(Ndivs,nodes,radius,color);
5969
-
5970 for( int i=0; i<node_count; i++ ){ //looping over tube segments
+
5970}
+
5971
-
5972 if( radius.at(i)<0 ){
-
5973 helios_runtime_error("ERROR (Context::addTube): Radius of tube must be positive.");
-
5974 }
+
+
5972std::vector<uint> Context::addTube(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color ){
+
5973
+
5974 const uint node_count = nodes.size();
5975
-
5976 if(i==0){
-
5977 vec.x=nodes[i+1].x-nodes[i].x;
-
5978 vec.y=nodes[i+1].y-nodes[i].y;
-
5979 vec.z=nodes[i+1].z-nodes[i].z;
-
5980 }else if(i==node_count-1){
-
5981 vec.x=nodes[i].x-nodes[i-1].x;
-
5982 vec.y=nodes[i].y-nodes[i-1].y;
-
5983 vec.z=nodes[i].z-nodes[i-1].z;
-
5984 }else{
-
5985 vec.x=0.5f*( (nodes[i].x-nodes[i-1].x)+(nodes[i+1].x-nodes[i].x) );
-
5986 vec.y=0.5f*( (nodes[i].y-nodes[i-1].y)+(nodes[i+1].y-nodes[i].y) );
-
5987 vec.z=0.5f*( (nodes[i].z-nodes[i-1].z)+(nodes[i+1].z-nodes[i].z) );
-
5988 }
+
5976 if( node_count==0 ){
+
5977 helios_runtime_error("ERROR (Context::addTube): Node and radius arrays are empty.");
+
5978 }else if( node_count!=radius.size() ){
+
5979 helios_runtime_error("ERROR (Context::addTube): Size of `nodes' and `radius' arguments must agree.");
+
5980 }else if( node_count!=color.size() ){
+
5981 helios_runtime_error("ERROR (Context::addTube): Size of `nodes' and `color' arguments must agree.");
+
5982 }
+
5983
+
5984 vec3 vec, convec;
+
5985 std::vector<float> cfact(radial_subdivisions + 1);
+
5986 std::vector<float> sfact(radial_subdivisions + 1);
+
5987 std::vector<std::vector<vec3> > xyz;
+
5988 resize_vector( xyz, node_count, radial_subdivisions + 1 );
5989
-
5990 convec = cross(nvec,vec);
-
5991 convec.normalize();
-
5992 nvec = cross(vec,convec);
-
5993 nvec.normalize();
-
5994
-
5995 for(int j=0; j < radial_subdivisions + 1; j++ ){
+
5990 vec3 nvec(0.1817f,0.6198f,0.7634f);//random vector to get things going
+
5991
+
5992 for(int j=0; j < radial_subdivisions + 1; j++ ){
+
5993 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(radial_subdivisions));
+
5994 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(radial_subdivisions));
+
5995 }
5996
-
5997 vec3 normal;
-
5998 normal.x=cfact[j]*radius[i]*nvec.x+sfact[j]*radius[i]*convec.x;
-
5999 normal.y=cfact[j]*radius[i]*nvec.y+sfact[j]*radius[i]*convec.y;
-
6000 normal.z=cfact[j]*radius[i]*nvec.z+sfact[j]*radius[i]*convec.z;
-
6001
-
6002 xyz[j][i].x=nodes[i].x+normal.x;
-
6003 xyz[j][i].y=nodes[i].y+normal.y;
-
6004 xyz[j][i].z=nodes[i].z+normal.z;
-
6005
-
6006 }
-
6007
-
6008 }
-
6009
-
6010 vec3 v0, v1, v2;
-
6011 std::vector<uint> UUIDs(2 * (node_count-1) * radial_subdivisions );
-
6012
-
6013 int ii=0;
-
6014 for( int i=0; i<node_count-1; i++ ){
-
6015 for(int j=0; j < radial_subdivisions; j++ ){
+
5997 for( int i=0; i<node_count; i++ ){ //looping over tube segments
+
5998
+
5999 if( radius.at(i)<0 ){
+
6000 helios_runtime_error("ERROR (Context::addTube): Radius of tube must be positive.");
+
6001 }
+
6002
+
6003 if(i==0){
+
6004 vec.x=nodes[i+1].x-nodes[i].x;
+
6005 vec.y=nodes[i+1].y-nodes[i].y;
+
6006 vec.z=nodes[i+1].z-nodes[i].z;
+
6007 }else if(i==node_count-1){
+
6008 vec.x=nodes[i].x-nodes[i-1].x;
+
6009 vec.y=nodes[i].y-nodes[i-1].y;
+
6010 vec.z=nodes[i].z-nodes[i-1].z;
+
6011 }else{
+
6012 vec.x=0.5f*( (nodes[i].x-nodes[i-1].x)+(nodes[i+1].x-nodes[i].x) );
+
6013 vec.y=0.5f*( (nodes[i].y-nodes[i-1].y)+(nodes[i+1].y-nodes[i].y) );
+
6014 vec.z=0.5f*( (nodes[i].z-nodes[i-1].z)+(nodes[i+1].z-nodes[i].z) );
+
6015 }
6016
-
6017 v0 = xyz[j][i];
-
6018 v1 = xyz[j+1][i+1];
-
6019 v2 = xyz[j+1][i];
-
6020
-
6021 UUIDs.at(ii) = addTriangle( v0, v1, v2, color.at(i) );
-
6022
-
6023 v0 = xyz[j][i];
-
6024 v1 = xyz[j][i+1];
-
6025 v2 = xyz[j+1][i+1];
-
6026
-
6027 UUIDs.at(ii+1) = addTriangle( v0, v1, v2, color.at(i) );
+
6017 convec = cross(nvec,vec);
+
6018 convec.normalize();
+
6019 nvec = cross(vec,convec);
+
6020 nvec.normalize();
+
6021
+
6022 for(int j=0; j < radial_subdivisions + 1; j++ ){
+
6023
+
6024 vec3 normal;
+
6025 normal.x=cfact[j]*radius[i]*nvec.x+sfact[j]*radius[i]*convec.x;
+
6026 normal.y=cfact[j]*radius[i]*nvec.y+sfact[j]*radius[i]*convec.y;
+
6027 normal.z=cfact[j]*radius[i]*nvec.z+sfact[j]*radius[i]*convec.z;
6028
-
6029 ii+=2;
-
6030 }
-
6031 }
+
6029 xyz[j][i].x=nodes[i].x+normal.x;
+
6030 xyz[j][i].y=nodes[i].y+normal.y;
+
6031 xyz[j][i].z=nodes[i].z+normal.z;
6032
-
6033 return UUIDs;
+
6033 }
6034
-
6035}
-
+
6035 }
6036
-
-
6037std::vector<uint> Context::addTube(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile ){
-
6038
-
6039 if( !validateTextureFileExtenstion(texturefile) ) {
-
6040 helios_runtime_error("ERROR (Context::addTube): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
6041 }else if( !doesTextureFileExist(texturefile) ) {
-
6042 helios_runtime_error("ERROR (Context::addTube): Texture file " + std::string(texturefile) + " does not exist.");
-
6043 }
-
6044
-
6045 const uint node_count = nodes.size();
-
6046
-
6047 if( node_count==0 ){
-
6048 helios_runtime_error("ERROR (Context::addTube): Node and radius arrays are empty.");
-
6049 }else if( node_count!=radius.size() ){
-
6050 helios_runtime_error("ERROR (Context::addTube): Size of `nodes' and `radius' arguments must agree.");
-
6051 }
-
6052
-
6053 vec3 vec, convec;
-
6054 std::vector<float> cfact(radial_subdivisions + 1);
-
6055 std::vector<float> sfact(radial_subdivisions + 1);
-
6056 std::vector<std::vector<vec3> > xyz, normal;
-
6057 std::vector<std::vector<vec2> > uv;
-
6058 resize_vector( xyz, node_count, radial_subdivisions + 1 );
-
6059 resize_vector( normal, node_count, radial_subdivisions + 1 );
-
6060 resize_vector( uv, node_count, radial_subdivisions + 1 );
+
6037 vec3 v0, v1, v2;
+
6038 std::vector<uint> UUIDs(2 * (node_count-1) * radial_subdivisions );
+
6039
+
6040 int ii=0;
+
6041 for( int i=0; i<node_count-1; i++ ){
+
6042 for(int j=0; j < radial_subdivisions; j++ ){
+
6043
+
6044 v0 = xyz[j][i];
+
6045 v1 = xyz[j+1][i+1];
+
6046 v2 = xyz[j+1][i];
+
6047
+
6048 UUIDs.at(ii) = addTriangle( v0, v1, v2, color.at(i) );
+
6049
+
6050 v0 = xyz[j][i];
+
6051 v1 = xyz[j][i+1];
+
6052 v2 = xyz[j+1][i+1];
+
6053
+
6054 UUIDs.at(ii+1) = addTriangle( v0, v1, v2, color.at(i) );
+
6055
+
6056 ii+=2;
+
6057 }
+
6058 }
+
6059
+
6060 return UUIDs;
6061
-
6062 vec3 nvec(0.1817f,0.6198f,0.7634f);//random vector to get things going
+
6062}
+
6063
-
6064 for(int j=0; j < radial_subdivisions + 1; j++ ){
-
6065 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(radial_subdivisions));
-
6066 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(radial_subdivisions));
-
6067 }
-
6068
-
6069 for( int i=0; i<node_count; i++ ){ //looping over tube segments
-
6070
-
6071 if( radius.at(i)<0 ){
-
6072 helios_runtime_error("ERROR (Context::addTube): Radius of tube must be positive.");
-
6073 }
-
6074
-
6075 if(i==0){
-
6076 vec.x=nodes[i+1].x-nodes[i].x;
-
6077 vec.y=nodes[i+1].y-nodes[i].y;
-
6078 vec.z=nodes[i+1].z-nodes[i].z;
-
6079 }else if(i==node_count-1){
-
6080 vec.x=nodes[i].x-nodes[i-1].x;
-
6081 vec.y=nodes[i].y-nodes[i-1].y;
-
6082 vec.z=nodes[i].z-nodes[i-1].z;
-
6083 }else{
-
6084 vec.x=0.5f*( (nodes[i].x-nodes[i-1].x)+(nodes[i+1].x-nodes[i].x) );
-
6085 vec.y=0.5f*( (nodes[i].y-nodes[i-1].y)+(nodes[i+1].y-nodes[i].y) );
-
6086 vec.z=0.5f*( (nodes[i].z-nodes[i-1].z)+(nodes[i+1].z-nodes[i].z) );
-
6087 }
+
+
6064std::vector<uint> Context::addTube(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile ){
+
6065
+
6066 if( !validateTextureFileExtenstion(texturefile) ) {
+
6067 helios_runtime_error("ERROR (Context::addTube): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
6068 }else if( !doesTextureFileExist(texturefile) ) {
+
6069 helios_runtime_error("ERROR (Context::addTube): Texture file " + std::string(texturefile) + " does not exist.");
+
6070 }
+
6071
+
6072 const uint node_count = nodes.size();
+
6073
+
6074 if( node_count==0 ){
+
6075 helios_runtime_error("ERROR (Context::addTube): Node and radius arrays are empty.");
+
6076 }else if( node_count!=radius.size() ){
+
6077 helios_runtime_error("ERROR (Context::addTube): Size of `nodes' and `radius' arguments must agree.");
+
6078 }
+
6079
+
6080 vec3 vec, convec;
+
6081 std::vector<float> cfact(radial_subdivisions + 1);
+
6082 std::vector<float> sfact(radial_subdivisions + 1);
+
6083 std::vector<std::vector<vec3> > xyz, normal;
+
6084 std::vector<std::vector<vec2> > uv;
+
6085 resize_vector( xyz, node_count, radial_subdivisions + 1 );
+
6086 resize_vector( normal, node_count, radial_subdivisions + 1 );
+
6087 resize_vector( uv, node_count, radial_subdivisions + 1 );
6088
-
6089 convec = cross(nvec,vec);
-
6090 convec.normalize();
-
6091 nvec = cross(vec,convec);
-
6092 nvec.normalize();
-
6093
-
6094 for(int j=0; j < radial_subdivisions + 1; j++ ){
-
6095 normal[j][i].x=cfact[j]*radius[i]*nvec.x+sfact[j]*radius[i]*convec.x;
-
6096 normal[j][i].y=cfact[j]*radius[i]*nvec.y+sfact[j]*radius[i]*convec.y;
-
6097 normal[j][i].z=cfact[j]*radius[i]*nvec.z+sfact[j]*radius[i]*convec.z;
-
6098
-
6099 xyz[j][i].x=nodes[i].x+normal[j][i].x;
-
6100 xyz[j][i].y=nodes[i].y+normal[j][i].y;
-
6101 xyz[j][i].z=nodes[i].z+normal[j][i].z;
-
6102
-
6103 uv[j][i].x = float(i)/float(node_count-1);
-
6104 uv[j][i].y = float(j)/float(radial_subdivisions);
-
6105
-
6106 normal[j][i] = normal[j][i]/radius[i];
-
6107 }
-
6108
-
6109 }
-
6110
-
6111 vec3 v0, v1, v2;
-
6112 vec2 uv0, uv1, uv2;
-
6113 std::vector<uint> UUIDs(2 * (node_count-1) * radial_subdivisions );
-
6114
-
6115 int ii=0;
-
6116 for( int i=0; i<node_count-1; i++ ){
-
6117 for(int j=0; j < radial_subdivisions; j++ ){
-
6118
-
6119 v0 = xyz[j][i];
-
6120 v1 = xyz[j+1][i+1];
-
6121 v2 = xyz[j+1][i];
-
6122
-
6123 uv0 = uv[j][i];
-
6124 uv1 = uv[j+1][i+1];
-
6125 uv2 = uv[j+1][i];
-
6126
-
6127 UUIDs.at(ii) = addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 );
-
6128
-
6129 v0 = xyz[j][i];
-
6130 v1 = xyz[j][i+1];
-
6131 v2 = xyz[j+1][i+1];
+
6089 vec3 nvec(0.1817f,0.6198f,0.7634f);//random vector to get things going
+
6090
+
6091 for(int j=0; j < radial_subdivisions + 1; j++ ){
+
6092 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(radial_subdivisions));
+
6093 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(radial_subdivisions));
+
6094 }
+
6095
+
6096 for( int i=0; i<node_count; i++ ){ //looping over tube segments
+
6097
+
6098 if( radius.at(i)<0 ){
+
6099 helios_runtime_error("ERROR (Context::addTube): Radius of tube must be positive.");
+
6100 }
+
6101
+
6102 if(i==0){
+
6103 vec.x=nodes[i+1].x-nodes[i].x;
+
6104 vec.y=nodes[i+1].y-nodes[i].y;
+
6105 vec.z=nodes[i+1].z-nodes[i].z;
+
6106 }else if(i==node_count-1){
+
6107 vec.x=nodes[i].x-nodes[i-1].x;
+
6108 vec.y=nodes[i].y-nodes[i-1].y;
+
6109 vec.z=nodes[i].z-nodes[i-1].z;
+
6110 }else{
+
6111 vec.x=0.5f*( (nodes[i].x-nodes[i-1].x)+(nodes[i+1].x-nodes[i].x) );
+
6112 vec.y=0.5f*( (nodes[i].y-nodes[i-1].y)+(nodes[i+1].y-nodes[i].y) );
+
6113 vec.z=0.5f*( (nodes[i].z-nodes[i-1].z)+(nodes[i+1].z-nodes[i].z) );
+
6114 }
+
6115
+
6116 convec = cross(nvec,vec);
+
6117 convec.normalize();
+
6118 nvec = cross(vec,convec);
+
6119 nvec.normalize();
+
6120
+
6121 for(int j=0; j < radial_subdivisions + 1; j++ ){
+
6122 normal[j][i].x=cfact[j]*radius[i]*nvec.x+sfact[j]*radius[i]*convec.x;
+
6123 normal[j][i].y=cfact[j]*radius[i]*nvec.y+sfact[j]*radius[i]*convec.y;
+
6124 normal[j][i].z=cfact[j]*radius[i]*nvec.z+sfact[j]*radius[i]*convec.z;
+
6125
+
6126 xyz[j][i].x=nodes[i].x+normal[j][i].x;
+
6127 xyz[j][i].y=nodes[i].y+normal[j][i].y;
+
6128 xyz[j][i].z=nodes[i].z+normal[j][i].z;
+
6129
+
6130 uv[j][i].x = float(i)/float(node_count-1);
+
6131 uv[j][i].y = float(j)/float(radial_subdivisions);
6132
-
6133 uv0 = uv[j][i];
-
6134 uv1 = uv[j][i+1];
-
6135 uv2 = uv[j+1][i+1];
-
6136
-
6137 UUIDs.at(ii+1) = addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 );
-
6138
-
6139 ii+=2;
-
6140 }
-
6141 }
-
6142
-
6143 return UUIDs;
-
6144
-
6145}
-
-
6146
-
-
6147std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv ){
-
6148
-
6149 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
-
6150
-
6151 return addBox(center,size,subdiv,color,false);
-
6152}
-
+
6133 normal[j][i] = normal[j][i]/radius[i];
+
6134 }
+
6135
+
6136 }
+
6137
+
6138 vec3 v0, v1, v2;
+
6139 vec2 uv0, uv1, uv2;
+
6140 std::vector<uint> UUIDs(2 * (node_count-1) * radial_subdivisions );
+
6141
+
6142 int ii=0;
+
6143 for( int i=0; i<node_count-1; i++ ){
+
6144 for(int j=0; j < radial_subdivisions; j++ ){
+
6145
+
6146 v0 = xyz[j][i];
+
6147 v1 = xyz[j+1][i+1];
+
6148 v2 = xyz[j+1][i];
+
6149
+
6150 uv0 = uv[j][i];
+
6151 uv1 = uv[j+1][i+1];
+
6152 uv2 = uv[j+1][i];
6153
-
-
6154std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color ){
-
6155 return addBox(center,size,subdiv,color,false);
-
6156}
-
-
6157
-
-
6158std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile ){
-
6159 return addBox(center,size,subdiv,texturefile,false);
-
6160}
-
-
6161
-
-
6162std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals ){
+
6154 UUIDs.at(ii) = addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 );
+
6155
+
6156 v0 = xyz[j][i];
+
6157 v1 = xyz[j][i+1];
+
6158 v2 = xyz[j+1][i+1];
+
6159
+
6160 uv0 = uv[j][i];
+
6161 uv1 = uv[j][i+1];
+
6162 uv2 = uv[j+1][i+1];
6163
-
6164 std::vector<uint> UUID;
+
6164 UUIDs.at(ii+1) = addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 );
6165
-
6166 vec3 subsize;
-
6167 subsize.x = size.x/float(subdiv.x);
-
6168 subsize.y = size.y/float(subdiv.y);
-
6169 subsize.z = size.z/float(subdiv.z);
-
6170
-
6171 vec3 subcenter;
-
6172 std::vector<uint> U;
+
6166 ii+=2;
+
6167 }
+
6168 }
+
6169
+
6170 return UUIDs;
+
6171
+
6172}
+
6173
-
6174 if( reverse_normals ){ //normals point inward
+
+
6174std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv ){
6175
-
6176 // x-z faces (vertical)
+
6176 RGBcolor color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
6177
-
6178 //right
-
6179 subcenter = center + make_vec3(0,0.5f*size.y,0);
-
6180 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), color );
-
6181 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6182
-
6183 //left
-
6184 subcenter = center - make_vec3(0,0.5f*size.y,0);
-
6185 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), color );
-
6186 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6187
-
6188 // y-z faces (vertical)
-
6189
-
6190 //front
-
6191 subcenter = center + make_vec3(0.5f*size.x,0,0);
-
6192 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), color );
-
6193 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6194
-
6195 //back
-
6196 subcenter = center - make_vec3(0.5f*size.x,0,0);
-
6197 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), color );
-
6198 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6199
-
6200 // x-y faces (horizontal)
-
6201
-
6202 //top
-
6203 subcenter = center + make_vec3(0,0,0.5f*size.z);
-
6204 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), color );
-
6205 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6206
-
6207 //bottom
-
6208 subcenter = center - make_vec3(0,0,0.5f*size.z);
-
6209 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), color );
-
6210 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6211
-
6212 }else{ //normals point outward
-
6213
-
6214 // x-z faces (vertical)
-
6215
-
6216 //right
-
6217 subcenter = center + make_vec3(0,0.5f*size.y,0);
-
6218 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), color );
-
6219 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6220
-
6221 //left
-
6222 subcenter = center - make_vec3(0,0.5f*size.y,0);
-
6223 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), color );
-
6224 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6225
-
6226 // y-z faces (vertical)
-
6227
-
6228 //front
-
6229 subcenter = center + make_vec3(0.5f*size.x,0,0);
-
6230 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), color );
-
6231 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6232
-
6233 //back
-
6234 subcenter = center - make_vec3(0.5f*size.x,0,0);
-
6235 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), color );
-
6236 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6237
-
6238 // x-y faces (horizontal)
-
6239
-
6240 //top
-
6241 subcenter = center + make_vec3(0,0,0.5f*size.z);
-
6242 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), color );
-
6243 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6244
-
6245 //bottom
-
6246 subcenter = center - make_vec3(0,0,0.5f*size.z);
-
6247 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), color );
-
6248 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6249
-
6250 }
-
6251
-
6252 return UUID;
-
6253
-
6254}
-
-
6255
-
-
6256std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals ){
-
6257
-
6258 if( !validateTextureFileExtenstion(texturefile) ) {
-
6259 helios_runtime_error("ERROR (Context::addBox): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
6260 }else if( !doesTextureFileExist(texturefile) ) {
-
6261 helios_runtime_error("ERROR (Context::addBox): Texture file " + std::string(texturefile) + " does not exist.");
-
6262 }
-
6263
-
6264 std::vector<uint> UUID;
-
6265
-
6266 vec3 subsize;
-
6267 subsize.x = size.x/float(subdiv.x);
-
6268 subsize.y = size.y/float(subdiv.y);
-
6269 subsize.z = size.z/float(subdiv.z);
-
6270
-
6271 vec3 subcenter;
-
6272 std::vector<uint> U;
-
6273
-
6274 if( reverse_normals ){ //normals point inward
-
6275
-
6276 // x-z faces (vertical)
-
6277
-
6278 //right
-
6279 subcenter = center + make_vec3(0,0.5f*size.y,0);
-
6280 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), texturefile );
-
6281 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6282
-
6283 //left
-
6284 subcenter = center - make_vec3(0,0.5f*size.y,0);
-
6285 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), texturefile );
-
6286 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6287
-
6288 // y-z faces (vertical)
-
6289
-
6290 //front
-
6291 subcenter = center + make_vec3(0.5f*size.x,0,0);
-
6292 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
-
6293 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6294
-
6295 //back
-
6296 subcenter = center - make_vec3(0.5f*size.x,0,0);
-
6297 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
-
6298 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6299
-
6300 // x-y faces (horizontal)
-
6301
-
6302 //top
-
6303 subcenter = center + make_vec3(0,0,0.5f*size.z);
-
6304 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), texturefile );
-
6305 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6306
-
6307 //bottom
-
6308 subcenter = center - make_vec3(0,0,0.5f*size.z);
-
6309 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), texturefile );
-
6310 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6311
-
6312 }else{ //normals point outward
-
6313
-
6314 // x-z faces (vertical)
-
6315
-
6316 //right
-
6317 subcenter = center + make_vec3(0,0.5f*size.y,0);
-
6318 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), texturefile );
-
6319 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6320
-
6321 //left
-
6322 subcenter = center - make_vec3(0,0.5f*size.y,0);
-
6323 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), texturefile );
-
6324 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6325
-
6326 // y-z faces (vertical)
-
6327
-
6328 //front
-
6329 subcenter = center + make_vec3(0.5f*size.x,0,0);
-
6330 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
-
6331 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6332
-
6333 //back
-
6334 subcenter = center - make_vec3(0.5f*size.x,0,0);
-
6335 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
-
6336 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6337
-
6338 // x-y faces (horizontal)
-
6339
-
6340 //top
-
6341 subcenter = center + make_vec3(0,0,0.5f*size.z);
-
6342 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), texturefile );
-
6343 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6344
-
6345 //bottom
-
6346 subcenter = center - make_vec3(0,0,0.5f*size.z);
-
6347 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), texturefile );
-
6348 UUID.insert( UUID.end(), U.begin(), U.end() );
-
6349
-
6350 }
-
6351
-
6352 return UUID;
-
6353
-
6354}
-
-
6355
-
-
6356std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size ){
-
6357 return addDisk(make_int2(Ndivs,1),center,size,make_SphericalCoord(0,0),make_RGBAcolor(1,0,0,1));
-
6358}
+
6178 return addBox(center,size,subdiv,color,false);
+
6179}
+
+
6180
+
+
6181std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color ){
+
6182 return addBox(center,size,subdiv,color,false);
+
6183}
+
+
6184
+
+
6185std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile ){
+
6186 return addBox(center,size,subdiv,texturefile,false);
+
6187}
+
+
6188
+
+
6189std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals ){
+
6190
+
6191 std::vector<uint> UUID;
+
6192
+
6193 vec3 subsize;
+
6194 subsize.x = size.x/float(subdiv.x);
+
6195 subsize.y = size.y/float(subdiv.y);
+
6196 subsize.z = size.z/float(subdiv.z);
+
6197
+
6198 vec3 subcenter;
+
6199 std::vector<uint> U;
+
6200
+
6201 if( reverse_normals ){ //normals point inward
+
6202
+
6203 // x-z faces (vertical)
+
6204
+
6205 //right
+
6206 subcenter = center + make_vec3(0,0.5f*size.y,0);
+
6207 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), color );
+
6208 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6209
+
6210 //left
+
6211 subcenter = center - make_vec3(0,0.5f*size.y,0);
+
6212 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), color );
+
6213 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6214
+
6215 // y-z faces (vertical)
+
6216
+
6217 //front
+
6218 subcenter = center + make_vec3(0.5f*size.x,0,0);
+
6219 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), color );
+
6220 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6221
+
6222 //back
+
6223 subcenter = center - make_vec3(0.5f*size.x,0,0);
+
6224 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), color );
+
6225 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6226
+
6227 // x-y faces (horizontal)
+
6228
+
6229 //top
+
6230 subcenter = center + make_vec3(0,0,0.5f*size.z);
+
6231 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), color );
+
6232 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6233
+
6234 //bottom
+
6235 subcenter = center - make_vec3(0,0,0.5f*size.z);
+
6236 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), color );
+
6237 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6238
+
6239 }else{ //normals point outward
+
6240
+
6241 // x-z faces (vertical)
+
6242
+
6243 //right
+
6244 subcenter = center + make_vec3(0,0.5f*size.y,0);
+
6245 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), color );
+
6246 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6247
+
6248 //left
+
6249 subcenter = center - make_vec3(0,0.5f*size.y,0);
+
6250 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), color );
+
6251 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6252
+
6253 // y-z faces (vertical)
+
6254
+
6255 //front
+
6256 subcenter = center + make_vec3(0.5f*size.x,0,0);
+
6257 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), color );
+
6258 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6259
+
6260 //back
+
6261 subcenter = center - make_vec3(0.5f*size.x,0,0);
+
6262 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), color );
+
6263 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6264
+
6265 // x-y faces (horizontal)
+
6266
+
6267 //top
+
6268 subcenter = center + make_vec3(0,0,0.5f*size.z);
+
6269 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), color );
+
6270 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6271
+
6272 //bottom
+
6273 subcenter = center - make_vec3(0,0,0.5f*size.z);
+
6274 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), color );
+
6275 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6276
+
6277 }
+
6278
+
6279 return UUID;
+
6280
+
6281}
+
6282
+
+
6283std::vector<uint> Context::addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals ){
+
6284
+
6285 if( !validateTextureFileExtenstion(texturefile) ) {
+
6286 helios_runtime_error("ERROR (Context::addBox): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
6287 }else if( !doesTextureFileExist(texturefile) ) {
+
6288 helios_runtime_error("ERROR (Context::addBox): Texture file " + std::string(texturefile) + " does not exist.");
+
6289 }
+
6290
+
6291 std::vector<uint> UUID;
+
6292
+
6293 vec3 subsize;
+
6294 subsize.x = size.x/float(subdiv.x);
+
6295 subsize.y = size.y/float(subdiv.y);
+
6296 subsize.z = size.z/float(subdiv.z);
+
6297
+
6298 vec3 subcenter;
+
6299 std::vector<uint> U;
+
6300
+
6301 if( reverse_normals ){ //normals point inward
+
6302
+
6303 // x-z faces (vertical)
+
6304
+
6305 //right
+
6306 subcenter = center + make_vec3(0,0.5f*size.y,0);
+
6307 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), texturefile );
+
6308 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6309
+
6310 //left
+
6311 subcenter = center - make_vec3(0,0.5f*size.y,0);
+
6312 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), texturefile );
+
6313 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6314
+
6315 // y-z faces (vertical)
+
6316
+
6317 //front
+
6318 subcenter = center + make_vec3(0.5f*size.x,0,0);
+
6319 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
+
6320 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6321
+
6322 //back
+
6323 subcenter = center - make_vec3(0.5f*size.x,0,0);
+
6324 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
+
6325 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6326
+
6327 // x-y faces (horizontal)
+
6328
+
6329 //top
+
6330 subcenter = center + make_vec3(0,0,0.5f*size.z);
+
6331 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), texturefile );
+
6332 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6333
+
6334 //bottom
+
6335 subcenter = center - make_vec3(0,0,0.5f*size.z);
+
6336 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), texturefile );
+
6337 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6338
+
6339 }else{ //normals point outward
+
6340
+
6341 // x-z faces (vertical)
+
6342
+
6343 //right
+
6344 subcenter = center + make_vec3(0,0.5f*size.y,0);
+
6345 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,0), make_int2(subdiv.x,subdiv.z), texturefile );
+
6346 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6347
+
6348 //left
+
6349 subcenter = center - make_vec3(0,0.5f*size.y,0);
+
6350 U = addTile( subcenter, make_vec2(size.x,size.z), make_SphericalCoord(0.5*M_PI,M_PI), make_int2(subdiv.x,subdiv.z), texturefile );
+
6351 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6352
+
6353 // y-z faces (vertical)
+
6354
+
6355 //front
+
6356 subcenter = center + make_vec3(0.5f*size.x,0,0);
+
6357 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,0.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
+
6358 UUID.insert( UUID.end(), U.begin(), U.end() );
6359
-
-
6360std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation ){
-
6361 return addDisk(make_int2(Ndivs,1),center,size,rotation,make_RGBAcolor(1,0,0,1));
-
6362}
-
-
6363
-
-
6364std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBcolor &color ){
-
6365 return addDisk(make_int2(Ndivs,1),center,size,rotation,make_RGBAcolor(color,1));
-
6366}
-
-
6367
-
-
6368std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBAcolor &color ){
-
6369 return addDisk(make_int2(Ndivs,1),center,size,rotation,color);
-
6370}
-
+
6360 //back
+
6361 subcenter = center - make_vec3(0.5f*size.x,0,0);
+
6362 U = addTile( subcenter, make_vec2(size.y,size.z), make_SphericalCoord(0.5*M_PI,1.5*M_PI), make_int2(subdiv.y,subdiv.z), texturefile );
+
6363 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6364
+
6365 // x-y faces (horizontal)
+
6366
+
6367 //top
+
6368 subcenter = center + make_vec3(0,0,0.5f*size.z);
+
6369 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(0,0), make_int2(subdiv.x,subdiv.y), texturefile );
+
6370 UUID.insert( UUID.end(), U.begin(), U.end() );
6371
-
-
6372std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const char* texture_file ){
-
6373 return addDisk(make_int2(Ndivs,1),center,size,rotation,texture_file);
-
6374}
-
-
6375
-
-
6376std::vector<uint> Context::addDisk(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBcolor &color ){
-
6377 return addDisk(Ndivs,center,size,rotation,make_RGBAcolor(color,1));
-
6378}
-
-
6379
-
-
6380std::vector<uint> Context::addDisk(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBAcolor &color ){
-
6381
-
6382 std::vector<uint> UUID;
-
6383 UUID.resize(Ndivs.x+Ndivs.x*(Ndivs.y-1)*2);
-
6384 int i=0;
-
6385 for( int r=0; r < Ndivs.y; r++ ) {
-
6386 for (int t = 0; t < Ndivs.x; t++) {
-
6387
-
6388 float dtheta = 2.f * float(M_PI) / float(Ndivs.x);
-
6389 float theta = dtheta*float(t);
-
6390 float theta_plus = dtheta*float(t+1);
-
6391
-
6392 float rx = size.x/float(Ndivs.y)*float(r);
-
6393 float ry = size.y/float(Ndivs.y)*float(r);
+
6372 //bottom
+
6373 subcenter = center - make_vec3(0,0,0.5f*size.z);
+
6374 U = addTile( subcenter, make_vec2(size.x,size.y), make_SphericalCoord(M_PI,0), make_int2(subdiv.x,subdiv.y), texturefile );
+
6375 UUID.insert( UUID.end(), U.begin(), U.end() );
+
6376
+
6377 }
+
6378
+
6379 return UUID;
+
6380
+
6381}
+
+
6382
+
+
6383std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size ){
+
6384 return addDisk(make_int2(Ndivs,1),center,size,make_SphericalCoord(0,0),make_RGBAcolor(1,0,0,1));
+
6385}
+
+
6386
+
+
6387std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation ){
+
6388 return addDisk(make_int2(Ndivs,1),center,size,rotation,make_RGBAcolor(1,0,0,1));
+
6389}
+
+
6390
+
+
6391std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBcolor &color ){
+
6392 return addDisk(make_int2(Ndivs,1),center,size,rotation,make_RGBAcolor(color,1));
+
6393}
+
6394
-
6395 float rx_plus = size.x/float(Ndivs.y)*float(r+1);
-
6396 float ry_plus = size.y/float(Ndivs.y)*float(r+1);
-
6397
-
6398 if( r==0 ) {
-
6399 UUID.at(i) = addTriangle(make_vec3(0, 0, 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
-
6400 }else{
-
6401 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx * cosf(theta), ry * sinf(theta), 0),make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), color);
-
6402 i++;
-
6403 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
-
6404 }
-
6405 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.elevation, "y");
-
6406 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.azimuth, "z");
-
6407 getPrimitivePointer_private(UUID.at(i))->translate(center);
+
+
6395std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBAcolor &color ){
+
6396 return addDisk(make_int2(Ndivs,1),center,size,rotation,color);
+
6397}
+
+
6398
+
+
6399std::vector<uint> Context::addDisk(uint Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const char* texture_file ){
+
6400 return addDisk(make_int2(Ndivs,1),center,size,rotation,texture_file);
+
6401}
+
+
6402
+
+
6403std::vector<uint> Context::addDisk(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBcolor &color ){
+
6404 return addDisk(Ndivs,center,size,rotation,make_RGBAcolor(color,1));
+
6405}
+
+
6406
+
+
6407std::vector<uint> Context::addDisk(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const RGBAcolor &color ){
6408
-
6409 i++;
-
6410 }
-
6411 }
-
6412
-
6413 return UUID;
+
6409 std::vector<uint> UUID;
+
6410 UUID.resize(Ndivs.x+Ndivs.x*(Ndivs.y-1)*2);
+
6411 int i=0;
+
6412 for( int r=0; r < Ndivs.y; r++ ) {
+
6413 for (int t = 0; t < Ndivs.x; t++) {
6414
-
6415}
-
-
6416
-
-
6417std::vector<uint> Context::addDisk(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const char* texturefile ){
+
6415 float dtheta = 2.f * float(M_PI) / float(Ndivs.x);
+
6416 float theta = dtheta*float(t);
+
6417 float theta_plus = dtheta*float(t+1);
6418
-
6419 if( !validateTextureFileExtenstion(texturefile) ) {
-
6420 helios_runtime_error("ERROR (Context::addDisk): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
6421 }else if( !doesTextureFileExist(texturefile) ) {
-
6422 helios_runtime_error("ERROR (Context::addDisk): Texture file " + std::string(texturefile) + " does not exist.");
-
6423 }
+
6419 float rx = size.x/float(Ndivs.y)*float(r);
+
6420 float ry = size.y/float(Ndivs.y)*float(r);
+
6421
+
6422 float rx_plus = size.x/float(Ndivs.y)*float(r+1);
+
6423 float ry_plus = size.y/float(Ndivs.y)*float(r+1);
6424
-
6425 std::vector<uint> UUID;
-
6426 UUID.resize(Ndivs.x+Ndivs.x*(Ndivs.y-1)*2);
-
6427 int i=0;
-
6428 for( int r=0; r < Ndivs.y; r++ ) {
-
6429 for (int t = 0; t < Ndivs.x; t++) {
-
6430
-
6431 float dtheta = 2.f * float(M_PI) / float(Ndivs.x);
-
6432 float theta = dtheta*float(t);
-
6433 float theta_plus = dtheta*float(t+1);
-
6434
-
6435 float rx = size.x/float(Ndivs.y)*float(r);
-
6436 float ry = size.y/float(Ndivs.y)*float(r);
-
6437 float rx_plus = size.x/float(Ndivs.y)*float(r+1);
-
6438 float ry_plus = size.y/float(Ndivs.y)*float(r+1);
+
6425 if( r==0 ) {
+
6426 UUID.at(i) = addTriangle(make_vec3(0, 0, 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
+
6427 }else{
+
6428 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx * cosf(theta), ry * sinf(theta), 0),make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), color);
+
6429 i++;
+
6430 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0),make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), color);
+
6431 }
+
6432 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.elevation, "y");
+
6433 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.azimuth, "z");
+
6434 getPrimitivePointer_private(UUID.at(i))->translate(center);
+
6435
+
6436 i++;
+
6437 }
+
6438 }
6439
-
6440 if( r==0 ) {
-
6441 UUID.at(i) = addTriangle(make_vec3(0, 0, 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile, make_vec2(0.5, 0.5), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)), make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.y)));
-
6442 }else{
-
6443 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx * cosf(theta), ry * sinf(theta), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), texturefile, make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.x), 0.5f * (1.f + sinf(theta_plus) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx / size.x), 0.5f * (1.f + sinf(theta) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)));
-
6444 i++;
-
6445 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile, make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.x), 0.5f * (1.f + sinf(theta_plus) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)), make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.y)));
-
6446 }
-
6447 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.elevation, "y");
-
6448 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.azimuth, "z");
-
6449 getPrimitivePointer_private(UUID.at(i))->translate(center);
-
6450
-
6451 i++;
-
6452 }
-
6453 }
-
6454
-
6455 return UUID;
-
6456
-
6457}
-
-
6458
-
-
6459std::vector<uint> Context::addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 ){
-
6460
-
6461 RGBcolor color;
-
6462 color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
-
6463
-
6464 return addCone(Ndivs, node0, node1, radius0, radius1, color);
-
6465
-
6466}
-
-
6467
-
-
6468std::vector<uint> Context::addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, RGBcolor &color ){
-
6469
-
6470 std::vector<helios::vec3> nodes{node0, node1};
-
6471 std::vector<float> radii{radius0, radius1};
-
6472
-
6473 vec3 vec, convec;
-
6474 std::vector<float> cfact(Ndivs+1);
-
6475 std::vector<float> sfact(Ndivs+1);
-
6476 std::vector<std::vector<vec3> > xyz, normal;
-
6477 xyz.resize(Ndivs+1);
-
6478 normal.resize(Ndivs+1);
-
6479 for( uint j=0; j<Ndivs+1; j++ ){
-
6480 xyz.at(j).resize(2);
-
6481 normal.at(j).resize(2);
-
6482 }
-
6483 vec3 nvec(0.1817f,0.6198f,0.7634f);//random vector to get things going
-
6484
-
6485 for( int j=0; j<Ndivs+1; j++ ){
-
6486 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(Ndivs));
-
6487 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(Ndivs));
-
6488 }
-
6489
-
6490 for( int i=0; i<2; i++ ){ //looping over cone segments
-
6491
-
6492 if(i==0){
-
6493 vec.x=nodes[i+1].x-nodes[i].x;
-
6494 vec.y=nodes[i+1].y-nodes[i].y;
-
6495 vec.z=nodes[i+1].z-nodes[i].z;
-
6496 }else if(i==1){
-
6497 vec.x=nodes[i].x-nodes[i-1].x;
-
6498 vec.y=nodes[i].y-nodes[i-1].y;
-
6499 vec.z=nodes[i].z-nodes[i-1].z;
-
6500 }
-
6501
-
6502 float norm;
-
6503 convec = cross(nvec,vec);
-
6504 norm=convec.magnitude();
-
6505 convec.x=convec.x/norm;
-
6506 convec.y=convec.y/norm;
-
6507 convec.z=convec.z/norm;
-
6508 nvec = cross(vec,convec);
-
6509 norm=nvec.magnitude();
-
6510 nvec.x=nvec.x/norm;
-
6511 nvec.y=nvec.y/norm;
-
6512 nvec.z=nvec.z/norm;
-
6513
-
6514
-
6515
-
6516 for( int j=0; j<Ndivs+1; j++ ){
-
6517 normal[j][i].x=cfact[j]*radii[i]*nvec.x+sfact[j]*radii[i]*convec.x;
-
6518 normal[j][i].y=cfact[j]*radii[i]*nvec.y+sfact[j]*radii[i]*convec.y;
-
6519 normal[j][i].z=cfact[j]*radii[i]*nvec.z+sfact[j]*radii[i]*convec.z;
-
6520
-
6521 xyz[j][i].x=nodes[i].x+normal[j][i].x;
-
6522 xyz[j][i].y=nodes[i].y+normal[j][i].y;
-
6523 xyz[j][i].z=nodes[i].z+normal[j][i].z;
-
6524
-
6525 normal[j][i] = normal[j][i]/radii[i];
-
6526 }
-
6527
-
6528 }
-
6529
-
6530 vec3 v0, v1, v2;
-
6531 std::vector<uint> UUID;
-
6532
-
6533 for( int i=0; i<2-1; i++ ){
-
6534 for( int j=0; j<Ndivs; j++ ){
-
6535
-
6536 v0 = xyz[j][i];
-
6537 v1 = xyz[j+1][i+1];
-
6538 v2 = xyz[j+1][i];
-
6539
-
6540 UUID.push_back(addTriangle( v0, v1, v2, color ));
+
6440 return UUID;
+
6441
+
6442}
+
+
6443
+
+
6444std::vector<uint> Context::addDisk(const int2 &Ndivs, const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const char* texturefile ){
+
6445
+
6446 if( !validateTextureFileExtenstion(texturefile) ) {
+
6447 helios_runtime_error("ERROR (Context::addDisk): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
6448 }else if( !doesTextureFileExist(texturefile) ) {
+
6449 helios_runtime_error("ERROR (Context::addDisk): Texture file " + std::string(texturefile) + " does not exist.");
+
6450 }
+
6451
+
6452 std::vector<uint> UUID;
+
6453 UUID.resize(Ndivs.x+Ndivs.x*(Ndivs.y-1)*2);
+
6454 int i=0;
+
6455 for( int r=0; r < Ndivs.y; r++ ) {
+
6456 for (int t = 0; t < Ndivs.x; t++) {
+
6457
+
6458 float dtheta = 2.f * float(M_PI) / float(Ndivs.x);
+
6459 float theta = dtheta*float(t);
+
6460 float theta_plus = dtheta*float(t+1);
+
6461
+
6462 float rx = size.x/float(Ndivs.y)*float(r);
+
6463 float ry = size.y/float(Ndivs.y)*float(r);
+
6464 float rx_plus = size.x/float(Ndivs.y)*float(r+1);
+
6465 float ry_plus = size.y/float(Ndivs.y)*float(r+1);
+
6466
+
6467 if( r==0 ) {
+
6468 UUID.at(i) = addTriangle(make_vec3(0, 0, 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile, make_vec2(0.5, 0.5), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)), make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.y)));
+
6469 }else{
+
6470 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx * cosf(theta), ry * sinf(theta), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), texturefile, make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.x), 0.5f * (1.f + sinf(theta_plus) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx / size.x), 0.5f * (1.f + sinf(theta) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)));
+
6471 i++;
+
6472 UUID.at(i) = addTriangle(make_vec3(rx * cosf(theta_plus), ry * sinf(theta_plus), 0), make_vec3(rx_plus * cosf(theta), ry_plus * sinf(theta), 0), make_vec3(rx_plus * cosf(theta_plus), ry_plus * sinf(theta_plus), 0), texturefile, make_vec2(0.5f * (1.f + cosf(theta_plus) * rx / size.x), 0.5f * (1.f + sinf(theta_plus) * ry / size.y)), make_vec2(0.5f * (1.f + cosf(theta) * rx_plus / size.x), 0.5f * (1.f + sinf(theta) * ry_plus / size.y)), make_vec2(0.5f * (1.f + cosf(theta_plus) * rx_plus / size.x), 0.5f * (1.f + sinf(theta_plus) * ry_plus / size.y)));
+
6473 }
+
6474 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.elevation, "y");
+
6475 getPrimitivePointer_private(UUID.at(i))->rotate(rotation.azimuth, "z");
+
6476 getPrimitivePointer_private(UUID.at(i))->translate(center);
+
6477
+
6478 i++;
+
6479 }
+
6480 }
+
6481
+
6482 return UUID;
+
6483
+
6484}
+
+
6485
+
+
6486std::vector<uint> Context::addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 ){
+
6487
+
6488 RGBcolor color;
+
6489 color = make_RGBcolor(0.f,0.75f,0.f); //Default color is green
+
6490
+
6491 return addCone(Ndivs, node0, node1, radius0, radius1, color);
+
6492
+
6493}
+
+
6494
+
+
6495std::vector<uint> Context::addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, RGBcolor &color ){
+
6496
+
6497 std::vector<helios::vec3> nodes{node0, node1};
+
6498 std::vector<float> radii{radius0, radius1};
+
6499
+
6500 vec3 vec, convec;
+
6501 std::vector<float> cfact(Ndivs+1);
+
6502 std::vector<float> sfact(Ndivs+1);
+
6503 std::vector<std::vector<vec3> > xyz, normal;
+
6504 xyz.resize(Ndivs+1);
+
6505 normal.resize(Ndivs+1);
+
6506 for( uint j=0; j<Ndivs+1; j++ ){
+
6507 xyz.at(j).resize(2);
+
6508 normal.at(j).resize(2);
+
6509 }
+
6510 vec3 nvec(0.1817f,0.6198f,0.7634f);//random vector to get things going
+
6511
+
6512 for( int j=0; j<Ndivs+1; j++ ){
+
6513 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(Ndivs));
+
6514 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(Ndivs));
+
6515 }
+
6516
+
6517 for( int i=0; i<2; i++ ){ //looping over cone segments
+
6518
+
6519 if(i==0){
+
6520 vec.x=nodes[i+1].x-nodes[i].x;
+
6521 vec.y=nodes[i+1].y-nodes[i].y;
+
6522 vec.z=nodes[i+1].z-nodes[i].z;
+
6523 }else if(i==1){
+
6524 vec.x=nodes[i].x-nodes[i-1].x;
+
6525 vec.y=nodes[i].y-nodes[i-1].y;
+
6526 vec.z=nodes[i].z-nodes[i-1].z;
+
6527 }
+
6528
+
6529 float norm;
+
6530 convec = cross(nvec,vec);
+
6531 norm=convec.magnitude();
+
6532 convec.x=convec.x/norm;
+
6533 convec.y=convec.y/norm;
+
6534 convec.z=convec.z/norm;
+
6535 nvec = cross(vec,convec);
+
6536 norm=nvec.magnitude();
+
6537 nvec.x=nvec.x/norm;
+
6538 nvec.y=nvec.y/norm;
+
6539 nvec.z=nvec.z/norm;
+
6540
6541
-
6542 v0 = xyz[j][i];
-
6543 v1 = xyz[j][i+1];
-
6544 v2 = xyz[j+1][i+1];
-
6545
-
6546 UUID.push_back(addTriangle( v0, v1, v2, color ));
+
6542
+
6543 for( int j=0; j<Ndivs+1; j++ ){
+
6544 normal[j][i].x=cfact[j]*radii[i]*nvec.x+sfact[j]*radii[i]*convec.x;
+
6545 normal[j][i].y=cfact[j]*radii[i]*nvec.y+sfact[j]*radii[i]*convec.y;
+
6546 normal[j][i].z=cfact[j]*radii[i]*nvec.z+sfact[j]*radii[i]*convec.z;
6547
-
6548
-
6549 }
-
6550 }
+
6548 xyz[j][i].x=nodes[i].x+normal[j][i].x;
+
6549 xyz[j][i].y=nodes[i].y+normal[j][i].y;
+
6550 xyz[j][i].z=nodes[i].z+normal[j][i].z;
6551
-
6552 return UUID;
-
6553
-
6554}
-
-
6555
-
-
6556std::vector<uint> Context::addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile ){
-
6557
-
6558 if( !validateTextureFileExtenstion(texturefile) ) {
-
6559 helios_runtime_error("ERROR (Context::addCone): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
-
6560 }else if( !doesTextureFileExist(texturefile) ) {
-
6561 helios_runtime_error("ERROR (Context::addCone): Texture file " + std::string(texturefile) + " does not exist.");
-
6562 }
-
6563
-
6564 std::vector<helios::vec3> nodes{node0, node1};
-
6565 std::vector<float> radii{radius0, radius1};
+
6552 normal[j][i] = normal[j][i]/radii[i];
+
6553 }
+
6554
+
6555 }
+
6556
+
6557 vec3 v0, v1, v2;
+
6558 std::vector<uint> UUID;
+
6559
+
6560 for( int i=0; i<2-1; i++ ){
+
6561 for( int j=0; j<Ndivs; j++ ){
+
6562
+
6563 v0 = xyz[j][i];
+
6564 v1 = xyz[j+1][i+1];
+
6565 v2 = xyz[j+1][i];
6566
-
6567 vec3 vec, convec;
-
6568 std::vector<float> cfact(Ndivs+1);
-
6569 std::vector<float> sfact(Ndivs+1);
-
6570 std::vector<std::vector<vec3> > xyz, normal;
-
6571 std::vector<std::vector<vec2> > uv;
-
6572 xyz.resize(Ndivs+1);
-
6573 normal.resize(Ndivs+1);
-
6574 uv.resize(Ndivs+1);
-
6575 for( uint j=0; j<Ndivs+1; j++ ){
-
6576 xyz.at(j).resize(2);
-
6577 normal.at(j).resize(2);
-
6578 uv.at(j).resize(2);
-
6579 }
-
6580 vec3 nvec(0.f,1.f,0.f);
-
6581
-
6582 for( int j=0; j<Ndivs+1; j++ ){
-
6583 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(Ndivs));
-
6584 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(Ndivs));
-
6585 }
-
6586
-
6587 for( int i=0; i<2; i++ ){ //looping over cone segments
-
6588
-
6589 if(i==0){
-
6590 vec.x=nodes[i+1].x-nodes[i].x;
-
6591 vec.y=nodes[i+1].y-nodes[i].y;
-
6592 vec.z=nodes[i+1].z-nodes[i].z;
-
6593 }else if(i==1){
-
6594 vec.x=nodes[i].x-nodes[i-1].x;
-
6595 vec.y=nodes[i].y-nodes[i-1].y;
-
6596 vec.z=nodes[i].z-nodes[i-1].z;
-
6597 }
-
6598
-
6599 float norm;
-
6600 convec = cross(nvec,vec);
-
6601 norm=convec.magnitude();
-
6602 convec.x=convec.x/norm;
-
6603 convec.y=convec.y/norm;
-
6604 convec.z=convec.z/norm;
-
6605 nvec = cross(vec,convec);
-
6606 norm=nvec.magnitude();
-
6607 nvec.x=nvec.x/norm;
-
6608 nvec.y=nvec.y/norm;
-
6609 nvec.z=nvec.z/norm;
-
6610
-
6611 for( int j=0; j<Ndivs+1; j++ ){
-
6612 normal[j][i].x=cfact[j]*radii[i]*nvec.x+sfact[j]*radii[i]*convec.x;
-
6613 normal[j][i].y=cfact[j]*radii[i]*nvec.y+sfact[j]*radii[i]*convec.y;
-
6614 normal[j][i].z=cfact[j]*radii[i]*nvec.z+sfact[j]*radii[i]*convec.z;
+
6567 UUID.push_back(addTriangle( v0, v1, v2, color ));
+
6568
+
6569 v0 = xyz[j][i];
+
6570 v1 = xyz[j][i+1];
+
6571 v2 = xyz[j+1][i+1];
+
6572
+
6573 UUID.push_back(addTriangle( v0, v1, v2, color ));
+
6574
+
6575
+
6576 }
+
6577 }
+
6578
+
6579 return UUID;
+
6580
+
6581}
+
+
6582
+
+
6583std::vector<uint> Context::addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile ){
+
6584
+
6585 if( !validateTextureFileExtenstion(texturefile) ) {
+
6586 helios_runtime_error("ERROR (Context::addCone): Texture file " + std::string(texturefile) + " is not PNG or JPEG format.");
+
6587 }else if( !doesTextureFileExist(texturefile) ) {
+
6588 helios_runtime_error("ERROR (Context::addCone): Texture file " + std::string(texturefile) + " does not exist.");
+
6589 }
+
6590
+
6591 std::vector<helios::vec3> nodes{node0, node1};
+
6592 std::vector<float> radii{radius0, radius1};
+
6593
+
6594 vec3 vec, convec;
+
6595 std::vector<float> cfact(Ndivs+1);
+
6596 std::vector<float> sfact(Ndivs+1);
+
6597 std::vector<std::vector<vec3> > xyz, normal;
+
6598 std::vector<std::vector<vec2> > uv;
+
6599 xyz.resize(Ndivs+1);
+
6600 normal.resize(Ndivs+1);
+
6601 uv.resize(Ndivs+1);
+
6602 for( uint j=0; j<Ndivs+1; j++ ){
+
6603 xyz.at(j).resize(2);
+
6604 normal.at(j).resize(2);
+
6605 uv.at(j).resize(2);
+
6606 }
+
6607 vec3 nvec(0.f,1.f,0.f);
+
6608
+
6609 for( int j=0; j<Ndivs+1; j++ ){
+
6610 cfact[j]=cosf(2.f*float(M_PI)*float(j)/float(Ndivs));
+
6611 sfact[j]=sinf(2.f*float(M_PI)*float(j)/float(Ndivs));
+
6612 }
+
6613
+
6614 for( int i=0; i<2; i++ ){ //looping over cone segments
6615
-
6616 xyz[j][i].x=nodes[i].x+normal[j][i].x;
-
6617 xyz[j][i].y=nodes[i].y+normal[j][i].y;
-
6618 xyz[j][i].z=nodes[i].z+normal[j][i].z;
-
6619
-
6620 uv[j][i].x = float(i)/float(2-1);
-
6621 uv[j][i].y = float(j)/float(Ndivs);
-
6622
-
6623 normal[j][i] = normal[j][i]/radii[i];
+
6616 if(i==0){
+
6617 vec.x=nodes[i+1].x-nodes[i].x;
+
6618 vec.y=nodes[i+1].y-nodes[i].y;
+
6619 vec.z=nodes[i+1].z-nodes[i].z;
+
6620 }else if(i==1){
+
6621 vec.x=nodes[i].x-nodes[i-1].x;
+
6622 vec.y=nodes[i].y-nodes[i-1].y;
+
6623 vec.z=nodes[i].z-nodes[i-1].z;
6624 }
6625
-
6626 }
-
6627
-
6628 vec3 v0, v1, v2;
-
6629 vec2 uv0, uv1, uv2;
-
6630 std::vector<uint> UUID;
-
6631
-
6632 for( int i=0; i<2-1; i++ ){
-
6633 for( int j=0; j<Ndivs; j++ ){
-
6634
-
6635 v0 = xyz[j][i];
-
6636 v1 = xyz[j+1][i+1];
-
6637 v2 = xyz[j+1][i];
-
6638
-
6639 uv0 = uv[j][i];
-
6640 uv1 = uv[j+1][i+1];
-
6641 uv2 = uv[j+1][i];
+
6626 float norm;
+
6627 convec = cross(nvec,vec);
+
6628 norm=convec.magnitude();
+
6629 convec.x=convec.x/norm;
+
6630 convec.y=convec.y/norm;
+
6631 convec.z=convec.z/norm;
+
6632 nvec = cross(vec,convec);
+
6633 norm=nvec.magnitude();
+
6634 nvec.x=nvec.x/norm;
+
6635 nvec.y=nvec.y/norm;
+
6636 nvec.z=nvec.z/norm;
+
6637
+
6638 for( int j=0; j<Ndivs+1; j++ ){
+
6639 normal[j][i].x=cfact[j]*radii[i]*nvec.x+sfact[j]*radii[i]*convec.x;
+
6640 normal[j][i].y=cfact[j]*radii[i]*nvec.y+sfact[j]*radii[i]*convec.y;
+
6641 normal[j][i].z=cfact[j]*radii[i]*nvec.z+sfact[j]*radii[i]*convec.z;
6642
-
6643 if( (v1-v0).magnitude()>1e-6 && (v2-v0).magnitude()>1e-6 && (v2-v1).magnitude()>1e-6 ){
-
6644 UUID.push_back(addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 ));
-
6645 }
+
6643 xyz[j][i].x=nodes[i].x+normal[j][i].x;
+
6644 xyz[j][i].y=nodes[i].y+normal[j][i].y;
+
6645 xyz[j][i].z=nodes[i].z+normal[j][i].z;
6646
-
6647 v0 = xyz[j][i];
-
6648 v1 = xyz[j][i+1];
-
6649 v2 = xyz[j+1][i+1];
-
6650
-
6651 uv0 = uv[j][i];
-
6652 uv1 = uv[j][i+1];
-
6653 uv2 = uv[j+1][i+1];
+
6647 uv[j][i].x = float(i)/float(2-1);
+
6648 uv[j][i].y = float(j)/float(Ndivs);
+
6649
+
6650 normal[j][i] = normal[j][i]/radii[i];
+
6651 }
+
6652
+
6653 }
6654
-
6655 if( (v1-v0).magnitude()>1e-6 && (v2-v0).magnitude()>1e-6 && (v2-v1).magnitude()>1e-6 ){
-
6656 UUID.push_back(addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 ));
-
6657 }
+
6655 vec3 v0, v1, v2;
+
6656 vec2 uv0, uv1, uv2;
+
6657 std::vector<uint> UUID;
6658
-
6659 }
-
6660 }
+
6659 for( int i=0; i<2-1; i++ ){
+
6660 for( int j=0; j<Ndivs; j++ ){
6661
-
6662 return UUID;
-
6663
-
6664}
-
+
6662 v0 = xyz[j][i];
+
6663 v1 = xyz[j+1][i+1];
+
6664 v2 = xyz[j+1][i];
6665
-
-
6666void Context::colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors ){
-
6667
-
6668 colorPrimitiveByDataPseudocolor(UUIDs,primitive_data,colormap, Ncolors,9999999,-9999999);
+
6666 uv0 = uv[j][i];
+
6667 uv1 = uv[j+1][i+1];
+
6668 uv2 = uv[j+1][i];
6669
-
6670}
-
-
6671
-
-
6672void Context::colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors, float data_min, float data_max ){
+
6670 if( (v1-v0).magnitude()>1e-6 && (v2-v0).magnitude()>1e-6 && (v2-v1).magnitude()>1e-6 ){
+
6671 UUID.push_back(addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 ));
+
6672 }
6673
-
6674 std::map<uint,float> pcolor_data;
-
6675
-
6676 float data_min_new=9999999;
-
6677 float data_max_new=-9999999;
-
6678 for( uint UUID : UUIDs ){
-
6679
-
6680 if( !doesPrimitiveExist(UUID) ){
-
6681 std::cerr << "WARNING (Context::colorPrimitiveDataPseudocolor): primitive for UUID " << std::to_string(UUID) << " does not exist. Skipping this primitive." << std::endl;
-
6682 continue;
-
6683 }
-
6684
-
6685 float dataf=0;
-
6686 if( doesPrimitiveDataExist(UUID,primitive_data.c_str()) ) {
-
6687
-
6688 if( getPrimitiveDataType(UUID,primitive_data.c_str())!=HELIOS_TYPE_FLOAT && getPrimitiveDataType(UUID,primitive_data.c_str())!=HELIOS_TYPE_INT && getPrimitiveDataType(UUID,primitive_data.c_str())!=HELIOS_TYPE_UINT && getPrimitiveDataType(UUID,primitive_data.c_str())!=HELIOS_TYPE_DOUBLE ){
-
6689 std::cerr << "WARNING (Context::colorPrimitiveDataPseudocolor): Only primitive data types of int, uint, float, and double are supported for this function. Skipping this primitive." << std::endl;
-
6690 continue;
-
6691 }
+
6674 v0 = xyz[j][i];
+
6675 v1 = xyz[j][i+1];
+
6676 v2 = xyz[j+1][i+1];
+
6677
+
6678 uv0 = uv[j][i];
+
6679 uv1 = uv[j][i+1];
+
6680 uv2 = uv[j+1][i+1];
+
6681
+
6682 if( (v1-v0).magnitude()>1e-6 && (v2-v0).magnitude()>1e-6 && (v2-v1).magnitude()>1e-6 ){
+
6683 UUID.push_back(addTriangle( v0, v1, v2, texturefile, uv0, uv1, uv2 ));
+
6684 }
+
6685
+
6686 }
+
6687 }
+
6688
+
6689 return UUID;
+
6690
+
6691}
+
6692
-
6693 if (getPrimitiveDataType(UUID, primitive_data.c_str()) ==
- -
6695 float data;
-
6696 getPrimitiveData(UUID, primitive_data.c_str(), data);
-
6697 dataf = data;
-
6698 } else if (getPrimitiveDataType(UUID, primitive_data.c_str()) ==
- -
6700 double data;
-
6701 getPrimitiveData(UUID, primitive_data.c_str(), data);
-
6702 dataf = float(data);
-
6703 } else if (getPrimitiveDataType(UUID, primitive_data.c_str()) ==
- -
6705 int data;
-
6706 getPrimitiveData(UUID, primitive_data.c_str(), data);
-
6707 dataf = float(data);
-
6708 } else if (getPrimitiveDataType(UUID, primitive_data.c_str()) ==
- -
6710 uint data;
-
6711 getPrimitiveData(UUID, primitive_data.c_str(), data);
-
6712 dataf = float(data);
-
6713 }
-
6714 }
-
6715
-
6716 if( data_min==9999999 && data_max==-9999999 ) {
-
6717 if (dataf < data_min_new) {
-
6718 data_min_new = dataf;
-
6719 }
-
6720 if (dataf > data_max_new) {
-
6721 data_max_new = dataf;
-
6722 }
-
6723 }
-
6724
-
6725 pcolor_data[UUID] = dataf;
-
6726
-
6727 }
-
6728
-
6729 if( data_min==9999999 && data_max==-9999999 ) {
-
6730 data_min = data_min_new;
-
6731 data_max = data_max_new;
-
6732 }
-
6733
-
6734 std::vector<RGBcolor> colormap_data = generateColormap( colormap, Ncolors );
-
6735
-
6736 std::map<std::string,std::vector<std::string> > cmap_texture_filenames;
-
6737
-
6738 for( auto &data : pcolor_data ) {
-
6739
-
6740 uint UUID = data.first;
-
6741 float pdata = data.second;
+
+
6693void Context::colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors ){
+
6694
+
6695 colorPrimitiveByDataPseudocolor(UUIDs,primitive_data,colormap, Ncolors,9999999,-9999999);
+
6696
+
6697}
+
+
6698
+
+
6699void Context::colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors, float data_min, float data_max ){
+
6700
+
6701 std::map<uint,float> pcolor_data;
+
6702
+
6703 float data_min_new=9999999;
+
6704 float data_max_new=-9999999;
+
6705 for( uint UUID : UUIDs ){
+
6706
+
6707 if( !doesPrimitiveExist(UUID) ){
+
6708 std::cerr << "WARNING (Context::colorPrimitiveDataPseudocolor): primitive for UUID " << std::to_string(UUID) << " does not exist. Skipping this primitive." << std::endl;
+
6709 continue;
+
6710 }
+
6711
+
6712 float dataf=0;
+
6713 if( doesPrimitiveDataExist(UUID,primitive_data.c_str()) ) {
+
6714
+
6715 if( getPrimitiveDataType(UUID,primitive_data.c_str())!=HELIOS_TYPE_FLOAT && getPrimitiveDataType(UUID,primitive_data.c_str())!=HELIOS_TYPE_INT && getPrimitiveDataType(UUID,primitive_data.c_str())!=HELIOS_TYPE_UINT && getPrimitiveDataType(UUID,primitive_data.c_str())!=HELIOS_TYPE_DOUBLE ){
+
6716 std::cerr << "WARNING (Context::colorPrimitiveDataPseudocolor): Only primitive data types of int, uint, float, and double are supported for this function. Skipping this primitive." << std::endl;
+
6717 continue;
+
6718 }
+
6719
+
6720 if (getPrimitiveDataType(UUID, primitive_data.c_str()) ==
+ +
6722 float data;
+
6723 getPrimitiveData(UUID, primitive_data.c_str(), data);
+
6724 dataf = data;
+
6725 } else if (getPrimitiveDataType(UUID, primitive_data.c_str()) ==
+ +
6727 double data;
+
6728 getPrimitiveData(UUID, primitive_data.c_str(), data);
+
6729 dataf = float(data);
+
6730 } else if (getPrimitiveDataType(UUID, primitive_data.c_str()) ==
+ +
6732 int data;
+
6733 getPrimitiveData(UUID, primitive_data.c_str(), data);
+
6734 dataf = float(data);
+
6735 } else if (getPrimitiveDataType(UUID, primitive_data.c_str()) ==
+ +
6737 uint data;
+
6738 getPrimitiveData(UUID, primitive_data.c_str(), data);
+
6739 dataf = float(data);
+
6740 }
+
6741 }
6742
-
6743 std::string texturefile = getPrimitiveTextureFile(UUID);
-
6744
-
6745 int cmap_ind = round((pdata - data_min) / (data_max - data_min) * float(Ncolors - 1));
-
6746
-
6747 if( cmap_ind<0 ){
-
6748 cmap_ind=0;
-
6749 }else if( cmap_ind>=Ncolors ){
-
6750 cmap_ind=Ncolors-1;
-
6751 }
-
6752
-
6753 if ( !texturefile.empty() && primitiveTextureHasTransparencyChannel(UUID)) { // primitive has texture with transparency channel
-
6754
- -
6756 setPrimitiveColor(UUID, colormap_data.at(cmap_ind));
-
6757
-
6758 } else { // primitive does not have texture with transparency channel - assign constant color
-
6759
-
6760 if (!getPrimitiveTextureFile(UUID).empty()) {
- -
6762 }
-
6763
-
6764 setPrimitiveColor(UUID, colormap_data.at(cmap_ind));
-
6765 }
-
6766 }
-
6767
-
6768}
-
+
6743 if( data_min==9999999 && data_max==-9999999 ) {
+
6744 if (dataf < data_min_new) {
+
6745 data_min_new = dataf;
+
6746 }
+
6747 if (dataf > data_max_new) {
+
6748 data_max_new = dataf;
+
6749 }
+
6750 }
+
6751
+
6752 pcolor_data[UUID] = dataf;
+
6753
+
6754 }
+
6755
+
6756 if( data_min==9999999 && data_max==-9999999 ) {
+
6757 data_min = data_min_new;
+
6758 data_max = data_max_new;
+
6759 }
+
6760
+
6761 std::vector<RGBcolor> colormap_data = generateColormap( colormap, Ncolors );
+
6762
+
6763 std::map<std::string,std::vector<std::string> > cmap_texture_filenames;
+
6764
+
6765 for( auto &data : pcolor_data ) {
+
6766
+
6767 uint UUID = data.first;
+
6768 float pdata = data.second;
6769
-
6770std::vector<RGBcolor> Context::generateColormap( const std::vector<helios::RGBcolor> &ctable, const std::vector<float> &cfrac, uint Ncolors ){
+
6770 std::string texturefile = getPrimitiveTextureFile(UUID);
6771
-
6772 if( Ncolors>9999 ){
-
6773 std::cerr << "WARNING (Context::generateColormap): Truncating number of color map textures to maximum value of 9999." << std::endl;
-
6774 }
-
6775
-
6776 if( ctable.size()!=cfrac.size() ){
-
6777 helios_runtime_error("ERROR (Context::generateColormap): The length of arguments 'ctable' and 'cfrac' must match.");
-
6778 }
-
6779 if( ctable.empty() ){
-
6780 helios_runtime_error("ERROR (Context::generateColormap): 'ctable' and 'cfrac' arguments contain empty vectors.");
-
6781 }
-
6782
-
6783 std::vector<RGBcolor> color_table;
-
6784 color_table.resize(Ncolors);
-
6785
-
6786 for (int i = 0; i < Ncolors; i++){
-
6787
-
6788 float frac = float(i)/float(Ncolors-1)*cfrac.back();
-
6789
-
6790 int j;
-
6791 for( j=0; j<cfrac.size()-1; j++ ){
-
6792 if( frac>=cfrac.at(j) && frac<=cfrac.at(j+1) ){
-
6793 break;
-
6794 }
-
6795 }
+
6772 int cmap_ind = round((pdata - data_min) / (data_max - data_min) * float(Ncolors - 1));
+
6773
+
6774 if( cmap_ind<0 ){
+
6775 cmap_ind=0;
+
6776 }else if( cmap_ind>=Ncolors ){
+
6777 cmap_ind=Ncolors-1;
+
6778 }
+
6779
+
6780 if ( !texturefile.empty() && primitiveTextureHasTransparencyChannel(UUID)) { // primitive has texture with transparency channel
+
6781
+ +
6783 setPrimitiveColor(UUID, colormap_data.at(cmap_ind));
+
6784
+
6785 } else { // primitive does not have texture with transparency channel - assign constant color
+
6786
+
6787 if (!getPrimitiveTextureFile(UUID).empty()) {
+ +
6789 }
+
6790
+
6791 setPrimitiveColor(UUID, colormap_data.at(cmap_ind));
+
6792 }
+
6793 }
+
6794
+
6795}
+
6796
-
6797 float cminus = std::fmaxf(0.f,cfrac.at(j));
-
6798 float cplus = std::fminf(1.f,cfrac.at(j+1));
-
6799
-
6800 float jfrac = (frac-cminus)/(cplus-cminus);
-
6801
-
6802 RGBcolor color;
-
6803 color.r = ctable.at(j).r+jfrac*(ctable.at(j+1).r-ctable.at(j).r);
-
6804 color.g = ctable.at(j).g+jfrac*(ctable.at(j+1).g-ctable.at(j).g);
-
6805 color.b = ctable.at(j).b+jfrac*(ctable.at(j+1).b-ctable.at(j).b);
-
6806
-
6807 color_table.at(i) = color;
-
6808
-
6809 }
-
6810
-
6811 return color_table;
+
6797std::vector<RGBcolor> Context::generateColormap( const std::vector<helios::RGBcolor> &ctable, const std::vector<float> &cfrac, uint Ncolors ){
+
6798
+
6799 if( Ncolors>9999 ){
+
6800 std::cerr << "WARNING (Context::generateColormap): Truncating number of color map textures to maximum value of 9999." << std::endl;
+
6801 }
+
6802
+
6803 if( ctable.size()!=cfrac.size() ){
+
6804 helios_runtime_error("ERROR (Context::generateColormap): The length of arguments 'ctable' and 'cfrac' must match.");
+
6805 }
+
6806 if( ctable.empty() ){
+
6807 helios_runtime_error("ERROR (Context::generateColormap): 'ctable' and 'cfrac' arguments contain empty vectors.");
+
6808 }
+
6809
+
6810 std::vector<RGBcolor> color_table;
+
6811 color_table.resize(Ncolors);
6812
-
6813}
+
6813 for (int i = 0; i < Ncolors; i++){
6814
-
6815std::vector<RGBcolor> Context::generateColormap( const std::string &colormap, uint Ncolors ){
+
6815 float frac = float(i)/float(Ncolors-1)*cfrac.back();
6816
-
6817 std::vector<RGBcolor> ctable_c;
-
6818 std::vector<float> clocs_c;
-
6819
-
6820 if( colormap == "hot" ) {
-
6821
-
6822 ctable_c.resize(5);
-
6823 ctable_c.at(0) = make_RGBcolor(0.f, 0.f, 0.f);
-
6824 ctable_c.at(1) = make_RGBcolor(0.5f, 0.f, 0.5f);
-
6825 ctable_c.at(2) = make_RGBcolor(1.f, 0.f, 0.f);
-
6826 ctable_c.at(3) = make_RGBcolor(1.f, 0.5f, 0.f);
-
6827 ctable_c.at(4) = make_RGBcolor(1.f, 1.f, 0.f);
+
6817 int j;
+
6818 for( j=0; j<cfrac.size()-1; j++ ){
+
6819 if( frac>=cfrac.at(j) && frac<=cfrac.at(j+1) ){
+
6820 break;
+
6821 }
+
6822 }
+
6823
+
6824 float cminus = std::fmaxf(0.f,cfrac.at(j));
+
6825 float cplus = std::fminf(1.f,cfrac.at(j+1));
+
6826
+
6827 float jfrac = (frac-cminus)/(cplus-cminus);
6828
-
6829 clocs_c.resize(5);
-
6830 clocs_c.at(0) = 0.f;
-
6831 clocs_c.at(1) = 0.25f;
-
6832 clocs_c.at(2) = 0.5f;
-
6833 clocs_c.at(3) = 0.75f;
-
6834 clocs_c.at(4) = 1.f;
+
6829 RGBcolor color;
+
6830 color.r = ctable.at(j).r+jfrac*(ctable.at(j+1).r-ctable.at(j).r);
+
6831 color.g = ctable.at(j).g+jfrac*(ctable.at(j+1).g-ctable.at(j).g);
+
6832 color.b = ctable.at(j).b+jfrac*(ctable.at(j+1).b-ctable.at(j).b);
+
6833
+
6834 color_table.at(i) = color;
6835
-
6836 }else if( colormap == "cool") {
+
6836 }
6837
-
6838 ctable_c.resize(2);
-
6839 ctable_c.at(1) = RGB::cyan;
-
6840 ctable_c.at(2) = RGB::magenta;
+
6838 return color_table;
+
6839
+
6840}
6841
-
6842 clocs_c.resize(2);
-
6843 clocs_c.at(1) = 0.f;
-
6844 clocs_c.at(2) = 1.f;
-
6845
-
6846 }else if( colormap == "lava" ) {
-
6847
-
6848 ctable_c.resize(5);
-
6849 ctable_c.at(0) = make_RGBcolor(0.f, 0.05f, 0.05f);
-
6850 ctable_c.at(1) = make_RGBcolor(0.f, 0.6f, 0.6f);
-
6851 ctable_c.at(2) = make_RGBcolor(1.f, 1.f, 1.f);
-
6852 ctable_c.at(3) = make_RGBcolor(1.f, 0.f, 0.f);
-
6853 ctable_c.at(4) = make_RGBcolor(0.5f, 0.f, 0.f);
-
6854
-
6855 clocs_c.resize(5);
-
6856 clocs_c.at(0) = 0.f;
-
6857 clocs_c.at(1) = 0.4f;
-
6858 clocs_c.at(2) = 0.5f;
-
6859 clocs_c.at(3) = 0.6f;
-
6860 clocs_c.at(4) = 1.f;
-
6861
-
6862 }else if( colormap == "rainbow" ){
-
6863
-
6864 ctable_c.resize(4);
-
6865 ctable_c.at(0) = RGB::navy;
+
6842std::vector<RGBcolor> Context::generateColormap( const std::string &colormap, uint Ncolors ){
+
6843
+
6844 std::vector<RGBcolor> ctable_c;
+
6845 std::vector<float> clocs_c;
+
6846
+
6847 if( colormap == "hot" ) {
+
6848
+
6849 ctable_c.resize(5);
+
6850 ctable_c.at(0) = make_RGBcolor(0.f, 0.f, 0.f);
+
6851 ctable_c.at(1) = make_RGBcolor(0.5f, 0.f, 0.5f);
+
6852 ctable_c.at(2) = make_RGBcolor(1.f, 0.f, 0.f);
+
6853 ctable_c.at(3) = make_RGBcolor(1.f, 0.5f, 0.f);
+
6854 ctable_c.at(4) = make_RGBcolor(1.f, 1.f, 0.f);
+
6855
+
6856 clocs_c.resize(5);
+
6857 clocs_c.at(0) = 0.f;
+
6858 clocs_c.at(1) = 0.25f;
+
6859 clocs_c.at(2) = 0.5f;
+
6860 clocs_c.at(3) = 0.75f;
+
6861 clocs_c.at(4) = 1.f;
+
6862
+
6863 }else if( colormap == "cool") {
+
6864
+
6865 ctable_c.resize(2);
6866 ctable_c.at(1) = RGB::cyan;
-
6867 ctable_c.at(2) = RGB::yellow;
-
6868 ctable_c.at(3) = make_RGBcolor( 0.75f, 0.f, 0.f );
-
6869
-
6870 clocs_c.resize(4);
-
6871 clocs_c.at(0) = 0.f;
-
6872 clocs_c.at(1) = 0.3f;
-
6873 clocs_c.at(2) = 0.7f;
-
6874 clocs_c.at(3) = 1.f;
-
6875
-
6876 }else if( colormap == "parula" ){
-
6877
-
6878 ctable_c.resize(4);
-
6879 ctable_c.at(0) = RGB::navy;
-
6880 ctable_c.at(1) = make_RGBcolor(0,0.6,0.6);
-
6881 ctable_c.at(2) = RGB::goldenrod;
-
6882 ctable_c.at(3) = RGB::yellow;
-
6883
-
6884 clocs_c.resize(4);
-
6885 clocs_c.at(0) = 0.f;
-
6886 clocs_c.at(1) = 0.4f;
-
6887 clocs_c.at(2) = 0.7f;
-
6888 clocs_c.at(3) = 1.f;
-
6889
-
6890 }else if( colormap == "gray" ) {
-
6891
-
6892 ctable_c.resize(2);
-
6893 ctable_c.at(0) = RGB::black;
-
6894 ctable_c.at(1) = RGB::white;
-
6895
-
6896 clocs_c.resize(2);
-
6897 clocs_c.at(0) = 0.f;
-
6898 clocs_c.at(1) = 1.f;
-
6899
-
6900 }else if( colormap == "green" ) {
-
6901
-
6902 ctable_c.resize(2);
-
6903 ctable_c.at(0) = RGB::black;
-
6904 ctable_c.at(1) = RGB::green;
-
6905
-
6906 clocs_c.resize(2);
-
6907 clocs_c.at(0) = 0.f;
-
6908 clocs_c.at(1) = 1.f;
-
6909
-
6910 }else{
-
6911 helios_runtime_error("ERROR (Context::generateColormapTextures): Unknown colormap "+colormap+".");
-
6912 }
-
6913
-
6914 return generateColormap( ctable_c, clocs_c, Ncolors );
-
6915
-
6916}
-
6917
-
6918std::vector<std::string> Context::generateTexturesFromColormap( const std::string &texturefile, const std::vector<RGBcolor> &colormap_data ){
-
6919
-
6920 uint Ncolors = colormap_data.size();
-
6921
-
6922 // check that texture file exists
-
6923 std::ifstream tfile(texturefile);
-
6924 if (!tfile) {
-
6925 helios_runtime_error("ERROR (Context::generateTexturesFromColormap): Texture file " + texturefile + " does not exist, or you do not have permission to read it.");
-
6926 }
-
6927 tfile.close();
+
6867 ctable_c.at(2) = RGB::magenta;
+
6868
+
6869 clocs_c.resize(2);
+
6870 clocs_c.at(1) = 0.f;
+
6871 clocs_c.at(2) = 1.f;
+
6872
+
6873 }else if( colormap == "lava" ) {
+
6874
+
6875 ctable_c.resize(5);
+
6876 ctable_c.at(0) = make_RGBcolor(0.f, 0.05f, 0.05f);
+
6877 ctable_c.at(1) = make_RGBcolor(0.f, 0.6f, 0.6f);
+
6878 ctable_c.at(2) = make_RGBcolor(1.f, 1.f, 1.f);
+
6879 ctable_c.at(3) = make_RGBcolor(1.f, 0.f, 0.f);
+
6880 ctable_c.at(4) = make_RGBcolor(0.5f, 0.f, 0.f);
+
6881
+
6882 clocs_c.resize(5);
+
6883 clocs_c.at(0) = 0.f;
+
6884 clocs_c.at(1) = 0.4f;
+
6885 clocs_c.at(2) = 0.5f;
+
6886 clocs_c.at(3) = 0.6f;
+
6887 clocs_c.at(4) = 1.f;
+
6888
+
6889 }else if( colormap == "rainbow" ){
+
6890
+
6891 ctable_c.resize(4);
+
6892 ctable_c.at(0) = RGB::navy;
+
6893 ctable_c.at(1) = RGB::cyan;
+
6894 ctable_c.at(2) = RGB::yellow;
+
6895 ctable_c.at(3) = make_RGBcolor( 0.75f, 0.f, 0.f );
+
6896
+
6897 clocs_c.resize(4);
+
6898 clocs_c.at(0) = 0.f;
+
6899 clocs_c.at(1) = 0.3f;
+
6900 clocs_c.at(2) = 0.7f;
+
6901 clocs_c.at(3) = 1.f;
+
6902
+
6903 }else if( colormap == "parula" ){
+
6904
+
6905 ctable_c.resize(4);
+
6906 ctable_c.at(0) = RGB::navy;
+
6907 ctable_c.at(1) = make_RGBcolor(0,0.6,0.6);
+
6908 ctable_c.at(2) = RGB::goldenrod;
+
6909 ctable_c.at(3) = RGB::yellow;
+
6910
+
6911 clocs_c.resize(4);
+
6912 clocs_c.at(0) = 0.f;
+
6913 clocs_c.at(1) = 0.4f;
+
6914 clocs_c.at(2) = 0.7f;
+
6915 clocs_c.at(3) = 1.f;
+
6916
+
6917 }else if( colormap == "gray" ) {
+
6918
+
6919 ctable_c.resize(2);
+
6920 ctable_c.at(0) = RGB::black;
+
6921 ctable_c.at(1) = RGB::white;
+
6922
+
6923 clocs_c.resize(2);
+
6924 clocs_c.at(0) = 0.f;
+
6925 clocs_c.at(1) = 1.f;
+
6926
+
6927 }else if( colormap == "green" ) {
6928
-
6929 // get file extension
-
6930 std::string file_ext = getFileExtension(texturefile);
-
6931
-
6932 // get file base/stem
-
6933 std::string file_base = getFileStem(texturefile);
-
6934
-
6935 std::vector<RGBcolor> color_table;
-
6936 color_table.resize(Ncolors);
-
6937
-
6938 std::vector<std::string> texture_filenames(Ncolors);
-
6939
-
6940 if (file_ext == "png" || file_ext == "PNG") {
-
6941
-
6942 std::vector<RGBAcolor> pixel_data;
-
6943 uint width, height;
-
6944 readPNG(texturefile, width, height, pixel_data);
-
6945
-
6946 for (int i = 0; i < Ncolors; i++) {
-
6947
-
6948 std::ostringstream filename;
-
6949 filename << "lib/images/colormap_" << file_base << "_" << std::setw(4) << std::setfill('0') << std::to_string(i) << ".png";
-
6950
-
6951 texture_filenames.at(i) = filename.str();
-
6952
-
6953 RGBcolor color = colormap_data.at(i);
-
6954
-
6955 for (int row = 0; row < height; row++) {
-
6956 for (int col = 0; col < width; col++) {
-
6957 pixel_data.at(row * width + col) = make_RGBAcolor(color, pixel_data.at(row * width + col).a);
-
6958 }
-
6959 }
-
6960
-
6961 writePNG(filename.str(), width, height, pixel_data);
-
6962 }
-
6963
-
6964 }
-
6965
-
6966 return texture_filenames;
-
6967
-
6968}
-
6969
-
- -
6971
-
6972 for(auto & primitive : primitives){
-
6973 Primitive* prim = getPrimitivePointer_private(primitive.first);
-
6974 delete prim;
-
6975 }
-
6976
-
6977 for(auto & object : objects){
-
6978 CompoundObject* obj = getObjectPointer(object.first);
-
6979 delete obj;
-
6980 }
+
6929 ctable_c.resize(2);
+
6930 ctable_c.at(0) = RGB::black;
+
6931 ctable_c.at(1) = RGB::green;
+
6932
+
6933 clocs_c.resize(2);
+
6934 clocs_c.at(0) = 0.f;
+
6935 clocs_c.at(1) = 1.f;
+
6936
+
6937 }else{
+
6938 helios_runtime_error("ERROR (Context::generateColormapTextures): Unknown colormap "+colormap+".");
+
6939 }
+
6940
+
6941 return generateColormap( ctable_c, clocs_c, Ncolors );
+
6942
+
6943}
+
6944
+
6945std::vector<std::string> Context::generateTexturesFromColormap( const std::string &texturefile, const std::vector<RGBcolor> &colormap_data ){
+
6946
+
6947 uint Ncolors = colormap_data.size();
+
6948
+
6949 // check that texture file exists
+
6950 std::ifstream tfile(texturefile);
+
6951 if (!tfile) {
+
6952 helios_runtime_error("ERROR (Context::generateTexturesFromColormap): Texture file " + texturefile + " does not exist, or you do not have permission to read it.");
+
6953 }
+
6954 tfile.close();
+
6955
+
6956 // get file extension
+
6957 std::string file_ext = getFileExtension(texturefile);
+
6958
+
6959 // get file base/stem
+
6960 std::string file_base = getFileStem(texturefile);
+
6961
+
6962 std::vector<RGBcolor> color_table;
+
6963 color_table.resize(Ncolors);
+
6964
+
6965 std::vector<std::string> texture_filenames(Ncolors);
+
6966
+
6967 if (file_ext == "png" || file_ext == "PNG") {
+
6968
+
6969 std::vector<RGBAcolor> pixel_data;
+
6970 uint width, height;
+
6971 readPNG(texturefile, width, height, pixel_data);
+
6972
+
6973 for (int i = 0; i < Ncolors; i++) {
+
6974
+
6975 std::ostringstream filename;
+
6976 filename << "lib/images/colormap_" << file_base << "_" << std::setw(4) << std::setfill('0') << std::to_string(i) << ".png";
+
6977
+
6978 texture_filenames.at(i) = filename.str();
+
6979
+
6980 RGBcolor color = colormap_data.at(i);
6981
-
6982}
-
-
6983
-
- -
6985 return getPrimitivePointer_private(UUID)->getType();
-
6986}
-
+
6982 for (int row = 0; row < height; row++) {
+
6983 for (int col = 0; col < width; col++) {
+
6984 pixel_data.at(row * width + col) = make_RGBAcolor(color, pixel_data.at(row * width + col).a);
+
6985 }
+
6986 }
6987
-
-
6988void Context::setPrimitiveParentObjectID(uint UUID, uint objID){
-
6989
-
6990 uint current_objID = getPrimitivePointer_private(UUID)->getParentObjectID();
-
6991 getPrimitivePointer_private(UUID)->setParentObjectID(objID);
-
6992
-
6993 if(current_objID != uint(0) && current_objID!=objID )
-
6994 {
-
6995
-
6996 if( doesObjectExist(current_objID) ) {
-
6997 objects.at(current_objID)->deleteChildPrimitive(UUID);
-
6998
-
6999 if(getObjectPointer_private(current_objID)->getPrimitiveUUIDs().size() == 0)
-
7000 {
-
7001 CompoundObject* obj = objects.at(current_objID);
-
7002 delete obj;
-
7003 objects.erase(current_objID);
- -
7005 }
-
7006 }
+
6988 writePNG(filename.str(), width, height, pixel_data);
+
6989 }
+
6990
+
6991 }
+
6992
+
6993 return texture_filenames;
+
6994
+
6995}
+
6996
+
+ +
6998
+
6999 for(auto & primitive : primitives){
+
7000 Primitive* prim = getPrimitivePointer_private(primitive.first);
+
7001 delete prim;
+
7002 }
+
7003
+
7004 for(auto & object : objects){
+
7005 CompoundObject* obj = getObjectPointer(object.first);
+
7006 delete obj;
7007 }
-
7008
+
7008
7009}
7010
-
7011void Context::setPrimitiveParentObjectID(const std::vector<uint> &UUIDs, uint objID) {
-
7012 for( uint UUID : UUIDs){
-
7013 setPrimitiveParentObjectID(UUID, objID);
-
7014 }
-
7015}
-
-
7016
-
- -
7018 return getPrimitivePointer_private(UUID)->getParentObjectID();
-
7019}
-
-
7020
-
7021
-
-
7022std::vector<uint> Context::getUniquePrimitiveParentObjectIDs(const std::vector<uint> &UUIDs) const {
-
7023 return getUniquePrimitiveParentObjectIDs(UUIDs, false);
-
7024}
-
-
7025
-
7026
-
-
7027std::vector<uint> Context::getUniquePrimitiveParentObjectIDs(const std::vector<uint> &UUIDs, bool include_ObjID_zero) const {
-
7028
-
7029 //vector of parent object ID for each primitive
-
7030 std::vector<uint> primitiveObjIDs;
-
7031 primitiveObjIDs.resize(UUIDs.size());
-
7032 for(uint i=0;i<UUIDs.size();i++)
-
7033 {
-
7034 primitiveObjIDs.at(i) = getPrimitivePointer_private(UUIDs.at(i))->getParentObjectID();
-
7035 }
-
7036
-
7037 // sort
-
7038 std::sort(primitiveObjIDs.begin(), primitiveObjIDs.end());
-
7039
-
7040 // unique
-
7041 auto it = unique(primitiveObjIDs.begin(), primitiveObjIDs.end());
-
7042 primitiveObjIDs.resize(distance(primitiveObjIDs.begin(), it));
-
7043
-
7044 // remove object ID = 0 from the output if desired and it exisits
-
7045 if(include_ObjID_zero == false & primitiveObjIDs.at(0) == uint(0))
-
7046 {
-
7047 primitiveObjIDs.erase(primitiveObjIDs.begin());
-
7048 }
-
7049
-
7050 return primitiveObjIDs;
+ +
7012 return getPrimitivePointer_private(UUID)->getType();
+
7013}
+
+
7014
+
+
7015void Context::setPrimitiveParentObjectID(uint UUID, uint objID){
+
7016
+
7017 uint current_objID = getPrimitivePointer_private(UUID)->getParentObjectID();
+
7018 getPrimitivePointer_private(UUID)->setParentObjectID(objID);
+
7019
+
7020 if(current_objID != uint(0) && current_objID!=objID )
+
7021 {
+
7022
+
7023 if( doesObjectExist(current_objID) ) {
+
7024 objects.at(current_objID)->deleteChildPrimitive(UUID);
+
7025
+
7026 if(getObjectPointer_private(current_objID)->getPrimitiveUUIDs().size() == 0)
+
7027 {
+
7028 CompoundObject* obj = objects.at(current_objID);
+
7029 delete obj;
+
7030 objects.erase(current_objID);
+ +
7032 }
+
7033 }
+
7034 }
+
7035
+
7036}
+
+
7037
+
+
7038void Context::setPrimitiveParentObjectID(const std::vector<uint> &UUIDs, uint objID) {
+
7039 for( uint UUID : UUIDs){
+
7040 setPrimitiveParentObjectID(UUID, objID);
+
7041 }
+
7042}
+
+
7043
+
+ +
7045 return getPrimitivePointer_private(UUID)->getParentObjectID();
+
7046}
+
+
7047
+
7048
+
+
7049std::vector<uint> Context::getUniquePrimitiveParentObjectIDs(const std::vector<uint> &UUIDs) const {
+
7050 return getUniquePrimitiveParentObjectIDs(UUIDs, false);
7051}
7052
-
-
7053float Context::getPrimitiveArea(uint UUID) const {
-
7054 return getPrimitivePointer_private(UUID)->getArea();
-
7055}
-
-
7056
-
-
7057void Context::getPrimitiveBoundingBox( uint UUID, vec3 &min_corner, vec3 &max_corner ) const{
-
7058 const std::vector<uint> UUIDs = {UUID};
-
7059 getPrimitiveBoundingBox( UUIDs, min_corner, max_corner );
-
7060}
-
-
7061
-
-
7062void Context::getPrimitiveBoundingBox( const std::vector<uint> &UUIDs, vec3 &min_corner, vec3 &max_corner ) const{
-
7063
-
7064
-
7065 uint p=0;
-
7066 for( uint UUID : UUIDs ){
-
7067
-
7068 if ( !doesPrimitiveExist(UUID) ){
-
7069 helios_runtime_error("ERROR (Context::getPrimitiveBoundingBox): Primitive with UUID of " + std::to_string(UUID) + " does not exist in the Context.");
-
7070 }
-
7071
-
7072 const std::vector<vec3> &vertices = getPrimitiveVertices(UUID);
-
7073
-
7074 if( p==0 ){
-
7075 min_corner = vertices.front();
-
7076 max_corner = min_corner;
-
7077 }
-
7078
-
7079 for ( const vec3 &vert : vertices ){
-
7080 if ( vert.x<min_corner.x ){
-
7081 min_corner.x = vert.x;
-
7082 }
-
7083 if ( vert.y<min_corner.y ){
-
7084 min_corner.y = vert.y;
-
7085 }
-
7086 if ( vert.z<min_corner.z ){
-
7087 min_corner.z = vert.z;
-
7088 }
-
7089 if ( vert.x>max_corner.x ){
-
7090 max_corner.x = vert.x;
-
7091 }
-
7092 if ( vert.y>max_corner.y ){
-
7093 max_corner.y = vert.y;
-
7094 }
-
7095 if ( vert.z>max_corner.z ){
-
7096 max_corner.z = vert.z;
-
7097 }
-
7098 }
-
7099
-
7100 p++;
-
7101 }
-
7102}
-
-
7103
-
- -
7105 return getPrimitivePointer_private(UUID)->getNormal();
-
7106}
-
-
7107
-
-
7108void Context::getPrimitiveTransformationMatrix(uint UUID, float (&T)[16] ) const {
-
7109 getPrimitivePointer_private(UUID)->getTransformationMatrix( T );
-
7110}
-
-
7111
-
-
7112void Context::setPrimitiveTransformationMatrix(uint UUID, float (&T)[16] ) {
-
7113 getPrimitivePointer_private(UUID)->setTransformationMatrix(T);
-
7114}
-
-
7115
-
-
7116void Context::setPrimitiveTransformationMatrix(const std::vector<uint> &UUIDs, float (&T)[16] ) {
-
7117 for( uint UUID : UUIDs){
-
7118 getPrimitivePointer_private(UUID)->setTransformationMatrix(T);
-
7119 }
-
7120}
-
-
7121
-
-
7122std::vector<helios::vec3> Context::getPrimitiveVertices(uint UUID) const {
-
7123 return getPrimitivePointer_private(UUID)->getVertices();
-
7124}
-
-
7125
+
7053
+
+
7054std::vector<uint> Context::getUniquePrimitiveParentObjectIDs(const std::vector<uint> &UUIDs, bool include_ObjID_zero) const {
+
7055
+
7056 //vector of parent object ID for each primitive
+
7057 std::vector<uint> primitiveObjIDs;
+
7058 primitiveObjIDs.resize(UUIDs.size());
+
7059 for(uint i=0;i<UUIDs.size();i++)
+
7060 {
+
7061 primitiveObjIDs.at(i) = getPrimitivePointer_private(UUIDs.at(i))->getParentObjectID();
+
7062 }
+
7063
+
7064 // sort
+
7065 std::sort(primitiveObjIDs.begin(), primitiveObjIDs.end());
+
7066
+
7067 // unique
+
7068 auto it = unique(primitiveObjIDs.begin(), primitiveObjIDs.end());
+
7069 primitiveObjIDs.resize(distance(primitiveObjIDs.begin(), it));
+
7070
+
7071 // remove object ID = 0 from the output if desired and it exisits
+
7072 if(include_ObjID_zero == false & primitiveObjIDs.at(0) == uint(0))
+
7073 {
+
7074 primitiveObjIDs.erase(primitiveObjIDs.begin());
+
7075 }
+
7076
+
7077 return primitiveObjIDs;
+
7078}
+
+
7079
+
+
7080float Context::getPrimitiveArea(uint UUID) const {
+
7081 return getPrimitivePointer_private(UUID)->getArea();
+
7082}
+
+
7083
+
+
7084void Context::getPrimitiveBoundingBox( uint UUID, vec3 &min_corner, vec3 &max_corner ) const{
+
7085 const std::vector<uint> UUIDs = {UUID};
+
7086 getPrimitiveBoundingBox( UUIDs, min_corner, max_corner );
+
7087}
+
+
7088
+
+
7089void Context::getPrimitiveBoundingBox( const std::vector<uint> &UUIDs, vec3 &min_corner, vec3 &max_corner ) const{
+
7090
+
7091
+
7092 uint p=0;
+
7093 for( uint UUID : UUIDs ){
+
7094
+
7095 if ( !doesPrimitiveExist(UUID) ){
+
7096 helios_runtime_error("ERROR (Context::getPrimitiveBoundingBox): Primitive with UUID of " + std::to_string(UUID) + " does not exist in the Context.");
+
7097 }
+
7098
+
7099 const std::vector<vec3> &vertices = getPrimitiveVertices(UUID);
+
7100
+
7101 if( p==0 ){
+
7102 min_corner = vertices.front();
+
7103 max_corner = min_corner;
+
7104 }
+
7105
+
7106 for ( const vec3 &vert : vertices ){
+
7107 if ( vert.x<min_corner.x ){
+
7108 min_corner.x = vert.x;
+
7109 }
+
7110 if ( vert.y<min_corner.y ){
+
7111 min_corner.y = vert.y;
+
7112 }
+
7113 if ( vert.z<min_corner.z ){
+
7114 min_corner.z = vert.z;
+
7115 }
+
7116 if ( vert.x>max_corner.x ){
+
7117 max_corner.x = vert.x;
+
7118 }
+
7119 if ( vert.y>max_corner.y ){
+
7120 max_corner.y = vert.y;
+
7121 }
+
7122 if ( vert.z>max_corner.z ){
+
7123 max_corner.z = vert.z;
+
7124 }
+
7125 }
7126
-
- -
7128 return getPrimitivePointer_private(UUID)->getColor();
+
7127 p++;
+
7128 }
7129}
7130
- -
7132 return getPrimitivePointer_private(UUID)->getColorRGB();
+ +
7132 return getPrimitivePointer_private(UUID)->getNormal();
7133}
7134
- -
7136 return getPrimitivePointer_private(UUID)->getColorRGBA();
+
7135void Context::getPrimitiveTransformationMatrix(uint UUID, float (&T)[16] ) const {
+
7136 getPrimitivePointer_private(UUID)->getTransformationMatrix( T );
7137}
7138
-
7139void Context::setPrimitiveColor(uint UUID, const RGBcolor &color) {
-
7140 getPrimitivePointer_private(UUID)->setColor( color );
+
7139void Context::setPrimitiveTransformationMatrix(uint UUID, float (&T)[16] ) {
+
7140 getPrimitivePointer_private(UUID)->setTransformationMatrix(T);
7141}
7142
-
7143void Context::setPrimitiveColor(const std::vector<uint> &UUIDs, const RGBcolor &color) {
+
7143void Context::setPrimitiveTransformationMatrix(const std::vector<uint> &UUIDs, float (&T)[16] ) {
7144 for( uint UUID : UUIDs){
-
7145 getPrimitivePointer_private(UUID)->setColor(color);
+
7145 getPrimitivePointer_private(UUID)->setTransformationMatrix(T);
7146 }
7147}
7148
-
7149void Context::setPrimitiveColor(uint UUID, const RGBAcolor &color) {
-
7150 getPrimitivePointer_private(UUID)->setColor( color );
+
7149std::vector<helios::vec3> Context::getPrimitiveVertices(uint UUID) const {
+
7150 return getPrimitivePointer_private(UUID)->getVertices();
7151}
7152
-
-
7153void Context::setPrimitiveColor(const std::vector<uint> &UUIDs, const RGBAcolor &color) {
-
7154 for( uint UUID : UUIDs){
-
7155 getPrimitivePointer_private(UUID)->setColor(color);
-
7156 }
-
7157}
-
-
7158
-
-
7159std::string Context::getPrimitiveTextureFile( uint UUID ) const{
-
7160 return getPrimitivePointer_private(UUID)->getTextureFile();
-
7161}
-
-
7162
-
-
7163void Context::setPrimitiveTextureFile( uint UUID, const std::string &texturefile ){
-
7164 getPrimitivePointer_private(UUID)->setTextureFile(texturefile.c_str());
-
7165}
-
-
7166
-
- -
7168 std::string texturefile = getPrimitivePointer_private(UUID)->getTextureFile();
-
7169 if( !texturefile.empty() && textures.find(texturefile)!=textures.end() ){
-
7170 return textures.at(texturefile).getImageResolution();
-
7171 }
-
7172 return make_int2(0,0);
-
7173}
-
-
7174
-
-
7175std::vector<helios::vec2> Context::getPrimitiveTextureUV( uint UUID ) const{
-
7176 return getPrimitivePointer_private(UUID)->getTextureUV();
-
7177}
-
-
7178
-
- -
7180 std::string texturefile = getPrimitivePointer_private(UUID)->getTextureFile();
-
7181 if( !texturefile.empty() && textures.find(texturefile)!=textures.end() ){
-
7182 return textures.at(texturefile).hasTransparencyChannel();
+
7153
+
+ +
7155 return getPrimitivePointer_private(UUID)->getColor();
+
7156}
+
+
7157
+
+ +
7159 return getPrimitivePointer_private(UUID)->getColorRGB();
+
7160}
+
+
7161
+
+ +
7163 return getPrimitivePointer_private(UUID)->getColorRGBA();
+
7164}
+
+
7165
+
+
7166void Context::setPrimitiveColor(uint UUID, const RGBcolor &color) {
+
7167 getPrimitivePointer_private(UUID)->setColor( color );
+
7168}
+
+
7169
+
+
7170void Context::setPrimitiveColor(const std::vector<uint> &UUIDs, const RGBcolor &color) {
+
7171 for( uint UUID : UUIDs){
+
7172 getPrimitivePointer_private(UUID)->setColor(color);
+
7173 }
+
7174}
+
+
7175
+
+
7176void Context::setPrimitiveColor(uint UUID, const RGBAcolor &color) {
+
7177 getPrimitivePointer_private(UUID)->setColor( color );
+
7178}
+
+
7179
+
+
7180void Context::setPrimitiveColor(const std::vector<uint> &UUIDs, const RGBAcolor &color) {
+
7181 for( uint UUID : UUIDs){
+
7182 getPrimitivePointer_private(UUID)->setColor(color);
7183 }
-
7184 return false;
-
7185}
-
-
7186
-
-
7187const std::vector<std::vector<bool>> * Context::getPrimitiveTextureTransparencyData(uint UUID ) const{
- -
7189 const std::vector<std::vector<bool> > *data = textures.at(getPrimitivePointer_private(UUID)->getTextureFile()).getTransparencyData();
-
7190 return data;
-
7191 }else{
-
7192 helios_runtime_error("ERROR (Context::getPrimitiveTransparencyData): Texture transparency data does not exist for primitive " + std::to_string(UUID) + ".");
-
7193 return 0;
-
7194 }
-
7195}
-
-
7196
-
- -
7198 getPrimitivePointer_private(UUID)->overrideTextureColor();
-
7199}
-
-
7200
-
-
7201void Context::overridePrimitiveTextureColor( const std::vector<uint> &UUIDs ){
-
7202 for( uint UUID : UUIDs ) {
-
7203 getPrimitivePointer_private(UUID)->overrideTextureColor();
-
7204 }
-
7205}
-
-
7206
-
- -
7208 getPrimitivePointer_private(UUID)->useTextureColor();
-
7209}
-
-
7210
-
-
7211void Context::usePrimitiveTextureColor( const std::vector<uint> &UUIDs ){
-
7212 for( uint UUID : UUIDs ) {
-
7213 getPrimitivePointer_private(UUID)->useTextureColor();
-
7214 }
-
7215}
-
-
7216
-
- -
7218 return getPrimitivePointer_private(UUID)->isTextureColorOverridden();
-
7219}
-
-
7220
-
-
7221float Context::getPrimitiveSolidFraction( uint UUID ) const{
-
7222 return getPrimitivePointer_private(UUID)->getSolidFraction();
-
7223}
-
-
7224
-
-
7225void Context::printPrimitiveInfo(uint UUID) const{
-
7226
-
7227 std::cout << "-------------------------------------------" << std::endl;
-
7228 std::cout << "Info for UUID " << UUID << std::endl;
-
7229 std::cout << "-------------------------------------------" << std::endl;
-
7230
-
7231 PrimitiveType type = getPrimitiveType(UUID);
-
7232 std::string stype;
-
7233 if( type == 0){
-
7234 stype = "PRIMITIVE_TYPE_PATCH";
-
7235 }else if(type == 1){
-
7236 stype = "PRIMITIVE_TYPE_TRIANGLE";
-
7237 }else if(type == 2){
-
7238 stype = "PRIMITIVE_TYPE_VOXEL";
-
7239 }
-
7240
-
7241 std::cout << "Type: " << stype << std::endl;
-
7242 std::cout << "Parent ObjID: " << getPrimitiveParentObjectID(UUID) << std::endl;
-
7243 std::cout << "Surface Area: " << getPrimitiveArea(UUID) << std::endl;
-
7244 std::cout << "Normal Vector: " << getPrimitiveNormal(UUID) << std::endl;
-
7245
-
7246 if(type == PRIMITIVE_TYPE_PATCH)
-
7247 {
-
7248 std::cout << "Patch Center: " << getPatchCenter(UUID) << std::endl;
-
7249 std::cout << "Patch Size: " << getPatchSize(UUID) << std::endl;
-
7250
-
7251 }else if(type == PRIMITIVE_TYPE_VOXEL){
-
7252
-
7253 std::cout << "Voxel Center: " << getVoxelCenter(UUID) << std::endl;
-
7254 std::cout << "Voxel Size: " << getVoxelSize(UUID) << std::endl;
-
7255 }
-
7256
-
7257 std::vector<vec3> primitive_vertices = getPrimitiveVertices(UUID);
-
7258 std::cout << "Vertices: " << std::endl;
-
7259 for(uint i=0; i<primitive_vertices.size();i++)
-
7260 {
-
7261 std::cout << " " << primitive_vertices.at(i) << std::endl;
-
7262 }
-
7263
-
7264 float T[16];
- -
7266 std::cout << "Transform: " << std::endl;
-
7267 std::cout << " " << T[0] << " " << T[1] << " " << T[2] << " " << T[3] << std::endl;
-
7268 std::cout << " " << T[4] << " " << T[5] << " " << T[6] << " " << T[7] << std::endl;
-
7269 std::cout << " " << T[8] << " " << T[9] << " " << T[10] << " " << T[11] << std::endl;
-
7270 std::cout << " " << T[12] << " " << T[13] << " " << T[14] << " " << T[15] << std::endl;
-
7271
-
7272 std::cout << "Color: " << getPrimitiveColor(UUID) << std::endl;
-
7273 std::cout << "Texture File: " << getPrimitiveTextureFile(UUID) << std::endl;
-
7274 std::cout << "Texture Size: " << getPrimitiveTextureSize(UUID) << std::endl;
-
7275 std::cout << "Texture UV: " << std::endl;
-
7276 std::vector<vec2> uv = getPrimitiveTextureUV(UUID);
-
7277 for(uint i=0; i<uv.size();i++)
-
7278 {
-
7279 std::cout << " " << uv.at(i) << std::endl;
-
7280 }
-
7281
-
7282 std::cout << "Texture Transparency: " << primitiveTextureHasTransparencyChannel(UUID) << std::endl;
-
7283 std::cout << "Color Overridden: " << isPrimitiveTextureColorOverridden(UUID) << std::endl;
-
7284 std::cout << "Solid Fraction: " << getPrimitiveSolidFraction(UUID) << std::endl;
-
7285
-
7286
-
7287 std::cout << "Primitive Data: " << std::endl;
-
7288 // Primitive* pointer = getPrimitivePointer_private(UUID);
-
7289 std::vector<std::string> pd = listPrimitiveData(UUID);
-
7290 for(uint i=0; i<pd.size();i++)
-
7291 {
-
7292 uint dsize = getPrimitiveDataSize(UUID, pd.at(i).c_str());
-
7293 HeliosDataType dtype = getPrimitiveDataType(UUID, pd.at(i).c_str());
-
7294 std::string dstype;
-
7295
-
7296 if( dtype==HELIOS_TYPE_INT ){
-
7297 dstype = "HELIOS_TYPE_INT";
-
7298 }else if( dtype==HELIOS_TYPE_UINT ){
-
7299 dstype = "HELIOS_TYPE_UINT";
-
7300 }else if( dtype==HELIOS_TYPE_FLOAT ){
-
7301 dstype = "HELIOS_TYPE_FLOAT";
-
7302 }else if( dtype==HELIOS_TYPE_DOUBLE ){
-
7303 dstype = "HELIOS_TYPE_DOUBLE";
-
7304 }else if( dtype==HELIOS_TYPE_VEC2 ){
-
7305 dstype = "HELIOS_TYPE_VEC2";
-
7306 }else if( dtype==HELIOS_TYPE_VEC3 ){
-
7307 dstype = "HELIOS_TYPE_VEC3";
-
7308 }else if( dtype==HELIOS_TYPE_VEC4 ){
-
7309 dstype = "HELIOS_TYPE_VEC4";
-
7310 }else if( dtype==HELIOS_TYPE_INT2 ){
-
7311 dstype = "HELIOS_TYPE_INT2";
-
7312 }else if( dtype==HELIOS_TYPE_INT3 ){
-
7313 dstype = "HELIOS_TYPE_INT3";
-
7314 }else if( dtype==HELIOS_TYPE_INT4 ){
-
7315 dstype = "HELIOS_TYPE_INT4";
-
7316 }else if( dtype==HELIOS_TYPE_STRING ){
-
7317 dstype = "HELIOS_TYPE_STRING";
-
7318 }else{
-
7319 assert(false);
-
7320 }
-
7321
+
7184}
+
+
7185
+
+
7186std::string Context::getPrimitiveTextureFile( uint UUID ) const{
+
7187 return getPrimitivePointer_private(UUID)->getTextureFile();
+
7188}
+
+
7189
+
+
7190void Context::setPrimitiveTextureFile( uint UUID, const std::string &texturefile ){
+
7191 getPrimitivePointer_private(UUID)->setTextureFile(texturefile.c_str());
+
7192}
+
+
7193
+
+ +
7195 std::string texturefile = getPrimitivePointer_private(UUID)->getTextureFile();
+
7196 if( !texturefile.empty() && textures.find(texturefile)!=textures.end() ){
+
7197 return textures.at(texturefile).getImageResolution();
+
7198 }
+
7199 return make_int2(0,0);
+
7200}
+
+
7201
+
+
7202std::vector<helios::vec2> Context::getPrimitiveTextureUV( uint UUID ) const{
+
7203 return getPrimitivePointer_private(UUID)->getTextureUV();
+
7204}
+
+
7205
+
+ +
7207 std::string texturefile = getPrimitivePointer_private(UUID)->getTextureFile();
+
7208 if( !texturefile.empty() && textures.find(texturefile)!=textures.end() ){
+
7209 return textures.at(texturefile).hasTransparencyChannel();
+
7210 }
+
7211 return false;
+
7212}
+
+
7213
+
+
7214const std::vector<std::vector<bool>> * Context::getPrimitiveTextureTransparencyData(uint UUID ) const{
+ +
7216 const std::vector<std::vector<bool> > *data = textures.at(getPrimitivePointer_private(UUID)->getTextureFile()).getTransparencyData();
+
7217 return data;
+
7218 }else{
+
7219 helios_runtime_error("ERROR (Context::getPrimitiveTransparencyData): Texture transparency data does not exist for primitive " + std::to_string(UUID) + ".");
+
7220 return 0;
+
7221 }
+
7222}
+
+
7223
+
+ +
7225 getPrimitivePointer_private(UUID)->overrideTextureColor();
+
7226}
+
+
7227
+
+
7228void Context::overridePrimitiveTextureColor( const std::vector<uint> &UUIDs ){
+
7229 for( uint UUID : UUIDs ) {
+
7230 getPrimitivePointer_private(UUID)->overrideTextureColor();
+
7231 }
+
7232}
+
+
7233
+
+ +
7235 getPrimitivePointer_private(UUID)->useTextureColor();
+
7236}
+
+
7237
+
+
7238void Context::usePrimitiveTextureColor( const std::vector<uint> &UUIDs ){
+
7239 for( uint UUID : UUIDs ) {
+
7240 getPrimitivePointer_private(UUID)->useTextureColor();
+
7241 }
+
7242}
+
+
7243
+
+ +
7245 return getPrimitivePointer_private(UUID)->isTextureColorOverridden();
+
7246}
+
+
7247
+
+
7248float Context::getPrimitiveSolidFraction( uint UUID ) const{
+
7249 return getPrimitivePointer_private(UUID)->getSolidFraction();
+
7250}
+
+
7251
+
+
7252void Context::printPrimitiveInfo(uint UUID) const{
+
7253
+
7254 std::cout << "-------------------------------------------" << std::endl;
+
7255 std::cout << "Info for UUID " << UUID << std::endl;
+
7256 std::cout << "-------------------------------------------" << std::endl;
+
7257
+
7258 PrimitiveType type = getPrimitiveType(UUID);
+
7259 std::string stype;
+
7260 if( type == 0){
+
7261 stype = "PRIMITIVE_TYPE_PATCH";
+
7262 }else if(type == 1){
+
7263 stype = "PRIMITIVE_TYPE_TRIANGLE";
+
7264 }else if(type == 2){
+
7265 stype = "PRIMITIVE_TYPE_VOXEL";
+
7266 }
+
7267
+
7268 std::cout << "Type: " << stype << std::endl;
+
7269 std::cout << "Parent ObjID: " << getPrimitiveParentObjectID(UUID) << std::endl;
+
7270 std::cout << "Surface Area: " << getPrimitiveArea(UUID) << std::endl;
+
7271 std::cout << "Normal Vector: " << getPrimitiveNormal(UUID) << std::endl;
+
7272
+
7273 if(type == PRIMITIVE_TYPE_PATCH)
+
7274 {
+
7275 std::cout << "Patch Center: " << getPatchCenter(UUID) << std::endl;
+
7276 std::cout << "Patch Size: " << getPatchSize(UUID) << std::endl;
+
7277
+
7278 }else if(type == PRIMITIVE_TYPE_VOXEL){
+
7279
+
7280 std::cout << "Voxel Center: " << getVoxelCenter(UUID) << std::endl;
+
7281 std::cout << "Voxel Size: " << getVoxelSize(UUID) << std::endl;
+
7282 }
+
7283
+
7284 std::vector<vec3> primitive_vertices = getPrimitiveVertices(UUID);
+
7285 std::cout << "Vertices: " << std::endl;
+
7286 for(uint i=0; i<primitive_vertices.size();i++)
+
7287 {
+
7288 std::cout << " " << primitive_vertices.at(i) << std::endl;
+
7289 }
+
7290
+
7291 float T[16];
+ +
7293 std::cout << "Transform: " << std::endl;
+
7294 std::cout << " " << T[0] << " " << T[1] << " " << T[2] << " " << T[3] << std::endl;
+
7295 std::cout << " " << T[4] << " " << T[5] << " " << T[6] << " " << T[7] << std::endl;
+
7296 std::cout << " " << T[8] << " " << T[9] << " " << T[10] << " " << T[11] << std::endl;
+
7297 std::cout << " " << T[12] << " " << T[13] << " " << T[14] << " " << T[15] << std::endl;
+
7298
+
7299 std::cout << "Color: " << getPrimitiveColor(UUID) << std::endl;
+
7300 std::cout << "Texture File: " << getPrimitiveTextureFile(UUID) << std::endl;
+
7301 std::cout << "Texture Size: " << getPrimitiveTextureSize(UUID) << std::endl;
+
7302 std::cout << "Texture UV: " << std::endl;
+
7303 std::vector<vec2> uv = getPrimitiveTextureUV(UUID);
+
7304 for(uint i=0; i<uv.size();i++)
+
7305 {
+
7306 std::cout << " " << uv.at(i) << std::endl;
+
7307 }
+
7308
+
7309 std::cout << "Texture Transparency: " << primitiveTextureHasTransparencyChannel(UUID) << std::endl;
+
7310 std::cout << "Color Overridden: " << isPrimitiveTextureColorOverridden(UUID) << std::endl;
+
7311 std::cout << "Solid Fraction: " << getPrimitiveSolidFraction(UUID) << std::endl;
+
7312
+
7313
+
7314 std::cout << "Primitive Data: " << std::endl;
+
7315 // Primitive* pointer = getPrimitivePointer_private(UUID);
+
7316 std::vector<std::string> pd = listPrimitiveData(UUID);
+
7317 for(uint i=0; i<pd.size();i++)
+
7318 {
+
7319 uint dsize = getPrimitiveDataSize(UUID, pd.at(i).c_str());
+
7320 HeliosDataType dtype = getPrimitiveDataType(UUID, pd.at(i).c_str());
+
7321 std::string dstype;
7322
-
7323 std::cout << " " << "[name: " << pd.at(i) << ", type: " << dstype << ", size: " << dsize << "]:" << std::endl;
-
7324
-
7325
-
7326 if( dtype==HELIOS_TYPE_INT ){
-
7327 std::vector<int> pdata;
-
7328 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7329 for(uint j=0; j<dsize;j++)
-
7330 {
-
7331 if(j < 10){
-
7332 std::cout << " " << pdata.at(j) << std::endl;
-
7333 }else{
-
7334 std::cout << " ..." << std::endl;
-
7335 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7336 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7337 break;
-
7338 }
-
7339
-
7340 }
-
7341 }else if( dtype==HELIOS_TYPE_UINT ){
-
7342 std::vector<uint> pdata;
-
7343 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7344 for(uint j=0; j<dsize;j++)
-
7345 {
-
7346 if(j < 10){
-
7347 std::cout << " " << pdata.at(j) << std::endl;
-
7348 }else{
-
7349 std::cout << " ..." << std::endl;
-
7350 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7351 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7352 break;
-
7353 }
-
7354
-
7355 }
-
7356 }else if( dtype==HELIOS_TYPE_FLOAT ){
-
7357 std::vector<float> pdata;
-
7358 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7359 for(uint j=0; j<dsize;j++)
-
7360 {
-
7361 if(j < 10){
-
7362 std::cout << " " << pdata.at(j) << std::endl;
-
7363 }else{
-
7364 std::cout << " ..." << std::endl;
-
7365 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7366 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7367 break;
-
7368 }
-
7369
-
7370 }
-
7371 }else if( dtype==HELIOS_TYPE_DOUBLE ){
-
7372 std::vector<double> pdata;
-
7373 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7374 for(uint j=0; j<dsize;j++)
-
7375 {
-
7376 if(j < 10){
-
7377 std::cout << " " << pdata.at(j) << std::endl;
-
7378 }else{
-
7379 std::cout << " ..." << std::endl;
-
7380 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7381 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7382 break;
-
7383 }
-
7384
-
7385 }
-
7386 }else if( dtype==HELIOS_TYPE_VEC2 ){
-
7387 std::vector<vec2> pdata;
-
7388 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7389 for(uint j=0; j<dsize;j++)
-
7390 {
-
7391 if(j < 10){
-
7392 std::cout << " " << pdata.at(j) << std::endl;
-
7393 }else{
-
7394 std::cout << " ..." << std::endl;
-
7395 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7396 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7397 break;
-
7398 }
-
7399
-
7400 }
-
7401 }else if( dtype==HELIOS_TYPE_VEC3 ){
-
7402 std::vector<vec3> pdata;
-
7403 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7404 for(uint j=0; j<dsize;j++)
-
7405 {
-
7406 if(j < 10){
-
7407 std::cout << " " << pdata.at(j) << std::endl;
-
7408 }else{
-
7409 std::cout << " ..." << std::endl;
-
7410 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7411 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7412 break;
-
7413 }
-
7414
-
7415 }
-
7416 }else if( dtype==HELIOS_TYPE_VEC4 ){
-
7417 std::vector<vec4> pdata;
-
7418 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7419 for(uint j=0; j<dsize;j++)
-
7420 {
-
7421 if(j < 10){
-
7422 std::cout << " " << pdata.at(j) << std::endl;
-
7423 }else{
-
7424 std::cout << " ..." << std::endl;
-
7425 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7426 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7427 break;
-
7428 }
-
7429
-
7430 }
-
7431 }else if( dtype==HELIOS_TYPE_INT2 ){
-
7432 std::vector<int2> pdata;
-
7433 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7434 for(uint j=0; j<dsize;j++)
-
7435 {
-
7436 if(j < 10){
-
7437 std::cout << " " << pdata.at(j) << std::endl;
-
7438 }else{
-
7439 std::cout << " ..." << std::endl;
-
7440 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7441 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7442 break;
-
7443 }
-
7444
-
7445 }
-
7446 }else if( dtype==HELIOS_TYPE_INT3 ){
-
7447 std::vector<int3> pdata;
-
7448 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7449 for(uint j=0; j<dsize;j++)
-
7450 {
-
7451 if(j < 10){
-
7452 std::cout << " " << pdata.at(j) << std::endl;
-
7453 }else{
-
7454 std::cout << " ..." << std::endl;
-
7455 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7456 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7457 break;
-
7458 }
-
7459
-
7460 }
-
7461 }else if( dtype==HELIOS_TYPE_INT4 ){
-
7462 std::vector<int4> pdata;
-
7463 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7464 for(uint j=0; j<dsize;j++)
-
7465 {
-
7466 if(j < 10){
-
7467 std::cout << " " << pdata.at(j) << std::endl;
-
7468 }else{
-
7469 std::cout << " ..." << std::endl;
-
7470 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7471 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7472 break;
-
7473 }
-
7474
-
7475 }
-
7476 }else if( dtype==HELIOS_TYPE_STRING ){
-
7477 std::vector<std::string> pdata;
-
7478 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
-
7479 for(uint j=0; j<dsize;j++)
-
7480 {
-
7481 if(j < 10){
-
7482 std::cout << " " << pdata.at(j) << std::endl;
-
7483 }else{
-
7484 std::cout << " ..." << std::endl;
-
7485 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7486 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7487 break;
-
7488 }
-
7489
-
7490 }
-
7491 }else{
-
7492 assert(false);
-
7493 }
-
7494
-
7495 }
-
7496 std::cout << "-------------------------------------------" << std::endl;
-
7497}
-
-
7498
-
-
7499void Context::printObjectInfo(uint ObjID) const{
-
7500
-
7501 std::cout << "-------------------------------------------" << std::endl;
-
7502 std::cout << "Info for ObjID " << ObjID << std::endl;
-
7503 std::cout << "-------------------------------------------" << std::endl;
-
7504
-
7505 ObjectType otype = getObjectType(ObjID);
-
7506 std::string ostype;
-
7507 if( otype == 0){
-
7508 ostype = "OBJECT_TYPE_TILE";
-
7509 }else if(otype == 1){
-
7510 ostype = "OBJECT_TYPE_SPHERE";
-
7511 }else if(otype == 2){
-
7512 ostype = "OBJECT_TYPE_TUBE";
-
7513 }else if(otype == 3){
-
7514 ostype = "OBJECT_TYPE_BOX";
-
7515 }else if(otype == 4){
-
7516 ostype = "OBJECT_TYPE_DISK";
-
7517 }else if(otype == 5){
-
7518 ostype = "OBJECT_TYPE_POLYMESH";
-
7519 }else if(otype == 6){
-
7520 ostype = "OBJECT_TYPE_CONE";
-
7521 }
-
7522
-
7523 std::cout << "Type: " << ostype << std::endl;
-
7524 std::cout << "Object Bounding Box Center: " << getObjectCenter(ObjID) << std::endl;
-
7525 std::cout << "One-sided Surface Area: " << getObjectArea(ObjID) << std::endl;
-
7526
-
7527 std::cout << "Primitive Count: " << getObjectPrimitiveCount(ObjID) << std::endl;
-
7528
- -
7530 {
-
7531 std::cout << "Object Primitives Complete" << std::endl;
-
7532 }else{
-
7533 std::cout << "Object Primitives Incomplete" << std::endl;
-
7534 }
-
7535
-
7536 std::cout << "Primitive UUIDs: " << std::endl;
-
7537 std::vector<uint> primitive_UUIDs = getObjectPrimitiveUUIDs(ObjID);
-
7538 for(uint i=0; i<primitive_UUIDs.size();i++)
-
7539 {
-
7540 if(i < 5){
-
7541 PrimitiveType ptype = getPrimitiveType(primitive_UUIDs.at(i));
-
7542 std::string pstype;
-
7543 if( ptype == 0){
-
7544 pstype = "PRIMITIVE_TYPE_PATCH";
-
7545 }else if(ptype == 1){
-
7546 pstype = "PRIMITIVE_TYPE_TRIANGLE";
-
7547 }
-
7548 std::cout << " " << primitive_UUIDs.at(i) << " (" << pstype << ")" << std::endl;
-
7549 }else{
-
7550 std::cout << " ..." << std::endl;
-
7551 PrimitiveType ptype = getPrimitiveType(primitive_UUIDs.at(primitive_UUIDs.size()-2));
-
7552 std::string pstype;
-
7553 if( ptype == 0){
-
7554 pstype = "PRIMITIVE_TYPE_PATCH";
-
7555 }else if(ptype == 1){
-
7556 pstype = "PRIMITIVE_TYPE_TRIANGLE";
-
7557 }
-
7558 std::cout << " " << primitive_UUIDs.at(primitive_UUIDs.size()-2) << " (" << pstype << ")" << std::endl;
-
7559 ptype = getPrimitiveType(primitive_UUIDs.at(primitive_UUIDs.size()-1));
-
7560 if( ptype == 0){
-
7561 pstype = "PRIMITIVE_TYPE_PATCH";
-
7562 }else if(ptype == 1){
-
7563 pstype = "PRIMITIVE_TYPE_TRIANGLE";
-
7564 }
-
7565 std::cout << " " << primitive_UUIDs.at(primitive_UUIDs.size()-1) << " (" << pstype << ")" << std::endl;
-
7566 break;
-
7567 }
-
7568 }
-
7569
-
7570 if(otype == OBJECT_TYPE_TILE)
-
7571 {
-
7572 std::cout << "Tile Center: " << getTileObjectCenter(ObjID) << std::endl;
-
7573 std::cout << "Tile Size: " << getTileObjectSize(ObjID) << std::endl;
-
7574 std::cout << "Tile Subdivision Count: " << getTileObjectSubdivisionCount(ObjID) << std::endl;
-
7575 std::cout << "Tile Normal: " << getTileObjectNormal(ObjID) << std::endl;
-
7576
-
7577 std::cout << "Tile Texture UV: " << std::endl;
-
7578 std::vector<vec2> uv = getTileObjectTextureUV(ObjID);
-
7579 for(uint i=0; i<uv.size();i++)
-
7580 {
-
7581 std::cout << " " << uv.at(i) << std::endl;
-
7582 }
-
7583
-
7584 std::cout << "Tile Vertices: " << std::endl;
-
7585 std::vector<vec3> primitive_vertices = getTileObjectVertices(ObjID);
-
7586 for(uint i=0; i<primitive_vertices.size();i++)
-
7587 {
-
7588 std::cout << " " << primitive_vertices.at(i) << std::endl;
-
7589 }
-
7590
-
7591
-
7592 }else if(otype == OBJECT_TYPE_SPHERE){
-
7593
-
7594 std::cout << "Sphere Center: " << getSphereObjectCenter(ObjID) << std::endl;
-
7595 std::cout << "Sphere Radius: " << getSphereObjectRadius(ObjID) << std::endl;
-
7596 std::cout << "Sphere Subdivision Count: " << getSphereObjectSubdivisionCount(ObjID) << std::endl;
-
7597
-
7598 }else if(otype == OBJECT_TYPE_TUBE){
-
7599
-
7600 std::cout << "Tube Subdivision Count: " << getTubeObjectSubdivisionCount(ObjID) << std::endl;
-
7601 std::cout << "Tube Nodes: " << std::endl;
-
7602 std::vector<vec3> nodes = getTubeObjectNodes(ObjID);
-
7603 for(uint i=0; i<nodes.size();i++)
-
7604 {
-
7605 if(i < 10){
-
7606 std::cout << " " << nodes.at(i) << std::endl;
-
7607 }else{
-
7608 std::cout << " ..." << std::endl;
-
7609 std::cout << " " << nodes.at(nodes.size()-2) << std::endl;
-
7610 std::cout << " " << nodes.at(nodes.size()-1) << std::endl;
-
7611 break;
-
7612 }
-
7613 }
-
7614 std::cout << "Tube Node Radii: " << std::endl;
-
7615 std::vector<float> noderadii = getTubeObjectNodeRadii(ObjID);
-
7616 for(uint i=0; i<noderadii.size();i++)
-
7617 {
-
7618 if(i < 10){
-
7619 std::cout << " " << noderadii.at(i) << std::endl;
-
7620 }else{
-
7621 std::cout << " ..." << std::endl;
-
7622 std::cout << " " << noderadii.at(noderadii.size()-2) << std::endl;
-
7623 std::cout << " " << noderadii.at(noderadii.size()-1) << std::endl;
-
7624 break;
-
7625 }
-
7626 }
-
7627 std::cout << "Tube Node Colors: " << std::endl;
-
7628 std::vector<helios::RGBcolor> nodecolors = getTubeObjectNodeColors(ObjID);
-
7629 for(uint i=0; i<nodecolors.size();i++)
-
7630 {
-
7631 if(i < 10){
-
7632 std::cout << " " << nodecolors.at(i) << std::endl;
-
7633 }else{
-
7634 std::cout << " ..." << std::endl;
-
7635 std::cout << " " << nodecolors.at(nodecolors.size()-2) << std::endl;
-
7636 std::cout << " " << nodecolors.at(nodecolors.size()-1) << std::endl;
-
7637 break;
-
7638 }
-
7639 }
-
7640
-
7641 }else if(otype == OBJECT_TYPE_BOX){
-
7642
-
7643 std::cout << "Box Center: " << getBoxObjectCenter(ObjID) << std::endl;
-
7644 std::cout << "Box Size: " << getBoxObjectSize(ObjID) << std::endl;
-
7645 std::cout << "Box Subdivision Count: " << getBoxObjectSubdivisionCount(ObjID) << std::endl;
-
7646
-
7647 }else if(otype == OBJECT_TYPE_DISK){
-
7648
-
7649 std::cout << "Disk Center: " << getDiskObjectCenter(ObjID) << std::endl;
-
7650 std::cout << "Disk Size: " << getDiskObjectSize(ObjID) << std::endl;
-
7651 std::cout << "Disk Subdivision Count: " << getDiskObjectSubdivisionCount(ObjID) << std::endl;
-
7652
-
7653 // }else if(type == OBJECT_TYPE_POLYMESH){
-
7654 // nothing for now
-
7655
-
7656 }else if(otype == OBJECT_TYPE_CONE){
-
7657
-
7658 std::cout << "Cone Length: " << getConeObjectLength(ObjID) << std::endl;
-
7659 std::cout << "Cone Axis Unit Vector: " << getConeObjectAxisUnitVector(ObjID) << std::endl;
-
7660 std::cout << "Cone Subdivision Count: " << getConeObjectSubdivisionCount(ObjID) << std::endl;
-
7661 std::cout << "Cone Nodes: " << std::endl;
-
7662 std::vector<vec3> nodes = getConeObjectNodes(ObjID);
-
7663 for(uint i=0; i<nodes.size();i++)
-
7664 {
-
7665 std::cout << " " << nodes.at(i) << std::endl;
+
7323 if( dtype==HELIOS_TYPE_INT ){
+
7324 dstype = "HELIOS_TYPE_INT";
+
7325 }else if( dtype==HELIOS_TYPE_UINT ){
+
7326 dstype = "HELIOS_TYPE_UINT";
+
7327 }else if( dtype==HELIOS_TYPE_FLOAT ){
+
7328 dstype = "HELIOS_TYPE_FLOAT";
+
7329 }else if( dtype==HELIOS_TYPE_DOUBLE ){
+
7330 dstype = "HELIOS_TYPE_DOUBLE";
+
7331 }else if( dtype==HELIOS_TYPE_VEC2 ){
+
7332 dstype = "HELIOS_TYPE_VEC2";
+
7333 }else if( dtype==HELIOS_TYPE_VEC3 ){
+
7334 dstype = "HELIOS_TYPE_VEC3";
+
7335 }else if( dtype==HELIOS_TYPE_VEC4 ){
+
7336 dstype = "HELIOS_TYPE_VEC4";
+
7337 }else if( dtype==HELIOS_TYPE_INT2 ){
+
7338 dstype = "HELIOS_TYPE_INT2";
+
7339 }else if( dtype==HELIOS_TYPE_INT3 ){
+
7340 dstype = "HELIOS_TYPE_INT3";
+
7341 }else if( dtype==HELIOS_TYPE_INT4 ){
+
7342 dstype = "HELIOS_TYPE_INT4";
+
7343 }else if( dtype==HELIOS_TYPE_STRING ){
+
7344 dstype = "HELIOS_TYPE_STRING";
+
7345 }else{
+
7346 assert(false);
+
7347 }
+
7348
+
7349
+
7350 std::cout << " " << "[name: " << pd.at(i) << ", type: " << dstype << ", size: " << dsize << "]:" << std::endl;
+
7351
+
7352
+
7353 if( dtype==HELIOS_TYPE_INT ){
+
7354 std::vector<int> pdata;
+
7355 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7356 for(uint j=0; j<dsize;j++)
+
7357 {
+
7358 if(j < 10){
+
7359 std::cout << " " << pdata.at(j) << std::endl;
+
7360 }else{
+
7361 std::cout << " ..." << std::endl;
+
7362 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7363 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7364 break;
+
7365 }
+
7366
+
7367 }
+
7368 }else if( dtype==HELIOS_TYPE_UINT ){
+
7369 std::vector<uint> pdata;
+
7370 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7371 for(uint j=0; j<dsize;j++)
+
7372 {
+
7373 if(j < 10){
+
7374 std::cout << " " << pdata.at(j) << std::endl;
+
7375 }else{
+
7376 std::cout << " ..." << std::endl;
+
7377 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7378 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7379 break;
+
7380 }
+
7381
+
7382 }
+
7383 }else if( dtype==HELIOS_TYPE_FLOAT ){
+
7384 std::vector<float> pdata;
+
7385 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7386 for(uint j=0; j<dsize;j++)
+
7387 {
+
7388 if(j < 10){
+
7389 std::cout << " " << pdata.at(j) << std::endl;
+
7390 }else{
+
7391 std::cout << " ..." << std::endl;
+
7392 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7393 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7394 break;
+
7395 }
+
7396
+
7397 }
+
7398 }else if( dtype==HELIOS_TYPE_DOUBLE ){
+
7399 std::vector<double> pdata;
+
7400 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7401 for(uint j=0; j<dsize;j++)
+
7402 {
+
7403 if(j < 10){
+
7404 std::cout << " " << pdata.at(j) << std::endl;
+
7405 }else{
+
7406 std::cout << " ..." << std::endl;
+
7407 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7408 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7409 break;
+
7410 }
+
7411
+
7412 }
+
7413 }else if( dtype==HELIOS_TYPE_VEC2 ){
+
7414 std::vector<vec2> pdata;
+
7415 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7416 for(uint j=0; j<dsize;j++)
+
7417 {
+
7418 if(j < 10){
+
7419 std::cout << " " << pdata.at(j) << std::endl;
+
7420 }else{
+
7421 std::cout << " ..." << std::endl;
+
7422 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7423 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7424 break;
+
7425 }
+
7426
+
7427 }
+
7428 }else if( dtype==HELIOS_TYPE_VEC3 ){
+
7429 std::vector<vec3> pdata;
+
7430 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7431 for(uint j=0; j<dsize;j++)
+
7432 {
+
7433 if(j < 10){
+
7434 std::cout << " " << pdata.at(j) << std::endl;
+
7435 }else{
+
7436 std::cout << " ..." << std::endl;
+
7437 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7438 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7439 break;
+
7440 }
+
7441
+
7442 }
+
7443 }else if( dtype==HELIOS_TYPE_VEC4 ){
+
7444 std::vector<vec4> pdata;
+
7445 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7446 for(uint j=0; j<dsize;j++)
+
7447 {
+
7448 if(j < 10){
+
7449 std::cout << " " << pdata.at(j) << std::endl;
+
7450 }else{
+
7451 std::cout << " ..." << std::endl;
+
7452 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7453 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7454 break;
+
7455 }
+
7456
+
7457 }
+
7458 }else if( dtype==HELIOS_TYPE_INT2 ){
+
7459 std::vector<int2> pdata;
+
7460 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7461 for(uint j=0; j<dsize;j++)
+
7462 {
+
7463 if(j < 10){
+
7464 std::cout << " " << pdata.at(j) << std::endl;
+
7465 }else{
+
7466 std::cout << " ..." << std::endl;
+
7467 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7468 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7469 break;
+
7470 }
+
7471
+
7472 }
+
7473 }else if( dtype==HELIOS_TYPE_INT3 ){
+
7474 std::vector<int3> pdata;
+
7475 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7476 for(uint j=0; j<dsize;j++)
+
7477 {
+
7478 if(j < 10){
+
7479 std::cout << " " << pdata.at(j) << std::endl;
+
7480 }else{
+
7481 std::cout << " ..." << std::endl;
+
7482 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7483 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7484 break;
+
7485 }
+
7486
+
7487 }
+
7488 }else if( dtype==HELIOS_TYPE_INT4 ){
+
7489 std::vector<int4> pdata;
+
7490 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7491 for(uint j=0; j<dsize;j++)
+
7492 {
+
7493 if(j < 10){
+
7494 std::cout << " " << pdata.at(j) << std::endl;
+
7495 }else{
+
7496 std::cout << " ..." << std::endl;
+
7497 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7498 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7499 break;
+
7500 }
+
7501
+
7502 }
+
7503 }else if( dtype==HELIOS_TYPE_STRING ){
+
7504 std::vector<std::string> pdata;
+
7505 getPrimitiveData( UUID, pd.at(i).c_str(), pdata );
+
7506 for(uint j=0; j<dsize;j++)
+
7507 {
+
7508 if(j < 10){
+
7509 std::cout << " " << pdata.at(j) << std::endl;
+
7510 }else{
+
7511 std::cout << " ..." << std::endl;
+
7512 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7513 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7514 break;
+
7515 }
+
7516
+
7517 }
+
7518 }else{
+
7519 assert(false);
+
7520 }
+
7521
+
7522 }
+
7523 std::cout << "-------------------------------------------" << std::endl;
+
7524}
+
+
7525
+
+
7526void Context::printObjectInfo(uint ObjID) const{
+
7527
+
7528 std::cout << "-------------------------------------------" << std::endl;
+
7529 std::cout << "Info for ObjID " << ObjID << std::endl;
+
7530 std::cout << "-------------------------------------------" << std::endl;
+
7531
+
7532 ObjectType otype = getObjectType(ObjID);
+
7533 std::string ostype;
+
7534 if( otype == 0){
+
7535 ostype = "OBJECT_TYPE_TILE";
+
7536 }else if(otype == 1){
+
7537 ostype = "OBJECT_TYPE_SPHERE";
+
7538 }else if(otype == 2){
+
7539 ostype = "OBJECT_TYPE_TUBE";
+
7540 }else if(otype == 3){
+
7541 ostype = "OBJECT_TYPE_BOX";
+
7542 }else if(otype == 4){
+
7543 ostype = "OBJECT_TYPE_DISK";
+
7544 }else if(otype == 5){
+
7545 ostype = "OBJECT_TYPE_POLYMESH";
+
7546 }else if(otype == 6){
+
7547 ostype = "OBJECT_TYPE_CONE";
+
7548 }
+
7549
+
7550 std::cout << "Type: " << ostype << std::endl;
+
7551 std::cout << "Object Bounding Box Center: " << getObjectCenter(ObjID) << std::endl;
+
7552 std::cout << "One-sided Surface Area: " << getObjectArea(ObjID) << std::endl;
+
7553
+
7554 std::cout << "Primitive Count: " << getObjectPrimitiveCount(ObjID) << std::endl;
+
7555
+ +
7557 {
+
7558 std::cout << "Object Primitives Complete" << std::endl;
+
7559 }else{
+
7560 std::cout << "Object Primitives Incomplete" << std::endl;
+
7561 }
+
7562
+
7563 std::cout << "Primitive UUIDs: " << std::endl;
+
7564 std::vector<uint> primitive_UUIDs = getObjectPrimitiveUUIDs(ObjID);
+
7565 for(uint i=0; i<primitive_UUIDs.size();i++)
+
7566 {
+
7567 if(i < 5){
+
7568 PrimitiveType ptype = getPrimitiveType(primitive_UUIDs.at(i));
+
7569 std::string pstype;
+
7570 if( ptype == 0){
+
7571 pstype = "PRIMITIVE_TYPE_PATCH";
+
7572 }else if(ptype == 1){
+
7573 pstype = "PRIMITIVE_TYPE_TRIANGLE";
+
7574 }
+
7575 std::cout << " " << primitive_UUIDs.at(i) << " (" << pstype << ")" << std::endl;
+
7576 }else{
+
7577 std::cout << " ..." << std::endl;
+
7578 PrimitiveType ptype = getPrimitiveType(primitive_UUIDs.at(primitive_UUIDs.size()-2));
+
7579 std::string pstype;
+
7580 if( ptype == 0){
+
7581 pstype = "PRIMITIVE_TYPE_PATCH";
+
7582 }else if(ptype == 1){
+
7583 pstype = "PRIMITIVE_TYPE_TRIANGLE";
+
7584 }
+
7585 std::cout << " " << primitive_UUIDs.at(primitive_UUIDs.size()-2) << " (" << pstype << ")" << std::endl;
+
7586 ptype = getPrimitiveType(primitive_UUIDs.at(primitive_UUIDs.size()-1));
+
7587 if( ptype == 0){
+
7588 pstype = "PRIMITIVE_TYPE_PATCH";
+
7589 }else if(ptype == 1){
+
7590 pstype = "PRIMITIVE_TYPE_TRIANGLE";
+
7591 }
+
7592 std::cout << " " << primitive_UUIDs.at(primitive_UUIDs.size()-1) << " (" << pstype << ")" << std::endl;
+
7593 break;
+
7594 }
+
7595 }
+
7596
+
7597 if(otype == OBJECT_TYPE_TILE)
+
7598 {
+
7599 std::cout << "Tile Center: " << getTileObjectCenter(ObjID) << std::endl;
+
7600 std::cout << "Tile Size: " << getTileObjectSize(ObjID) << std::endl;
+
7601 std::cout << "Tile Subdivision Count: " << getTileObjectSubdivisionCount(ObjID) << std::endl;
+
7602 std::cout << "Tile Normal: " << getTileObjectNormal(ObjID) << std::endl;
+
7603
+
7604 std::cout << "Tile Texture UV: " << std::endl;
+
7605 std::vector<vec2> uv = getTileObjectTextureUV(ObjID);
+
7606 for(uint i=0; i<uv.size();i++)
+
7607 {
+
7608 std::cout << " " << uv.at(i) << std::endl;
+
7609 }
+
7610
+
7611 std::cout << "Tile Vertices: " << std::endl;
+
7612 std::vector<vec3> primitive_vertices = getTileObjectVertices(ObjID);
+
7613 for(uint i=0; i<primitive_vertices.size();i++)
+
7614 {
+
7615 std::cout << " " << primitive_vertices.at(i) << std::endl;
+
7616 }
+
7617
+
7618
+
7619 }else if(otype == OBJECT_TYPE_SPHERE){
+
7620
+
7621 std::cout << "Sphere Center: " << getSphereObjectCenter(ObjID) << std::endl;
+
7622 std::cout << "Sphere Radius: " << getSphereObjectRadius(ObjID) << std::endl;
+
7623 std::cout << "Sphere Subdivision Count: " << getSphereObjectSubdivisionCount(ObjID) << std::endl;
+
7624
+
7625 }else if(otype == OBJECT_TYPE_TUBE){
+
7626
+
7627 std::cout << "Tube Subdivision Count: " << getTubeObjectSubdivisionCount(ObjID) << std::endl;
+
7628 std::cout << "Tube Nodes: " << std::endl;
+
7629 std::vector<vec3> nodes = getTubeObjectNodes(ObjID);
+
7630 for(uint i=0; i<nodes.size();i++)
+
7631 {
+
7632 if(i < 10){
+
7633 std::cout << " " << nodes.at(i) << std::endl;
+
7634 }else{
+
7635 std::cout << " ..." << std::endl;
+
7636 std::cout << " " << nodes.at(nodes.size()-2) << std::endl;
+
7637 std::cout << " " << nodes.at(nodes.size()-1) << std::endl;
+
7638 break;
+
7639 }
+
7640 }
+
7641 std::cout << "Tube Node Radii: " << std::endl;
+
7642 std::vector<float> noderadii = getTubeObjectNodeRadii(ObjID);
+
7643 for(uint i=0; i<noderadii.size();i++)
+
7644 {
+
7645 if(i < 10){
+
7646 std::cout << " " << noderadii.at(i) << std::endl;
+
7647 }else{
+
7648 std::cout << " ..." << std::endl;
+
7649 std::cout << " " << noderadii.at(noderadii.size()-2) << std::endl;
+
7650 std::cout << " " << noderadii.at(noderadii.size()-1) << std::endl;
+
7651 break;
+
7652 }
+
7653 }
+
7654 std::cout << "Tube Node Colors: " << std::endl;
+
7655 std::vector<helios::RGBcolor> nodecolors = getTubeObjectNodeColors(ObjID);
+
7656 for(uint i=0; i<nodecolors.size();i++)
+
7657 {
+
7658 if(i < 10){
+
7659 std::cout << " " << nodecolors.at(i) << std::endl;
+
7660 }else{
+
7661 std::cout << " ..." << std::endl;
+
7662 std::cout << " " << nodecolors.at(nodecolors.size()-2) << std::endl;
+
7663 std::cout << " " << nodecolors.at(nodecolors.size()-1) << std::endl;
+
7664 break;
+
7665 }
7666 }
-
7667 std::cout << "Cone Node Radii: " << std::endl;
-
7668 std::vector<float> noderadii = getConeObjectNodeRadii(ObjID);
-
7669 for(uint i=0; i<noderadii.size();i++)
-
7670 {
-
7671 std::cout << " " << noderadii.at(i) << std::endl;
-
7672 }
-
7673 }
-
7674
-
7675
-
7676 float T[16];
- -
7678 std::cout << "Transform: " << std::endl;
-
7679 std::cout << " " << T[0] << " " << T[1] << " " << T[2] << " " << T[3] << std::endl;
-
7680 std::cout << " " << T[4] << " " << T[5] << " " << T[6] << " " << T[7] << std::endl;
-
7681 std::cout << " " << T[8] << " " << T[9] << " " << T[10] << " " << T[11] << std::endl;
-
7682 std::cout << " " << T[12] << " " << T[13] << " " << T[14] << " " << T[15] << std::endl;
-
7683
-
7684 std::cout << "Texture File: " << getObjectTextureFile(ObjID) << std::endl;
-
7685
-
7686 std::cout << "Object Data: " << std::endl;
-
7687 // Primitive* pointer = getPrimitivePointer_private(ObjID);
-
7688 std::vector<std::string> pd = listObjectData(ObjID);
-
7689 for(uint i=0; i<pd.size();i++)
-
7690 {
-
7691 uint dsize = getObjectDataSize(ObjID, pd.at(i).c_str());
-
7692 HeliosDataType dtype = getObjectDataType(ObjID, pd.at(i).c_str());
-
7693 std::string dstype;
-
7694
-
7695 if( dtype==HELIOS_TYPE_INT ){
-
7696 dstype = "HELIOS_TYPE_INT";
-
7697 }else if( dtype==HELIOS_TYPE_UINT ){
-
7698 dstype = "HELIOS_TYPE_UINT";
-
7699 }else if( dtype==HELIOS_TYPE_FLOAT ){
-
7700 dstype = "HELIOS_TYPE_FLOAT";
-
7701 }else if( dtype==HELIOS_TYPE_DOUBLE ){
-
7702 dstype = "HELIOS_TYPE_DOUBLE";
-
7703 }else if( dtype==HELIOS_TYPE_VEC2 ){
-
7704 dstype = "HELIOS_TYPE_VEC2";
-
7705 }else if( dtype==HELIOS_TYPE_VEC3 ){
-
7706 dstype = "HELIOS_TYPE_VEC3";
-
7707 }else if( dtype==HELIOS_TYPE_VEC4 ){
-
7708 dstype = "HELIOS_TYPE_VEC4";
-
7709 }else if( dtype==HELIOS_TYPE_INT2 ){
-
7710 dstype = "HELIOS_TYPE_INT2";
-
7711 }else if( dtype==HELIOS_TYPE_INT3 ){
-
7712 dstype = "HELIOS_TYPE_INT3";
-
7713 }else if( dtype==HELIOS_TYPE_INT4 ){
-
7714 dstype = "HELIOS_TYPE_INT4";
-
7715 }else if( dtype==HELIOS_TYPE_STRING ){
-
7716 dstype = "HELIOS_TYPE_STRING";
-
7717 }else{
-
7718 assert(false);
-
7719 }
-
7720
+
7667
+
7668 }else if(otype == OBJECT_TYPE_BOX){
+
7669
+
7670 std::cout << "Box Center: " << getBoxObjectCenter(ObjID) << std::endl;
+
7671 std::cout << "Box Size: " << getBoxObjectSize(ObjID) << std::endl;
+
7672 std::cout << "Box Subdivision Count: " << getBoxObjectSubdivisionCount(ObjID) << std::endl;
+
7673
+
7674 }else if(otype == OBJECT_TYPE_DISK){
+
7675
+
7676 std::cout << "Disk Center: " << getDiskObjectCenter(ObjID) << std::endl;
+
7677 std::cout << "Disk Size: " << getDiskObjectSize(ObjID) << std::endl;
+
7678 std::cout << "Disk Subdivision Count: " << getDiskObjectSubdivisionCount(ObjID) << std::endl;
+
7679
+
7680 // }else if(type == OBJECT_TYPE_POLYMESH){
+
7681 // nothing for now
+
7682
+
7683 }else if(otype == OBJECT_TYPE_CONE){
+
7684
+
7685 std::cout << "Cone Length: " << getConeObjectLength(ObjID) << std::endl;
+
7686 std::cout << "Cone Axis Unit Vector: " << getConeObjectAxisUnitVector(ObjID) << std::endl;
+
7687 std::cout << "Cone Subdivision Count: " << getConeObjectSubdivisionCount(ObjID) << std::endl;
+
7688 std::cout << "Cone Nodes: " << std::endl;
+
7689 std::vector<vec3> nodes = getConeObjectNodes(ObjID);
+
7690 for(uint i=0; i<nodes.size();i++)
+
7691 {
+
7692 std::cout << " " << nodes.at(i) << std::endl;
+
7693 }
+
7694 std::cout << "Cone Node Radii: " << std::endl;
+
7695 std::vector<float> noderadii = getConeObjectNodeRadii(ObjID);
+
7696 for(uint i=0; i<noderadii.size();i++)
+
7697 {
+
7698 std::cout << " " << noderadii.at(i) << std::endl;
+
7699 }
+
7700 }
+
7701
+
7702
+
7703 float T[16];
+ +
7705 std::cout << "Transform: " << std::endl;
+
7706 std::cout << " " << T[0] << " " << T[1] << " " << T[2] << " " << T[3] << std::endl;
+
7707 std::cout << " " << T[4] << " " << T[5] << " " << T[6] << " " << T[7] << std::endl;
+
7708 std::cout << " " << T[8] << " " << T[9] << " " << T[10] << " " << T[11] << std::endl;
+
7709 std::cout << " " << T[12] << " " << T[13] << " " << T[14] << " " << T[15] << std::endl;
+
7710
+
7711 std::cout << "Texture File: " << getObjectTextureFile(ObjID) << std::endl;
+
7712
+
7713 std::cout << "Object Data: " << std::endl;
+
7714 // Primitive* pointer = getPrimitivePointer_private(ObjID);
+
7715 std::vector<std::string> pd = listObjectData(ObjID);
+
7716 for(uint i=0; i<pd.size();i++)
+
7717 {
+
7718 uint dsize = getObjectDataSize(ObjID, pd.at(i).c_str());
+
7719 HeliosDataType dtype = getObjectDataType(ObjID, pd.at(i).c_str());
+
7720 std::string dstype;
7721
-
7722 std::cout << " " << "[name: " << pd.at(i) << ", type: " << dstype << ", size: " << dsize << "]:" << std::endl;
-
7723
-
7724
-
7725 if( dtype==HELIOS_TYPE_INT ){
-
7726 std::vector<int> pdata;
-
7727 getObjectData( ObjID, pd.at(i).c_str(), pdata );
-
7728 for(uint j=0; j<dsize;j++)
-
7729 {
-
7730 if(j < 10){
-
7731 std::cout << " " << pdata.at(j) << std::endl;
-
7732 }else{
-
7733 std::cout << " ..." << std::endl;
-
7734 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7735 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7736 break;
-
7737 }
-
7738
-
7739 }
-
7740 }else if( dtype==HELIOS_TYPE_UINT ){
-
7741 std::vector<uint> pdata;
-
7742 getObjectData( ObjID, pd.at(i).c_str(), pdata );
-
7743 for(uint j=0; j<dsize;j++)
-
7744 {
-
7745 if(j < 10){
-
7746 std::cout << " " << pdata.at(j) << std::endl;
-
7747 }else{
-
7748 std::cout << " ..." << std::endl;
-
7749 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7750 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7751 break;
-
7752 }
-
7753
-
7754 }
-
7755 }else if( dtype==HELIOS_TYPE_FLOAT ){
-
7756 std::vector<float> pdata;
-
7757 getObjectData( ObjID, pd.at(i).c_str(), pdata );
-
7758 for(uint j=0; j<dsize;j++)
-
7759 {
-
7760 if(j < 10){
-
7761 std::cout << " " << pdata.at(j) << std::endl;
-
7762 }else{
-
7763 std::cout << " ..." << std::endl;
-
7764 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7765 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7766 break;
-
7767 }
-
7768
-
7769 }
-
7770 }else if( dtype==HELIOS_TYPE_DOUBLE ){
-
7771 std::vector<double> pdata;
-
7772 getObjectData(ObjID, pd.at(i).c_str(), pdata );
-
7773 for(uint j=0; j<dsize;j++)
-
7774 {
-
7775 if(j < 10){
-
7776 std::cout << " " << pdata.at(j) << std::endl;
-
7777 }else{
-
7778 std::cout << " ..." << std::endl;
-
7779 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7780 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7781 break;
-
7782 }
-
7783
-
7784 }
-
7785 }else if( dtype==HELIOS_TYPE_VEC2 ){
-
7786 std::vector<vec2> pdata;
-
7787 getObjectData(ObjID, pd.at(i).c_str(), pdata );
-
7788 for(uint j=0; j<dsize;j++)
-
7789 {
-
7790 if(j < 10){
-
7791 std::cout << " " << pdata.at(j) << std::endl;
-
7792 }else{
-
7793 std::cout << " ..." << std::endl;
-
7794 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7795 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7796 break;
-
7797 }
-
7798
-
7799 }
-
7800 }else if( dtype==HELIOS_TYPE_VEC3 ){
-
7801 std::vector<vec3> pdata;
-
7802 getObjectData(ObjID, pd.at(i).c_str(), pdata );
-
7803 for(uint j=0; j<dsize;j++)
-
7804 {
-
7805 if(j < 10){
-
7806 std::cout << " " << pdata.at(j) << std::endl;
-
7807 }else{
-
7808 std::cout << " ..." << std::endl;
-
7809 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7810 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7811 break;
-
7812 }
-
7813
-
7814 }
-
7815 }else if( dtype==HELIOS_TYPE_VEC4 ){
-
7816 std::vector<vec4> pdata;
-
7817 getObjectData(ObjID, pd.at(i).c_str(), pdata );
-
7818 for(uint j=0; j<dsize;j++)
-
7819 {
-
7820 if(j < 10){
-
7821 std::cout << " " << pdata.at(j) << std::endl;
-
7822 }else{
-
7823 std::cout << " ..." << std::endl;
-
7824 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7825 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7826 break;
-
7827 }
-
7828
-
7829 }
-
7830 }else if( dtype==HELIOS_TYPE_INT2 ){
-
7831 std::vector<int2> pdata;
-
7832 getObjectData(ObjID, pd.at(i).c_str(), pdata );
-
7833 for(uint j=0; j<dsize;j++)
-
7834 {
-
7835 if(j < 10){
-
7836 std::cout << " " << pdata.at(j) << std::endl;
-
7837 }else{
-
7838 std::cout << " ..." << std::endl;
-
7839 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7840 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7841 break;
-
7842 }
-
7843
-
7844 }
-
7845 }else if( dtype==HELIOS_TYPE_INT3 ){
-
7846 std::vector<int3> pdata;
-
7847 getObjectData(ObjID, pd.at(i).c_str(), pdata );
-
7848 for(uint j=0; j<dsize;j++)
-
7849 {
-
7850 if(j < 10){
-
7851 std::cout << " " << pdata.at(j) << std::endl;
-
7852 }else{
-
7853 std::cout << " ..." << std::endl;
-
7854 std::cout << " " << pdata.at(dsize-2) << std::endl;
-
7855 std::cout << " " << pdata.at(dsize-1) << std::endl;
-
7856 break;
-
7857 }
-
7858
-
7859 }
-
7860 }else if( dtype==HELIOS_TYPE_INT4 ){
-
7861 std::vector<int4> pdata;
-
7862 getObjectData(ObjID, pd.at(i).c_str(), pdata );
-
7863 for(uint j=0; j<dsize;j++)
-
7864 {
-
7865 if(j < 10){
-
7866 std::cout << " " << pdata.at(j) << std::endl;
-
7867 }else{
-
7868 std::cout << " ..." << std::endl;
-
7869 break;
-
7870 }
-
7871
-
7872 }
-
7873 }else if( dtype==HELIOS_TYPE_STRING ){
-
7874 std::vector<std::string> pdata;
-
7875 getObjectData(ObjID, pd.at(i).c_str(), pdata );
-
7876 for(uint j=0; j<dsize;j++)
-
7877 {
-
7878 if(j < 10){
-
7879 std::cout << " " << pdata.at(j) << std::endl;
-
7880 }else{
-
7881 std::cout << " ..." << std::endl;
-
7882 break;
-
7883 }
-
7884
-
7885 }
-
7886 }else{
-
7887 assert(false);
-
7888 }
-
7889
-
7890 }
-
7891 std::cout << "-------------------------------------------" << std::endl;
-
7892}
-
-
7893
-
7894CompoundObject* Context::getObjectPointer_private( uint ObjID ) const{
-
7895 if( objects.find(ObjID) == objects.end() ){
-
7896 helios_runtime_error("ERROR (Context::getObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
7897 }
-
7898 return objects.at(ObjID);
-
7899}
-
7900
-
-
7901void Context::hideObject( const std::vector<uint> &ObjIDs ){
-
7902 for( uint ObjID : ObjIDs ) {
-
7903 if( !doesObjectExist(ObjID) ){
-
7904 helios_runtime_error("ERROR (Context::hideObject): Object ID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
7905 }
-
7906 objects.at(ObjID)->ishidden = true;
-
7907 for( uint UUID : objects.at(ObjID)->getPrimitiveUUIDs() ){
-
7908 primitives.at(UUID)->ishidden = true;
-
7909 }
-
7910 }
-
7911}
-
-
7912
-
-
7913bool Context::isObjectHidden( uint ObjID ) const{
-
7914 if( !doesObjectExist(ObjID) ){
-
7915 helios_runtime_error("ERROR (Context::isObjectHidden): Object ID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
7916 }
-
7917 return objects.at(ObjID)->ishidden;
-
7918}
-
-
7919
-
-
7920float Context::getObjectArea(uint ObjID) const {
-
7921 return getObjectPointer_private(ObjID)->getArea();
-
7922}
-
-
7923
-
-
7924uint Context::getObjectPrimitiveCount(uint ObjID) const {
-
7925 return getObjectPointer_private(ObjID)->getPrimitiveCount();
+
7722 if( dtype==HELIOS_TYPE_INT ){
+
7723 dstype = "HELIOS_TYPE_INT";
+
7724 }else if( dtype==HELIOS_TYPE_UINT ){
+
7725 dstype = "HELIOS_TYPE_UINT";
+
7726 }else if( dtype==HELIOS_TYPE_FLOAT ){
+
7727 dstype = "HELIOS_TYPE_FLOAT";
+
7728 }else if( dtype==HELIOS_TYPE_DOUBLE ){
+
7729 dstype = "HELIOS_TYPE_DOUBLE";
+
7730 }else if( dtype==HELIOS_TYPE_VEC2 ){
+
7731 dstype = "HELIOS_TYPE_VEC2";
+
7732 }else if( dtype==HELIOS_TYPE_VEC3 ){
+
7733 dstype = "HELIOS_TYPE_VEC3";
+
7734 }else if( dtype==HELIOS_TYPE_VEC4 ){
+
7735 dstype = "HELIOS_TYPE_VEC4";
+
7736 }else if( dtype==HELIOS_TYPE_INT2 ){
+
7737 dstype = "HELIOS_TYPE_INT2";
+
7738 }else if( dtype==HELIOS_TYPE_INT3 ){
+
7739 dstype = "HELIOS_TYPE_INT3";
+
7740 }else if( dtype==HELIOS_TYPE_INT4 ){
+
7741 dstype = "HELIOS_TYPE_INT4";
+
7742 }else if( dtype==HELIOS_TYPE_STRING ){
+
7743 dstype = "HELIOS_TYPE_STRING";
+
7744 }else{
+
7745 assert(false);
+
7746 }
+
7747
+
7748
+
7749 std::cout << " " << "[name: " << pd.at(i) << ", type: " << dstype << ", size: " << dsize << "]:" << std::endl;
+
7750
+
7751
+
7752 if( dtype==HELIOS_TYPE_INT ){
+
7753 std::vector<int> pdata;
+
7754 getObjectData( ObjID, pd.at(i).c_str(), pdata );
+
7755 for(uint j=0; j<dsize;j++)
+
7756 {
+
7757 if(j < 10){
+
7758 std::cout << " " << pdata.at(j) << std::endl;
+
7759 }else{
+
7760 std::cout << " ..." << std::endl;
+
7761 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7762 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7763 break;
+
7764 }
+
7765
+
7766 }
+
7767 }else if( dtype==HELIOS_TYPE_UINT ){
+
7768 std::vector<uint> pdata;
+
7769 getObjectData( ObjID, pd.at(i).c_str(), pdata );
+
7770 for(uint j=0; j<dsize;j++)
+
7771 {
+
7772 if(j < 10){
+
7773 std::cout << " " << pdata.at(j) << std::endl;
+
7774 }else{
+
7775 std::cout << " ..." << std::endl;
+
7776 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7777 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7778 break;
+
7779 }
+
7780
+
7781 }
+
7782 }else if( dtype==HELIOS_TYPE_FLOAT ){
+
7783 std::vector<float> pdata;
+
7784 getObjectData( ObjID, pd.at(i).c_str(), pdata );
+
7785 for(uint j=0; j<dsize;j++)
+
7786 {
+
7787 if(j < 10){
+
7788 std::cout << " " << pdata.at(j) << std::endl;
+
7789 }else{
+
7790 std::cout << " ..." << std::endl;
+
7791 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7792 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7793 break;
+
7794 }
+
7795
+
7796 }
+
7797 }else if( dtype==HELIOS_TYPE_DOUBLE ){
+
7798 std::vector<double> pdata;
+
7799 getObjectData(ObjID, pd.at(i).c_str(), pdata );
+
7800 for(uint j=0; j<dsize;j++)
+
7801 {
+
7802 if(j < 10){
+
7803 std::cout << " " << pdata.at(j) << std::endl;
+
7804 }else{
+
7805 std::cout << " ..." << std::endl;
+
7806 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7807 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7808 break;
+
7809 }
+
7810
+
7811 }
+
7812 }else if( dtype==HELIOS_TYPE_VEC2 ){
+
7813 std::vector<vec2> pdata;
+
7814 getObjectData(ObjID, pd.at(i).c_str(), pdata );
+
7815 for(uint j=0; j<dsize;j++)
+
7816 {
+
7817 if(j < 10){
+
7818 std::cout << " " << pdata.at(j) << std::endl;
+
7819 }else{
+
7820 std::cout << " ..." << std::endl;
+
7821 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7822 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7823 break;
+
7824 }
+
7825
+
7826 }
+
7827 }else if( dtype==HELIOS_TYPE_VEC3 ){
+
7828 std::vector<vec3> pdata;
+
7829 getObjectData(ObjID, pd.at(i).c_str(), pdata );
+
7830 for(uint j=0; j<dsize;j++)
+
7831 {
+
7832 if(j < 10){
+
7833 std::cout << " " << pdata.at(j) << std::endl;
+
7834 }else{
+
7835 std::cout << " ..." << std::endl;
+
7836 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7837 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7838 break;
+
7839 }
+
7840
+
7841 }
+
7842 }else if( dtype==HELIOS_TYPE_VEC4 ){
+
7843 std::vector<vec4> pdata;
+
7844 getObjectData(ObjID, pd.at(i).c_str(), pdata );
+
7845 for(uint j=0; j<dsize;j++)
+
7846 {
+
7847 if(j < 10){
+
7848 std::cout << " " << pdata.at(j) << std::endl;
+
7849 }else{
+
7850 std::cout << " ..." << std::endl;
+
7851 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7852 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7853 break;
+
7854 }
+
7855
+
7856 }
+
7857 }else if( dtype==HELIOS_TYPE_INT2 ){
+
7858 std::vector<int2> pdata;
+
7859 getObjectData(ObjID, pd.at(i).c_str(), pdata );
+
7860 for(uint j=0; j<dsize;j++)
+
7861 {
+
7862 if(j < 10){
+
7863 std::cout << " " << pdata.at(j) << std::endl;
+
7864 }else{
+
7865 std::cout << " ..." << std::endl;
+
7866 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7867 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7868 break;
+
7869 }
+
7870
+
7871 }
+
7872 }else if( dtype==HELIOS_TYPE_INT3 ){
+
7873 std::vector<int3> pdata;
+
7874 getObjectData(ObjID, pd.at(i).c_str(), pdata );
+
7875 for(uint j=0; j<dsize;j++)
+
7876 {
+
7877 if(j < 10){
+
7878 std::cout << " " << pdata.at(j) << std::endl;
+
7879 }else{
+
7880 std::cout << " ..." << std::endl;
+
7881 std::cout << " " << pdata.at(dsize-2) << std::endl;
+
7882 std::cout << " " << pdata.at(dsize-1) << std::endl;
+
7883 break;
+
7884 }
+
7885
+
7886 }
+
7887 }else if( dtype==HELIOS_TYPE_INT4 ){
+
7888 std::vector<int4> pdata;
+
7889 getObjectData(ObjID, pd.at(i).c_str(), pdata );
+
7890 for(uint j=0; j<dsize;j++)
+
7891 {
+
7892 if(j < 10){
+
7893 std::cout << " " << pdata.at(j) << std::endl;
+
7894 }else{
+
7895 std::cout << " ..." << std::endl;
+
7896 break;
+
7897 }
+
7898
+
7899 }
+
7900 }else if( dtype==HELIOS_TYPE_STRING ){
+
7901 std::vector<std::string> pdata;
+
7902 getObjectData(ObjID, pd.at(i).c_str(), pdata );
+
7903 for(uint j=0; j<dsize;j++)
+
7904 {
+
7905 if(j < 10){
+
7906 std::cout << " " << pdata.at(j) << std::endl;
+
7907 }else{
+
7908 std::cout << " ..." << std::endl;
+
7909 break;
+
7910 }
+
7911
+
7912 }
+
7913 }else{
+
7914 assert(false);
+
7915 }
+
7916
+
7917 }
+
7918 std::cout << "-------------------------------------------" << std::endl;
+
7919}
+
+
7920
+
7921CompoundObject* Context::getObjectPointer_private( uint ObjID ) const{
+
7922 if( objects.find(ObjID) == objects.end() ){
+
7923 helios_runtime_error("ERROR (Context::getObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
7924 }
+
7925 return objects.at(ObjID);
7926}
-
7927
- -
7929 return getObjectPointer_private(ObjID)->getObjectCenter();
-
7930}
-
-
7931
-
-
7932std::string Context::getObjectTextureFile(uint ObjID) const{
-
7933 return getObjectPointer_private(ObjID)->getTextureFile();
-
7934}
-
-
7935
-
-
7936void Context::getObjectTransformationMatrix(uint ObjID, float (&T)[16] ) const {
-
7937 getObjectPointer_private(ObjID)->getTransformationMatrix( T );
+
7928void Context::hideObject( const std::vector<uint> &ObjIDs ){
+
7929 for( uint ObjID : ObjIDs ) {
+
7930 if( !doesObjectExist(ObjID) ){
+
7931 helios_runtime_error("ERROR (Context::hideObject): Object ID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
7932 }
+
7933 objects.at(ObjID)->ishidden = true;
+
7934 for( uint UUID : objects.at(ObjID)->getPrimitiveUUIDs() ){
+
7935 primitives.at(UUID)->ishidden = true;
+
7936 }
+
7937 }
7938}
7939
-
7940void Context::setObjectTransformationMatrix(uint ObjID, float (&T)[16] ) {
-
7941 getObjectPointer_private(ObjID)->setTransformationMatrix(T);
-
7942}
-
-
7943
-
-
7944void Context::setObjectTransformationMatrix(const std::vector<uint> &ObjIDs, float (&T)[16] ) {
-
7945 for( uint ObjID : ObjIDs){
-
7946 getObjectPointer_private(ObjID)->setTransformationMatrix(T);
-
7947 }
-
7948}
-
-
7949
-
-
7950bool Context::objectHasTexture( uint ObjID ) const{
-
7951 return getObjectPointer_private(ObjID)->hasTexture();
-
7952}
-
-
7953
-
-
7954void Context::setObjectColor(uint ObjID, const RGBcolor &color) {
-
7955 getObjectPointer_private(ObjID)->setColor( color );
-
7956}
-
-
7957
-
-
7958void Context::setObjectColor(const std::vector<uint> &ObjIDs, const RGBcolor &color) {
-
7959 for( uint ObjID : ObjIDs){
-
7960 getObjectPointer_private(ObjID)->setColor(color);
-
7961 }
-
7962}
-
-
7963
-
-
7964void Context::setObjectColor(uint ObjID, const RGBAcolor &color) {
-
7965 getObjectPointer_private(ObjID)->setColor( color );
-
7966}
-
-
7967
-
-
7968void Context::setObjectColor(const std::vector<uint> &ObjIDs, const RGBAcolor &color) {
-
7969 for( uint ObjID : ObjIDs){
-
7970 getObjectPointer_private(ObjID)->setColor(color);
-
7971 }
-
7972}
-
-
7973
-
-
7974bool Context::doesObjectContainPrimitive(uint ObjID, uint UUID ){
-
7975 return getObjectPointer_private(ObjID)->doesObjectContainPrimitive( UUID );
-
7976}
-
-
7977
-
- -
7979 getObjectPointer_private(ObjID)->overrideTextureColor();
-
7980}
-
-
7981
-
-
7982void Context::overrideObjectTextureColor( const std::vector<uint> &ObjIDs) {
-
7983 for( uint ObjID : ObjIDs ) {
-
7984 getObjectPointer_private(ObjID)->overrideTextureColor();
-
7985 }
-
7986}
-
-
7987
-
- -
7989 getObjectPointer_private(ObjID)->useTextureColor();
-
7990}
-
-
7991
-
-
7992void Context::useObjectTextureColor( const std::vector<uint> &ObjIDs) {
-
7993 for( uint ObjID : ObjIDs ) {
-
7994 getObjectPointer_private(ObjID)->useTextureColor();
-
7995 }
-
7996}
-
-
7997
-
-
7998void Context::getObjectBoundingBox( uint ObjID, vec3 &min_corner, vec3 &max_corner ) const {
-
7999 std::vector<uint> ObjIDs{ObjID};
-
8000 getObjectBoundingBox(ObjIDs,min_corner,max_corner);
-
8001}
-
-
8002
-
-
8003void Context::getObjectBoundingBox( const std::vector<uint> &ObjIDs, vec3 &min_corner, vec3 &max_corner ) const{
+
7940bool Context::isObjectHidden( uint ObjID ) const{
+
7941 if( !doesObjectExist(ObjID) ){
+
7942 helios_runtime_error("ERROR (Context::isObjectHidden): Object ID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
7943 }
+
7944 return objects.at(ObjID)->ishidden;
+
7945}
+
+
7946
+
+
7947float Context::getObjectArea(uint ObjID) const {
+
7948 return getObjectPointer_private(ObjID)->getArea();
+
7949}
+
+
7950
+
+
7951uint Context::getObjectPrimitiveCount(uint ObjID) const {
+
7952 return getObjectPointer_private(ObjID)->getPrimitiveCount();
+
7953}
+
+
7954
+
+ +
7956 return getObjectPointer_private(ObjID)->getObjectCenter();
+
7957}
+
+
7958
+
+
7959std::string Context::getObjectTextureFile(uint ObjID) const{
+
7960 return getObjectPointer_private(ObjID)->getTextureFile();
+
7961}
+
+
7962
+
+
7963void Context::getObjectTransformationMatrix(uint ObjID, float (&T)[16] ) const {
+
7964 getObjectPointer_private(ObjID)->getTransformationMatrix( T );
+
7965}
+
+
7966
+
+
7967void Context::setObjectTransformationMatrix(uint ObjID, float (&T)[16] ) {
+
7968 getObjectPointer_private(ObjID)->setTransformationMatrix(T);
+
7969}
+
+
7970
+
+
7971void Context::setObjectTransformationMatrix(const std::vector<uint> &ObjIDs, float (&T)[16] ) {
+
7972 for( uint ObjID : ObjIDs){
+
7973 getObjectPointer_private(ObjID)->setTransformationMatrix(T);
+
7974 }
+
7975}
+
+
7976
+
+
7977bool Context::objectHasTexture( uint ObjID ) const{
+
7978 return getObjectPointer_private(ObjID)->hasTexture();
+
7979}
+
+
7980
+
+
7981void Context::setObjectColor(uint ObjID, const RGBcolor &color) {
+
7982 getObjectPointer_private(ObjID)->setColor( color );
+
7983}
+
+
7984
+
+
7985void Context::setObjectColor(const std::vector<uint> &ObjIDs, const RGBcolor &color) {
+
7986 for( uint ObjID : ObjIDs){
+
7987 getObjectPointer_private(ObjID)->setColor(color);
+
7988 }
+
7989}
+
+
7990
+
+
7991void Context::setObjectColor(uint ObjID, const RGBAcolor &color) {
+
7992 getObjectPointer_private(ObjID)->setColor( color );
+
7993}
+
+
7994
+
+
7995void Context::setObjectColor(const std::vector<uint> &ObjIDs, const RGBAcolor &color) {
+
7996 for( uint ObjID : ObjIDs){
+
7997 getObjectPointer_private(ObjID)->setColor(color);
+
7998 }
+
7999}
+
+
8000
+
+
8001bool Context::doesObjectContainPrimitive(uint ObjID, uint UUID ){
+
8002 return getObjectPointer_private(ObjID)->doesObjectContainPrimitive( UUID );
+
8003}
+
8004
-
8005 uint o=0;
-
8006 for( uint ObjID : ObjIDs ) {
-
8007
-
8008 if ( objects.find(ObjID) == objects.end()){
-
8009 helios_runtime_error("ERROR (Context::getObjectBoundingBox): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8010 }
-
8011
-
8012 const std::vector<uint> &UUIDs = objects.at(ObjID)->getPrimitiveUUIDs();
-
8013
-
8014 uint p=0;
-
8015 for (uint UUID: UUIDs) {
-
8016
-
8017 const std::vector<vec3> &vertices = getPrimitiveVertices(UUID);
-
8018
-
8019 if( p==0 && o==0 ){
-
8020 min_corner = vertices.front();
-
8021 max_corner = min_corner;
-
8022 p++;
-
8023 continue;
-
8024 }
-
8025
-
8026 for (const vec3 &vert: vertices) {
-
8027 if (vert.x < min_corner.x) {
-
8028 min_corner.x = vert.x;
-
8029 }
-
8030 if (vert.y < min_corner.y) {
-
8031 min_corner.y = vert.y;
-
8032 }
-
8033 if (vert.z < min_corner.z) {
-
8034 min_corner.z = vert.z;
-
8035 }
-
8036 if (vert.x > max_corner.x) {
-
8037 max_corner.x = vert.x;
-
8038 }
-
8039 if (vert.y > max_corner.y) {
-
8040 max_corner.y = vert.y;
-
8041 }
-
8042 if (vert.z > max_corner.z) {
-
8043 max_corner.z = vert.z;
-
8044 }
-
8045 }
-
8046 }
-
8047
-
8048 o++;
-
8049 }
-
8050
-
8051}
+
+ +
8006 getObjectPointer_private(ObjID)->overrideTextureColor();
+
8007}
+
+
8008
+
+
8009void Context::overrideObjectTextureColor( const std::vector<uint> &ObjIDs) {
+
8010 for( uint ObjID : ObjIDs ) {
+
8011 getObjectPointer_private(ObjID)->overrideTextureColor();
+
8012 }
+
8013}
+
+
8014
+
+ +
8016 getObjectPointer_private(ObjID)->useTextureColor();
+
8017}
+
8018
+
+
8019void Context::useObjectTextureColor( const std::vector<uint> &ObjIDs) {
+
8020 for( uint ObjID : ObjIDs ) {
+
8021 getObjectPointer_private(ObjID)->useTextureColor();
+
8022 }
+
8023}
+
+
8024
+
+
8025void Context::getObjectBoundingBox( uint ObjID, vec3 &min_corner, vec3 &max_corner ) const {
+
8026 std::vector<uint> ObjIDs{ObjID};
+
8027 getObjectBoundingBox(ObjIDs,min_corner,max_corner);
+
8028}
+
+
8029
+
+
8030void Context::getObjectBoundingBox( const std::vector<uint> &ObjIDs, vec3 &min_corner, vec3 &max_corner ) const{
+
8031
+
8032 uint o=0;
+
8033 for( uint ObjID : ObjIDs ) {
+
8034
+
8035 if ( objects.find(ObjID) == objects.end()){
+
8036 helios_runtime_error("ERROR (Context::getObjectBoundingBox): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8037 }
+
8038
+
8039 const std::vector<uint> &UUIDs = objects.at(ObjID)->getPrimitiveUUIDs();
+
8040
+
8041 uint p=0;
+
8042 for (uint UUID: UUIDs) {
+
8043
+
8044 const std::vector<vec3> &vertices = getPrimitiveVertices(UUID);
+
8045
+
8046 if( p==0 && o==0 ){
+
8047 min_corner = vertices.front();
+
8048 max_corner = min_corner;
+
8049 p++;
+
8050 continue;
+
8051 }
8052
-
8053Tile* Context::getTileObjectPointer_private(uint ObjID ) const{
-
8054 if( objects.find(ObjID) == objects.end() ){
-
8055 helios_runtime_error("ERROR (Context::getTileObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8056 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_TILE ){
-
8057 helios_runtime_error("ERROR (Context::getTileObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Tile Object.");
-
8058 }
-
8059 return dynamic_cast<Tile*>(objects.at(ObjID));
-
8060}
-
8061
-
8062Sphere* Context::getSphereObjectPointer_private(uint ObjID ) const{
-
8063 if( objects.find(ObjID) == objects.end() ){
-
8064 helios_runtime_error("ERROR (Context::getSphereObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8065 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_SPHERE ){
-
8066 helios_runtime_error("ERROR (Context::getSphereObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Sphere Object.");
-
8067 }
-
8068 return dynamic_cast<Sphere*>(objects.at(ObjID));
-
8069}
-
8070
-
8071Tube* Context::getTubeObjectPointer_private(uint ObjID ) const{
-
8072 if( objects.find(ObjID) == objects.end() ){
-
8073 helios_runtime_error("ERROR (Context::getTubeObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8074 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_TUBE ){
-
8075 helios_runtime_error("ERROR (Context::getTubeObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Tube Object.");
+
8053 for (const vec3 &vert: vertices) {
+
8054 if (vert.x < min_corner.x) {
+
8055 min_corner.x = vert.x;
+
8056 }
+
8057 if (vert.y < min_corner.y) {
+
8058 min_corner.y = vert.y;
+
8059 }
+
8060 if (vert.z < min_corner.z) {
+
8061 min_corner.z = vert.z;
+
8062 }
+
8063 if (vert.x > max_corner.x) {
+
8064 max_corner.x = vert.x;
+
8065 }
+
8066 if (vert.y > max_corner.y) {
+
8067 max_corner.y = vert.y;
+
8068 }
+
8069 if (vert.z > max_corner.z) {
+
8070 max_corner.z = vert.z;
+
8071 }
+
8072 }
+
8073 }
+
8074
+
8075 o++;
8076 }
-
8077 return dynamic_cast<Tube*>(objects.at(ObjID));
+
8077
8078}
+
8079
-
8080Box* Context::getBoxObjectPointer_private(uint ObjID ) const{
+
8080Tile* Context::getTileObjectPointer_private(uint ObjID ) const{
8081 if( objects.find(ObjID) == objects.end() ){
-
8082 helios_runtime_error("ERROR (Context::getBoxObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8083 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_BOX ){
-
8084 helios_runtime_error("ERROR (Context::getBoxObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Box Object.");
+
8082 helios_runtime_error("ERROR (Context::getTileObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8083 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_TILE ){
+
8084 helios_runtime_error("ERROR (Context::getTileObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Tile Object.");
8085 }
-
8086 return dynamic_cast<Box*>(objects.at(ObjID));
+
8086 return dynamic_cast<Tile*>(objects.at(ObjID));
8087}
8088
-
8089Disk* Context::getDiskObjectPointer_private(uint ObjID ) const{
+
8089Sphere* Context::getSphereObjectPointer_private(uint ObjID ) const{
8090 if( objects.find(ObjID) == objects.end() ){
-
8091 helios_runtime_error("ERROR (Context::getDiskObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8092 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_DISK ){
-
8093 helios_runtime_error("ERROR (Context::getDiskObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Disk Object.");
+
8091 helios_runtime_error("ERROR (Context::getSphereObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8092 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_SPHERE ){
+
8093 helios_runtime_error("ERROR (Context::getSphereObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Sphere Object.");
8094 }
-
8095 return dynamic_cast<Disk*>(objects.at(ObjID));
+
8095 return dynamic_cast<Sphere*>(objects.at(ObjID));
8096}
8097
-
8098Polymesh* Context::getPolymeshObjectPointer_private(uint ObjID ) const{
+
8098Tube* Context::getTubeObjectPointer_private(uint ObjID ) const{
8099 if( objects.find(ObjID) == objects.end() ){
-
8100 helios_runtime_error("ERROR (Context::getPolymeshObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8101 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_POLYMESH ){
-
8102 helios_runtime_error("ERROR (Context::getPolymeshObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Polymesh Object.");
+
8100 helios_runtime_error("ERROR (Context::getTubeObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8101 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_TUBE ){
+
8102 helios_runtime_error("ERROR (Context::getTubeObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Tube Object.");
8103 }
-
8104 return dynamic_cast<Polymesh*>(objects.at(ObjID));
+
8104 return dynamic_cast<Tube*>(objects.at(ObjID));
8105}
8106
-
8107Cone* Context::getConeObjectPointer_private(uint ObjID ) const{
+
8107Box* Context::getBoxObjectPointer_private(uint ObjID ) const{
8108 if( objects.find(ObjID) == objects.end() ){
-
8109 helios_runtime_error("ERROR (Context::getConeObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8110 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_CONE ){
-
8111 helios_runtime_error("ERROR (Context::getConeObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Cone Object.");
+
8109 helios_runtime_error("ERROR (Context::getBoxObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8110 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_BOX ){
+
8111 helios_runtime_error("ERROR (Context::getBoxObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Box Object.");
8112 }
-
8113 return dynamic_cast<Cone*>(objects.at(ObjID));
+
8113 return dynamic_cast<Box*>(objects.at(ObjID));
8114}
8115
-
- -
8117 return getTileObjectPointer_private(ObjID)->getCenter();
-
8118}
-
-
8119
-
- -
8121 return getTileObjectPointer_private(ObjID)->getSize();
-
8122}
-
-
8123
-
- -
8125 return getTileObjectPointer_private(ObjID)->getSubdivisionCount();
-
8126}
-
-
8127
-
- -
8129 return getTileObjectPointer_private(ObjID)->getNormal();
-
8130}
-
-
8131
-
-
8132std::vector<helios::vec2> Context::getTileObjectTextureUV(uint ObjID) const {
-
8133 return getTileObjectPointer_private(ObjID)->getTextureUV();
-
8134}
-
-
8135
-
-
8136std::vector<helios::vec3> Context::getTileObjectVertices(uint ObjID) const {
-
8137 return getTileObjectPointer_private(ObjID)->getVertices();
-
8138}
-
-
8139
-
- -
8141 return getSphereObjectPointer_private(ObjID)->getCenter();
-
8142}
-
-
8143
-
- -
8145 return getSphereObjectPointer_private(ObjID)->getRadius();
-
8146}
-
-
8147
-
- -
8149 return getSphereObjectPointer_private(ObjID)->getSubdivisionCount();
-
8150}
-
-
8151
-
-
8152float Context::getSphereObjectVolume(uint ObjID) const {
-
8153 return getSphereObjectPointer_private(ObjID)->getVolume();
-
8154}
-
-
8155
-
- -
8157 return getTubeObjectPointer_private(ObjID)->getSubdivisionCount();
-
8158}
-
-
8159
-
-
8160std::vector<helios::vec3> Context::getTubeObjectNodes(uint ObjID) const {
-
8161 return getTubeObjectPointer_private(ObjID)->getNodes();
-
8162}
-
-
8163
-
-
8164std::vector<float> Context::getTubeObjectNodeRadii(uint ObjID) const {
-
8165 return getTubeObjectPointer_private(ObjID)->getNodeRadii();
-
8166}
-
-
8167
-
-
8168std::vector<RGBcolor> Context::getTubeObjectNodeColors(uint ObjID) const {
-
8169 return getTubeObjectPointer_private(ObjID)->getNodeColors();
-
8170}
-
-
8171
-
-
8172float Context::getTubeObjectVolume(uint ObjID) const {
-
8173 return getTubeObjectPointer_private(ObjID)->getVolume();
-
8174}
-
-
8175
-
-
8176float Context::getTubeObjectSegmentVolume( uint ObjID, uint segment_index ) const{
-
8177 return getTubeObjectPointer_private(ObjID)->getSegmentVolume(segment_index);
-
8178}
-
-
8179
-
-
8180void Context::appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float node_radius, const RGBcolor &node_color ){
-
8181 if( objects.find(ObjID) == objects.end() ) {
-
8182 helios_runtime_error("ERROR (Context::appendTubeSegment): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8183 }
-
8184 dynamic_cast<Tube*>(objects.at(ObjID))->appendTubeSegment(node_position, node_radius, node_color);
+
8116Disk* Context::getDiskObjectPointer_private(uint ObjID ) const{
+
8117 if( objects.find(ObjID) == objects.end() ){
+
8118 helios_runtime_error("ERROR (Context::getDiskObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8119 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_DISK ){
+
8120 helios_runtime_error("ERROR (Context::getDiskObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Disk Object.");
+
8121 }
+
8122 return dynamic_cast<Disk*>(objects.at(ObjID));
+
8123}
+
8124
+
8125Polymesh* Context::getPolymeshObjectPointer_private(uint ObjID ) const{
+
8126 if( objects.find(ObjID) == objects.end() ){
+
8127 helios_runtime_error("ERROR (Context::getPolymeshObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8128 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_POLYMESH ){
+
8129 helios_runtime_error("ERROR (Context::getPolymeshObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Polymesh Object.");
+
8130 }
+
8131 return dynamic_cast<Polymesh*>(objects.at(ObjID));
+
8132}
+
8133
+
8134Cone* Context::getConeObjectPointer_private(uint ObjID ) const{
+
8135 if( objects.find(ObjID) == objects.end() ){
+
8136 helios_runtime_error("ERROR (Context::getConeObjectPointer): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8137 }else if( objects.at(ObjID)->getObjectType()!=OBJECT_TYPE_CONE ){
+
8138 helios_runtime_error("ERROR (Context::getConeObjectPointer): ObjectID of " + std::to_string(ObjID) + " is not a Cone Object.");
+
8139 }
+
8140 return dynamic_cast<Cone*>(objects.at(ObjID));
+
8141}
+
8142
+
+ +
8144 return getTileObjectPointer_private(ObjID)->getCenter();
+
8145}
+
+
8146
+
+ +
8148 return getTileObjectPointer_private(ObjID)->getSize();
+
8149}
+
+
8150
+
+ +
8152 return getTileObjectPointer_private(ObjID)->getSubdivisionCount();
+
8153}
+
+
8154
+
+ +
8156 return getTileObjectPointer_private(ObjID)->getNormal();
+
8157}
+
+
8158
+
+
8159std::vector<helios::vec2> Context::getTileObjectTextureUV(uint ObjID) const {
+
8160 return getTileObjectPointer_private(ObjID)->getTextureUV();
+
8161}
+
+
8162
+
+
8163std::vector<helios::vec3> Context::getTileObjectVertices(uint ObjID) const {
+
8164 return getTileObjectPointer_private(ObjID)->getVertices();
+
8165}
+
+
8166
+
+ +
8168 return getSphereObjectPointer_private(ObjID)->getCenter();
+
8169}
+
+
8170
+
+ +
8172 return getSphereObjectPointer_private(ObjID)->getRadius();
+
8173}
+
+
8174
+
+ +
8176 return getSphereObjectPointer_private(ObjID)->getSubdivisionCount();
+
8177}
+
+
8178
+
+
8179float Context::getSphereObjectVolume(uint ObjID) const {
+
8180 return getSphereObjectPointer_private(ObjID)->getVolume();
+
8181}
+
+
8182
+
+ +
8184 return getTubeObjectPointer_private(ObjID)->getSubdivisionCount();
8185}
8186
-
8187void Context::appendTubeSegment( uint ObjID, const helios::vec3 &node_position, float node_radius, const char* texturefile, const helios::vec2 &textureuv_ufrac ){
-
8188 if( objects.find(ObjID) == objects.end() ) {
-
8189 helios_runtime_error("ERROR (Context::appendTubeSegment): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8190 }
-
8191 dynamic_cast<Tube*>(objects.at(ObjID))->appendTubeSegment(node_position, node_radius, texturefile, textureuv_ufrac);
-
8192}
-
-
8193
-
-
8194void Context::scaleTubeGirth( uint ObjID, float scale_factor ){
-
8195 if( objects.find(ObjID) == objects.end() ) {
-
8196 helios_runtime_error("ERROR (Context::scaleTubeGirth): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8197 }
-
8198 dynamic_cast<Tube*>(objects.at(ObjID))->scaleTubeGirth(scale_factor);
-
8199}
-
-
8200
-
-
8201void Context::setTubeRadii( uint ObjID, const std::vector<float> &node_radii ){
-
8202 if( objects.find(ObjID) == objects.end() ) {
-
8203 helios_runtime_error("ERROR (Context::setTubeRadii): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8204 }
-
8205 dynamic_cast<Tube*>(objects.at(ObjID))->setTubeRadii(node_radii);
-
8206}
-
-
8207
-
-
8208void Context::scaleTubeLength( uint ObjID, float scale_factor ){
-
8209 if( objects.find(ObjID) == objects.end() ) {
-
8210 helios_runtime_error("ERROR (Context::scaleTubeLength): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8211 }
-
8212 dynamic_cast<Tube*>(objects.at(ObjID))->scaleTubeLength(scale_factor);
-
8213}
-
-
8214
-
-
8215void Context::setTubeNodes( uint ObjID, const std::vector<helios::vec3> &node_xyz ){
-
8216 if( objects.find(ObjID) == objects.end() ) {
-
8217 helios_runtime_error("ERROR (Context::setTubeNodes): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
-
8218 }
-
8219 dynamic_cast<Tube*>(objects.at(ObjID))->setTubeNodes(node_xyz);
-
8220}
-
-
8221
-
- -
8223 return getBoxObjectPointer_private(ObjID)->getCenter();
-
8224}
-
-
8225
-
- -
8227 return getBoxObjectPointer_private(ObjID)->getSize();
-
8228}
-
-
8229
-
- -
8231 return getBoxObjectPointer_private(ObjID)->getSubdivisionCount();
-
8232}
-
-
8233
-
-
8234float Context::getBoxObjectVolume(uint ObjID) const {
-
8235 return getBoxObjectPointer_private(ObjID)->getVolume();
-
8236}
-
-
8237
-
- -
8239 return getDiskObjectPointer_private(ObjID)->getCenter();
+
8187std::vector<helios::vec3> Context::getTubeObjectNodes(uint ObjID) const {
+
8188 return getTubeObjectPointer_private(ObjID)->getNodes();
+
8189}
+
+
8190
+
+
8191std::vector<float> Context::getTubeObjectNodeRadii(uint ObjID) const {
+
8192 return getTubeObjectPointer_private(ObjID)->getNodeRadii();
+
8193}
+
+
8194
+
+
8195std::vector<RGBcolor> Context::getTubeObjectNodeColors(uint ObjID) const {
+
8196 return getTubeObjectPointer_private(ObjID)->getNodeColors();
+
8197}
+
+
8198
+
+
8199float Context::getTubeObjectVolume(uint ObjID) const {
+
8200 return getTubeObjectPointer_private(ObjID)->getVolume();
+
8201}
+
+
8202
+
+
8203float Context::getTubeObjectSegmentVolume( uint ObjID, uint segment_index ) const{
+
8204 return getTubeObjectPointer_private(ObjID)->getSegmentVolume(segment_index);
+
8205}
+
+
8206
+
+
8207void Context::appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float node_radius, const RGBcolor &node_color ){
+
8208 if( objects.find(ObjID) == objects.end() ) {
+
8209 helios_runtime_error("ERROR (Context::appendTubeSegment): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8210 }
+
8211 dynamic_cast<Tube*>(objects.at(ObjID))->appendTubeSegment(node_position, node_radius, node_color);
+
8212}
+
+
8213
+
+
8214void Context::appendTubeSegment( uint ObjID, const helios::vec3 &node_position, float node_radius, const char* texturefile, const helios::vec2 &textureuv_ufrac ){
+
8215 if( objects.find(ObjID) == objects.end() ) {
+
8216 helios_runtime_error("ERROR (Context::appendTubeSegment): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8217 }
+
8218 dynamic_cast<Tube*>(objects.at(ObjID))->appendTubeSegment(node_position, node_radius, texturefile, textureuv_ufrac);
+
8219}
+
+
8220
+
+
8221void Context::scaleTubeGirth( uint ObjID, float scale_factor ){
+
8222 if( objects.find(ObjID) == objects.end() ) {
+
8223 helios_runtime_error("ERROR (Context::scaleTubeGirth): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8224 }
+
8225 dynamic_cast<Tube*>(objects.at(ObjID))->scaleTubeGirth(scale_factor);
+
8226}
+
+
8227
+
+
8228void Context::setTubeRadii( uint ObjID, const std::vector<float> &node_radii ){
+
8229 if( objects.find(ObjID) == objects.end() ) {
+
8230 helios_runtime_error("ERROR (Context::setTubeRadii): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8231 }
+
8232 dynamic_cast<Tube*>(objects.at(ObjID))->setTubeRadii(node_radii);
+
8233}
+
+
8234
+
+
8235void Context::scaleTubeLength( uint ObjID, float scale_factor ){
+
8236 if( objects.find(ObjID) == objects.end() ) {
+
8237 helios_runtime_error("ERROR (Context::scaleTubeLength): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8238 }
+
8239 dynamic_cast<Tube*>(objects.at(ObjID))->scaleTubeLength(scale_factor);
8240}
8241
- -
8243 return getDiskObjectPointer_private(ObjID)->getSize();
-
8244}
-
-
8245
-
- -
8247 return getDiskObjectPointer_private(ObjID)->getSubdivisionCount().x;
-
8248}
-
-
8249
-
- -
8251 return getConeObjectPointer_private(ObjID)->getSubdivisionCount();
-
8252}
-
-
8253
-
-
8254std::vector<helios::vec3> Context::getConeObjectNodes(uint ObjID) const {
-
8255 return getConeObjectPointer_private(ObjID)->getNodeCoordinates();
-
8256}
-
-
8257
-
-
8258std::vector<float> Context::getConeObjectNodeRadii(uint ObjID) const {
-
8259 return getConeObjectPointer_private(ObjID)->getNodeRadii();
-
8260}
-
-
8261
-
-
8262helios::vec3 Context::getConeObjectNode(uint ObjID, int number) const {
-
8263 return getConeObjectPointer_private(ObjID)->getNodeCoordinate(number);
-
8264}
-
-
8265
-
-
8266float Context::getConeObjectNodeRadius(uint ObjID, int number) const {
-
8267 return getConeObjectPointer_private(ObjID)->getNodeRadius(number);
-
8268}
-
-
8269
-
- -
8271 return getConeObjectPointer_private(ObjID)->getAxisUnitVector();
-
8272}
-
-
8273
-
-
8274float Context::getConeObjectLength(uint ObjID) const {
-
8275 return getConeObjectPointer_private(ObjID)->getLength();
-
8276}
-
-
8277
-
-
8278float Context::getConeObjectVolume(uint ObjID) const {
-
8279 return getConeObjectPointer_private(ObjID)->getVolume();
-
8280}
-
-
8281
-
-
8282float Context::getPolymeshObjectVolume(uint ObjID) const {
-
8283 return getPolymeshObjectPointer_private(ObjID)->getVolume();
-
8284}
+
8242void 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
+
+
8249void Context::setTubeNodes( uint ObjID, const std::vector<helios::vec3> &node_xyz ){
+
8250 if( objects.find(ObjID) == objects.end() ) {
+
8251 helios_runtime_error("ERROR (Context::setTubeNodes): ObjectID of " + std::to_string(ObjID) + " does not exist in the Context.");
+
8252 }
+
8253 dynamic_cast<Tube*>(objects.at(ObjID))->setTubeNodes(node_xyz);
+
8254}
+
+
8255
+
+ +
8257 return getBoxObjectPointer_private(ObjID)->getCenter();
+
8258}
+
+
8259
+
+ +
8261 return getBoxObjectPointer_private(ObjID)->getSize();
+
8262}
+
+
8263
+
+ +
8265 return getBoxObjectPointer_private(ObjID)->getSubdivisionCount();
+
8266}
+
+
8267
+
+
8268float Context::getBoxObjectVolume(uint ObjID) const {
+
8269 return getBoxObjectPointer_private(ObjID)->getVolume();
+
8270}
+
+
8271
+
+ +
8273 return getDiskObjectPointer_private(ObjID)->getCenter();
+
8274}
+
+
8275
+
+ +
8277 return getDiskObjectPointer_private(ObjID)->getSize();
+
8278}
+
+
8279
+
+ +
8281 return getDiskObjectPointer_private(ObjID)->getSubdivisionCount().x;
+
8282}
+
+
8283
+
+ +
8285 return getConeObjectPointer_private(ObjID)->getSubdivisionCount();
+
8286}
+
+
8287
+
+
8288std::vector<helios::vec3> Context::getConeObjectNodes(uint ObjID) const {
+
8289 return getConeObjectPointer_private(ObjID)->getNodeCoordinates();
+
8290}
+
+
8291
+
+
8292std::vector<float> Context::getConeObjectNodeRadii(uint ObjID) const {
+
8293 return getConeObjectPointer_private(ObjID)->getNodeRadii();
+
8294}
+
+
8295
+
+
8296helios::vec3 Context::getConeObjectNode(uint ObjID, int number) const {
+
8297 return getConeObjectPointer_private(ObjID)->getNodeCoordinate(number);
+
8298}
+
+
8299
+
+
8300float Context::getConeObjectNodeRadius(uint ObjID, int number) const {
+
8301 return getConeObjectPointer_private(ObjID)->getNodeRadius(number);
+
8302}
+
+
8303
+
+ +
8305 return getConeObjectPointer_private(ObjID)->getAxisUnitVector();
+
8306}
+
+
8307
+
+
8308float Context::getConeObjectLength(uint ObjID) const {
+
8309 return getConeObjectPointer_private(ObjID)->getLength();
+
8310}
+
+
8311
+
+
8312float Context::getConeObjectVolume(uint ObjID) const {
+
8313 return getConeObjectPointer_private(ObjID)->getVolume();
+
8314}
+
+
8315
+
+
8316float Context::getPolymeshObjectVolume(uint ObjID) const {
+
8317 return getPolymeshObjectPointer_private(ObjID)->getVolume();
+
8318}
HeliosDataType
Data types.
Definition Context.h:41
@@ -9125,7 +9170,7 @@
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
PrimitiveType
Type of primitive element.
Definition Context.h:31
@ PRIMITIVE_TYPE_PATCH
< Rectangular primitive
Definition Context.h:33
-
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
+
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
@ PRIMITIVE_TYPE_TRIANGLE
< Triangular primitive
Definition Context.h:35
ObjectType
Type of compound object.
Definition Context.h:128
@ OBJECT_TYPE_BOX
Box.
Definition Context.h:136
@@ -9135,13 +9180,13 @@
@ OBJECT_TYPE_DISK
< Disk
Definition Context.h:138
@ OBJECT_TYPE_TILE
< Tile
Definition Context.h:130
@ OBJECT_TYPE_SPHERE
< Sphere
Definition Context.h:132
-
Box compound object class.
Definition Context.h:759
-
float getVolume() const
Get the volume of the box object.
Definition Context.cpp:4004
-
void setSubdivisionCount(const helios::int3 &subdiv)
Set the number of box sub-patch divisions.
Definition Context.cpp:4000
-
helios::int3 getSubdivisionCount() const
Get the number of sub-patch divisions of the box object in each Cartesian direction.
Definition Context.cpp:3996
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the box object.
Definition Context.cpp:3980
-
Box(uint a_OID, const std::vector< uint > &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:3941
-
vec3 getSize() const
Get the dimensions of the box object in each Cartesian direction.
Definition Context.cpp:3961
+
Box compound object class.
Definition Context.h:765
+
float getVolume() const
Get the volume of the box object.
Definition Context.cpp:4031
+
void setSubdivisionCount(const helios::int3 &subdiv)
Set the number of box sub-patch divisions.
Definition Context.cpp:4027
+
helios::int3 getSubdivisionCount() const
Get the number of sub-patch divisions of the box object in each Cartesian direction.
Definition Context.cpp:4023
+
vec3 getCenter() const
Get the Cartesian coordinates of the center of the box object.
Definition Context.cpp:4007
+
Box(uint a_OID, const std::vector< uint > &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:3968
+
vec3 getSize() const
Get the dimensions of the box object in each Cartesian direction.
Definition Context.cpp:3988
void rotate(float rotation_radians, const char *rotation_axis_xyz_string)
Method to rotate a Compound Object about the x-, y-, or z-axis.
Definition Context.cpp:2377
void setPrimitiveUUIDs(const std::vector< uint > &UUIDs)
Method to set the UUIDs of object child primitives.
Definition Context.cpp:2517
@@ -9165,185 +9210,186 @@
void useTextureColor()
For all primitives in the Compound Object, use the texture map to color the primitives rather than th...
Definition Context.cpp:2331
bool doesObjectContainPrimitive(uint UUID)
Check whether a primitive is a member of the object based on its UUID.
Definition Context.cpp:2262
helios::vec3 getObjectCenter() const
Calculate the Cartesian (x,y,z) point of the center of a bounding box for the Compound Object.
Definition Context.cpp:2268
-
Cone compound object class.
Definition Context.h:847
-
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the cone object.
Definition Context.cpp:4171
-
Cone(uint a_OID, const std::vector< uint > &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0, float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4107
-
float getNodeRadius(int node_index) const
Get the radius of a cone object node.
Definition Context.cpp:4163
-
void setSubdivisionCount(uint subdiv)
Set the number of radial sub-triangle divisions.
Definition Context.cpp:4175
-
helios::vec3 getNodeCoordinate(int node_index) const
Get the Cartesian coordinates of a cone object node.
Definition Context.cpp:4144
-
helios::vec3 getAxisUnitVector() const
Get a unit vector pointing in the direction of the cone central axis.
Definition Context.cpp:4179
-
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4130
-
void scaleLength(float S)
Method to scale the length of the cone.
Definition Context.cpp:4212
-
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition Context.cpp:4261
-
float getLength() const
Get the length of the cone along the axial direction.
Definition Context.cpp:4197
-
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4159
-
float getVolume() const
Get the volume of the cone object.
Definition Context.cpp:4302
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Cone compound object class.
Definition Context.h:853
+
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the cone object.
Definition Context.cpp:4198
+
Cone(uint a_OID, const std::vector< uint > &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0, float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4134
+
float getNodeRadius(int node_index) const
Get the radius of a cone object node.
Definition Context.cpp:4190
+
void setSubdivisionCount(uint subdiv)
Set the number of radial sub-triangle divisions.
Definition Context.cpp:4202
+
helios::vec3 getNodeCoordinate(int node_index) const
Get the Cartesian coordinates of a cone object node.
Definition Context.cpp:4171
+
helios::vec3 getAxisUnitVector() const
Get a unit vector pointing in the direction of the cone central axis.
Definition Context.cpp:4206
+
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4157
+
void scaleLength(float S)
Method to scale the length of the cone.
Definition Context.cpp:4239
+
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition Context.cpp:4288
+
float getLength() const
Get the length of the cone along the axial direction.
Definition Context.cpp:4224
+
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4186
+
float getVolume() const
Get the volume of the cone object.
Definition Context.cpp:4329
+
Stores the state associated with simulation.
Definition Context.h:1888
void copyPrimitiveData(uint sourceUUID, uint destinationUUID)
copy all primitive data from one primitive to another
-
std::vector< helios::vec2 > getTileObjectTextureUV(uint ObjID) const
get the texture UV coordinates of a tile object from the context
Definition Context.cpp:8132
+
std::vector< helios::vec2 > getTileObjectTextureUV(uint ObjID) const
get the texture UV coordinates of a tile object from the context
Definition Context.cpp:8159
void setTileObjectSubdivisionCount(const std::vector< uint > &ObjectIDs, const int2 &new_subdiv)
Change the subdivision count of a tile object.
Definition Context.cpp:2982
-
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7139
-
void getPrimitiveTransformationMatrix(uint UUID, float(&T)[16]) const
Method to return the Affine transformation matrix of a Primitive.
Definition Context.cpp:7108
-
void scaleTubeLength(uint ObjID, float scale_factor)
Scale the length of a tube object by an arbitrary factor for all tube nodes.
Definition Context.cpp:8208
-
bool isObjectHidden(uint ObjID) const
Query if an object is hidden.
Definition Context.cpp:7913
+
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7166
+
void getPrimitiveTransformationMatrix(uint UUID, float(&T)[16]) const
Method to return the Affine transformation matrix of a Primitive.
Definition Context.cpp:7135
+
void scaleTubeLength(uint ObjID, float scale_factor)
Scale the length of a tube object by an arbitrary factor for all tube nodes.
Definition Context.cpp:8235
+
bool isObjectHidden(uint ObjID) const
Query if an object is hidden.
Definition Context.cpp:7940
std::vector< std::string > listTimeseriesVariables() const
List all existing timeseries variables.
Definition Context.cpp:2036
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:2897
-
float getTubeObjectSegmentVolume(uint ObjID, uint segment_index) const
get the volume of a segment within a Tube object
Definition Context.cpp:8176
-
helios::RGBcolor getPrimitiveColor(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7127
+
float getTubeObjectSegmentVolume(uint ObjID, uint segment_index) const
get the volume of a segment within a Tube object
Definition Context.cpp:8203
+
helios::RGBcolor getPrimitiveColor(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7154
uint copyObject(uint ObjID)
Make a copy of a Compound Objects from the context.
Definition Context.cpp:2642
float randn()
Draw a random number from a normal distribution with mean = 0, stddev = 1.
Definition Context.cpp:1204
-
Disk * getDiskObjectPointer(uint ObjID) const
Get a pointer to a Disk Compound Object.
Definition Context.cpp:4022
-
void overrideObjectTextureColor(uint ObjID)
Override the color in the texture map for all primitives in the Compound Object, in which case the pr...
Definition Context.cpp:7978
-
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:7022
+
Disk * getDiskObjectPointer(uint ObjID) const
Get a pointer to a Disk Compound Object.
Definition Context.cpp:4049
+
void overrideObjectTextureColor(uint ObjID)
Override the color in the texture map for all primitives in the Compound Object, in which case the pr...
Definition Context.cpp:8005
+
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:7049
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
void getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single object.
Definition Context.cpp:7998
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
-
Box * getBoxObjectPointer(uint ObjID) const
Get a pointer to a Box Compound Object.
Definition Context.cpp:3954
+
void getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single object.
Definition Context.cpp:8025
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
+
Box * getBoxObjectPointer(uint ObjID) const
Get a pointer to a Box Compound Object.
Definition Context.cpp:3981
void cleanDeletedUUIDs(std::vector< uint > &UUIDs) const
Delete UUIDs from vector if primitives no longer exist (1D vector)
Definition Context.cpp:1793
-
uint getConeObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Cone object from the context
Definition Context.cpp:8250
-
helios::vec3 getDiskObjectCenter(uint ObjID) const
get the center of a Disk object from the context
Definition Context.cpp:8238
+
uint getConeObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Cone object from the context
Definition Context.cpp:8284
+
helios::vec3 getDiskObjectCenter(uint ObjID) const
get the center of a Disk object from the context
Definition Context.cpp:8272
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
int getJulianDate() const
Get simulation date by Julian day.
Definition Context.cpp:1132
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
-
helios::int3 getBoxObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Box object from the context
Definition Context.cpp:8230
-
uint getTubeObjectSubdivisionCount(uint ObjectID) const
get the subdivision count of a Tube object from the context
Definition Context.cpp:8156
-
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
-
~Context()
Context destructor.
Definition Context.cpp:6970
-
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7017
+
helios::int3 getBoxObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Box object from the context
Definition Context.cpp:8264
+
uint getTubeObjectSubdivisionCount(uint ObjectID) const
get the subdivision count of a Tube object from the context
Definition Context.cpp:8183
+
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
+
~Context()
Context destructor.
Definition Context.cpp:6997
+
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7044
std::vector< uint > getAllObjectIDs() const
Get the IDs for all Compound Objects in the Context.
Definition Context.cpp:2589
-
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4123
+
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4150
void seedRandomGenerator(uint seed)
Set seed for random generator.
Definition Context.cpp:45
void getObjectData(uint objID, const char *label, int &data) const
Get data associated with a compound object.
-
void printPrimitiveInfo(uint UUID) const
Prints primitive properties to console (useful for debugging purposes)
Definition Context.cpp:7225
+
void printPrimitiveInfo(uint UUID) const
Prints primitive properties to console (useful for debugging purposes)
Definition Context.cpp:7252
void markGeometryClean()
Mark the Context geometry as "clean", meaning that the geometry has not been modified since last set ...
Definition Context.cpp:149
void getDomainBoundingSphere(helios::vec3 &center, float &radius) const
Get the center and radius of a sphere that bounds all primitives in the domain.
Definition Context.cpp:2116
void rotateObject(uint ObjID, float rotation_radians, const char *rotation_axis_xyz)
Rotate a single compound object about the x, y, or z axis.
Definition Context.cpp:2847
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
helios::vec3 getPatchCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a patch element.
Definition Context.cpp:1693
-
helios::vec2 getTileObjectSize(uint ObjID) const
get the size of a tile object from the context
Definition Context.cpp:8120
-
uint getObjectPrimitiveCount(uint ObjID) const
Method to return the number of primitives contained in the object.
Definition Context.cpp:7924
+
helios::vec2 getTileObjectSize(uint ObjID) const
get the size of a tile object from the context
Definition Context.cpp:8147
+
uint getObjectPrimitiveCount(uint ObjID) const
Method to return the number of primitives contained in the object.
Definition Context.cpp:7951
uint getPrimitiveDataSize(uint UUID, const char *label) const
Get the size/length of primitive data.
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
-
helios::RGBAcolor getPrimitiveColorRGBA(uint UUID) const
Method to return the diffuse color of a Primitive with transparency.
Definition Context.cpp:7135
-
helios::vec3 getBoxObjectSize(uint ObjID) const
get the size of a Box object from the context
Definition Context.cpp:8226
-
helios::vec3 getSphereObjectCenter(uint ObjID) const
get the center of a Sphere object from the context
Definition Context.cpp:8140
-
helios::vec3 getObjectCenter(uint ObjID) const
Method to return the Cartesian (x,y,z) point of the center of a bounding box for the object.
Definition Context.cpp:7928
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7159
+
helios::RGBAcolor getPrimitiveColorRGBA(uint UUID) const
Method to return the diffuse color of a Primitive with transparency.
Definition Context.cpp:7162
+
helios::vec3 getBoxObjectSize(uint ObjID) const
get the size of a Box object from the context
Definition Context.cpp:8260
+
helios::vec3 getSphereObjectCenter(uint ObjID) const
get the center of a Sphere object from the context
Definition Context.cpp:8167
+
helios::vec3 getObjectCenter(uint ObjID) const
Method to return the Cartesian (x,y,z) point of the center of a bounding box for the object.
Definition Context.cpp:7955
+
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7186
uint getObjectCount() const
Get the total number of objects that have been created in the Context.
Definition Context.cpp:2581
-
helios::vec3 getConeObjectNode(uint ObjID, int number) const
get a node of a Cone object from the context
Definition Context.cpp:8262
-
float getTubeObjectVolume(uint ObjID) const
get the volume of a Tube object from the context
Definition Context.cpp:8172
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7175
+
helios::vec3 getConeObjectNode(uint ObjID, int number) const
get a node of a Cone object from the context
Definition Context.cpp:8296
+
float getTubeObjectVolume(uint ObjID) const
get the volume of a Tube object from the context
Definition Context.cpp:8199
+
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7202
void cropDomainZ(const vec2 &zbounds)
Crop the domain in the z-direction such that all primitives lie within some specified z interval.
Definition Context.cpp:2190
-
Polymesh * getPolymeshObjectPointer(uint ObjID) const
Get a pointer to a Polygon Mesh Compound Object.
Definition Context.cpp:4081
+
Polymesh * getPolymeshObjectPointer(uint ObjID) const
Get a pointer to a Polygon Mesh Compound Object.
Definition Context.cpp:4108
void cropDomainX(const vec2 &xbounds)
Crop the domain in the x-direction such that all primitives lie within some specified x interval.
Definition Context.cpp:2144
-
helios::vec3 getSphereObjectRadius(uint ObjID) const
get the radius of a Sphere object from the context
Definition Context.cpp:8144
+
helios::vec3 getSphereObjectRadius(uint ObjID) const
get the radius of a Sphere object from the context
Definition Context.cpp:8171
void setDate(int day, int month, int year)
Set simulation date by day, month, year.
Definition Context.cpp:1059
-
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:6988
-
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7179
+
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7015
+
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7206
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
void usePrimitiveTextureColor(uint UUID)
Use the texture map to color the primitive rather than the constant RGB color. This is function rever...
Definition Context.cpp:7207
-
bool doesObjectContainPrimitive(uint ObjID, uint UUID)
Method to check if an Object contains a Primitive.
Definition Context.cpp:7974
+
void usePrimitiveTextureColor(uint UUID)
Use the texture map to color the primitive rather than the constant RGB color. This is function rever...
Definition Context.cpp:7234
+
bool doesObjectContainPrimitive(uint ObjID, uint UUID)
Method to check if an Object contains a Primitive.
Definition Context.cpp:8001
const char * getMonthString() const
Get a string corresponding to the month of the simulation date.
Definition Context.cpp:1103
std::vector< uint > filterObjectsByData(const std::vector< uint > &ObjIDs, const char *object_data, float threshold, const char *comparator) const
Get a vector of object IDs that meet filtering criteria based on object data.
Definition Context.cpp:2750
-
void setObjectColor(uint ObjID, const helios::RGBcolor &color)
Method to set the diffuse color of an Object.
Definition Context.cpp:7954
+
void setObjectColor(uint ObjID, const helios::RGBcolor &color)
Method to set the diffuse color of an Object.
Definition Context.cpp:7981
void setTriangleVertices(uint UUID, const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
//! Manually set the Triangle vertices
Definition Context.cpp:1722
-
void appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float radius, const RGBcolor &color)
Append a tube segment to an existing tube object.
Definition Context.cpp:8180
+
void appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float radius, const RGBcolor &color)
Append a tube segment to an existing tube object.
Definition Context.cpp:8207
bool isGeometryDirty() const
Query whether the Context geometry is "dirty", meaning has the geometry been modified since last set ...
Definition Context.cpp:157
-
helios::vec3 getTileObjectNormal(uint ObjID) const
get the normal of a tile object from the context
Definition Context.cpp:8128
+
helios::vec3 getTileObjectNormal(uint ObjID) const
get the normal of a tile object from the context
Definition Context.cpp:8155
Context()
Context default constructor.
Definition Context.cpp:20
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
+
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:7011
helios::vec3 getVoxelSize(uint UUID) const
Get the size of a voxel element.
Definition Context.cpp:1741
-
std::vector< float > getTubeObjectNodeRadii(uint ObjID) const
get the node radii of a Tube object from the context
Definition Context.cpp:8164
-
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7221
+
std::vector< float > getTubeObjectNodeRadii(uint ObjID) const
get the node radii of a Tube object from the context
Definition Context.cpp:8191
+
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7248
void translateObject(uint ObjID, const vec3 &shift)
Translate a single compound object.
Definition Context.cpp:2837
void scaleObjectAboutCenter(uint ObjID, const helios::vec3 &scalefact)
Method to scale a compound object in the x-, y- and z-directions.
Definition Context.cpp:2887
void cropDomainY(const vec2 &ybounds)
Crop the domain in the y-direction such that all primitives lie within some specified y interval.
Definition Context.cpp:2167
helios::ObjectType getObjectType(uint ObjID) const
Get an enumeration specifying the type of the object.
Definition Context.cpp:2940
-
void colorPrimitiveByDataPseudocolor(const std::vector< uint > &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors)
Overwrite primitive color based on a pseudocolor mapping of primitive data values.
Definition Context.cpp:6666
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
std::vector< RGBcolor > getTubeObjectNodeColors(uint ObjID) const
get the node colors of a Tube object from the context
Definition Context.cpp:8168
+
void colorPrimitiveByDataPseudocolor(const std::vector< uint > &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors)
Overwrite primitive color based on a pseudocolor mapping of primitive data values.
Definition Context.cpp:6693
+
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
std::vector< RGBcolor > getTubeObjectNodeColors(uint ObjID) const
get the node colors of a Tube object from the context
Definition Context.cpp:8195
std::vector< std::string > listPrimitiveData(uint UUID) const
Return labels for all primitive data for this particular primitive.
std::vector< uint > getObjectPrimitiveUUIDs(uint ObjID) const
Get primitive UUIDs associated with compound object (single object ID input)
Definition Context.cpp:2907
+
void pruneTubeNodes(uint ObjID, uint node_index)
Remove a portion of the tube downstream of a specified node.
Definition Context.cpp:8242
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
-
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7167
+
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7194
helios::vec3 getTriangleVertex(uint UUID, uint number) const
Get a single vertex of a Triangle based on an index.
Definition Context.cpp:1711
helios::Time getTime() const
Get the simulation time.
Definition Context.cpp:1166
-
helios::RGBcolor getPrimitiveColorRGB(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7131
+
helios::RGBcolor getPrimitiveColorRGB(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7158
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:2046
-
uint getDiskObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Disk object from the context
Definition Context.cpp:8246
-
void setPrimitiveTextureFile(uint UUID, const std::string &texturefile)
Set the texture map file for a primitive.
Definition Context.cpp:7163
-
std::vector< helios::vec3 > getConeObjectNodes(uint ObjID) const
get the nodes of a Cone object from the context
Definition Context.cpp:8254
+
uint getDiskObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Disk object from the context
Definition Context.cpp:8280
+
void setPrimitiveTextureFile(uint UUID, const std::string &texturefile)
Set the texture map file for a primitive.
Definition Context.cpp:7190
+
std::vector< helios::vec3 > getConeObjectNodes(uint ObjID) const
get the nodes of a Cone object from the context
Definition Context.cpp:8288
void hidePrimitive(const std::vector< uint > &UUIDs)
Hide primitives in the Context such that their UUIDs are not returned in Context::getAllUUIDs()
Definition Context.cpp:1777
Sphere * getSphereObjectPointer(uint ObjID) const
Get a pointer to a Sphere Compound Object.
Definition Context.cpp:3410
-
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:7197
-
helios::int2 getTileObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a tile object from the context
Definition Context.cpp:8124
+
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:7224
+
helios::int2 getTileObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a tile object from the context
Definition Context.cpp:8151
bool isPrimitiveHidden(uint UUID) const
Query whether a primitive is hidden.
Definition Context.cpp:1786
helios::Date getDate() const
Get simulation date.
Definition Context.cpp:1099
-
void printObjectInfo(uint ObjID) const
Prints object properties to console (useful for debugging purposes)
Definition Context.cpp:7499
+
void printObjectInfo(uint ObjID) const
Prints object properties to console (useful for debugging purposes)
Definition Context.cpp:7526
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition Context.cpp:49
-
void hideObject(const std::vector< uint > &ObjIDs)
Hide compound objects in the Context such that their object IDs are not returned in Context::getAllOb...
Definition Context.cpp:7901
+
void hideObject(const std::vector< uint > &ObjIDs)
Hide compound objects in the Context such that their object IDs are not returned in Context::getAllOb...
Definition Context.cpp:7928
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7187
+
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7214
float getTileObjectAreaRatio(uint ObjectID) const
Get the area ratio of a tile object (total object area / sub-patch area)
Definition Context.cpp:2944
bool doesObjectExist(uint ObjID) const
Check whether Compound Object exists in the Context.
Definition Context.cpp:2585
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
-
std::vector< helios::vec3 > getTubeObjectNodes(uint ObjID) const
get the nodes of a Tube object from the context
Definition Context.cpp:8160
-
helios::vec3 getTileObjectCenter(uint ObjID) const
Get the Cartesian (x,y,z) center position of a tile object.
Definition Context.cpp:8116
-
void scaleTubeGirth(uint ObjID, float scale_factor)
Scale the girth for all nodes of a tube object.
Definition Context.cpp:8194
-
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:7217
+
std::vector< helios::vec3 > getTubeObjectNodes(uint ObjID) const
get the nodes of a Tube object from the context
Definition Context.cpp:8187
+
helios::vec3 getTileObjectCenter(uint ObjID) const
Get the Cartesian (x,y,z) center position of a tile object.
Definition Context.cpp:8143
+
void scaleTubeGirth(uint ObjID, float scale_factor)
Scale the girth for all nodes of a tube object.
Definition Context.cpp:8221
+
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:7244
void deleteObject(uint ObjID)
Delete a single Compound Object from the context.
Definition Context.cpp:2609
-
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition Context.cpp:7920
-
std::string getObjectTextureFile(uint ObjID) const
Method to return the texture map file of an Object.
Definition Context.cpp:7932
-
float getPolymeshObjectVolume(uint ObjID) const
Get the volume of a Polygon Mesh object from the context.
Definition Context.cpp:8282
+
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition Context.cpp:7947
+
std::string getObjectTextureFile(uint ObjID) const
Method to return the texture map file of an Object.
Definition Context.cpp:7959
+
float getPolymeshObjectVolume(uint ObjID) const
Get the volume of a Polygon Mesh object from the context.
Definition Context.cpp:8316
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1491
Tube * getTubeObjectPointer(uint ObjID) const
Get a pointer to a Tube Compound Object.
Definition Context.cpp:3486
helios::vec2 getPatchSize(uint UUID) const
Get the size of a patch element.
Definition Context.cpp:1684
-
std::vector< helios::vec3 > getTileObjectVertices(uint ObjID) const
get the vertices of a tile object from the context
Definition Context.cpp:8136
+
std::vector< helios::vec3 > getTileObjectVertices(uint ObjID) const
get the vertices of a tile object from the context
Definition Context.cpp:8163
void markGeometryDirty()
Mark the Context geometry as "dirty", meaning that the geometry has been modified since last set as c...
Definition Context.cpp:153
-
void getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single primitive.
Definition Context.cpp:7057
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7104
+
void getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single primitive.
Definition Context.cpp:7084
+
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7131
uint getObjectDataSize(uint objID, const char *label) const
Get the size/length of primitive data.
-
helios::vec3 getConeObjectAxisUnitVector(uint ObjID) const
get the axis unit vector of a Cone object from the context
Definition Context.cpp:8270
+
helios::vec3 getConeObjectAxisUnitVector(uint ObjID) const
get the axis unit vector of a Cone object from the context
Definition Context.cpp:8304
helios::vec3 getVoxelCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a voxel element.
Definition Context.cpp:1750
-
helios::vec2 getDiskObjectSize(uint ObjID) const
get the size of a Disk object from the context
Definition Context.cpp:8242
+
helios::vec2 getDiskObjectSize(uint ObjID) const
get the size of a Disk object from the context
Definition Context.cpp:8276
bool doesPrimitiveExist(uint UUID) const
Check if primitive exists for a given UUID.
Definition Context.cpp:1659
bool areObjectPrimitivesComplete(uint objID) const
Method to query whether all object primitives are in tact.
Definition Context.cpp:2540
-
float getConeObjectLength(uint ObjID) const
get the length of a Cone object from the context
Definition Context.cpp:8274
+
float getConeObjectLength(uint ObjID) const
get the length of a Cone object from the context
Definition Context.cpp:8308
Tile * getTileObjectPointer(uint ObjID) const
Get a pointer to a Tile Compound Object.
Definition Context.cpp:3312
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:1512
-
void useObjectTextureColor(uint ObjID)
For all primitives in the Compound Object, use the texture map to color the primitives rather than th...
Definition Context.cpp:7988
-
uint getSphereObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Sphere object from the context
Definition Context.cpp:8148
+
void useObjectTextureColor(uint ObjID)
For all primitives in the Compound Object, use the texture map to color the primitives rather than th...
Definition Context.cpp:8015
+
uint getSphereObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Sphere object from the context
Definition Context.cpp:8175
void setLocation(const helios::Location &location)
Set the location of the simulation (latitude, longitude, and UTC offset)
Definition Context.cpp:1170
std::vector< std::string > listObjectData(uint ObjID) const
Return labels for all object data for this particular object.
-
std::vector< float > getConeObjectNodeRadii(uint ObjID) const
get the node radii of a Cone object from the context
Definition Context.cpp:8258
-
float getBoxObjectVolume(uint ObjID) const
get the volume of a Box object from the context
Definition Context.cpp:8234
+
std::vector< float > getConeObjectNodeRadii(uint ObjID) const
get the node radii of a Cone object from the context
Definition Context.cpp:8292
+
float getBoxObjectVolume(uint ObjID) const
get the volume of a Box object from the context
Definition Context.cpp:8268
void copyObjectData(uint source_objID, uint destination_objID)
copy all object data from one compound object to another
void setTime(int minute, int hour)
Set simulation time.
Definition Context.cpp:1136
-
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:7122
-
float getSphereObjectVolume(uint ObjID) const
get the volume of a Sphere object from the context
Definition Context.cpp:8152
-
void setObjectTransformationMatrix(uint ObjID, float(&T)[16])
Method to set the Affine transformation matrix of an Object.
Definition Context.cpp:7940
+
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:7149
+
float getSphereObjectVolume(uint ObjID) const
get the volume of a Sphere object from the context
Definition Context.cpp:8179
+
void setObjectTransformationMatrix(uint ObjID, float(&T)[16])
Method to set the Affine transformation matrix of an Object.
Definition Context.cpp:7967
void cropDomain(std::vector< uint > &UUIDs, const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds)
Crop specified UUIDs such that they lie within some specified axis-aligned box.
Definition Context.cpp:2213
-
void setTubeNodes(uint ObjID, const std::vector< helios::vec3 > &node_xyz)
Set tube vertex coordinates at each segment node.
Definition Context.cpp:8215
+
void setTubeNodes(uint ObjID, const std::vector< helios::vec3 > &node_xyz)
Set tube vertex coordinates at each segment node.
Definition Context.cpp:8249
helios::Location getLocation() const
Get the location of the simulation (latitude, longitude, and UTC offset)
Definition Context.cpp:1174
-
float getConeObjectNodeRadius(uint ObjID, int number) const
get a node radius of a Cone object from the context
Definition Context.cpp:8266
+
float getConeObjectNodeRadius(uint ObjID, int number) const
get a node radius of a Cone object from the context
Definition Context.cpp:8300
void cleanDeletedObjectIDs(std::vector< uint > &objIDs) const
Delete Object IDs from vector if objects no longer exist (1D vector)
Definition Context.cpp:2544
-
float getConeObjectVolume(uint ObjID) const
get the volume of a Cone object from the context
Definition Context.cpp:8278
-
helios::vec3 getBoxObjectCenter(uint ObjID) const
get the center of a Box object from the context
Definition Context.cpp:8222
+
float getConeObjectVolume(uint ObjID) const
get the volume of a Cone object from the context
Definition Context.cpp:8312
+
helios::vec3 getBoxObjectCenter(uint ObjID) const
get the center of a Box object from the context
Definition Context.cpp:8256
HeliosDataType getObjectDataType(uint objID, const char *label) const
Get the Helios data type of primitive data.
-
void setPrimitiveTransformationMatrix(uint UUID, float(&T)[16])
Method to set the Affine transformation matrix of a Primitive.
Definition Context.cpp:7112
-
void getObjectTransformationMatrix(uint ObjID, float(&T)[16]) const
Method to return the Affine transformation matrix of an Object.
Definition Context.cpp:7936
-
void setTubeRadii(uint ObjID, const std::vector< float > &node_radii)
Set tube radii at each segment node.
Definition Context.cpp:8201
-
bool objectHasTexture(uint ObjID) const
Method to check whether an Object has texture data.
Definition Context.cpp:7950
+
void setPrimitiveTransformationMatrix(uint UUID, float(&T)[16])
Method to set the Affine transformation matrix of a Primitive.
Definition Context.cpp:7139
+
void getObjectTransformationMatrix(uint ObjID, float(&T)[16]) const
Method to return the Affine transformation matrix of an Object.
Definition Context.cpp:7963
+
void setTubeRadii(uint ObjID, const std::vector< float > &node_radii)
Set tube radii at each segment node.
Definition Context.cpp:8228
+
bool objectHasTexture(uint ObjID) const
Method to check whether an Object has texture data.
Definition Context.cpp:7977
void scaleObject(uint ObjID, const helios::vec3 &scalefact)
Method to scale a compound object in the x-, y- and z-directions.
Definition Context.cpp:2877
-
Disk compound object class.
Definition Context.h:795
-
vec2 getSize() const
Get the lateral dimensions of the disk object.
Definition Context.cpp:4029
-
int2 getSubdivisionCount() const
Get the number of sub-triangle divisions of the disk object.
Definition Context.cpp:4061
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the disk object.
Definition Context.cpp:4045
-
Disk(uint a_OID, const std::vector< uint > &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4009
-
void setSubdivisionCount(int2 subdiv)
Set the number of disk sub-triangle divisions.
Definition Context.cpp:4065
-
Polymesh compound object class.
Definition Context.h:828
-
Polymesh(uint a_OID, const std::vector< uint > &a_UUIDs, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4069
-
float getVolume() const
Get the volume of the polymesh object.
Definition Context.cpp:4088
+
Disk compound object class.
Definition Context.h:801
+
vec2 getSize() const
Get the lateral dimensions of the disk object.
Definition Context.cpp:4056
+
int2 getSubdivisionCount() const
Get the number of sub-triangle divisions of the disk object.
Definition Context.cpp:4088
+
vec3 getCenter() const
Get the Cartesian coordinates of the center of the disk object.
Definition Context.cpp:4072
+
Disk(uint a_OID, const std::vector< uint > &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4036
+
void setSubdivisionCount(int2 subdiv)
Set the number of disk sub-triangle divisions.
Definition Context.cpp:4092
+
Polymesh compound object class.
Definition Context.h:834
+
Polymesh(uint a_OID, const std::vector< uint > &a_UUIDs, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4096
+
float getVolume() const
Get the volume of the polymesh object.
Definition Context.cpp:4115
Sphere compound object class.
Definition Context.h:624
uint getSubdivisionCount() const
Get the number of sub-patch divisions of the sphere object.
Definition Context.cpp:3455
helios::vec3 getRadius() const
Get the radius of the sphere.
Definition Context.cpp:3417
@@ -9351,7 +9397,6 @@
vec3 getCenter() const
Get the Cartesian coordinates of the center of the sphere object.
Definition Context.cpp:3439
Sphere(uint a_OID, const std::vector< uint > &a_UUIDs, uint a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:3397
void setSubdivisionCount(uint subdiv)
Set the number of sphere tesselation divisions.
Definition Context.cpp:3459
-
Texture map data structure.
Definition Context.h:67
std::string getTextureFile() const
Get the name/path of the texture map file.
Definition Context.cpp:129
bool hasTransparencyChannel() const
Check whether the texture has a transparency channel.
Definition Context.cpp:137
helios::int2 getImageResolution() const
Get the size of the texture in pixels (horizontal x vertical)
Definition Context.cpp:133
@@ -9371,6 +9416,7 @@
float getSegmentVolume(uint segment_index) const
Get the volume of a segment within the tube object.
Definition Context.cpp:3561
std::vector< float > getNodeRadii() const
Get the radius at each of the tube object nodes.
Definition Context.cpp:3508
void scaleTubeGirth(float S)
Scale the girth of the tube object.
Definition Context.cpp:3826
+
void pruneTubeNodes(uint node_index)
Remove a portion of the tube downstream of a specified node.
Definition Context.cpp:3916
void setTubeRadii(const std::vector< float > &node_radii)
Set tube radii at each segment node.
Definition Context.cpp:3846
std::vector< std::vector< helios::vec3 > > getTriangleVertices() const
Get positions of triangle vertices comprising the tube object.
Definition Context.cpp:3529
float getVolume() const
Get the volume of the tube object.
Definition Context.cpp:3547
@@ -9397,19 +9443,19 @@
std::vector< std::vector< bool > > readPNGAlpha(const std::string &filename)
Function to read the alpha channel from a PNG image.
Definition global.cpp:1488
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
void writePNG(const std::string &filename, uint width, uint height, const std::vector< helios::RGBAcolor > &pixel_data)
Function to write a PNG image based on pixel data.
Definition global.cpp:1676
-
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:5256
-
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:4728
-
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5426
-
std::vector< uint > addDisk(uint Ndivs, const helios::vec3 &center, const helios::vec2 &size)
Add new Disk geometric primitive to the Context given its center, and size.
Definition Context.cpp:6356
-
std::vector< uint > addBox(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:6147
-
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5000
-
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition Context.cpp:5399
-
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5646
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
-
std::vector< uint > addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone to the Context.
Definition Context.cpp:6459
-
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4310
+
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:5283
+
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:4755
+
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5453
+
std::vector< uint > addDisk(uint Ndivs, const helios::vec3 &center, const helios::vec2 &size)
Add new Disk geometric primitive to the Context given its center, and size.
Definition Context.cpp:6383
+
std::vector< uint > addBox(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:6174
+
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5027
+
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition Context.cpp:5426
+
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5673
+
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5957
+
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5836
+
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4577
+
std::vector< uint > addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone to the Context.
Definition Context.cpp:6486
+
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4337
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
void makeRotationMatrix(float rotation, const char *axis, float(&transform)[16])
Construct a rotation matrix to perform rotation about the x-, y-, or z-axis.
Definition global.cpp:313
void makeTranslationMatrix(const helios::vec3 &translation, float(&transform)[16])
Construct translation matrix.
Definition global.cpp:436
@@ -9448,9 +9494,6 @@
int year
Year in YYYY format.
R-G-B-A color vector.
-
float r
Red color component.
-
float b
Blue color component.
-
float g
Green color component.
R-G-B color vector.
float b
Blue color component.
float r
Red color component.
@@ -9462,27 +9505,30 @@
int second
Second of minute.
int hour
Hour of day.
int minute
Minute of hour.
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
float magnitude() const
Compute the vector magnitude.
- -
+ + diff --git a/doc/html/_context_8h.html b/doc/html/_context_8h.html index a9051e71c..d2f7ec895 100644 --- a/doc/html/_context_8h.html +++ b/doc/html/_context_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Data Structures | @@ -301,10 +307,13 @@

+ + diff --git a/doc/html/_context_8h.js b/doc/html/_context_8h.js new file mode 100644 index 000000000..a73c231fe --- /dev/null +++ b/doc/html/_context_8h.js @@ -0,0 +1,42 @@ +var _context_8h = +[ + [ "helios::Texture", "classhelios_1_1_texture.html", "classhelios_1_1_texture" ], + [ "helios::GlobalData", "structhelios_1_1_global_data.html", null ], + [ "helios::CompoundObject", "classhelios_1_1_compound_object.html", "classhelios_1_1_compound_object" ], + [ "helios::Tile", "classhelios_1_1_tile.html", "classhelios_1_1_tile" ], + [ "helios::Sphere", "classhelios_1_1_sphere.html", "classhelios_1_1_sphere" ], + [ "helios::Tube", "classhelios_1_1_tube.html", "classhelios_1_1_tube" ], + [ "helios::Box", "classhelios_1_1_box.html", "classhelios_1_1_box" ], + [ "helios::Disk", "classhelios_1_1_disk.html", "classhelios_1_1_disk" ], + [ "helios::Polymesh", "classhelios_1_1_polymesh.html", "classhelios_1_1_polymesh" ], + [ "helios::Cone", "classhelios_1_1_cone.html", "classhelios_1_1_cone" ], + [ "helios::XMLparser", "classhelios_1_1_x_m_lparser.html", null ], + [ "helios::Context", "classhelios_1_1_context.html", "classhelios_1_1_context" ], + [ "helios::HeliosDataType", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3", [ + [ "helios::HELIOS_TYPE_INT", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3a7a7039490fc92b5d76ca18b70563ed52", null ], + [ "helios::HELIOS_TYPE_UINT", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3aa8887c77409aaaecc3cd1a097488776f", null ], + [ "helios::HELIOS_TYPE_FLOAT", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3ae8cb6622468bda0078b0bcfde7677ba0", null ], + [ "helios::HELIOS_TYPE_DOUBLE", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3a520daf05a1b3086aabd6cbe6a712c1c3", null ], + [ "helios::HELIOS_TYPE_VEC2", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3a6269d91d936a3d60a8a763ec122ba233", null ], + [ "helios::HELIOS_TYPE_VEC3", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3a8da4db5333fb4d726d17ad82300c9d6c", null ], + [ "helios::HELIOS_TYPE_VEC4", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3ade0fe2a24f299ca147b95a0eebe43e5d", null ], + [ "helios::HELIOS_TYPE_INT2", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3ad586d734313fa5492db5b8cc84d9eabd", null ], + [ "helios::HELIOS_TYPE_INT3", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3a28e69c60e380496c8c35892e76ee4ad3", null ], + [ "helios::HELIOS_TYPE_INT4", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3aa6e12ea3a9160f59a1208f7cbb6c1ce7", null ], + [ "helios::HELIOS_TYPE_STRING", "_context_8h.html#a935eb2a4249411a8f376a27820c70de3a7c1f526f519f173e5931fd73b78ccbb3", null ] + ] ], + [ "helios::ObjectType", "_context_8h.html#ad0894682f41916c84c2026b3cb8ac682", [ + [ "helios::OBJECT_TYPE_TILE", "_context_8h.html#ad0894682f41916c84c2026b3cb8ac682aed347b5fb08bc5551b61310a964f0bde", null ], + [ "helios::OBJECT_TYPE_SPHERE", "_context_8h.html#ad0894682f41916c84c2026b3cb8ac682af4e336a18e47e54ca6e9a7f57e665175", null ], + [ "helios::OBJECT_TYPE_TUBE", "_context_8h.html#ad0894682f41916c84c2026b3cb8ac682a4c8545d7bc5d79cd8d150eca0624b623", null ], + [ "helios::OBJECT_TYPE_BOX", "_context_8h.html#ad0894682f41916c84c2026b3cb8ac682a2f065407387865d0564746c763c78d66", null ], + [ "helios::OBJECT_TYPE_DISK", "_context_8h.html#ad0894682f41916c84c2026b3cb8ac682a7d26aca591c366d41bca9d184a07ee51", null ], + [ "helios::OBJECT_TYPE_POLYMESH", "_context_8h.html#ad0894682f41916c84c2026b3cb8ac682a40bb0200100d500b738a6c3efc70df38", null ], + [ "helios::OBJECT_TYPE_CONE", "_context_8h.html#ad0894682f41916c84c2026b3cb8ac682a6bcd175267f2f6d4f4a75b8e1e520def", null ] + ] ], + [ "helios::PrimitiveType", "_context_8h.html#aa2778fcacd9c556a5ce0d9de2ffc1601", [ + [ "helios::PRIMITIVE_TYPE_PATCH", "_context_8h.html#aa2778fcacd9c556a5ce0d9de2ffc1601a6fcd29f0c812849b3eb5bedec52cd744", null ], + [ "helios::PRIMITIVE_TYPE_TRIANGLE", "_context_8h.html#aa2778fcacd9c556a5ce0d9de2ffc1601aeed8005c1692d92beefcbafe8147207c", null ], + [ "helios::PRIMITIVE_TYPE_VOXEL", "_context_8h.html#aa2778fcacd9c556a5ce0d9de2ffc1601a963e2e943d9bd4d5c4648473802cf78c", null ] + ] ] +]; \ No newline at end of file diff --git a/doc/html/_context_8h_source.html b/doc/html/_context_8h_source.html index e35a69ef7..0ee4249f9 100644 --- a/doc/html/_context_8h_source.html +++ b/doc/html/_context_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Context.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef HELIOS_CONTEXT
17#define HELIOS_CONTEXT
18
19#include <utility>
20
21#include "global.h"
-
22
-
24
+
22
+
24
+
25
26namespace helios {
27
-
28class Context; //forward declaration of Context class
-
29
+
28class Context; //forward declaration of Context class
+
29
-
39
+
39
@@ -140,15 +148,15 @@
64};
-
65
+
65
-
67class Texture{
+
67class Texture{
68public:
69
-
70 Texture()= default;
+
70 Texture()= default;
71
-
73
-
76 explicit Texture( const char* texture_file );
+
73
+
76 explicit Texture( const char* texture_file );
77
79 std::string getTextureFile() const;
80
@@ -168,7 +176,7 @@
98 float solidfraction{};
99};
-
100
+
100
103
@@ -195,7 +203,7 @@
123
124
125//---------- COMPOUND OBJECTS ----------------//
-
126
+
126
@@ -228,10 +236,10 @@
167
169 float getArea() const;
170
-
172
+
172
174 void setColor( const helios::RGBcolor& color );
175
-
177
+
177
180 void setColor( const helios::RGBAcolor& color );
181
@@ -242,153 +250,153 @@
190
192 std::string getTextureFile( ) const;
193
-
195
+
195
198 void translate( const helios::vec3& shift );
199
-
201
+
201
205 void rotate(float rotation_radians, const char* rotation_axis_xyz_string );
206
-
208
+
208
212 void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector );
213
-
215
+
215
220 void rotate(float rotation_radians, const helios::vec3& origin, const helios::vec3& rotation_axis_vector );
-
221
-
223
+
221
+
223
226 void scale( const helios::vec3 &scale );
-
227
-
229
+
227
+
229
232 void scaleAboutCenter( const helios::vec3 &scale );
-
233
-
235
+
233
+
235
239 void scaleAboutPoint( const helios::vec3 &scale, const helios::vec3 &point );
240
-
242
+
242
245 void getTransformationMatrix( float (&T)[16] ) const;
246
-
248
+
248
251 void setTransformationMatrix( float (&T)[16] );
252
-
254
+
254
257 void setPrimitiveUUIDs( const std::vector<uint> &UUIDs );
258
-
260
+
260
263 void deleteChildPrimitive( uint UUID );
264
-
266
+
266
269 void deleteChildPrimitive( const std::vector<uint> &UUIDs );
270
-
272
+
272
275 bool arePrimitivesComplete() const;
276
277 //-------- Object Data Methods ---------- //
278
-
280
+
280
284 void setObjectData( const char* label, const int& data );
285
-
287
+
287
291 void setObjectData( const char* label, const uint& data );
292
-
294
+
294
298 void setObjectData( const char* label, const float& data );
299
-
301
+
301
305 void setObjectData( const char* label, const double& data );
306
-
308
+
308
312 void setObjectData( const char* label, const helios::vec2& data );
313
-
315
+
315
319 void setObjectData( const char* label, const helios::vec3& data );
320
-
322
+
322
326 void setObjectData( const char* label, const helios::vec4& data );
327
-
329
+
329
333 void setObjectData( const char* label, const helios::int2& data );
334
-
336
+
336
340 void setObjectData( const char* label, const helios::int3& data );
341
-
343
+
343
347 void setObjectData( const char* label, const helios::int4& data );
348
-
350
+
350
354 void setObjectData( const char* label, const std::string& data );
355
-
357
+
357
364 void setObjectData( const char* label, HeliosDataType type, uint size, void* data );
365
-
367
+
367
371 void getObjectData( const char* label, int& data ) const;
372
-
374
+
374
378 void getObjectData( const char* label, std::vector<int>& data ) const;
379
-
381
+
381
385 void getObjectData( const char* label, uint& data ) const;
386
-
388
+
388
392 void getObjectData( const char* label, std::vector<uint>& data ) const;
393
-
395
+
395
399 void getObjectData( const char* label, float& data ) const;
400
-
402
+
402
406 void getObjectData( const char* label, std::vector<float>& data ) const;
407
-
409
+
409
413 void getObjectData( const char* label, double& data ) const;
414
-
416
+
416
420 void getObjectData( const char* label, std::vector<double>& data ) const;
421
-
423
+
423
427 void getObjectData( const char* label, vec2& data ) const;
428
-
430
+
430
434 void getObjectData( const char* label, std::vector<vec2>& data ) const;
435
437 void getObjectData( const char* label, vec3& data ) const;
438
-
440
+
440
444 void getObjectData( const char* label, std::vector<vec3>& data ) const;
-
446
+
446
450 void getObjectData( const char* label, vec4& data ) const;
-
452
+
452
456 void getObjectData( const char* label, std::vector<vec4>& data ) const;
-
458
+
458
462 void getObjectData( const char* label, int2& data ) const;
-
464
+
464
468 void getObjectData( const char* label, std::vector<int2>& data ) const;
-
470
+
470
474 void getObjectData( const char* label, int3& data ) const;
-
476
+
476
480 void getObjectData( const char* label, std::vector<int3>& data ) const;
-
482
+
482
486 void getObjectData( const char* label, int4& data ) const;
-
488
+
488
492 void getObjectData( const char* label, std::vector<int4>& data ) const;
-
494
+
494
498 void getObjectData( const char* label, std::string& data ) const;
-
500
+
500
504 void getObjectData( const char* label, std::vector<std::string>& data ) const;
505
-
507
+
507
512 HeliosDataType getObjectDataType( const char* label ) const;
513
-
515
+
515
519 uint getObjectDataSize( const char* label ) const;
520
-
522
+
522
526 bool doesObjectDataExist( const char* label ) const;
527
-
529
+
529
532 void clearObjectData( const char* label );
533
535 std::vector<std::string> listObjectData() const;
536
-
537 friend class Context;
+
537 friend class Context;
538
539protected:
540
@@ -424,9 +432,9 @@
577
578};
-
579
+
579
-
581class Tile : public CompoundObject {
+
581class Tile : public CompoundObject {
582public:
583
585 Tile(uint a_OID, const std::vector<uint> &a_UUIDs, const int2 &a_subdiv, const char *a_texturefile, helios::Context *a_context);
@@ -439,7 +447,7 @@
595
598
-
600
+
600
604 void setSubdivisionCount( const helios::int2 &subdiv );
605
607 std::vector<helios::vec3> getVertices() const;
@@ -452,13 +460,13 @@
616
617 helios::int2 subdiv;
618
-
619 friend class CompoundObject;
+
619 friend class CompoundObject;
620
621};
-
622
+
622
-
624class Sphere : public CompoundObject {
+
624class Sphere : public CompoundObject {
625public:
626
628 Sphere(uint a_OID, const std::vector<uint> &a_UUIDs, uint a_subdiv, const char *a_texturefile, helios::Context *a_context);
@@ -471,22 +479,22 @@
638
640 uint getSubdivisionCount() const;
641
-
643
+
643
646 void setSubdivisionCount(uint subdiv );
-
647
+
647
649 float getVolume() const;
650
651protected:
652
653 uint subdiv;
654
-
655 friend class CompoundObject;
+
655 friend class CompoundObject;
656
657};
-
658
+
658
-
660class Tube : public CompoundObject {
+
660class Tube : public CompoundObject {
661public:
662
664 Tube(uint a_OID, const std::vector<uint> &a_UUIDs, const std::vector<vec3> &a_nodes, const std::vector<float> &a_radius, const std::vector<helios::RGBcolor> &a_colors, const std::vector<std::vector<helios::vec3>> &a_triangle_vertices,
@@ -499,2391 +507,2398 @@
674 std::vector<float> getNodeRadii() const;
675
677 std::vector<helios::RGBcolor> getNodeColors() const;
-
678
+
678
680 std::vector<std::vector<helios::vec3>> getTriangleVertices() const;
681
683 uint getSubdivisionCount() const;
-
684
+
684
686 float getLength() const;
-
687
+
687
689 float getVolume() const;
-
690
-
692
+
690
+
692
695 float getSegmentVolume( uint segment_index ) const;
-
696
-
698
+
696
+
698
703 void appendTubeSegment( const helios::vec3 &node_position, float node_radius, const helios::RGBcolor &node_color );
-
704
-
706
+
704
+
706
712 void appendTubeSegment( const helios::vec3 &node_position, float node_radius, const char* texturefile, const helios::vec2 &textureuv_ufrac );
-
713
-
715
+
713
+
715
718 void scaleTubeGirth( float S);
-
719
-
721
+
719
+
721
724 void setTubeRadii( const std::vector<float> &node_radii );
-
725
-
727
+
725
+
727
730 void scaleTubeLength( float S );
-
731
-
733
+
731
+
733
736 void setTubeNodes( const std::vector<helios::vec3> &node_xyz );
-
737
-
738protected:
-
739
-
740 std::vector<helios::vec3> nodes;
-
741
-
742 std::vector<std::vector<helios::vec3>> triangle_vertices; //first index is the tube segment ring, second index is vertex within segment ring, third index is the vertex within triangle
+
737
+
739
+
742 void pruneTubeNodes( uint node_index );
743
-
744 std::vector<float> radius;
+
744protected:
745
-
746 std::vector<helios::RGBcolor> colors;
-
747
-
748 uint subdiv;
+
746 std::vector<helios::vec3> nodes;
+
747
+
748 std::vector<std::vector<helios::vec3>> triangle_vertices; //first index is the tube segment ring, second index is vertex within segment ring, third index is the vertex within triangle
749
-
750 void updateTriangleVertices();
-
751
-
752
-
753
-
754 friend class CompoundObject;
-
755
-
756};
-
+
750 std::vector<float> radius;
+
751
+
752 std::vector<helios::RGBcolor> colors;
+
753
+
754 uint subdiv;
+
755
+
756 void updateTriangleVertices();
757
-
-
759class Box : public CompoundObject {
-
760public:
+
758
+
759
+
760 friend class CompoundObject;
761
-
763 Box(uint a_OID, const std::vector<uint> &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
764
-
766 ~Box() override = default;
+
762};
+
+
763
+
+
765class Box : public CompoundObject {
+
766public:
767
-
769 vec3 getSize() const;
+
769 Box(uint a_OID, const std::vector<uint> &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context);
770
-
772 vec3 getCenter() const;
+
772 ~Box() override = default;
773
- +
775 vec3 getSize() const;
776
-
778
-
781 void setSubdivisionCount( const helios::int3 &subdiv );
-
782
-
784 float getVolume() const;
-
785
-
786protected:
-
787
-
788 helios::int3 subdiv;
-
789
-
790 friend class CompoundObject;
+
778 vec3 getCenter() const;
+
779
+ +
782
+
784
+
787 void setSubdivisionCount( const helios::int3 &subdiv );
+
788
+
790 float getVolume() const;
791
-
792};
-
-
793
-
-
795class Disk : public CompoundObject {
-
796public:
+
792protected:
+
793
+
794 helios::int3 subdiv;
+
795
+
796 friend class CompoundObject;
797
-
799 Disk(uint a_OID, const std::vector<uint> &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
800
-
802 ~Disk() override = default;
+
798};
+
+
799
+
+
801class Disk : public CompoundObject {
+
802public:
803
-
805 vec2 getSize() const;
+
805 Disk(uint a_OID, const std::vector<uint> &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context);
806
-
808 vec3 getCenter() const;
+
808 ~Disk() override = default;
809
- +
811 vec2 getSize() const;
812
-
814
-
817 void setSubdivisionCount(int2 subdiv );
+
814 vec3 getCenter() const;
+
815
+
818
-
819protected:
-
820
-
821 int2 subdiv;
-
822
-
823 friend class CompoundObject;
+
820
+
823 void setSubdivisionCount(int2 subdiv );
824
-
825};
-
-
826
-
-
828class Polymesh : public CompoundObject {
-
829public:
+
825protected:
+
826
+
827 int2 subdiv;
+
828
+
829 friend class CompoundObject;
830
-
832 Polymesh(uint a_OID, const std::vector<uint> &a_UUIDs, const char *a_texturefile, helios::Context *a_context);
-
833
-
835 ~Polymesh() override = default;
-
836
-
838 float getVolume() const;
-
839
-
840protected:
-
841
-
842 friend class CompoundObject;
-
843
-
844};
+
831};
-
845
-
-
847class Cone : public CompoundObject {
-
848public:
+
832
+
+
834class Polymesh : public CompoundObject {
+
835public:
+
836
+
838 Polymesh(uint a_OID, const std::vector<uint> &a_UUIDs, const char *a_texturefile, helios::Context *a_context);
+
839
+
841 ~Polymesh() override = default;
+
842
+
844 float getVolume() const;
+
845
+
846protected:
+
847
+
848 friend class CompoundObject;
849
-
851 Cone(uint a_OID, const std::vector<uint> &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0, float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context);
-
852
-
854 ~Cone() override = default;
+
850};
+
+
851
+
+
853class Cone : public CompoundObject {
+
854public:
855
-
857
-
860 std::vector<helios::vec3> getNodeCoordinates() const;
+
857 Cone(uint a_OID, const std::vector<uint> &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0, float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context);
+
858
+
860 ~Cone() override = default;
861
-
863
-
867 helios::vec3 getNodeCoordinate(int node_index) const;
-
868
-
870
-
873 std::vector<float> getNodeRadii() const;
+
863
+
866 std::vector<helios::vec3> getNodeCoordinates() const;
+
867
+
869
+
873 helios::vec3 getNodeCoordinate(int node_index) const;
874
-
876
-
880 float getNodeRadius(int node_index) const;
-
881
-
883 uint getSubdivisionCount() const;
-
884
-
886
-
889 void setSubdivisionCount( uint subdiv );
+
876
+
879 std::vector<float> getNodeRadii() const;
+
880
+
882
+
886 float getNodeRadius(int node_index) const;
+
887
+
889 uint getSubdivisionCount() const;
890
- -
893
-
895 float getLength() const;
+
892
+
895 void setSubdivisionCount( uint subdiv );
896
-
898
-
901 void scaleLength( float S );
+ +
899
+
901 float getLength() const;
902
-
904
-
907 void scaleGirth( float S );
-
908
-
910 float getVolume() const;
-
911
-
912protected:
-
913
-
914 std::vector<helios::vec3> nodes;
-
915 std::vector<float> radii;
-
916
-
917 uint subdiv;
-
918
-
919 friend class CompoundObject;
-
920
-
921};
+
904
+
907 void scaleLength( float S );
+
908
+
910
+
913 void scaleGirth( float S );
+
914
+
916 float getVolume() const;
+
917
+
918protected:
+
919
+
920 std::vector<helios::vec3> nodes;
+
921 std::vector<float> radii;
+
922
+
923 uint subdiv;
+
924
+
925 friend class CompoundObject;
+
926
+
927};
-
922
-
923
-
925
-
929class Primitive{
-
930public:
-
931
-
933 virtual ~Primitive()= default;
-
934
-
936
-
939 uint getUUID() const;
+
928
+
929
+
931
+
935class Primitive{
+
936public:
+
937
+
939 virtual ~Primitive()= default;
940
-
942
-
945 PrimitiveType getType() const;
+
942
+
945 uint getUUID() const;
946
-
948
-
951 void setParentObjectID( uint objID );
+
948
+
951 PrimitiveType getType() const;
952
-
954 uint getParentObjectID()const;
-
955
-
957 virtual float getArea() const = 0;
+
954
+
957 void setParentObjectID( uint objID );
958
-
960 virtual helios::vec3 getNormal() const = 0;
+
960 uint getParentObjectID()const;
961
-
963
-
966 void getTransformationMatrix( float (&T)[16] ) const;
+
963 virtual float getArea() const = 0;
+
964
+
966 virtual helios::vec3 getNormal() const = 0;
967
-
969
-
972 void setTransformationMatrix( float (&T)[16] );
+
969
+
972 void getTransformationMatrix( float (&T)[16] ) const;
973
-
975 virtual std::vector<helios::vec3> getVertices( ) const = 0;
-
976
-
978 virtual helios::vec3 getCenter() const = 0;
+
975
+
978 void setTransformationMatrix( float (&T)[16] );
979
-
981 helios::RGBcolor getColor() const;
+
981 virtual std::vector<helios::vec3> getVertices( ) const = 0;
982
-
984 helios::RGBcolor getColorRGB() const;
+
984 virtual helios::vec3 getCenter() const = 0;
985
-
987 helios::RGBAcolor getColorRGBA() const;
+
987 helios::RGBcolor getColor() const;
988
-
990
-
993 void setColor( const helios::RGBcolor& color );
+
990 helios::RGBcolor getColorRGB() const;
+
991
+
993 helios::RGBAcolor getColorRGBA() const;
994
-
996
-
999 void setColor( const helios::RGBAcolor& color );
+
996
+
999 void setColor( const helios::RGBcolor& color );
1000
-
1002 bool hasTexture( ) const;
-
1003
-
1005 std::string getTextureFile( ) const;
-
1006
-
1008
-
1011 void setTextureFile( const char* texture );
-
1012
-
1014
-
1017 std::vector<vec2> getTextureUV( );
-
1018
-
1019
-
1021
-
1024 void setTextureUV( const std::vector<vec2> &uv );
-
1025
-
1027 void overrideTextureColor( );
-
1028
-
1030 void useTextureColor( );
+
1002
+
1005 void setColor( const helios::RGBAcolor& color );
+
1006
+
1008 bool hasTexture( ) const;
+
1009
+
1011 std::string getTextureFile( ) const;
+
1012
+
1014
+
1017 void setTextureFile( const char* texture );
+
1018
+
1020
+
1023 std::vector<vec2> getTextureUV( );
+
1024
+
1025
+
1027
+
1030 void setTextureUV( const std::vector<vec2> &uv );
1031
-
1033 bool isTextureColorOverridden( ) const;
+
1033 void overrideTextureColor( );
1034
-
1036
-
1039 float getSolidFraction() const;
-
1040
-
1042
-
1045 void setSolidFraction( float solidFraction );
-
1046
-
1048
-
1051 void applyTransform( float (&T)[16] );
-
1052
-
1054
-
1057 void translate( const helios::vec3& shift );
-
1058
-
1060
-
1064 virtual void rotate(float rotation_radians, const char* rotation_axis_xyz_string ) = 0;
-
1065
-
1067
-
1071 virtual void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ) = 0;
-
1072
-
1074
-
1079 virtual void rotate(float rotation_radians, const helios::vec3 &origin, const helios::vec3 &rotation_axis_vector ) = 0;
-
1080
-
1082
-
1085 void scale( const helios::vec3 &S );
-
1086
-
1088
-
1092 void scale( const helios::vec3 &S, const helios::vec3 &point );
-
1093
-
1094 //-------- Primitive Data Methods ---------- //
-
1095
-
1097
-
1101 void setPrimitiveData( const char* label, const int& data );
-
1102
-
1104
-
1108 void setPrimitiveData( const char* label, const uint& data );
-
1109
-
1111
-
1115 void setPrimitiveData( const char* label, const float& data );
-
1116
-
1118
-
1122 void setPrimitiveData( const char* label, const double& data );
-
1123
-
1125
-
1129 void setPrimitiveData( const char* label, const helios::vec2& data );
-
1130
-
1132
-
1136 void setPrimitiveData( const char* label, const helios::vec3& data );
-
1137
-
1139
-
1143 void setPrimitiveData( const char* label, const helios::vec4& data );
-
1144
-
1146
-
1150 void setPrimitiveData( const char* label, const helios::int2& data );
-
1151
-
1153
-
1157 void setPrimitiveData( const char* label, const helios::int3& data );
-
1158
-
1160
-
1164 void setPrimitiveData( const char* label, const helios::int4& data );
-
1165
-
1167
-
1171 void setPrimitiveData( const char* label, const std::string& data );
-
1173
-
1180 void setPrimitiveData( const char* label, HeliosDataType type, uint size, void* data );
-
1182
-
1186 void getPrimitiveData( const char* label, int& data ) const;
-
1188
-
1192 void getPrimitiveData( const char* label, std::vector<int>& data ) const;
-
1194
-
1198 void getPrimitiveData( const char* label, uint& data ) const;
-
1200
-
1204 void getPrimitiveData( const char* label, std::vector<uint>& data ) const;
-
1206
-
1210 void getPrimitiveData( const char* label, float& data ) const;
-
1212
-
1216 void getPrimitiveData( const char* label, std::vector<float>& data ) const;
-
1218
-
1222 void getPrimitiveData( const char* label, double& data ) const;
-
1224
-
1228 void getPrimitiveData( const char* label, std::vector<double>& data ) const;
-
1230
-
1234 void getPrimitiveData( const char* label, vec2& data ) const;
-
1236
-
1240 void getPrimitiveData( const char* label, std::vector<vec2>& data ) const;
-
1242
-
1246 void getPrimitiveData( const char* label, vec3& data ) const;
-
1248
-
1252 void getPrimitiveData( const char* label, std::vector<vec3>& data ) const;
-
1254
-
1258 void getPrimitiveData( const char* label, vec4& data ) const;
-
1260
-
1264 void getPrimitiveData( const char* label, std::vector<vec4>& data ) const;
-
1266
-
1270 void getPrimitiveData( const char* label, int2& data ) const;
-
1272
-
1276 void getPrimitiveData( const char* label, std::vector<int2>& data ) const;
-
1278
-
1282 void getPrimitiveData( const char* label, int3& data ) const;
-
1284
-
1288 void getPrimitiveData( const char* label, std::vector<int3>& data ) const;
-
1290
-
1294 void getPrimitiveData( const char* label, int4& data ) const;
-
1296
-
1300 void getPrimitiveData( const char* label, std::vector<int4>& data ) const;
-
1302
-
1306 void getPrimitiveData( const char* label, std::string& data ) const;
-
1308
-
1312 void getPrimitiveData( const char* label, std::vector<std::string>& data ) const;
-
1313
-
1315
-
1320 HeliosDataType getPrimitiveDataType( const char* label ) const;
-
1321
-
1323
-
1327 uint getPrimitiveDataSize( const char* label ) const;
-
1328
-
1330
-
1334 bool doesPrimitiveDataExist( const char* label ) const;
-
1335
-
1337
-
1340 void clearPrimitiveData( const char* label );
+
1036 void useTextureColor( );
+
1037
+
1039 bool isTextureColorOverridden( ) const;
+
1040
+
1042
+
1045 float getSolidFraction() const;
+
1046
+
1048
+
1051 void setSolidFraction( float solidFraction );
+
1052
+
1054
+
1057 void applyTransform( float (&T)[16] );
+
1058
+
1060
+
1063 void translate( const helios::vec3& shift );
+
1064
+
1066
+
1070 virtual void rotate(float rotation_radians, const char* rotation_axis_xyz_string ) = 0;
+
1071
+
1073
+
1077 virtual void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ) = 0;
+
1078
+
1080
+
1085 virtual void rotate(float rotation_radians, const helios::vec3 &origin, const helios::vec3 &rotation_axis_vector ) = 0;
+
1086
+
1088
+
1091 void scale( const helios::vec3 &S );
+
1092
+
1094
+
1098 void scale( const helios::vec3 &S, const helios::vec3 &point );
+
1099
+
1100 //-------- Primitive Data Methods ---------- //
+
1101
+
1103
+
1107 void setPrimitiveData( const char* label, const int& data );
+
1108
+
1110
+
1114 void setPrimitiveData( const char* label, const uint& data );
+
1115
+
1117
+
1121 void setPrimitiveData( const char* label, const float& data );
+
1122
+
1124
+
1128 void setPrimitiveData( const char* label, const double& data );
+
1129
+
1131
+
1135 void setPrimitiveData( const char* label, const helios::vec2& data );
+
1136
+
1138
+
1142 void setPrimitiveData( const char* label, const helios::vec3& data );
+
1143
+
1145
+
1149 void setPrimitiveData( const char* label, const helios::vec4& data );
+
1150
+
1152
+
1156 void setPrimitiveData( const char* label, const helios::int2& data );
+
1157
+
1159
+
1163 void setPrimitiveData( const char* label, const helios::int3& data );
+
1164
+
1166
+
1170 void setPrimitiveData( const char* label, const helios::int4& data );
+
1171
+
1173
+
1177 void setPrimitiveData( const char* label, const std::string& data );
+
1179
+
1186 void setPrimitiveData( const char* label, HeliosDataType type, uint size, void* data );
+
1188
+
1192 void getPrimitiveData( const char* label, int& data ) const;
+
1194
+
1198 void getPrimitiveData( const char* label, std::vector<int>& data ) const;
+
1200
+
1204 void getPrimitiveData( const char* label, uint& data ) const;
+
1206
+
1210 void getPrimitiveData( const char* label, std::vector<uint>& data ) const;
+
1212
+
1216 void getPrimitiveData( const char* label, float& data ) const;
+
1218
+
1222 void getPrimitiveData( const char* label, std::vector<float>& data ) const;
+
1224
+
1228 void getPrimitiveData( const char* label, double& data ) const;
+
1230
+
1234 void getPrimitiveData( const char* label, std::vector<double>& data ) const;
+
1236
+
1240 void getPrimitiveData( const char* label, vec2& data ) const;
+
1242
+
1246 void getPrimitiveData( const char* label, std::vector<vec2>& data ) const;
+
1248
+
1252 void getPrimitiveData( const char* label, vec3& data ) const;
+
1254
+
1258 void getPrimitiveData( const char* label, std::vector<vec3>& data ) const;
+
1260
+
1264 void getPrimitiveData( const char* label, vec4& data ) const;
+
1266
+
1270 void getPrimitiveData( const char* label, std::vector<vec4>& data ) const;
+
1272
+
1276 void getPrimitiveData( const char* label, int2& data ) const;
+
1278
+
1282 void getPrimitiveData( const char* label, std::vector<int2>& data ) const;
+
1284
+
1288 void getPrimitiveData( const char* label, int3& data ) const;
+
1290
+
1294 void getPrimitiveData( const char* label, std::vector<int3>& data ) const;
+
1296
+
1300 void getPrimitiveData( const char* label, int4& data ) const;
+
1302
+
1306 void getPrimitiveData( const char* label, std::vector<int4>& data ) const;
+
1308
+
1312 void getPrimitiveData( const char* label, std::string& data ) const;
+
1314
+
1318 void getPrimitiveData( const char* label, std::vector<std::string>& data ) const;
+
1319
+
1321
+
1326 HeliosDataType getPrimitiveDataType( const char* label ) const;
+
1327
+
1329
+
1333 uint getPrimitiveDataSize( const char* label ) const;
+
1334
+
1336
+
1340 bool doesPrimitiveDataExist( const char* label ) const;
1341
-
1343 std::vector<std::string> listPrimitiveData() const;
-
1344
-
1345 virtual void calculateSolidFraction( const std::map<std::string,Texture> &textures ) = 0;
-
1346
-
1347 friend class Context;
-
1348
-
1349protected:
-
1350
-
1352 uint UUID;
-
1353
-
1355 PrimitiveType prim_type;
+
1343
+
1346 void clearPrimitiveData( const char* label );
+
1347
+
1349 std::vector<std::string> listPrimitiveData() const;
+
1350
+
1351 virtual void calculateSolidFraction( const std::map<std::string,Texture> &textures ) = 0;
+
1352
+
1353 friend class Context;
+
1354
+
1355protected:
1356
-
1358 uint parent_object_ID;
+
1358 uint UUID;
1359
-
1361 helios::RGBAcolor color;
+
1361 PrimitiveType prim_type;
1362
-
1364 std::string texturefile;
-
1366 float transform[16];
-
1367
-
1369 std::vector<vec2> uv;
-
1370
-
1372 float solid_fraction;
+
1364 uint parent_object_ID;
+
1365
+
1367 helios::RGBAcolor color;
+
1368
+
1370 std::string texturefile;
+
1372 float transform[16];
1373
-
1374 std::map<std::string,HeliosDataType > primitive_data_types;
-
1375 std::map<std::string, std::vector<int> > primitive_data_int;
-
1376 std::map<std::string, std::vector<uint> > primitive_data_uint;
-
1377 std::map<std::string, std::vector<float> > primitive_data_float;
-
1378 std::map<std::string, std::vector<double> > primitive_data_double;
-
1379 std::map<std::string, std::vector<vec2> > primitive_data_vec2;
-
1380 std::map<std::string, std::vector<vec3> > primitive_data_vec3;
-
1381 std::map<std::string, std::vector<vec4> > primitive_data_vec4;
-
1382 std::map<std::string, std::vector<int2> > primitive_data_int2;
-
1383 std::map<std::string, std::vector<int3> > primitive_data_int3;
-
1384 std::map<std::string, std::vector<int4> > primitive_data_int4;
-
1385 std::map<std::string, std::vector<std::string> > primitive_data_string;
-
1386 std::map<std::string, std::vector<bool> > primitive_data_bool;
-
1387
-
1388 bool texturecoloroverridden = false;
-
1389
-
1390 bool ishidden = false;
-
1391
-
1392};
-
1393
-
1394
-
1396
-
1401class Patch : public Primitive{
-
1402public:
-
1403
-
1405
-
1410 Patch( const helios::RGBAcolor& color, uint parent_objID, uint UUID );
-
1411
-
1413
-
1418 Patch( const char* texturefile, float solid_fraction, uint parent_objID, uint UUID );
-
1419
-
1421
-
1427 Patch( const char* texturefile, const std::vector<helios::vec2>& uv, const std::map<std::string,Texture> &textures, uint parent_objID, uint UUID );
-
1428
-
1430 ~Patch() override= default;
-
1431
-
1433
-
1436 float getArea() const override;
+
1375 std::vector<vec2> uv;
+
1376
+
1378 float solid_fraction;
+
1379
+
1380 std::map<std::string,HeliosDataType > primitive_data_types;
+
1381 std::map<std::string, std::vector<int> > primitive_data_int;
+
1382 std::map<std::string, std::vector<uint> > primitive_data_uint;
+
1383 std::map<std::string, std::vector<float> > primitive_data_float;
+
1384 std::map<std::string, std::vector<double> > primitive_data_double;
+
1385 std::map<std::string, std::vector<vec2> > primitive_data_vec2;
+
1386 std::map<std::string, std::vector<vec3> > primitive_data_vec3;
+
1387 std::map<std::string, std::vector<vec4> > primitive_data_vec4;
+
1388 std::map<std::string, std::vector<int2> > primitive_data_int2;
+
1389 std::map<std::string, std::vector<int3> > primitive_data_int3;
+
1390 std::map<std::string, std::vector<int4> > primitive_data_int4;
+
1391 std::map<std::string, std::vector<std::string> > primitive_data_string;
+
1392 std::map<std::string, std::vector<bool> > primitive_data_bool;
+
1393
+
1394 bool texturecoloroverridden = false;
+
1395
+
1396 bool ishidden = false;
+
1397
+
1398};
+
1399
+
1400
+
1402
+
1407class Patch : public Primitive{
+
1408public:
+
1409
+
1411
+
1416 Patch( const helios::RGBAcolor& color, uint parent_objID, uint UUID );
+
1417
+
1419
+
1424 Patch( const char* texturefile, float solid_fraction, uint parent_objID, uint UUID );
+
1425
+
1427
+
1433 Patch( const char* texturefile, const std::vector<helios::vec2>& uv, const std::map<std::string,Texture> &textures, uint parent_objID, uint UUID );
+
1434
+
1436 ~Patch() override= default;
1437
-
1439
-
1442 helios::vec3 getNormal() const override;
+
1439
+
1442 float getArea() const override;
1443
-
1445
-
1448 std::vector<helios::vec3> getVertices() const override;
+
1445
+
1448 helios::vec3 getNormal() const override;
1449
-
1451
-
1454 helios::vec2 getSize() const;
+
1451
+
1454 std::vector<helios::vec3> getVertices() const override;
1455
-
1457
-
1460 helios::vec3 getCenter() const override;
+
1457
+
1460 helios::vec2 getSize() const;
1461
-
1463
-
1467 void rotate(float rotation_radians, const char* rotation_axis_xyz_string ) override;
-
1468
-
1470
-
1474 void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ) override;
-
1475
-
1477
-
1482 void rotate(float rotation_radians, const helios::vec3 &origin, const helios::vec3 &rotation_axis_vector ) override;
-
1483
-
1485 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
-
1486
-
1487};
-
1488
-
1490
-
1495class Triangle : public Primitive{
-
1496public:
-
1497
-
1499
-
1507 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBAcolor& color, uint parent_objID, uint UUID );
-
1508
-
1510
-
1519 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texturefile, const std::vector<helios::vec2>& uv, float solid_fraction, uint parent_objID, uint UUID );
-
1520
-
1522
-
1532 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texturefile, const std::vector<helios::vec2>& uv, const std::map<std::string,Texture> &textures, uint parent_objID, uint UUID );
-
1533
-
1535 ~Triangle() override= default;
-
1536
-
1538
-
1541 float getArea() const override;
+
1463
+
1466 helios::vec3 getCenter() const override;
+
1467
+
1469
+
1473 void rotate(float rotation_radians, const char* rotation_axis_xyz_string ) override;
+
1474
+
1476
+
1480 void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ) override;
+
1481
+
1483
+
1488 void rotate(float rotation_radians, const helios::vec3 &origin, const helios::vec3 &rotation_axis_vector ) override;
+
1489
+
1491 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
+
1492
+
1493};
+
1494
+
1496
+
1501class Triangle : public Primitive{
+
1502public:
+
1503
+
1505
+
1513 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBAcolor& color, uint parent_objID, uint UUID );
+
1514
+
1516
+
1525 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texturefile, const std::vector<helios::vec2>& uv, float solid_fraction, uint parent_objID, uint UUID );
+
1526
+
1528
+
1538 Triangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texturefile, const std::vector<helios::vec2>& uv, const std::map<std::string,Texture> &textures, uint parent_objID, uint UUID );
+
1539
+
1541 ~Triangle() override= default;
1542
-
1544
-
1547 helios::vec3 getNormal() const override;
+
1544
+
1547 float getArea() const override;
1548
-
1550
-
1553 std::vector<helios::vec3> getVertices() const override;
+
1550
+
1553 helios::vec3 getNormal() const override;
1554
-
1556
-
1560 helios::vec3 getVertex( int vertex_index );
-
1561
-
1563
-
1566 helios::vec3 getCenter() const override;
+
1556
+
1559 std::vector<helios::vec3> getVertices() const override;
+
1560
+
1562
+
1566 helios::vec3 getVertex( int vertex_index );
1567
-
1569
-
1573 void rotate(float rotation_radians, const char* rotation_axis_xyz_string ) override;
-
1574
-
1576
-
1580 void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ) override;
-
1581
-
1583
-
1588 void rotate(float rotation_radians, const helios::vec3 &origin, const helios::vec3 &rotation_axis_vector ) override;
-
1589
-
1591 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
-
1592
-
1594
-
1599 void setVertices(const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
-
1600
-
1601private:
-
1602
-
1603// //!(x,y,z) coordinates of triangle vertex #0
-
1604// helios::vec3 vertex0;
-
1605//
-
1606// //!(x,y,z) coordinates of triangle vertex #1
-
1607// helios::vec3 vertex1;
-
1608//
-
1609// //!(x,y,z) coordinates of triangle vertex #2
-
1610// helios::vec3 vertex2;
-
1611
-
1612 void makeTransformationMatrix( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
-
1613
-
1614 bool edgeFunction(const helios::vec2 &a, const helios::vec2 &b, const helios::vec2 &c);
-
1615
-
1616};
-
1617
+
1569
+
1572 helios::vec3 getCenter() const override;
+
1573
+
1575
+
1579 void rotate(float rotation_radians, const char* rotation_axis_xyz_string ) override;
+
1580
+
1582
+
1586 void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ) override;
+
1587
+
1589
+
1594 void rotate(float rotation_radians, const helios::vec3 &origin, const helios::vec3 &rotation_axis_vector ) override;
+
1595
+
1597 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
+
1598
+
1600
+
1605 void setVertices(const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
+
1606
+
1607private:
+
1608
+
1609// //!(x,y,z) coordinates of triangle vertex #0
+
1610// helios::vec3 vertex0;
+
1611//
+
1612// //!(x,y,z) coordinates of triangle vertex #1
+
1613// helios::vec3 vertex1;
+
1614//
+
1615// //!(x,y,z) coordinates of triangle vertex #2
+
1616// helios::vec3 vertex2;
+
1617
+
1618 void makeTransformationMatrix( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
1619
-
1622class Voxel : public Primitive{
-
1623public:
-
1624
-
1626
-
1631 Voxel( const helios::RGBAcolor& color, uint parent_objID, uint UUID );
-
1632
-
1634 ~Voxel() override= default;
-
1635
-
1637
-
1640 float getArea() const override;
+
1620 bool edgeFunction(const helios::vec2 &a, const helios::vec2 &b, const helios::vec2 &c);
+
1621
+
1622};
+
1623
+
1625
+
1628class Voxel : public Primitive{
+
1629public:
+
1630
+
1632
+
1637 Voxel( const helios::RGBAcolor& color, uint parent_objID, uint UUID );
+
1638
+
1640 ~Voxel() override= default;
1641
-
1643 helios::vec3 getNormal() const override;
-
1644
-
1646
-
1649 std::vector<helios::vec3> getVertices() const override;
+
1643
+
1646 float getArea() const override;
+
1647
+
1649 helios::vec3 getNormal() const override;
1650
-
1652
-
1655 float getVolume();
+
1652
+
1655 std::vector<helios::vec3> getVertices() const override;
1656
-
1658
-
1661 helios::vec3 getCenter() const override;
+
1658
+
1661 float getVolume();
1662
-
1664
-
1667 helios::vec3 getSize();
+
1664
+
1667 helios::vec3 getCenter() const override;
1668
-
1670
-
1674 void rotate(float rotation_radians, const char* rotation_axis_xyz_string ) override;
-
1675
-
1677
-
1681 void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ) override;
-
1682
-
1683
-
1685
-
1690 void rotate(float rotation_radians, const helios::vec3 &origin, const helios::vec3 &rotation_axis_vector ) override;
-
1691
-
1693 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
-
1694
-
1695};
-
1696
-
- -
1699public:
-
1700
-
1702
-
1707 static int parse_data_float( const pugi::xml_node &node_data, std::vector<float> &data );
-
1708
-
1710
-
1715 static int parse_data_double( const pugi::xml_node &node_data, std::vector<double> &data );
-
1716
-
1718
-
1723 static int parse_data_int( const pugi::xml_node &node_data, std::vector<int> &data );
-
1724
-
1726
-
1731 static int parse_data_uint( const pugi::xml_node &node_data, std::vector<uint> &data );
-
1732
-
1734
-
1739 static int parse_data_string( const pugi::xml_node &node_data, std::vector<std::string> &data );
-
1740
-
1742
-
1747 static int parse_data_vec2( const pugi::xml_node &node_data, std::vector<vec2> &data );
-
1748
-
1750
-
1755 static int parse_data_vec3( const pugi::xml_node &node_data, std::vector<vec3> &data );
-
1756
-
1758
-
1763 static int parse_data_vec4( const pugi::xml_node &node_data, std::vector<vec4> &data );
-
1764
-
1766
-
1771 static int parse_data_int2( const pugi::xml_node &node_data, std::vector<int2> &data );
-
1772
-
1774
-
1779 static int parse_data_int3( const pugi::xml_node &node_data, std::vector<int3> &data );
-
1780
-
1782
-
1787 static int parse_data_int4( const pugi::xml_node &node_data, std::vector<int4> &data );
-
1788
-
1790
-
1795 static int parse_objID( const pugi::xml_node &node_data, uint &objID );
-
1796
-
1798
-
1803 static int parse_transform( const pugi::xml_node &node_data, float (&transform)[16] );
-
1804
-
1806
-
1811 static int parse_texture( const pugi::xml_node &node_data, std::string &texture );
-
1812
-
1814
-
1819 static int parse_textureUV( const pugi::xml_node &node_data, std::vector<vec2> &uvs );
-
1820
-
1822
-
1827 static int parse_solid_fraction( const pugi::xml_node &node_data, float &solid_fraction );
-
1828
-
1830
-
1835 static int parse_vertices( const pugi::xml_node &node_data, std::vector<float> &vertices );
-
1836
-
1838
-
1843 static int parse_subdivisions( const pugi::xml_node &node_data, uint &subdivisions );
-
1844
-
1846
-
1851 static int parse_subdivisions( const pugi::xml_node &node_data, int2 &subdivisions );
-
1852
-
1854
-
1859 static int parse_subdivisions( const pugi::xml_node &node_data, int3 &subdivisions );
-
1860
-
1862
-
1867 static int parse_nodes( const pugi::xml_node &node_data, std::vector<vec3> &nodes );
-
1868
-
1870
-
1875 static int parse_radius( const pugi::xml_node &node_data, std::vector<float> &radius );
-
1876
-
1877};
+
1670
+
1673 helios::vec3 getSize();
+
1674
+
1676
+
1680 void rotate(float rotation_radians, const char* rotation_axis_xyz_string ) override;
+
1681
+
1683
+
1687 void rotate(float rotation_radians, const helios::vec3& rotation_axis_vector ) override;
+
1688
+
1689
+
1691
+
1696 void rotate(float rotation_radians, const helios::vec3 &origin, const helios::vec3 &rotation_axis_vector ) override;
+
1697
+
1699 void calculateSolidFraction( const std::map<std::string,Texture> &textures ) override;
+
1700
+
1701};
+
1702
+
+ +
1705public:
+
1706
+
1708
+
1713 static int parse_data_float( const pugi::xml_node &node_data, std::vector<float> &data );
+
1714
+
1716
+
1721 static int parse_data_double( const pugi::xml_node &node_data, std::vector<double> &data );
+
1722
+
1724
+
1729 static int parse_data_int( const pugi::xml_node &node_data, std::vector<int> &data );
+
1730
+
1732
+
1737 static int parse_data_uint( const pugi::xml_node &node_data, std::vector<uint> &data );
+
1738
+
1740
+
1745 static int parse_data_string( const pugi::xml_node &node_data, std::vector<std::string> &data );
+
1746
+
1748
+
1753 static int parse_data_vec2( const pugi::xml_node &node_data, std::vector<vec2> &data );
+
1754
+
1756
+
1761 static int parse_data_vec3( const pugi::xml_node &node_data, std::vector<vec3> &data );
+
1762
+
1764
+
1769 static int parse_data_vec4( const pugi::xml_node &node_data, std::vector<vec4> &data );
+
1770
+
1772
+
1777 static int parse_data_int2( const pugi::xml_node &node_data, std::vector<int2> &data );
+
1778
+
1780
+
1785 static int parse_data_int3( const pugi::xml_node &node_data, std::vector<int3> &data );
+
1786
+
1788
+
1793 static int parse_data_int4( const pugi::xml_node &node_data, std::vector<int4> &data );
+
1794
+
1796
+
1801 static int parse_objID( const pugi::xml_node &node_data, uint &objID );
+
1802
+
1804
+
1809 static int parse_transform( const pugi::xml_node &node_data, float (&transform)[16] );
+
1810
+
1812
+
1817 static int parse_texture( const pugi::xml_node &node_data, std::string &texture );
+
1818
+
1820
+
1825 static int parse_textureUV( const pugi::xml_node &node_data, std::vector<vec2> &uvs );
+
1826
+
1828
+
1833 static int parse_solid_fraction( const pugi::xml_node &node_data, float &solid_fraction );
+
1834
+
1836
+
1841 static int parse_vertices( const pugi::xml_node &node_data, std::vector<float> &vertices );
+
1842
+
1844
+
1849 static int parse_subdivisions( const pugi::xml_node &node_data, uint &subdivisions );
+
1850
+
1852
+
1857 static int parse_subdivisions( const pugi::xml_node &node_data, int2 &subdivisions );
+
1858
+
1860
+
1865 static int parse_subdivisions( const pugi::xml_node &node_data, int3 &subdivisions );
+
1866
+
1868
+
1873 static int parse_nodes( const pugi::xml_node &node_data, std::vector<vec3> &nodes );
+
1874
+
1876
+
1881 static int parse_radius( const pugi::xml_node &node_data, std::vector<float> &radius );
+
1882
+
1883};
-
1878
-
1880
-
- -
1883private:
-
1884
-
1885 //---------- PRIMITIVE/OBJECT HELIOS::VECTORS ----------------//
-
1886
-
1888
-
1892 Primitive* getPrimitivePointer_private( uint UUID ) const;
-
1893
-
1895
-
1899 Patch* getPatchPointer_private( uint UUID ) const;
-
1900
-
1901
-
1903
-
1907 Triangle* getTrianglePointer_private( uint UUID ) const;
-
1908
-
1909
-
1911
-
1915 Voxel* getVoxelPointer_private( uint UUID ) const;
-
1916
-
1918
-
1922 CompoundObject* getObjectPointer_private( uint ObjID ) const;
-
1923
-
1925
-
1929 Tile* getTileObjectPointer_private( uint ObjID ) const;
-
1930
-
1932
-
1936 Sphere* getSphereObjectPointer_private( uint ObjID ) const;
-
1937
-
1939
-
1943 Tube* getTubeObjectPointer_private( uint ObjID ) const;
-
1944
-
1946
-
1950 Box* getBoxObjectPointer_private( uint ObjID ) const;
-
1951
-
1953
-
1957 Disk* getDiskObjectPointer_private( uint ObjID ) const;
-
1958
-
1960
-
1964 Polymesh* getPolymeshObjectPointer_private( uint ObjID ) const;
-
1965
-
1967
-
1971 Cone* getConeObjectPointer_private( uint ObjID ) const;
-
1972
-
1973
-
1975
-
1976 std::map<uint,Primitive*> primitives;
-
1977
-
1979 std::map<uint,CompoundObject*> objects;
-
1980
-
1982 std::map<std::string, std::vector<float> > timeseries_data;
+
1884
+
1886
+
+ +
1889private:
+
1890
+
1891 //---------- PRIMITIVE/OBJECT HELIOS::VECTORS ----------------//
+
1892
+
1894
+
1898 Primitive* getPrimitivePointer_private( uint UUID ) const;
+
1899
+
1901
+
1905 Patch* getPatchPointer_private( uint UUID ) const;
+
1906
+
1907
+
1909
+
1913 Triangle* getTrianglePointer_private( uint UUID ) const;
+
1914
+
1915
+
1917
+
1921 Voxel* getVoxelPointer_private( uint UUID ) const;
+
1922
+
1924
+
1928 CompoundObject* getObjectPointer_private( uint ObjID ) const;
+
1929
+
1931
+
1935 Tile* getTileObjectPointer_private( uint ObjID ) const;
+
1936
+
1938
+
1942 Sphere* getSphereObjectPointer_private( uint ObjID ) const;
+
1943
+
1945
+
1949 Tube* getTubeObjectPointer_private( uint ObjID ) const;
+
1950
+
1952
+
1956 Box* getBoxObjectPointer_private( uint ObjID ) const;
+
1957
+
1959
+
1963 Disk* getDiskObjectPointer_private( uint ObjID ) const;
+
1964
+
1966
+
1970 Polymesh* getPolymeshObjectPointer_private( uint ObjID ) const;
+
1971
+
1973
+
1977 Cone* getConeObjectPointer_private( uint ObjID ) const;
+
1978
+
1979
+
1981
+
1982 std::map<uint,Primitive*> primitives;
1983
-
1985
-
1986 std::map<std::string, std::vector<double> > timeseries_datevalue;
-
1987
-
1988 //------------ TEXTURES ----------------//
+
1985 std::map<uint,CompoundObject*> objects;
+
1986
+
1988 std::map<std::string, std::vector<float> > timeseries_data;
1989
-
1990 std::map<std::string,Texture> textures;
-
1991
-
1992 void addTexture( const char* texture_file );
-
1993
-
1994 bool doesTextureFileExist(const char* texture_file ) const;
-
1995
-
1996 bool validateTextureFileExtenstion( const char* texture_file ) const;
+
1991
+
1992 std::map<std::string, std::vector<double> > timeseries_datevalue;
+
1993
+
1994 //------------ TEXTURES ----------------//
+
1995
+
1996 std::map<std::string,Texture> textures;
1997
-
1998 //----------- GLOBAL DATA -------------//
-
1999
-
2000 std::map<std::string, GlobalData> globaldata;
-
2001
-
2002 //---------- CONTEXT PRIVATE MEMBER VARIABLES ---------//
+
1998 void addTexture( const char* texture_file );
+
1999
+
2000 bool doesTextureFileExist(const char* texture_file ) const;
+
2001
+
2002 bool validateTextureFileExtenstion( const char* texture_file ) const;
2003
-
2005
-
2008 helios::Date sim_date;
+
2004 //----------- GLOBAL DATA -------------//
+
2005
+
2006 std::map<std::string, GlobalData> globaldata;
+
2007
+
2008 //---------- CONTEXT PRIVATE MEMBER VARIABLES ---------//
2009
-
2011
-
2014 helios::Time sim_time;
-
2015
-
2017 helios::Location sim_location;
-
2018
-
2020 std::minstd_rand0 generator;
-
2021
-
2023 std::uniform_real_distribution<float> unif_distribution;
+
2011
+
2014 helios::Date sim_date;
+
2015
+
2017
+
2020 helios::Time sim_time;
+
2021
+
2023 helios::Location sim_location;
2024
-
2026 std::normal_distribution<float> norm_distribution;
+
2026 std::minstd_rand0 generator;
2027
-
2028 //---------- CONTEXT I/O ---------//
-
2029
-
2030 std::vector<std::string> XMLfiles;
-
2031
-
2032 struct OBJmaterial{
-
2033
-
2034 RGBcolor color;
-
2035 std::string texture;
-
2036 uint materialID;
-
2037 bool textureHasTransparency = false;
-
2038 bool textureColorIsOverridden = false;
+
2029 std::uniform_real_distribution<float> unif_distribution;
+
2030
+
2032 std::normal_distribution<float> norm_distribution;
+
2033
+
2034 //---------- CONTEXT I/O ---------//
+
2035
+
2036 std::vector<std::string> XMLfiles;
+
2037
+
2038 struct OBJmaterial{
2039
-
2040 OBJmaterial( const RGBcolor &a_color, std::string a_texture, uint a_materialID ) : color{a_color}, texture{std::move(a_texture)}, materialID{a_materialID} {};
-
2041
-
2042 };
-
2043
-
2044 static std::map<std::string,OBJmaterial> loadMTL(const std::string &filebase, const std::string &material_file );
-
2045
-
2046 void loadPData( pugi::xml_node p, uint UUID );
-
2047
-
2048 void loadOData( pugi::xml_node p, uint ID );
+
2040 RGBcolor color;
+
2041 std::string texture;
+
2042 uint materialID;
+
2043 bool textureHasTransparency = false;
+
2044 bool textureColorIsOverridden = false;
+
2045
+
2046 OBJmaterial( const RGBcolor &a_color, std::string a_texture, uint a_materialID ) : color{a_color}, texture{std::move(a_texture)}, materialID{a_materialID} {};
+
2047
+
2048 };
2049
-
2050 void loadOsubPData( pugi::xml_node p, uint ID );
+
2050 static std::map<std::string,OBJmaterial> loadMTL(const std::string &filebase, const std::string &material_file );
2051
-
2052 void writeDataToXMLstream( const char* data_group, const std::vector<std::string> &data_labels, void* ptr, std::ofstream &outfile ) const;
-
2053
-
2054 std::vector<std::string> generateTexturesFromColormap( const std::string &texturefile, const std::vector<RGBcolor> &colormap_data );
-
2055
-
2056 std::vector<RGBcolor> generateColormap( const std::string &colormap, uint Ncolors );
-
2057
-
2058 std::vector<RGBcolor> generateColormap( const std::vector<helios::RGBcolor> &ctable, const std::vector<float> &cfrac, uint Ncolors );
+
2052 void loadPData( pugi::xml_node p, uint UUID );
+
2053
+
2054 void loadOData( pugi::xml_node p, uint ID );
+
2055
+
2056 void loadOsubPData( pugi::xml_node p, uint ID );
+
2057
+
2058 void writeDataToXMLstream( const char* data_group, const std::vector<std::string> &data_labels, void* ptr, std::ofstream &outfile ) const;
2059
-
2060
-
2061 //---------- CONTEXT INITIALIZATION FLAGS ---------//
-
2062
-
2064 bool isgeometrydirty;
-
2065
-
2066 uint currentUUID;
-
2067
-
2068 uint currentObjectID;
-
2069
-
2070public:
+
2060 std::vector<std::string> generateTexturesFromColormap( const std::string &texturefile, const std::vector<RGBcolor> &colormap_data );
+
2061
+
2062 std::vector<RGBcolor> generateColormap( const std::string &colormap, uint Ncolors );
+
2063
+
2064 std::vector<RGBcolor> generateColormap( const std::vector<helios::RGBcolor> &ctable, const std::vector<float> &cfrac, uint Ncolors );
+
2065
+
2066
+
2067 //---------- CONTEXT INITIALIZATION FLAGS ---------//
+
2068
+
2070 bool isgeometrydirty;
2071
-
2073 Context();
-
2074
-
2076 ~Context();
-
2077
-
2079 Context( const Context& ) = delete;
-
2080
-
2082 void operator=( const Context& ) = delete;
-
2083
-
2085
-
2088 static int selfTest();
-
2089
-
2091
-
2094 void seedRandomGenerator(uint seed);
-
2095
-
2097
-
2100 std::minstd_rand0* getRandomGenerator();
-
2101
-
2103
-
2107 void markGeometryClean();
-
2108
-
2110
-
2114 void markGeometryDirty();
-
2115
-
2117
-
2121 bool isGeometryDirty() const;
-
2122
-
2124
-
2127 uint addPatch();
+
2072 uint currentUUID;
+
2073
+
2074 uint currentObjectID;
+
2075
+
2076public:
+
2077
+
2079 Context();
+
2080
+
2082 ~Context();
+
2083
+
2085 Context( const Context& ) = delete;
+
2086
+
2088 void operator=( const Context& ) = delete;
+
2089
+
2091
+
2094 static int selfTest();
+
2095
+
2097
+
2100 void seedRandomGenerator(uint seed);
+
2101
+
2103
+
2106 std::minstd_rand0* getRandomGenerator();
+
2107
+
2109
+
2113 void markGeometryClean();
+
2114
+
2116
+
2120 void markGeometryDirty();
+
2121
+
2123
+
2127 bool isGeometryDirty() const;
2128
-
2130
-
2137 uint addPatch( const helios::vec3& center, const helios::vec2& size );
-
2138
-
2140
-
2148 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
-
2149
-
2151
-
2158 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
2159
-
2161
-
2167 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
2168
-
2170
-
2178 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
-
2179
-
2181
-
2191 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file, const helios::vec2& uv_center, const helios::vec2& uv_size );
-
2192
-
2194
-
2201 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
-
2202
-
2204
-
2212 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBcolor& color );
-
2213
-
2215
-
2223 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBAcolor& color );
-
2224
-
2226
-
2238 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texture_file, const helios::vec2& uv0, const helios::vec2& uv1, const helios::vec2& uv2 );
-
2239
-
2241
-
2248 uint addVoxel( const helios::vec3& center, const helios::vec3& size );
-
2249
-
2251
-
2259 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation );
-
2260
-
2262
-
2269 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation, const helios::RGBcolor& color );
-
2270
-
2272
-
2279 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation, const helios::RGBAcolor& color );
-
2280
-
2282
-
2286 void translatePrimitive( uint UUID, const vec3& shift );
-
2287
-
2289
-
2293 void translatePrimitive( const std::vector<uint>& UUIDs, const vec3& shift );
-
2294
-
2296
-
2301 void rotatePrimitive( uint UUID, float rot, const char* axis );
-
2302
-
2304
-
2309 void rotatePrimitive( const std::vector<uint>& UUIDs, float rot, const char* axis );
-
2310
-
2312
-
2317 void rotatePrimitive( uint UUID, float rot, const helios::vec3& axis );
-
2318
-
2320
-
2325 void rotatePrimitive(const std::vector<uint>& UUIDs, float rot, const vec3 &axis );
-
2326
-
2328
-
2334 void rotatePrimitive( uint UUID, float rot, const helios::vec3& origin, const helios::vec3& axis );
-
2335
-
2337
-
2343 void rotatePrimitive(const std::vector<uint>& UUIDs, float rot, const helios::vec3& origin, const vec3 &axis );
-
2344
-
2346
-
2350 void scalePrimitive( uint UUID, const helios::vec3& S );
-
2351
-
2353
-
2357 void scalePrimitive( const std::vector<uint>& UUIDs, const helios::vec3& S );
-
2358
-
2360
-
2365 void scalePrimitiveAboutPoint( uint UUID, const helios::vec3& S, const helios::vec3 point );
-
2366
-
2368
-
2373 void scalePrimitiveAboutPoint( const std::vector<uint>& UUIDs, const helios::vec3& S, const helios::vec3 point );
-
2374
-
2376
-
2379 void deletePrimitive( uint UUID );
+
2130
+
2133 uint addPatch();
+
2134
+
2136
+
2143 uint addPatch( const helios::vec3& center, const helios::vec2& size );
+
2144
+
2146
+
2154 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
+
2155
+
2157
+
2164 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
+
2165
+
2167
+
2173 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
+
2174
+
2176
+
2184 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
+
2185
+
2187
+
2197 uint addPatch( const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file, const helios::vec2& uv_center, const helios::vec2& uv_size );
+
2198
+
2200
+
2207 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
+
2208
+
2210
+
2218 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBcolor& color );
+
2219
+
2221
+
2229 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const helios::RGBAcolor& color );
+
2230
+
2232
+
2244 uint addTriangle( const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2, const char* texture_file, const helios::vec2& uv0, const helios::vec2& uv1, const helios::vec2& uv2 );
+
2245
+
2247
+
2254 uint addVoxel( const helios::vec3& center, const helios::vec3& size );
+
2255
+
2257
+
2265 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation );
+
2266
+
2268
+
2275 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation, const helios::RGBcolor& color );
+
2276
+
2278
+
2285 uint addVoxel( const helios::vec3& center, const helios::vec3& size, const float& rotation, const helios::RGBAcolor& color );
+
2286
+
2288
+
2292 void translatePrimitive( uint UUID, const vec3& shift );
+
2293
+
2295
+
2299 void translatePrimitive( const std::vector<uint>& UUIDs, const vec3& shift );
+
2300
+
2302
+
2307 void rotatePrimitive( uint UUID, float rot, const char* axis );
+
2308
+
2310
+
2315 void rotatePrimitive( const std::vector<uint>& UUIDs, float rot, const char* axis );
+
2316
+
2318
+
2323 void rotatePrimitive( uint UUID, float rot, const helios::vec3& axis );
+
2324
+
2326
+
2331 void rotatePrimitive(const std::vector<uint>& UUIDs, float rot, const vec3 &axis );
+
2332
+
2334
+
2340 void rotatePrimitive( uint UUID, float rot, const helios::vec3& origin, const helios::vec3& axis );
+
2341
+
2343
+
2349 void rotatePrimitive(const std::vector<uint>& UUIDs, float rot, const helios::vec3& origin, const vec3 &axis );
+
2350
+
2352
+
2356 void scalePrimitive( uint UUID, const helios::vec3& S );
+
2357
+
2359
+
2363 void scalePrimitive( const std::vector<uint>& UUIDs, const helios::vec3& S );
+
2364
+
2366
+
2371 void scalePrimitiveAboutPoint( uint UUID, const helios::vec3& S, const helios::vec3 point );
+
2372
+
2374
+
2379 void scalePrimitiveAboutPoint( const std::vector<uint>& UUIDs, const helios::vec3& S, const helios::vec3 point );
2380
-
2382
-
2385 void deletePrimitive( const std::vector<uint>& UUIDs );
+
2382
+
2385 void deletePrimitive( uint UUID );
2386
-
2388
-
2392 uint copyPrimitive(uint UUID );
-
2393
-
2395
-
2399 std::vector<uint> copyPrimitive(const std::vector<uint> &UUIDs );
-
2400
-
2402
-
2406 void copyPrimitiveData(uint sourceUUID, uint destinationUUID);
-
2407
-
2409
-
2414 void renamePrimitiveData( uint UUID, const char* old_label, const char* new_label );
-
2415
-
2417
-
2422 void duplicatePrimitiveData( uint UUID, const char* old_label, const char* new_label );
-
2423
-
2425
-
2428 bool doesPrimitiveExist( uint UUID ) const;
-
2429
-
2431
-
2435 bool doesPrimitiveExist( const std::vector<uint> &UUIDs ) const;
-
2436
-
2438
-
2443 helios::vec2 getPatchSize( uint UUID ) const;
-
2444
-
2446
-
2451 helios::vec3 getPatchCenter( uint UUID ) const;
-
2452
-
2454
-
2460 helios::vec3 getTriangleVertex( uint UUID, uint number ) const;
-
2461
-
2463
-
2469 void setTriangleVertices( uint UUID, const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
-
2470
-
2472
-
2477 helios::vec3 getVoxelCenter( uint UUID ) const;
-
2478
-
2480
-
2485 helios::vec3 getVoxelSize( uint UUID ) const;
-
2486
-
2488
-
2492 uint getPrimitiveCount() const;
-
2493
-
2495 std::vector<uint> getAllUUIDs() const;
-
2496
-
2498
-
2501 void hidePrimitive( const std::vector<uint> &UUIDs );
-
2502
-
2504
-
2508 bool isPrimitiveHidden( uint UUID ) const;
-
2509
-
2511
-
2514 void cleanDeletedUUIDs( std::vector<uint> &UUIDs ) const;
-
2515
-
2517
-
2520 void cleanDeletedUUIDs( std::vector<std::vector<uint>> &UUIDs ) const;
-
2521
-
2523
-
2526 void cleanDeletedUUIDs( std::vector<std::vector<std::vector<uint>>> &UUIDs ) const;
-
2527
-
2528 //-------- Primitive Data Methods ---------- //
-
2529
-
2531
-
2536 void setPrimitiveData( const uint& UUID, const char* label, const int& data );
-
2537
-
2539
-
2544 void setPrimitiveData( const uint& UUID, const char* label, const uint& data );
-
2545
-
2547
-
2552 void setPrimitiveData( const uint& UUID, const char* label, const float& data );
-
2553
-
2555
-
2559 void setPrimitiveData( const uint& UUID, const char* label, const double& data );
-
2560
-
2562
-
2567 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec2& data );
-
2568
-
2570
-
2575 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec3& data );
-
2576
-
2578
-
2583 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec4& data );
-
2584
-
2586
-
2591 void setPrimitiveData( const uint& UUID, const char* label, const helios::int2& data );
-
2592
-
2594
-
2599 void setPrimitiveData( const uint& UUID, const char* label, const helios::int3& data );
-
2600
-
2602
-
2607 void setPrimitiveData( const uint& UUID, const char* label, const helios::int4& data );
-
2608
-
2610
-
2615 void setPrimitiveData( const uint& UUID, const char* label, const std::string& data );
-
2616
-
2618
-
2625 void setPrimitiveData( const uint& UUIDs, const char* label, HeliosDataType type, uint size, void* data );
-
2626
-
2628
-
2633 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const int& data );
-
2634
-
2636
-
2641 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const uint& data );
-
2642
-
2644
-
2649 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const float& data );
-
2650
-
2652
-
2656 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const double& data );
-
2657
-
2659
-
2664 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec2& data );
-
2665
-
2667
-
2672 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec3& data );
-
2673
-
2675
-
2680 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec4& data );
-
2681
-
2683
-
2688 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int2& data );
-
2689
-
2691
-
2696 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int3& data );
-
2697
-
2699
-
2704 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int4& data );
-
2705
-
2707
-
2712 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const std::string& data );
-
2713
-
2715
-
2720 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const int& data );
-
2721
-
2723
-
2728 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const uint& data );
-
2729
-
2731
-
2736 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const float& data );
-
2737
-
2739
-
2743 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const double& data );
-
2744
-
2746
-
2751 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec2& data );
-
2752
-
2754
-
2759 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec3& data );
-
2760
-
2762
-
2767 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec4& data );
-
2768
-
2770
-
2775 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int2& data );
-
2776
-
2778
-
2783 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int3& data );
-
2784
-
2786
-
2791 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int4& data );
-
2792
-
2794
-
2799 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const std::string& data );
-
2800
-
2802
-
2807 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const int& data );
-
2808
-
2810
-
2815 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const uint& data );
-
2816
-
2818
-
2823 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const float& data );
-
2824
-
2826
-
2830 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const double& data );
-
2831
-
2833
-
2838 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec2& data );
-
2839
-
2841
-
2846 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec3& data );
-
2847
-
2849
-
2854 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec4& data );
-
2855
-
2857
-
2862 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int2& data );
-
2863
-
2865
-
2870 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int3& data );
-
2871
-
2873
-
2878 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int4& data );
-
2879
-
2881
-
2886 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const std::string& data );
-
2887
-
2889
-
2894 void getPrimitiveData( uint UUID, const char* label, int& data ) const;
-
2895
-
2897
-
2902 void getPrimitiveData( uint UUID, const char* label, std::vector<int>& data ) const;
-
2903
-
2905
-
2910 void getPrimitiveData( uint UUID, const char* label, uint& data ) const;
-
2911
-
2913
-
2918 void getPrimitiveData( uint UUID, const char* label, std::vector<uint>& data ) const;
-
2919
-
2921
-
2926 void getPrimitiveData( uint UUID, const char* label, float& data ) const;
-
2927
-
2929
-
2934 void getPrimitiveData( uint UUID, const char* label, std::vector<float>& data ) const;
-
2935
-
2937
-
2942 void getPrimitiveData( uint UUID, const char* label, double& data ) const;
-
2943
-
2945
-
2950 void getPrimitiveData( uint UUID, const char* label, std::vector<double>& data ) const;
-
2951
-
2953
-
2958 void getPrimitiveData( uint UUID, const char* label, vec2& data ) const;
-
2959
-
2961
-
2966 void getPrimitiveData( uint UUID, const char* label, std::vector<vec2>& data ) const;
-
2967
-
2969
-
2974 void getPrimitiveData( uint UUID, const char* label, vec3& data ) const;
-
2975
-
2977
-
2982 void getPrimitiveData( uint UUID, const char* label, std::vector<vec3>& data ) const;
-
2983
-
2985
-
2990 void getPrimitiveData( uint UUID, const char* label, vec4& data ) const;
-
2991
-
2993
-
2998 void getPrimitiveData( uint UUID, const char* label, std::vector<vec4>& data ) const;
-
2999
-
3001
-
3006 void getPrimitiveData( uint UUID, const char* label, int2& data ) const;
-
3007
-
3009
-
3014 void getPrimitiveData( uint UUID, const char* label, std::vector<int2>& data ) const;
-
3015
-
3017
-
3022 void getPrimitiveData( uint UUID, const char* label, int3& data ) const;
-
3023
-
3025
-
3030 void getPrimitiveData( uint UUID, const char* label, std::vector<int3>& data ) const;
-
3031
-
3033
-
3038 void getPrimitiveData( uint UUID, const char* label, int4& data ) const;
-
3039
-
3041
-
3046 void getPrimitiveData( uint UUID, const char* label, std::vector<int4>& data ) const;
-
3047
-
3049
-
3054 void getPrimitiveData( uint UUID, const char* label, std::string& data ) const;
-
3055
-
3057
-
3062 void getPrimitiveData( uint UUID, const char* label, std::vector<std::string>& data ) const;
-
3063
-
3065
-
3071 HeliosDataType getPrimitiveDataType( uint UUID, const char* label ) const;
-
3072
-
3074
-
3079 uint getPrimitiveDataSize( uint UUID, const char* label ) const;
-
3080
-
3082
-
3087 bool doesPrimitiveDataExist( uint UUID, const char* label ) const;
-
3088
-
3090
-
3094 void clearPrimitiveData( uint UUID, const char* label );
-
3095
-
3097
-
3101 void clearPrimitiveData( const std::vector<uint>& UUIDs, const char* label );
-
3102
-
3104
-
3108 PrimitiveType getPrimitiveType( uint UUID ) const;
-
3109
-
3111
-
3115 void setPrimitiveParentObjectID( uint UUID, uint objID );
-
3116
-
3118
-
3122 void setPrimitiveParentObjectID( const std::vector<uint> &UUIDs, uint objID );
-
3123
-
3125
-
3128 uint getPrimitiveParentObjectID( uint UUID )const;
+
2388
+
2391 void deletePrimitive( const std::vector<uint>& UUIDs );
+
2392
+
2394
+
2398 uint copyPrimitive(uint UUID );
+
2399
+
2401
+
2405 std::vector<uint> copyPrimitive(const std::vector<uint> &UUIDs );
+
2406
+
2408
+
2412 void copyPrimitiveData(uint sourceUUID, uint destinationUUID);
+
2413
+
2415
+
2420 void renamePrimitiveData( uint UUID, const char* old_label, const char* new_label );
+
2421
+
2423
+
2428 void duplicatePrimitiveData( uint UUID, const char* old_label, const char* new_label );
+
2429
+
2431
+
2434 bool doesPrimitiveExist( uint UUID ) const;
+
2435
+
2437
+
2441 bool doesPrimitiveExist( const std::vector<uint> &UUIDs ) const;
+
2442
+
2444
+
2449 helios::vec2 getPatchSize( uint UUID ) const;
+
2450
+
2452
+
2457 helios::vec3 getPatchCenter( uint UUID ) const;
+
2458
+
2460
+
2466 helios::vec3 getTriangleVertex( uint UUID, uint number ) const;
+
2467
+
2469
+
2475 void setTriangleVertices( uint UUID, const helios::vec3& vertex0, const helios::vec3& vertex1, const helios::vec3& vertex2 );
+
2476
+
2478
+
2483 helios::vec3 getVoxelCenter( uint UUID ) const;
+
2484
+
2486
+
2491 helios::vec3 getVoxelSize( uint UUID ) const;
+
2492
+
2494
+
2498 uint getPrimitiveCount() const;
+
2499
+
2501 std::vector<uint> getAllUUIDs() const;
+
2502
+
2504
+
2507 void hidePrimitive( const std::vector<uint> &UUIDs );
+
2508
+
2510
+
2514 bool isPrimitiveHidden( uint UUID ) const;
+
2515
+
2517
+
2520 void cleanDeletedUUIDs( std::vector<uint> &UUIDs ) const;
+
2521
+
2523
+
2526 void cleanDeletedUUIDs( std::vector<std::vector<uint>> &UUIDs ) const;
+
2527
+
2529
+
2532 void cleanDeletedUUIDs( std::vector<std::vector<std::vector<uint>>> &UUIDs ) const;
+
2533
+
2534 //-------- Primitive Data Methods ---------- //
+
2535
+
2537
+
2542 void setPrimitiveData( const uint& UUID, const char* label, const int& data );
+
2543
+
2545
+
2550 void setPrimitiveData( const uint& UUID, const char* label, const uint& data );
+
2551
+
2553
+
2558 void setPrimitiveData( const uint& UUID, const char* label, const float& data );
+
2559
+
2561
+
2565 void setPrimitiveData( const uint& UUID, const char* label, const double& data );
+
2566
+
2568
+
2573 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec2& data );
+
2574
+
2576
+
2581 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec3& data );
+
2582
+
2584
+
2589 void setPrimitiveData( const uint& UUID, const char* label, const helios::vec4& data );
+
2590
+
2592
+
2597 void setPrimitiveData( const uint& UUID, const char* label, const helios::int2& data );
+
2598
+
2600
+
2605 void setPrimitiveData( const uint& UUID, const char* label, const helios::int3& data );
+
2606
+
2608
+
2613 void setPrimitiveData( const uint& UUID, const char* label, const helios::int4& data );
+
2614
+
2616
+
2621 void setPrimitiveData( const uint& UUID, const char* label, const std::string& data );
+
2622
+
2624
+
2631 void setPrimitiveData( const uint& UUIDs, const char* label, HeliosDataType type, uint size, void* data );
+
2632
+
2634
+
2639 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const int& data );
+
2640
+
2642
+
2647 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const uint& data );
+
2648
+
2650
+
2655 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const float& data );
+
2656
+
2658
+
2662 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const double& data );
+
2663
+
2665
+
2670 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec2& data );
+
2671
+
2673
+
2678 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec3& data );
+
2679
+
2681
+
2686 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::vec4& data );
+
2687
+
2689
+
2694 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int2& data );
+
2695
+
2697
+
2702 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int3& data );
+
2703
+
2705
+
2710 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const helios::int4& data );
+
2711
+
2713
+
2718 void setPrimitiveData( const std::vector<uint>& UUIDs, const char* label, const std::string& data );
+
2719
+
2721
+
2726 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const int& data );
+
2727
+
2729
+
2734 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const uint& data );
+
2735
+
2737
+
2742 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const float& data );
+
2743
+
2745
+
2749 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const double& data );
+
2750
+
2752
+
2757 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec2& data );
+
2758
+
2760
+
2765 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec3& data );
+
2766
+
2768
+
2773 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::vec4& data );
+
2774
+
2776
+
2781 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int2& data );
+
2782
+
2784
+
2789 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int3& data );
+
2790
+
2792
+
2797 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const helios::int4& data );
+
2798
+
2800
+
2805 void setPrimitiveData( const std::vector<std::vector<uint> >& UUIDs, const char* label, const std::string& data );
+
2806
+
2808
+
2813 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const int& data );
+
2814
+
2816
+
2821 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const uint& data );
+
2822
+
2824
+
2829 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const float& data );
+
2830
+
2832
+
2836 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const double& data );
+
2837
+
2839
+
2844 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec2& data );
+
2845
+
2847
+
2852 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec3& data );
+
2853
+
2855
+
2860 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::vec4& data );
+
2861
+
2863
+
2868 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int2& data );
+
2869
+
2871
+
2876 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int3& data );
+
2877
+
2879
+
2884 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const helios::int4& data );
+
2885
+
2887
+
2892 void setPrimitiveData( const std::vector<std::vector<std::vector<uint> > >& UUIDs, const char* label, const std::string& data );
+
2893
+
2895
+
2900 void getPrimitiveData( uint UUID, const char* label, int& data ) const;
+
2901
+
2903
+
2908 void getPrimitiveData( uint UUID, const char* label, std::vector<int>& data ) const;
+
2909
+
2911
+
2916 void getPrimitiveData( uint UUID, const char* label, uint& data ) const;
+
2917
+
2919
+
2924 void getPrimitiveData( uint UUID, const char* label, std::vector<uint>& data ) const;
+
2925
+
2927
+
2932 void getPrimitiveData( uint UUID, const char* label, float& data ) const;
+
2933
+
2935
+
2940 void getPrimitiveData( uint UUID, const char* label, std::vector<float>& data ) const;
+
2941
+
2943
+
2948 void getPrimitiveData( uint UUID, const char* label, double& data ) const;
+
2949
+
2951
+
2956 void getPrimitiveData( uint UUID, const char* label, std::vector<double>& data ) const;
+
2957
+
2959
+
2964 void getPrimitiveData( uint UUID, const char* label, vec2& data ) const;
+
2965
+
2967
+
2972 void getPrimitiveData( uint UUID, const char* label, std::vector<vec2>& data ) const;
+
2973
+
2975
+
2980 void getPrimitiveData( uint UUID, const char* label, vec3& data ) const;
+
2981
+
2983
+
2988 void getPrimitiveData( uint UUID, const char* label, std::vector<vec3>& data ) const;
+
2989
+
2991
+
2996 void getPrimitiveData( uint UUID, const char* label, vec4& data ) const;
+
2997
+
2999
+
3004 void getPrimitiveData( uint UUID, const char* label, std::vector<vec4>& data ) const;
+
3005
+
3007
+
3012 void getPrimitiveData( uint UUID, const char* label, int2& data ) const;
+
3013
+
3015
+
3020 void getPrimitiveData( uint UUID, const char* label, std::vector<int2>& data ) const;
+
3021
+
3023
+
3028 void getPrimitiveData( uint UUID, const char* label, int3& data ) const;
+
3029
+
3031
+
3036 void getPrimitiveData( uint UUID, const char* label, std::vector<int3>& data ) const;
+
3037
+
3039
+
3044 void getPrimitiveData( uint UUID, const char* label, int4& data ) const;
+
3045
+
3047
+
3052 void getPrimitiveData( uint UUID, const char* label, std::vector<int4>& data ) const;
+
3053
+
3055
+
3060 void getPrimitiveData( uint UUID, const char* label, std::string& data ) const;
+
3061
+
3063
+
3068 void getPrimitiveData( uint UUID, const char* label, std::vector<std::string>& data ) const;
+
3069
+
3071
+
3077 HeliosDataType getPrimitiveDataType( uint UUID, const char* label ) const;
+
3078
+
3080
+
3085 uint getPrimitiveDataSize( uint UUID, const char* label ) const;
+
3086
+
3088
+
3093 bool doesPrimitiveDataExist( uint UUID, const char* label ) const;
+
3094
+
3096
+
3100 void clearPrimitiveData( uint UUID, const char* label );
+
3101
+
3103
+
3107 void clearPrimitiveData( const std::vector<uint>& UUIDs, const char* label );
+
3108
+
3110
+
3114 PrimitiveType getPrimitiveType( uint UUID ) const;
+
3115
+
3117
+
3121 void setPrimitiveParentObjectID( uint UUID, uint objID );
+
3122
+
3124
+
3128 void setPrimitiveParentObjectID( const std::vector<uint> &UUIDs, uint objID );
3129
-
3131
-
3134 std::vector<uint> getUniquePrimitiveParentObjectIDs(const std::vector<uint> &UUIDs) const;
+
3131
+
3134 uint getPrimitiveParentObjectID( uint UUID )const;
3135
-
3137
-
3140 std::vector<uint> getUniquePrimitiveParentObjectIDs(const std::vector<uint> &UUIDs, bool include_ObjID_zero) const;
+
3137
+
3140 std::vector<uint> getUniquePrimitiveParentObjectIDs(const std::vector<uint> &UUIDs) const;
3141
-
3143
-
3146 float getPrimitiveArea( uint UUID ) const;
-
3147
-
3149
-
3154 void getPrimitiveBoundingBox( uint UUID, vec3 &min_corner, vec3 &max_corner ) const;
-
3155
-
3157
-
3162 void getPrimitiveBoundingBox( const std::vector<uint> &UUID, vec3 &min_corner, vec3 &max_corner ) const;
-
3163
-
3165
-
3168 void hideObject( const std::vector<uint> &ObjIDs );
-
3169
-
3171
-
3175 bool isObjectHidden( uint ObjID ) const;
-
3176
-
3178
-
3181 float getObjectArea( uint ObjID ) const;
+
3143
+
3146 std::vector<uint> getUniquePrimitiveParentObjectIDs(const std::vector<uint> &UUIDs, bool include_ObjID_zero) const;
+
3147
+
3149
+
3152 float getPrimitiveArea( uint UUID ) const;
+
3153
+
3155
+
3160 void getPrimitiveBoundingBox( uint UUID, vec3 &min_corner, vec3 &max_corner ) const;
+
3161
+
3163
+
3168 void getPrimitiveBoundingBox( const std::vector<uint> &UUID, vec3 &min_corner, vec3 &max_corner ) const;
+
3169
+
3171
+
3174 void hideObject( const std::vector<uint> &ObjIDs );
+
3175
+
3177
+
3181 bool isObjectHidden( uint ObjID ) const;
3182
-
3184
-
3187 uint getObjectPrimitiveCount( uint ObjID ) const;
+
3184
+
3187 float getObjectArea( uint ObjID ) const;
3188
-
3190
-
3193 helios::vec3 getObjectCenter( uint ObjID ) const;
-
3194
-
3196
-
3200 void setObjectColor( uint ObjID, const helios::RGBcolor& color );
-
3201
-
3203
-
3207 void setObjectColor( const std::vector<uint> &ObjIDs, const helios::RGBcolor& color );
-
3208
-
3210
-
3214 void setObjectColor( uint ObjID, const helios::RGBAcolor& color );
-
3215
-
3217
-
3221 void setObjectColor( const std::vector<uint> &ObjIDs, const helios::RGBAcolor& color );
-
3222
-
3224
-
3227 std::string getObjectTextureFile( uint ObjID ) const;
+
3190
+
3193 uint getObjectPrimitiveCount( uint ObjID ) const;
+
3194
+
3196
+
3199 helios::vec3 getObjectCenter( uint ObjID ) const;
+
3200
+
3202
+
3206 void setObjectColor( uint ObjID, const helios::RGBcolor& color );
+
3207
+
3209
+
3213 void setObjectColor( const std::vector<uint> &ObjIDs, const helios::RGBcolor& color );
+
3214
+
3216
+
3220 void setObjectColor( uint ObjID, const helios::RGBAcolor& color );
+
3221
+
3223
+
3227 void setObjectColor( const std::vector<uint> &ObjIDs, const helios::RGBAcolor& color );
3228
-
3230
-
3234 void getObjectTransformationMatrix( uint ObjID, float (&T)[16] ) const;
-
3235
-
3237
-
3241 void setObjectTransformationMatrix( uint ObjID, float (&T)[16] );
-
3242
-
3244
-
3248 void setObjectTransformationMatrix( const std::vector<uint> &ObjIDs, float (&T)[16] );
-
3249
-
3251
-
3254 bool objectHasTexture( uint ObjID ) const;
+
3230
+
3233 std::string getObjectTextureFile( uint ObjID ) const;
+
3234
+
3236
+
3240 void getObjectTransformationMatrix( uint ObjID, float (&T)[16] ) const;
+
3241
+
3243
+
3247 void setObjectTransformationMatrix( uint ObjID, float (&T)[16] );
+
3248
+
3250
+
3254 void setObjectTransformationMatrix( const std::vector<uint> &ObjIDs, float (&T)[16] );
3255
-
3257
-
3261 bool doesObjectContainPrimitive(uint ObjID, uint UUID );
-
3262
-
3264
-
3267 void overrideObjectTextureColor( uint ObjID );
-
3268
-
3270
-
3273 void overrideObjectTextureColor( const std::vector<uint> &ObjIDs );
-
3274
-
3276
-
3279 void useObjectTextureColor( uint ObjID );
-
3280
-
3282
-
3285 void useObjectTextureColor( const std::vector<uint> &ObjIDs );
-
3286
-
3288
-
3293 void getObjectBoundingBox( uint ObjID, vec3 &min_corner, vec3 &max_corner ) const;
-
3294
-
3296
-
3301 void getObjectBoundingBox( const std::vector<uint> &ObjID, vec3 &min_corner, vec3 &max_corner ) const;
-
3302
-
3304
-
3307 void printObjectInfo(uint ObjID) const;
+
3257
+
3260 bool objectHasTexture( uint ObjID ) const;
+
3261
+
3263
+
3267 bool doesObjectContainPrimitive(uint ObjID, uint UUID );
+
3268
+
3270
+
3273 void overrideObjectTextureColor( uint ObjID );
+
3274
+
3276
+
3279 void overrideObjectTextureColor( const std::vector<uint> &ObjIDs );
+
3280
+
3282
+
3285 void useObjectTextureColor( uint ObjID );
+
3286
+
3288
+
3291 void useObjectTextureColor( const std::vector<uint> &ObjIDs );
+
3292
+
3294
+
3299 void getObjectBoundingBox( uint ObjID, vec3 &min_corner, vec3 &max_corner ) const;
+
3300
+
3302
+
3307 void getObjectBoundingBox( const std::vector<uint> &ObjID, vec3 &min_corner, vec3 &max_corner ) const;
3308
-
3310 std::vector<std::string> listObjectData(uint ObjID) const;
-
3311
-
3313 std::vector<std::string> listPrimitiveData(uint UUID) const;
+
3310
+
3313 void printObjectInfo(uint ObjID) const;
3314
-
3316
-
3320 float getPrimitiveSolidFraction( uint UUID ) const;
-
3321
-
3323
-
3326 helios::vec3 getPrimitiveNormal( uint UUID ) const;
+
3316 std::vector<std::string> listObjectData(uint ObjID) const;
+
3317
+
3319 std::vector<std::string> listPrimitiveData(uint UUID) const;
+
3320
+
3322
+
3326 float getPrimitiveSolidFraction( uint UUID ) const;
3327
-
3329
-
3333 void getPrimitiveTransformationMatrix( uint UUID, float (&T)[16] ) const;
-
3334
-
3336
-
3340 void setPrimitiveTransformationMatrix( uint UUID, float (&T)[16] );
-
3341
-
3343
-
3347 void setPrimitiveTransformationMatrix( const std::vector<uint> &UUIDs, float (&T)[16] );
-
3348
-
3350
-
3353 std::vector<helios::vec3> getPrimitiveVertices( uint UUID ) const;
+
3329
+
3332 helios::vec3 getPrimitiveNormal( uint UUID ) const;
+
3333
+
3335
+
3339 void getPrimitiveTransformationMatrix( uint UUID, float (&T)[16] ) const;
+
3340
+
3342
+
3346 void setPrimitiveTransformationMatrix( uint UUID, float (&T)[16] );
+
3347
+
3349
+
3353 void setPrimitiveTransformationMatrix( const std::vector<uint> &UUIDs, float (&T)[16] );
3354
-
3356
-
3359 helios::RGBcolor getPrimitiveColor( uint UUID ) const;
+
3356
+
3359 std::vector<helios::vec3> getPrimitiveVertices( uint UUID ) const;
3360
-
3362
-
3365 helios::RGBcolor getPrimitiveColorRGB( uint UUID ) const;
+
3362
+
3365 helios::RGBcolor getPrimitiveColor( uint UUID ) const;
3366
-
3368
-
3371 helios::RGBAcolor getPrimitiveColorRGBA( uint UUID ) const;
+
3368
+
3371 helios::RGBcolor getPrimitiveColorRGB( uint UUID ) const;
3372
-
3374
-
3378 void setPrimitiveColor( uint UUID, const helios::RGBcolor& color );
-
3379
-
3381
-
3385 void setPrimitiveColor( const std::vector<uint> &UUIDs, const helios::RGBcolor& color );
-
3386
-
3388
-
3392 void setPrimitiveColor( uint UUID, const helios::RGBAcolor& color );
-
3393
-
3395
-
3399 void setPrimitiveColor( const std::vector<uint> &UUIDs, const helios::RGBAcolor& color );
-
3400
-
3402
-
3406 std::string getPrimitiveTextureFile( uint UUID ) const;
-
3407
-
3408
-
3410
-
3414 void setPrimitiveTextureFile( uint UUID, const std::string &texturefile );
-
3415
-
3417
-
3421 helios::int2 getPrimitiveTextureSize( uint UUID ) const;
-
3422
-
3424
-
3427 std::vector<vec2> getPrimitiveTextureUV( uint UUID ) const;
+
3374
+
3377 helios::RGBAcolor getPrimitiveColorRGBA( uint UUID ) const;
+
3378
+
3380
+
3384 void setPrimitiveColor( uint UUID, const helios::RGBcolor& color );
+
3385
+
3387
+
3391 void setPrimitiveColor( const std::vector<uint> &UUIDs, const helios::RGBcolor& color );
+
3392
+
3394
+
3398 void setPrimitiveColor( uint UUID, const helios::RGBAcolor& color );
+
3399
+
3401
+
3405 void setPrimitiveColor( const std::vector<uint> &UUIDs, const helios::RGBAcolor& color );
+
3406
+
3408
+
3412 std::string getPrimitiveTextureFile( uint UUID ) const;
+
3413
+
3414
+
3416
+
3420 void setPrimitiveTextureFile( uint UUID, const std::string &texturefile );
+
3421
+
3423
+
3427 helios::int2 getPrimitiveTextureSize( uint UUID ) const;
3428
-
3430
-
3434 bool primitiveTextureHasTransparencyChannel(uint UUID ) const;
-
3435
-
3437
-
3441 const std::vector<std::vector<bool>> * getPrimitiveTextureTransparencyData(uint UUID) const;
-
3442
-
3444
-
3447 void overridePrimitiveTextureColor( uint UUID );
-
3448
-
3450
-
3453 void overridePrimitiveTextureColor( const std::vector<uint> &UUIDs );
-
3454
-
3456
-
3459 void usePrimitiveTextureColor( uint UUID );
-
3460
-
3462
-
3465 void usePrimitiveTextureColor( const std::vector<uint> &UUIDs );
-
3466
-
3468
-
3471 bool isPrimitiveTextureColorOverridden( uint UUID ) const;
-
3472
-
3474
-
3477 void printPrimitiveInfo(uint UUID) const;
+
3430
+
3433 std::vector<vec2> getPrimitiveTextureUV( uint UUID ) const;
+
3434
+
3436
+
3440 bool primitiveTextureHasTransparencyChannel(uint UUID ) const;
+
3441
+
3443
+
3447 const std::vector<std::vector<bool>> * getPrimitiveTextureTransparencyData(uint UUID) const;
+
3448
+
3450
+
3453 void overridePrimitiveTextureColor( uint UUID );
+
3454
+
3456
+
3459 void overridePrimitiveTextureColor( const std::vector<uint> &UUIDs );
+
3460
+
3462
+
3465 void usePrimitiveTextureColor( uint UUID );
+
3466
+
3468
+
3471 void usePrimitiveTextureColor( const std::vector<uint> &UUIDs );
+
3472
+
3474
+
3477 bool isPrimitiveTextureColorOverridden( uint UUID ) const;
3478
-
3479 //-------- Compound Object Data Methods ---------- //
-
3480
-
3482
-
3487 void setObjectData( uint objID, const char* label, const int& data );
-
3488
-
3490
-
3495 void setObjectData( uint objID, const char* label, const uint& data );
-
3496
-
3498
-
3503 void setObjectData( uint objID, const char* label, const float& data );
-
3504
-
3506
-
3510 void setObjectData( uint objID, const char* label, const double& data );
-
3511
-
3513
-
3518 void setObjectData( uint objID, const char* label, const helios::vec2& data );
-
3519
-
3521
-
3526 void setObjectData( uint objID, const char* label, const helios::vec3& data );
-
3527
-
3529
-
3534 void setObjectData( uint objID, const char* label, const helios::vec4& data );
-
3535
-
3537
-
3542 void setObjectData( uint objID, const char* label, const helios::int2& data );
-
3543
-
3545
-
3550 void setObjectData( uint objID, const char* label, const helios::int3& data );
-
3551
-
3553
-
3558 void setObjectData( uint objID, const char* label, const helios::int4& data );
-
3559
-
3561
-
3566 void setObjectData( uint objID, const char* label, const std::string& data );
-
3567
-
3569
-
3576 void setObjectData( uint objIDs, const char* label, HeliosDataType type, uint size, void* data );
-
3577
-
3579
-
3584 void setObjectData( const std::vector<uint>& objIDs, const char* label, const int& data );
-
3585
-
3587
-
3592 void setObjectData( const std::vector<uint>& objIDs, const char* label, const uint& data );
-
3593
-
3595
-
3600 void setObjectData( const std::vector<uint>& objIDs, const char* label, const float& data );
-
3601
-
3603
-
3607 void setObjectData( const std::vector<uint>& objIDs, const char* label, const double& data );
-
3608
-
3610
-
3615 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec2& data );
-
3616
-
3618
-
3623 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec3& data );
-
3624
-
3626
-
3631 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec4& data );
-
3632
-
3634
-
3639 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int2& data );
-
3640
-
3642
-
3647 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int3& data );
-
3648
-
3650
-
3655 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int4& data );
-
3656
-
3658
-
3663 void setObjectData( const std::vector<uint>& objIDs, const char* label, const std::string& data );
-
3664
-
3666
-
3671 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const int& data );
-
3672
-
3674
-
3679 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const uint& data );
-
3680
-
3682
-
3687 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const float& data );
-
3688
-
3690
-
3694 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const double& data );
-
3695
-
3697
-
3702 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec2& data );
-
3703
-
3705
-
3710 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec3& data );
-
3711
-
3713
-
3718 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec4& data );
-
3719
-
3721
-
3726 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int2& data );
-
3727
-
3729
-
3734 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int3& data );
-
3735
-
3737
-
3742 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int4& data );
-
3743
-
3745
-
3750 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const std::string& data );
-
3752
-
3757 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const int& data );
-
3758
-
3760
-
3765 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const uint& data );
-
3766
-
3768
-
3773 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const float& data );
-
3774
-
3776
-
3780 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const double& data );
-
3781
-
3783
-
3788 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec2& data );
-
3789
-
3791
-
3796 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec3& data );
-
3797
-
3799
-
3804 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec4& data );
-
3805
-
3807
-
3812 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int2& data );
-
3813
-
3815
-
3820 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int3& data );
-
3821
-
3823
-
3828 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int4& data );
-
3829
-
3831
-
3836 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const std::string& data );
-
3837
-
3839
-
3844 void getObjectData( uint objID, const char* label, int& data ) const;
-
3845
-
3847
-
3852 void getObjectData( uint objID, const char* label, std::vector<int>& data ) const;
-
3853
-
3855
-
3860 void getObjectData( uint objID, const char* label, uint& data ) const;
-
3861
-
3863
-
3868 void getObjectData( uint objID, const char* label, std::vector<uint>& data ) const;
-
3869
-
3871
-
3876 void getObjectData( uint objID, const char* label, float& data ) const;
-
3877
-
3879
-
3884 void getObjectData( uint objID, const char* label, std::vector<float>& data ) const;
-
3885
-
3887
-
3892 void getObjectData( uint objID, const char* label, double& data ) const;
-
3893
-
3895
-
3900 void getObjectData( uint objID, const char* label, std::vector<double>& data ) const;
-
3901
-
3903
-
3908 void getObjectData( uint objID, const char* label, vec2& data ) const;
-
3909
-
3911
-
3916 void getObjectData( uint objID, const char* label, std::vector<vec2>& data ) const;
-
3917
-
3919
-
3924 void getObjectData( uint objID, const char* label, vec3& data ) const;
-
3925
-
3927
-
3932 void getObjectData( uint objID, const char* label, std::vector<vec3>& data ) const;
-
3933
-
3935
-
3940 void getObjectData( uint objID, const char* label, vec4& data ) const;
-
3941
-
3943
-
3948 void getObjectData( uint objID, const char* label, std::vector<vec4>& data ) const;
-
3949
-
3951
-
3956 void getObjectData( uint objID, const char* label, int2& data ) const;
-
3957
-
3959
-
3964 void getObjectData( uint objID, const char* label, std::vector<int2>& data ) const;
-
3965
-
3967
-
3972 void getObjectData( uint objID, const char* label, int3& data ) const;
-
3973
-
3975
-
3980 void getObjectData( uint objID, const char* label, std::vector<int3>& data ) const;
-
3981
-
3983
-
3988 void getObjectData( uint objID, const char* label, int4& data ) const;
-
3989
-
3991
-
3996 void getObjectData( uint objID, const char* label, std::vector<int4>& data ) const;
-
3997
-
3999
-
4004 void getObjectData( uint objID, const char* label, std::string& data ) const;
-
4005
-
4007
-
4012 void getObjectData( uint objID, const char* label, std::vector<std::string>& data ) const;
-
4013
-
4015
-
4021 HeliosDataType getObjectDataType( uint objID, const char* label ) const;
-
4022
-
4024
-
4029 uint getObjectDataSize( uint objID, const char* label ) const;
-
4030
-
4032
-
4037 bool doesObjectDataExist( uint objID, const char* label ) const;
-
4038
-
4040
-
4044 void clearObjectData( uint objID, const char* label );
-
4045
-
4047
-
4051 void clearObjectData( const std::vector<uint>& objIDs, const char* label );
-
4052
-
4054
-
4058 bool areObjectPrimitivesComplete( uint objID ) const;
-
4059
-
4061
-
4064 void cleanDeletedObjectIDs( std::vector<uint> &objIDs ) const;
-
4065
-
4067
-
4070 void cleanDeletedObjectIDs( std::vector<std::vector<uint>> &objIDs ) const;
-
4071
-
4073
-
4076 void cleanDeletedObjectIDs( std::vector<std::vector<std::vector<uint>>> &objIDs ) const;
-
4077
-
4078 //-------- Global Data Methods ---------- //
-
4079
-
4081
-
4085 void setGlobalData( const char* label, const int& data );
-
4086
-
4088
-
4092 void setGlobalData( const char* label, const uint& data );
-
4093
-
4095
-
4099 void setGlobalData( const char* label, const float& data );
-
4100
-
4102
-
4106 void setGlobalData( const char* label, const double& data );
-
4107
-
4109
-
4113 void setGlobalData( const char* label, const helios::vec2& data );
-
4114
-
4116
-
4120 void setGlobalData( const char* label, const helios::vec3& data );
-
4121
-
4123
-
4127 void setGlobalData( const char* label, const helios::vec4& data );
-
4128
-
4130
-
4134 void setGlobalData( const char* label, const helios::int2& data );
-
4135
-
4137
-
4141 void setGlobalData( const char* label, const helios::int3& data );
-
4142
-
4144
-
4149 void setGlobalData( const char* label, const helios::int4& data );
-
4150
-
4152
-
4156 void setGlobalData( const char* label, const std::string& data );
-
4157
-
4159
-
4164 void setGlobalData( const char* label, HeliosDataType type, size_t size, void* data );
-
4165
-
4167
-
4171 void renameGlobalData( const char* old_label, const char* new_label );
-
4172
-
4174
-
4178 void duplicateGlobalData(const char* old_label, const char* new_label );
-
4179
-
4181
-
4184 void clearGlobalData( const char* label );
-
4185
-
4187
-
4191 void getGlobalData( const char* label, int& data ) const;
-
4192
-
4194
-
4198 void getGlobalData( const char* label, std::vector<int>& data ) const;
-
4199
-
4201
-
4205 void getGlobalData( const char* label, uint& data ) const;
-
4206
-
4208
-
4212 void getGlobalData( const char* label, std::vector<uint>& data ) const;
-
4213
-
4215
-
4219 void getGlobalData( const char* label, float& data ) const;
-
4220
-
4222
-
4226 void getGlobalData( const char* label, std::vector<float>& data ) const;
-
4227
-
4229
-
4233 void getGlobalData( const char* label, double& data ) const;
-
4234
-
4236
-
4240 void getGlobalData( const char* label, std::vector<double>& data ) const;
-
4241
-
4243
-
4247 void getGlobalData( const char* label, helios::vec2& data ) const;
-
4248
-
4250
-
4254 void getGlobalData( const char* label, std::vector<helios::vec2>& data ) const;
-
4255
-
4257
-
4261 void getGlobalData( const char* label, helios::vec3& data ) const;
-
4262
-
4264
-
4268 void getGlobalData( const char* label, std::vector<helios::vec3>& data ) const;
-
4269
-
4271
-
4275 void getGlobalData( const char* label, helios::vec4& data ) const;
-
4276
-
4278
-
4282 void getGlobalData( const char* label, std::vector<helios::vec4>& data ) const;
-
4283
-
4285
-
4289 void getGlobalData( const char* label, helios::int2& data ) const;
-
4290
-
4292
-
4296 void getGlobalData( const char* label, std::vector<helios::int2>& data ) const;
-
4297
-
4299
-
4303 void getGlobalData( const char* label, helios::int3& data ) const;
-
4304
-
4306
-
4310 void getGlobalData( const char* label, std::vector<helios::int3>& data ) const;
-
4311
-
4313
-
4317 void getGlobalData( const char* label, helios::int4& data ) const;
-
4318
-
4320
-
4324 void getGlobalData( const char* label, std::vector<helios::int4>& data ) const;
-
4325
-
4327
-
4331 void getGlobalData( const char* label, std::string& data ) const;
-
4332
-
4334
-
4338 void getGlobalData( const char* label, std::vector<std::string>& data ) const;
-
4339
-
4341
-
4345 HeliosDataType getGlobalDataType( const char* label ) const;
-
4346
-
4348
-
4352 size_t getGlobalDataSize( const char* label ) const;
-
4353
-
4355
-
4358 std::vector<std::string> listGlobalData() const;
-
4359
-
4361
-
4365 bool doesGlobalDataExist( const char* label ) const;
-
4366
-
4368
-
4373 void incrementGlobalData( const char* label, int increment );
-
4374
-
4376
-
4381 void incrementGlobalData( const char* label, uint increment );
-
4382
-
4384
-
4389 void incrementGlobalData( const char* label, float increment );
-
4390
-
4392
-
4397 void incrementGlobalData( const char* label, double increment );
-
4398
-
4399 //--------- Compound Objects Methods -------------//
-
4400
-
4402
-
4405 CompoundObject* getObjectPointer( uint ObjID ) const;
+
3480
+
3483 void printPrimitiveInfo(uint UUID) const;
+
3484
+
3485 //-------- Compound Object Data Methods ---------- //
+
3486
+
3488
+
3493 void setObjectData( uint objID, const char* label, const int& data );
+
3494
+
3496
+
3501 void setObjectData( uint objID, const char* label, const uint& data );
+
3502
+
3504
+
3509 void setObjectData( uint objID, const char* label, const float& data );
+
3510
+
3512
+
3516 void setObjectData( uint objID, const char* label, const double& data );
+
3517
+
3519
+
3524 void setObjectData( uint objID, const char* label, const helios::vec2& data );
+
3525
+
3527
+
3532 void setObjectData( uint objID, const char* label, const helios::vec3& data );
+
3533
+
3535
+
3540 void setObjectData( uint objID, const char* label, const helios::vec4& data );
+
3541
+
3543
+
3548 void setObjectData( uint objID, const char* label, const helios::int2& data );
+
3549
+
3551
+
3556 void setObjectData( uint objID, const char* label, const helios::int3& data );
+
3557
+
3559
+
3564 void setObjectData( uint objID, const char* label, const helios::int4& data );
+
3565
+
3567
+
3572 void setObjectData( uint objID, const char* label, const std::string& data );
+
3573
+
3575
+
3582 void setObjectData( uint objIDs, const char* label, HeliosDataType type, uint size, void* data );
+
3583
+
3585
+
3590 void setObjectData( const std::vector<uint>& objIDs, const char* label, const int& data );
+
3591
+
3593
+
3598 void setObjectData( const std::vector<uint>& objIDs, const char* label, const uint& data );
+
3599
+
3601
+
3606 void setObjectData( const std::vector<uint>& objIDs, const char* label, const float& data );
+
3607
+
3609
+
3613 void setObjectData( const std::vector<uint>& objIDs, const char* label, const double& data );
+
3614
+
3616
+
3621 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec2& data );
+
3622
+
3624
+
3629 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec3& data );
+
3630
+
3632
+
3637 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::vec4& data );
+
3638
+
3640
+
3645 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int2& data );
+
3646
+
3648
+
3653 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int3& data );
+
3654
+
3656
+
3661 void setObjectData( const std::vector<uint>& objIDs, const char* label, const helios::int4& data );
+
3662
+
3664
+
3669 void setObjectData( const std::vector<uint>& objIDs, const char* label, const std::string& data );
+
3670
+
3672
+
3677 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const int& data );
+
3678
+
3680
+
3685 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const uint& data );
+
3686
+
3688
+
3693 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const float& data );
+
3694
+
3696
+
3700 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const double& data );
+
3701
+
3703
+
3708 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec2& data );
+
3709
+
3711
+
3716 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec3& data );
+
3717
+
3719
+
3724 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::vec4& data );
+
3725
+
3727
+
3732 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int2& data );
+
3733
+
3735
+
3740 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int3& data );
+
3741
+
3743
+
3748 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const helios::int4& data );
+
3749
+
3751
+
3756 void setObjectData( const std::vector<std::vector<uint> >& objIDs, const char* label, const std::string& data );
+
3758
+
3763 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const int& data );
+
3764
+
3766
+
3771 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const uint& data );
+
3772
+
3774
+
3779 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const float& data );
+
3780
+
3782
+
3786 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const double& data );
+
3787
+
3789
+
3794 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec2& data );
+
3795
+
3797
+
3802 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec3& data );
+
3803
+
3805
+
3810 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::vec4& data );
+
3811
+
3813
+
3818 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int2& data );
+
3819
+
3821
+
3826 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int3& data );
+
3827
+
3829
+
3834 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const helios::int4& data );
+
3835
+
3837
+
3842 void setObjectData( const std::vector<std::vector<std::vector<uint> > >& objIDs, const char* label, const std::string& data );
+
3843
+
3845
+
3850 void getObjectData( uint objID, const char* label, int& data ) const;
+
3851
+
3853
+
3858 void getObjectData( uint objID, const char* label, std::vector<int>& data ) const;
+
3859
+
3861
+
3866 void getObjectData( uint objID, const char* label, uint& data ) const;
+
3867
+
3869
+
3874 void getObjectData( uint objID, const char* label, std::vector<uint>& data ) const;
+
3875
+
3877
+
3882 void getObjectData( uint objID, const char* label, float& data ) const;
+
3883
+
3885
+
3890 void getObjectData( uint objID, const char* label, std::vector<float>& data ) const;
+
3891
+
3893
+
3898 void getObjectData( uint objID, const char* label, double& data ) const;
+
3899
+
3901
+
3906 void getObjectData( uint objID, const char* label, std::vector<double>& data ) const;
+
3907
+
3909
+
3914 void getObjectData( uint objID, const char* label, vec2& data ) const;
+
3915
+
3917
+
3922 void getObjectData( uint objID, const char* label, std::vector<vec2>& data ) const;
+
3923
+
3925
+
3930 void getObjectData( uint objID, const char* label, vec3& data ) const;
+
3931
+
3933
+
3938 void getObjectData( uint objID, const char* label, std::vector<vec3>& data ) const;
+
3939
+
3941
+
3946 void getObjectData( uint objID, const char* label, vec4& data ) const;
+
3947
+
3949
+
3954 void getObjectData( uint objID, const char* label, std::vector<vec4>& data ) const;
+
3955
+
3957
+
3962 void getObjectData( uint objID, const char* label, int2& data ) const;
+
3963
+
3965
+
3970 void getObjectData( uint objID, const char* label, std::vector<int2>& data ) const;
+
3971
+
3973
+
3978 void getObjectData( uint objID, const char* label, int3& data ) const;
+
3979
+
3981
+
3986 void getObjectData( uint objID, const char* label, std::vector<int3>& data ) const;
+
3987
+
3989
+
3994 void getObjectData( uint objID, const char* label, int4& data ) const;
+
3995
+
3997
+
4002 void getObjectData( uint objID, const char* label, std::vector<int4>& data ) const;
+
4003
+
4005
+
4010 void getObjectData( uint objID, const char* label, std::string& data ) const;
+
4011
+
4013
+
4018 void getObjectData( uint objID, const char* label, std::vector<std::string>& data ) const;
+
4019
+
4021
+
4027 HeliosDataType getObjectDataType( uint objID, const char* label ) const;
+
4028
+
4030
+
4035 uint getObjectDataSize( uint objID, const char* label ) const;
+
4036
+
4038
+
4043 bool doesObjectDataExist( uint objID, const char* label ) const;
+
4044
+
4046
+
4050 void clearObjectData( uint objID, const char* label );
+
4051
+
4053
+
4057 void clearObjectData( const std::vector<uint>& objIDs, const char* label );
+
4058
+
4060
+
4064 bool areObjectPrimitivesComplete( uint objID ) const;
+
4065
+
4067
+
4070 void cleanDeletedObjectIDs( std::vector<uint> &objIDs ) const;
+
4071
+
4073
+
4076 void cleanDeletedObjectIDs( std::vector<std::vector<uint>> &objIDs ) const;
+
4077
+
4079
+
4082 void cleanDeletedObjectIDs( std::vector<std::vector<std::vector<uint>>> &objIDs ) const;
+
4083
+
4084 //-------- Global Data Methods ---------- //
+
4085
+
4087
+
4091 void setGlobalData( const char* label, const int& data );
+
4092
+
4094
+
4098 void setGlobalData( const char* label, const uint& data );
+
4099
+
4101
+
4105 void setGlobalData( const char* label, const float& data );
+
4106
+
4108
+
4112 void setGlobalData( const char* label, const double& data );
+
4113
+
4115
+
4119 void setGlobalData( const char* label, const helios::vec2& data );
+
4120
+
4122
+
4126 void setGlobalData( const char* label, const helios::vec3& data );
+
4127
+
4129
+
4133 void setGlobalData( const char* label, const helios::vec4& data );
+
4134
+
4136
+
4140 void setGlobalData( const char* label, const helios::int2& data );
+
4141
+
4143
+
4147 void setGlobalData( const char* label, const helios::int3& data );
+
4148
+
4150
+
4154
+
4155 void setGlobalData( const char* label, const helios::int4& data );
+
4156
+
4158
+
4162 void setGlobalData( const char* label, const std::string& data );
+
4163
+
4165
+
4170 void setGlobalData( const char* label, HeliosDataType type, size_t size, void* data );
+
4171
+
4173
+
4177 void renameGlobalData( const char* old_label, const char* new_label );
+
4178
+
4180
+
4184 void duplicateGlobalData(const char* old_label, const char* new_label );
+
4185
+
4187
+
4190 void clearGlobalData( const char* label );
+
4191
+
4193
+
4197 void getGlobalData( const char* label, int& data ) const;
+
4198
+
4200
+
4204 void getGlobalData( const char* label, std::vector<int>& data ) const;
+
4205
+
4207
+
4211 void getGlobalData( const char* label, uint& data ) const;
+
4212
+
4214
+
4218 void getGlobalData( const char* label, std::vector<uint>& data ) const;
+
4219
+
4221
+
4225 void getGlobalData( const char* label, float& data ) const;
+
4226
+
4228
+
4232 void getGlobalData( const char* label, std::vector<float>& data ) const;
+
4233
+
4235
+
4239 void getGlobalData( const char* label, double& data ) const;
+
4240
+
4242
+
4246 void getGlobalData( const char* label, std::vector<double>& data ) const;
+
4247
+
4249
+
4253 void getGlobalData( const char* label, helios::vec2& data ) const;
+
4254
+
4256
+
4260 void getGlobalData( const char* label, std::vector<helios::vec2>& data ) const;
+
4261
+
4263
+
4267 void getGlobalData( const char* label, helios::vec3& data ) const;
+
4268
+
4270
+
4274 void getGlobalData( const char* label, std::vector<helios::vec3>& data ) const;
+
4275
+
4277
+
4281 void getGlobalData( const char* label, helios::vec4& data ) const;
+
4282
+
4284
+
4288 void getGlobalData( const char* label, std::vector<helios::vec4>& data ) const;
+
4289
+
4291
+
4295 void getGlobalData( const char* label, helios::int2& data ) const;
+
4296
+
4298
+
4302 void getGlobalData( const char* label, std::vector<helios::int2>& data ) const;
+
4303
+
4305
+
4309 void getGlobalData( const char* label, helios::int3& data ) const;
+
4310
+
4312
+
4316 void getGlobalData( const char* label, std::vector<helios::int3>& data ) const;
+
4317
+
4319
+
4323 void getGlobalData( const char* label, helios::int4& data ) const;
+
4324
+
4326
+
4330 void getGlobalData( const char* label, std::vector<helios::int4>& data ) const;
+
4331
+
4333
+
4337 void getGlobalData( const char* label, std::string& data ) const;
+
4338
+
4340
+
4344 void getGlobalData( const char* label, std::vector<std::string>& data ) const;
+
4345
+
4347
+
4351 HeliosDataType getGlobalDataType( const char* label ) const;
+
4352
+
4354
+
4358 size_t getGlobalDataSize( const char* label ) const;
+
4359
+
4361
+
4364 std::vector<std::string> listGlobalData() const;
+
4365
+
4367
+
4371 bool doesGlobalDataExist( const char* label ) const;
+
4372
+
4374
+
4379 void incrementGlobalData( const char* label, int increment );
+
4380
+
4382
+
4387 void incrementGlobalData( const char* label, uint increment );
+
4388
+
4390
+
4395 void incrementGlobalData( const char* label, float increment );
+
4396
+
4398
+
4403 void incrementGlobalData( const char* label, double increment );
+
4404
+
4405 //--------- Compound Objects Methods -------------//
4406
-
4408
-
4411 uint getObjectCount() const;
+
4408
+
4411 CompoundObject* getObjectPointer( uint ObjID ) const;
4412
-
4414
-
4417 bool doesObjectExist( uint ObjID ) const;
+
4414
+
4417 uint getObjectCount() const;
4418
-
4420
-
4423 std::vector<uint> getAllObjectIDs() const;
+
4420
+
4423 bool doesObjectExist( uint ObjID ) const;
4424
-
4426
-
4429 void deleteObject(uint ObjID );
+
4426
+
4429 std::vector<uint> getAllObjectIDs() const;
4430
-
4432
-
4435 void deleteObject(const std::vector<uint> &ObjIDs );
+
4432
+
4435 void deleteObject(uint ObjID );
4436
-
4438
-
4442 uint copyObject(uint ObjID );
-
4443
-
4445
-
4449 std::vector<uint> copyObject(const std::vector<uint> &ObjIDs );
-
4450
-
4452
-
4456 void copyObjectData(uint source_objID, uint destination_objID);
-
4457
-
4459
-
4463 void duplicateObjectData( uint objID, const char* old_label, const char* new_label );
-
4464
-
4466
-
4470 void renameObjectData( uint objID, const char* old_label, const char* new_label );
-
4471
-
4473
-
4479 std::vector<uint> filterObjectsByData( const std::vector<uint> &ObjIDs, const char* object_data, float threshold, const char* comparator) const;
-
4480
-
4482
-
4486 void translateObject(uint ObjID, const vec3& shift );
-
4487
-
4489
-
4493 void translateObject(const std::vector<uint>& ObjIDs, const vec3& shift );
-
4494
-
4496
-
4501 void rotateObject(uint ObjID, float rotation_radians, const char* rotation_axis_xyz );
-
4502
-
4504
-
4509 void rotateObject(const std::vector<uint>& ObjIDs, float rotation_radians, const char* rotation_axis_xyz );
-
4510
-
4512
-
4517 void rotateObject(uint ObjID, float rotation_radians, const vec3& rotation_axis_vector );
-
4518
-
4520
-
4525 void rotateObject(const std::vector<uint>& ObjIDs, float rotation_radians, const vec3& rotation_axis_vector );
-
4526
-
4528
-
4534 void rotateObject(uint ObjID, float rotation_radians, const vec3& rotation_origin, const vec3& rotation_axis_vector );
-
4535
-
4537
-
4543 void rotateObject(const std::vector<uint>& ObjIDs, float rotation_radians, const vec3& rotation_origin, const vec3& rotation_axis_vector );
-
4544
-
4546
-
4550 void scaleObject( uint ObjID, const helios::vec3 &scalefact );
-
4551
-
4553
-
4557 void scaleObject( const std::vector<uint>& ObjIDs, const helios::vec3 &scalefact );
-
4558
-
4560
-
4564 void scaleObjectAboutCenter( uint ObjID, const helios::vec3 &scalefact );
-
4565
-
4567
-
4571 void scaleObjectAboutCenter( const std::vector<uint>& ObjIDs, const helios::vec3 &scalefact );
-
4572
-
4574
-
4579 void scaleObjectAboutPoint( uint ObjID, const helios::vec3 &scalefact, const helios::vec3 &point );
-
4580
-
4582
-
4587 void scaleObjectAboutPoint( const std::vector<uint>& ObjIDs, const helios::vec3 &scalefact, const helios::vec3 &point );
-
4588
-
4590
-
4593 std::vector<uint> getObjectPrimitiveUUIDs( uint ObjID ) const;
-
4594
-
4596
-
4599 std::vector<uint> getObjectPrimitiveUUIDs( const std::vector<uint> &ObjIDs) const;
-
4600
-
4602
-
4605 std::vector<uint> getObjectPrimitiveUUIDs( const std::vector<std::vector<uint> > &ObjIDs) const;
-
4606
-
4608
-
4611 helios::ObjectType getObjectType( uint ObjID ) const;
+
4438
+
4441 void deleteObject(const std::vector<uint> &ObjIDs );
+
4442
+
4444
+
4448 uint copyObject(uint ObjID );
+
4449
+
4451
+
4455 std::vector<uint> copyObject(const std::vector<uint> &ObjIDs );
+
4456
+
4458
+
4462 void copyObjectData(uint source_objID, uint destination_objID);
+
4463
+
4465
+
4469 void duplicateObjectData( uint objID, const char* old_label, const char* new_label );
+
4470
+
4472
+
4476 void renameObjectData( uint objID, const char* old_label, const char* new_label );
+
4477
+
4479
+
4485 std::vector<uint> filterObjectsByData( const std::vector<uint> &ObjIDs, const char* object_data, float threshold, const char* comparator) const;
+
4486
+
4488
+
4492 void translateObject(uint ObjID, const vec3& shift );
+
4493
+
4495
+
4499 void translateObject(const std::vector<uint>& ObjIDs, const vec3& shift );
+
4500
+
4502
+
4507 void rotateObject(uint ObjID, float rotation_radians, const char* rotation_axis_xyz );
+
4508
+
4510
+
4515 void rotateObject(const std::vector<uint>& ObjIDs, float rotation_radians, const char* rotation_axis_xyz );
+
4516
+
4518
+
4523 void rotateObject(uint ObjID, float rotation_radians, const vec3& rotation_axis_vector );
+
4524
+
4526
+
4531 void rotateObject(const std::vector<uint>& ObjIDs, float rotation_radians, const vec3& rotation_axis_vector );
+
4532
+
4534
+
4540 void rotateObject(uint ObjID, float rotation_radians, const vec3& rotation_origin, const vec3& rotation_axis_vector );
+
4541
+
4543
+
4549 void rotateObject(const std::vector<uint>& ObjIDs, float rotation_radians, const vec3& rotation_origin, const vec3& rotation_axis_vector );
+
4550
+
4552
+
4556 void scaleObject( uint ObjID, const helios::vec3 &scalefact );
+
4557
+
4559
+
4563 void scaleObject( const std::vector<uint>& ObjIDs, const helios::vec3 &scalefact );
+
4564
+
4566
+
4570 void scaleObjectAboutCenter( uint ObjID, const helios::vec3 &scalefact );
+
4571
+
4573
+
4577 void scaleObjectAboutCenter( const std::vector<uint>& ObjIDs, const helios::vec3 &scalefact );
+
4578
+
4580
+
4585 void scaleObjectAboutPoint( uint ObjID, const helios::vec3 &scalefact, const helios::vec3 &point );
+
4586
+
4588
+
4593 void scaleObjectAboutPoint( const std::vector<uint>& ObjIDs, const helios::vec3 &scalefact, const helios::vec3 &point );
+
4594
+
4596
+
4599 std::vector<uint> getObjectPrimitiveUUIDs( uint ObjID ) const;
+
4600
+
4602
+
4605 std::vector<uint> getObjectPrimitiveUUIDs( const std::vector<uint> &ObjIDs) const;
+
4606
+
4608
+
4611 std::vector<uint> getObjectPrimitiveUUIDs( const std::vector<std::vector<uint> > &ObjIDs) const;
4612
-
4614
-
4617 Tile* getTileObjectPointer(uint ObjID ) const;
+
4614
+
4617 helios::ObjectType getObjectType( uint ObjID ) const;
4618
-
4620
-
4623 float getTileObjectAreaRatio(uint ObjectID) const;
+
4620
+
4623 Tile* getTileObjectPointer(uint ObjID ) const;
4624
-
4626
-
4629 std::vector<float> getTileObjectAreaRatio(const std::vector<uint> &ObjectID) const;
+
4626
+
4629 float getTileObjectAreaRatio(uint ObjectID) const;
4630
-
4632
-
4636 void setTileObjectSubdivisionCount(const std::vector<uint> &ObjectIDs, const int2 &new_subdiv);
-
4637
-
4639
-
4643 void setTileObjectSubdivisionCount(const std::vector<uint> &ObjectIDs, float area_ratio);
-
4644
-
4646
-
4651 helios::vec3 getTileObjectCenter(uint ObjID) const;
-
4652
-
4654
-
4657 helios::vec2 getTileObjectSize(uint ObjID) const;
+
4632
+
4635 std::vector<float> getTileObjectAreaRatio(const std::vector<uint> &ObjectID) const;
+
4636
+
4638
+
4642 void setTileObjectSubdivisionCount(const std::vector<uint> &ObjectIDs, const int2 &new_subdiv);
+
4643
+
4645
+
4649 void setTileObjectSubdivisionCount(const std::vector<uint> &ObjectIDs, float area_ratio);
+
4650
+
4652
+
4657 helios::vec3 getTileObjectCenter(uint ObjID) const;
4658
-
4660
- +
4660
+
4663 helios::vec2 getTileObjectSize(uint ObjID) const;
4664
-
4666
-
4669 helios::vec3 getTileObjectNormal(uint ObjID) const;
+
4666
+
4670
-
4672
-
4675 std::vector<helios::vec2> getTileObjectTextureUV(uint ObjID) const;
+
4672
+
4675 helios::vec3 getTileObjectNormal(uint ObjID) const;
4676
-
4678
-
4681 std::vector<helios::vec3> getTileObjectVertices(uint ObjID) const;
+
4678
+
4681 std::vector<helios::vec2> getTileObjectTextureUV(uint ObjID) const;
4682
-
4684
-
4687 Sphere* getSphereObjectPointer(uint ObjID ) const;
+
4684
+
4687 std::vector<helios::vec3> getTileObjectVertices(uint ObjID) const;
4688
-
4690
-
4693 helios::vec3 getSphereObjectCenter(uint ObjID) const;
+
4690
+
4693 Sphere* getSphereObjectPointer(uint ObjID ) const;
4694
-
4696
-
4699 helios::vec3 getSphereObjectRadius(uint ObjID) const;
+
4696
+
4699 helios::vec3 getSphereObjectCenter(uint ObjID) const;
4700
-
4702
-
4705 uint getSphereObjectSubdivisionCount(uint ObjID) const;
-
4706
-
4708
-
4711 float getSphereObjectVolume( uint ObjID ) const;
-
4712
-
4714
-
4717 Tube* getTubeObjectPointer(uint ObjID ) const;
+
4702
+
4705 helios::vec3 getSphereObjectRadius(uint ObjID) const;
+
4706
+
4708
+
4711 uint getSphereObjectSubdivisionCount(uint ObjID) const;
+
4712
+
4714
+
4717 float getSphereObjectVolume( uint ObjID ) const;
4718
-
4720
-
4723 uint getTubeObjectSubdivisionCount(uint ObjectID) const;
+
4720
+
4723 Tube* getTubeObjectPointer(uint ObjID ) const;
4724
-
4726
-
4729 std::vector<helios::vec3> getTubeObjectNodes(uint ObjID) const;
+
4726
+
4729 uint getTubeObjectSubdivisionCount(uint ObjectID) const;
4730
-
4732
-
4735 std::vector<float> getTubeObjectNodeRadii(uint ObjID) const;
+
4732
+
4735 std::vector<helios::vec3> getTubeObjectNodes(uint ObjID) const;
4736
-
4738
-
4741 std::vector<RGBcolor> getTubeObjectNodeColors(uint ObjID) const;
-
4742
-
4744
-
4747 float getTubeObjectVolume( uint ObjID ) const;
-
4748
-
4750
-
4754 float getTubeObjectSegmentVolume( uint ObjID, uint segment_index ) const;
-
4755
-
4757
-
4763 void appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float radius, const RGBcolor &color );
-
4764
-
4766
-
4773 void appendTubeSegment( uint ObjID, const helios::vec3 &node_position, float node_radius, const char* texturefile, const helios::vec2 &textureuv_ufrac );
-
4774
-
4776
-
4780 void scaleTubeGirth( uint ObjID, float scale_factor );
-
4781
-
4783
-
4787 void setTubeRadii( uint ObjID, const std::vector<float> &node_radii );
-
4788
-
4790
-
4794 void scaleTubeLength( uint ObjID, float scale_factor );
-
4795
-
4797
-
4801 void setTubeNodes( uint ObjID, const std::vector<helios::vec3> &node_xyz );
-
4802
-
4804
-
4807 Box* getBoxObjectPointer(uint ObjID ) const;
-
4808
-
4810
-
4813 helios::vec3 getBoxObjectCenter(uint ObjID) const;
-
4814
-
4816
-
4819 helios::vec3 getBoxObjectSize(uint ObjID) const;
-
4820
-
4822
- -
4826
-
4828
-
4831 float getBoxObjectVolume( uint ObjID ) const;
-
4832
-
4834
-
4837 Disk* getDiskObjectPointer(uint ObjID ) const;
-
4838
-
4840
-
4843 helios::vec3 getDiskObjectCenter(uint ObjID) const;
-
4844
-
4846
-
4849 helios::vec2 getDiskObjectSize(uint ObjID) const;
-
4850
-
4852
-
4855 uint getDiskObjectSubdivisionCount(uint ObjID) const;
-
4856
-
4858
-
4861 Polymesh* getPolymeshObjectPointer(uint ObjID ) const;
-
4862
-
4864
-
4867 float getPolymeshObjectVolume( uint ObjID ) const;
-
4868
-
4870
-
4873 Cone* getConeObjectPointer( uint ObjID ) const;
-
4874
-
4876
-
4879 uint getConeObjectSubdivisionCount(uint ObjID) const;
-
4880
-
4882
-
4885 std::vector<helios::vec3> getConeObjectNodes(uint ObjID) const;
-
4886
-
4888
-
4891 std::vector<float> getConeObjectNodeRadii(uint ObjID) const;
-
4892
-
4894
-
4897 helios::vec3 getConeObjectNode(uint ObjID, int number) const;
-
4898
-
4900
-
4903 float getConeObjectNodeRadius(uint ObjID, int number) const;
-
4904
-
4906
-
4909 helios::vec3 getConeObjectAxisUnitVector(uint ObjID) const;
-
4910
-
4912
-
4916 float getConeObjectLength(uint ObjID) const;
-
4917
-
4919
-
4922 float getConeObjectVolume( uint ObjID ) const;
+
4738
+
4741 std::vector<float> getTubeObjectNodeRadii(uint ObjID) const;
+
4742
+
4744
+
4747 std::vector<RGBcolor> getTubeObjectNodeColors(uint ObjID) const;
+
4748
+
4750
+
4753 float getTubeObjectVolume( uint ObjID ) const;
+
4754
+
4756
+
4760 float getTubeObjectSegmentVolume( uint ObjID, uint segment_index ) const;
+
4761
+
4763
+
4769 void appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float radius, const RGBcolor &color );
+
4770
+
4772
+
4779 void appendTubeSegment( uint ObjID, const helios::vec3 &node_position, float node_radius, const char* texturefile, const helios::vec2 &textureuv_ufrac );
+
4780
+
4782
+
4786 void scaleTubeGirth( uint ObjID, float scale_factor );
+
4787
+
4789
+
4793 void setTubeRadii( uint ObjID, const std::vector<float> &node_radii );
+
4794
+
4796
+
4800 void scaleTubeLength( uint ObjID, float scale_factor );
+
4801
+
4803
+
4807 void pruneTubeNodes( uint ObjID, uint node_index );
+
4808
+
4810
+
4814 void setTubeNodes( uint ObjID, const std::vector<helios::vec3> &node_xyz );
+
4815
+
4817
+
4820 Box* getBoxObjectPointer(uint ObjID ) const;
+
4821
+
4823
+
4826 helios::vec3 getBoxObjectCenter(uint ObjID) const;
+
4827
+
4829
+
4832 helios::vec3 getBoxObjectSize(uint ObjID) const;
+
4833
+
4835
+ +
4839
+
4841
+
4844 float getBoxObjectVolume( uint ObjID ) const;
+
4845
+
4847
+
4850 Disk* getDiskObjectPointer(uint ObjID ) const;
+
4851
+
4853
+
4856 helios::vec3 getDiskObjectCenter(uint ObjID) const;
+
4857
+
4859
+
4862 helios::vec2 getDiskObjectSize(uint ObjID) const;
+
4863
+
4865
+
4868 uint getDiskObjectSubdivisionCount(uint ObjID) const;
+
4869
+
4871
+
4874 Polymesh* getPolymeshObjectPointer(uint ObjID ) const;
+
4875
+
4877
+
4880 float getPolymeshObjectVolume( uint ObjID ) const;
+
4881
+
4883
+
4886 Cone* getConeObjectPointer( uint ObjID ) const;
+
4887
+
4889
+
4892 uint getConeObjectSubdivisionCount(uint ObjID) const;
+
4893
+
4895
+
4898 std::vector<helios::vec3> getConeObjectNodes(uint ObjID) const;
+
4899
+
4901
+
4904 std::vector<float> getConeObjectNodeRadii(uint ObjID) const;
+
4905
+
4907
+
4910 helios::vec3 getConeObjectNode(uint ObjID, int number) const;
+
4911
+
4913
+
4916 float getConeObjectNodeRadius(uint ObjID, int number) const;
+
4917
+
4919
+
4922 helios::vec3 getConeObjectAxisUnitVector(uint ObjID) const;
4923
-
4925
-
4934 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv);
-
4935
-
4937
-
4946 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color );
-
4947
-
4949
-
4958 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile );
-
4959
-
4961
-
4969 uint addSphereObject(uint Ndivs, const vec3 &center, float radius );
-
4970
-
4972
-
4980 uint addSphereObject(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color );
-
4981
-
4983
-
4991 uint addSphereObject(uint Ndivs, const vec3 &center, float radius, const char* texturefile );
-
4992
-
4994
-
5002 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius );
-
5003
-
5005
-
5013 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const RGBcolor &color );
-
5014
-
5016
-
5024 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const char* texturefile );
-
5025
-
5027
-
5036 uint addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius );
-
5037
-
5039
-
5048 uint addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color );
-
5049
-
5051
-
5061 uint addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile );
-
5062
-
5064
-
5075 uint addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile, const std::vector<float> &textureuv_vfrac );
-
5076
-
5078
-
5087 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv );
-
5088
-
5090
-
5099 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color );
-
5100
-
5102
-
5111 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile );
-
5112
-
5114
-
5124 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals );
+
4925
+
4929 float getConeObjectLength(uint ObjID) const;
+
4930
+
4932
+
4935 float getConeObjectVolume( uint ObjID ) const;
+
4936
+
4938
+
4947 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv);
+
4948
+
4950
+
4959 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color );
+
4960
+
4962
+
4971 uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile );
+
4972
+
4974
+
4982 uint addSphereObject(uint Ndivs, const vec3 &center, float radius );
+
4983
+
4985
+
4993 uint addSphereObject(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color );
+
4994
+
4996
+
5004 uint addSphereObject(uint Ndivs, const vec3 &center, float radius, const char* texturefile );
+
5005
+
5007
+
5015 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius );
+
5016
+
5018
+
5026 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const RGBcolor &color );
+
5027
+
5029
+
5037 uint addSphereObject(uint Ndivs, const vec3 &center, const vec3 &radius, const char* texturefile );
+
5038
+
5040
+
5049 uint addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius );
+
5050
+
5052
+
5061 uint addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color );
+
5062
+
5064
+
5074 uint addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile );
+
5075
+
5077
+
5088 uint addTubeObject(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile, const std::vector<float> &textureuv_vfrac );
+
5089
+
5091
+
5100 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv );
+
5101
+
5103
+
5112 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color );
+
5113
+
5115
+
5124 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile );
5125
-
5127
-
5136 uint addBoxObject(vec3 center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals );
-
5137
-
5139
-
5148 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size );
-
5149
-
5151
-
5160 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
-
5161
-
5163
-
5172 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
5173
-
5175
-
5184 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
5185
-
5187
-
5197 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
-
5198
-
5200
-
5209 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
5210
-
5212
-
5221 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
5222
-
5224
-
5234 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texturefile );
-
5235
-
5237
-
5242 uint addPolymeshObject(const std::vector<uint> &UUIDs );
-
5243
-
5245
-
5256 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 );
-
5257
-
5259
-
5270 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const RGBcolor &color );
-
5271
-
5273
-
5284 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile );
-
5285
-
5287
-
5295 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius );
-
5296
-
5298
-
5306 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color );
-
5307
-
5309
-
5317 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius, const char* texturefile );
-
5318
-
5320
-
5329 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv );
-
5330
-
5332
-
5341 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color );
-
5342
-
5344
-
5353 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile );
-
5354
-
5356
-
5365 std::vector<uint> addTube(uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius );
-
5366
-
5368
-
5377 std::vector<uint> addTube(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color );
-
5378
-
5380
-
5389 std::vector<uint> addTube(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile );
-
5390
-
5392
-
5401 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv );
-
5402
-
5404
-
5413 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color );
-
5414
-
5416
-
5425 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile );
-
5426
-
5428
-
5438 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals );
+
5127
+
5137 uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals );
+
5138
+
5140
+
5149 uint addBoxObject(vec3 center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals );
+
5150
+
5152
+
5161 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size );
+
5162
+
5164
+
5173 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
+
5174
+
5176
+
5185 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
+
5186
+
5188
+
5197 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
+
5198
+
5200
+
5210 uint addDiskObject(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
+
5211
+
5213
+
5222 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
+
5223
+
5225
+
5234 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
+
5235
+
5237
+
5247 uint addDiskObject(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texturefile );
+
5248
+
5250
+
5255 uint addPolymeshObject(const std::vector<uint> &UUIDs );
+
5256
+
5258
+
5269 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 );
+
5270
+
5272
+
5283 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const RGBcolor &color );
+
5284
+
5286
+
5297 uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile );
+
5298
+
5300
+
5308 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius );
+
5309
+
5311
+
5319 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius, const RGBcolor &color );
+
5320
+
5322
+
5330 std::vector<uint> addSphere(uint Ndivs, const vec3 &center, float radius, const char* texturefile );
+
5331
+
5333
+
5342 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv );
+
5343
+
5345
+
5354 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const RGBcolor &color );
+
5355
+
5357
+
5366 std::vector<uint> addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv, const char* texturefile );
+
5367
+
5369
+
5378 std::vector<uint> addTube(uint Ndivs, const std::vector<vec3> &nodes, const std::vector<float> &radius );
+
5379
+
5381
+
5390 std::vector<uint> addTube(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const std::vector<RGBcolor> &color );
+
5391
+
5393
+
5402 std::vector<uint> addTube(uint radial_subdivisions, const std::vector<vec3> &nodes, const std::vector<float> &radius, const char* texturefile );
+
5403
+
5405
+
5414 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv );
+
5415
+
5417
+
5426 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color );
+
5427
+
5429
+
5438 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile );
5439
-
5441
-
5450 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals );
-
5451
-
5453
-
5462 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size );
-
5463
-
5465
-
5474 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
-
5475
-
5477
-
5486 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
5487
-
5489
-
5498 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
5499
-
5501
-
5511 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
-
5512
-
5514
-
5523 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
-
5524
-
5526
-
5535 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
-
5536
-
5538
-
5548 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texturefile );
-
5549
-
5551
-
5561 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 );
+
5441
+
5451 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const RGBcolor &color, bool reverse_normals );
+
5452
+
5454
+
5463 std::vector<uint> addBox(const vec3 &center, const vec3 &size, const int3 &subdiv, const char* texturefile, bool reverse_normals );
+
5464
+
5466
+
5475 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size );
+
5476
+
5478
+
5487 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation );
+
5488
+
5490
+
5499 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
+
5500
+
5502
+
5511 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
+
5512
+
5514
+
5524 std::vector<uint> addDisk(uint Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texture_file );
+
5525
+
5527
+
5536 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBcolor& color );
+
5537
+
5539
+
5548 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const helios::RGBAcolor& color );
+
5549
+
5551
+
5561 std::vector<uint> addDisk(const int2 &Ndivs, const helios::vec3& center, const helios::vec2& size, const helios::SphericalCoord& rotation, const char* texturefile );
5562
-
5564
-
5574 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, RGBcolor &color );
+
5564
+
5574 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1 );
5575
-
5577
-
5587 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile );
+
5577
+
5587 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, RGBcolor &color );
5588
-
5590
-
5597 void addTimeseriesData(const char* label, float value, const Date &date, const Time &time );
-
5598
-
5600
-
5605 void setCurrentTimeseriesPoint(const char* label, uint index );
-
5606
-
5608
-
5615 float queryTimeseriesData(const char* label, const Date &date, const Time &time ) const;
-
5616
-
5618
-
5623 float queryTimeseriesData( const char* label ) const;
-
5624
-
5626
-
5632 float queryTimeseriesData( const char* label, uint index ) const;
-
5633
-
5635
-
5641 Time queryTimeseriesTime( const char* label, uint index ) const;
-
5642
-
5644
-
5650 Date queryTimeseriesDate( const char* label, uint index ) const;
-
5651
-
5653
-
5657 uint getTimeseriesLength( const char* label ) const;
-
5658
-
5660
-
5664 bool doesTimeseriesVariableExist( const char* label ) const;
-
5665
-
5667 std::vector<std::string> listTimeseriesVariables() const;
-
5668
-
5670 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 );
-
5671
-
5673
-
5678 void getDomainBoundingBox( helios::vec2& xbounds, helios::vec2& ybounds, helios::vec2& zbounds ) const;
-
5679
-
5681
-
5687 void getDomainBoundingBox( const std::vector<uint>& UUIDs, helios::vec2& xbounds, helios::vec2& ybounds, helios::vec2& zbounds ) const;
-
5688
-
5690
-
5694 void getDomainBoundingSphere( helios::vec3& center, float& radius ) const;
-
5695
-
5697
-
5702 void getDomainBoundingSphere( const std::vector<uint>& UUIDs, helios::vec3& center, float& radius ) const;
-
5703
-
5705
-
5708 void cropDomainX(const vec2 &xbounds );
-
5709
-
5711
-
5714 void cropDomainY(const vec2 &ybounds );
-
5715
-
5717
-
5720 void cropDomainZ(const vec2 &zbounds );
-
5721
-
5723
-
5729 void cropDomain( std::vector<uint> &UUIDs, const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds );
-
5730
-
5732
-
5737 void cropDomain(const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds );
-
5738
-
5740
-
5746 void colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors );
-
5747
-
5749
-
5757 void colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors, float data_min, float data_max );
-
5758
-
5760
-
5766 std::vector<uint> loadXML( const char* filename, bool quiet = false );
-
5767
-
5769
-
5772 std::vector<std::string> getLoadedXMLFiles();
-
5773
-
5775
-
5781 static bool scanXMLForTag( const std::string &filename, const std::string &tag, const std::string &label="" );
-
5782
-
5784
-
5788 void writeXML( const char* filename, bool quiet = false ) const;
-
5789
-
5791
-
5796 void writeXML( const char* filename, const std::vector<uint> &UUIDs, bool quiet = false ) const;
-
5797
-
5799
-
5804 void writeXML_byobject( const char* filename, const std::vector<uint> &UUIDs, bool quiet = false ) const;
-
5805
-
5807
-
5812 void writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, bool print_header = false ) const;
-
5813
-
5815
-
5821 void writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, const std::vector<uint> &UUIDs, bool print_header = false ) const;
-
5822
-
5824
-
5830 std::vector<uint> loadPLY(const char* filename, bool silent=false );
-
5831
-
5833
-
5842 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const std::string &upaxis="YUP", bool silent=false );
-
5843
-
5845
-
5855 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const std::string &upaxis="YUP", bool silent=false );
+
5590
+
5600 std::vector<uint> addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1, const char* texturefile );
+
5601
+
5603
+
5610 void addTimeseriesData(const char* label, float value, const Date &date, const Time &time );
+
5611
+
5613
+
5618 void setCurrentTimeseriesPoint(const char* label, uint index );
+
5619
+
5621
+
5628 float queryTimeseriesData(const char* label, const Date &date, const Time &time ) const;
+
5629
+
5631
+
5636 float queryTimeseriesData( const char* label ) const;
+
5637
+
5639
+
5645 float queryTimeseriesData( const char* label, uint index ) const;
+
5646
+
5648
+
5654 Time queryTimeseriesTime( const char* label, uint index ) const;
+
5655
+
5657
+
5663 Date queryTimeseriesDate( const char* label, uint index ) const;
+
5664
+
5666
+
5670 uint getTimeseriesLength( const char* label ) const;
+
5671
+
5673
+
5677 bool doesTimeseriesVariableExist( const char* label ) const;
+
5678
+
5680 std::vector<std::string> listTimeseriesVariables() const;
+
5681
+
5683 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 );
+
5684
+
5686
+
5691 void getDomainBoundingBox( helios::vec2& xbounds, helios::vec2& ybounds, helios::vec2& zbounds ) const;
+
5692
+
5694
+
5700 void getDomainBoundingBox( const std::vector<uint>& UUIDs, helios::vec2& xbounds, helios::vec2& ybounds, helios::vec2& zbounds ) const;
+
5701
+
5703
+
5707 void getDomainBoundingSphere( helios::vec3& center, float& radius ) const;
+
5708
+
5710
+
5715 void getDomainBoundingSphere( const std::vector<uint>& UUIDs, helios::vec3& center, float& radius ) const;
+
5716
+
5718
+
5721 void cropDomainX(const vec2 &xbounds );
+
5722
+
5724
+
5727 void cropDomainY(const vec2 &ybounds );
+
5728
+
5730
+
5733 void cropDomainZ(const vec2 &zbounds );
+
5734
+
5736
+
5742 void cropDomain( std::vector<uint> &UUIDs, const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds );
+
5743
+
5745
+
5750 void cropDomain(const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds );
+
5751
+
5753
+
5759 void colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors );
+
5760
+
5762
+
5770 void colorPrimitiveByDataPseudocolor( const std::vector<uint> &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors, float data_min, float data_max );
+
5771
+
5773
+
5779 std::vector<uint> loadXML( const char* filename, bool quiet = false );
+
5780
+
5782
+
5785 std::vector<std::string> getLoadedXMLFiles();
+
5786
+
5788
+
5794 static bool scanXMLForTag( const std::string &filename, const std::string &tag, const std::string &label="" );
+
5795
+
5797
+
5801 void writeXML( const char* filename, bool quiet = false ) const;
+
5802
+
5804
+
5809 void writeXML( const char* filename, const std::vector<uint> &UUIDs, bool quiet = false ) const;
+
5810
+
5812
+
5817 void writeXML_byobject( const char* filename, const std::vector<uint> &UUIDs, bool quiet = false ) const;
+
5818
+
5820
+
5825 void writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, bool print_header = false ) const;
+
5826
+
5828
+
5834 void writePrimitiveData( std::string filename, const std::vector<std::string> &column_format, const std::vector<uint> &UUIDs, bool print_header = false ) const;
+
5835
+
5837
+
5843 std::vector<uint> loadPLY(const char* filename, bool silent=false );
+
5844
+
5846
+
5855 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const std::string &upaxis="YUP", bool silent=false );
5856
-
5858
-
5867 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const RGBcolor &default_color, const std::string &upaxis="YUP", bool silent=false );
-
5868
-
5870
-
5880 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const std::string &upaxis="YUP", bool silent=false );
+
5858
+
5868 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const std::string &upaxis="YUP", bool silent=false );
+
5869
+
5871
+
5880 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const RGBcolor &default_color, const std::string &upaxis="YUP", bool silent=false );
5881
-
5883
-
5886 void writePLY( const char* filename ) const;
-
5887
-
5889
-
5893 std::vector<uint> loadOBJ(const char* filename, bool silent=false );
+
5883
+
5893 std::vector<uint> loadPLY(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const std::string &upaxis="YUP", bool silent=false );
5894
-
5896
-
5905 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, bool silent=false );
-
5906
-
5908
-
5918 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent=false );
-
5919
-
5920
-
5922
-
5932 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, const helios::vec3 &scale, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent=false );
-
5933
-
5935
-
5938 void writeOBJ( const std::string &filename ) const;
-
5939
-
5941
-
5945 void writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs ) const;
-
5946
-
5948
-
5953 void writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_dat_fields ) const;
-
5954
-
5956
-
5962 void setDate( int day, int month, int year );
-
5963
-
5965
-
5969 void setDate(const Date &date );
-
5970
-
5972
-
5977 void setDate( int Julian_day, int year );
-
5978
-
5980
-
5984 helios::Date getDate() const;
-
5985
-
5987
-
5991 const char* getMonthString() const;
-
5992
-
5994
-
5998 int getJulianDate() const;
-
5999
-
6001
-
6007 void setTime( int minute, int hour );
-
6008
-
6010
-
6017 void setTime( int second, int minute, int hour );
-
6018
-
6020
-
6025 void setTime(const Time &time );
-
6026
-
6028
-
6032 helios::Time getTime() const;
-
6033
-
6035
-
6038 void setLocation( const helios::Location &location );
-
6039
-
6041
- -
6045
-
6047
-
6050 float randu();
-
6051
-
6053
-
6058 float randu( float min, float max );
-
6059
-
6061
-
6066 int randu( int min, int max );
-
6067
-
6069
-
6072 float randn();
-
6073
-
6075
-
6080 float randn( float mean, float stddev );
-
6081
-
6083
-
6087 void duplicatePrimitiveData( const char* existing_data_label, const char* copy_data_label );
-
6088
-
6090
-
6095 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, float &mean ) const;
-
6096
-
6098
-
6103 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, double &mean ) const;
-
6104
-
6106
-
6111 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &mean ) const;
-
6112
-
6114
-
6119 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &mean ) const;
-
6120
-
6122
-
6127 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &mean ) const;
-
6128
-
6130
-
6135 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, float &awt_mean ) const;
-
6136
-
6138
-
6143 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, double &awt_mean ) const;
-
6144
-
6146
-
6151 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &awt_mean ) const;
-
6152
-
6154
-
6159 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &awt_mean ) const;
-
6160
-
6162
-
6167 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &awt_mean ) const;
-
6168
-
6170
-
6175 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, float &sum ) const;
-
6176
-
6178
-
6183 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, double &sum ) const;
-
6184
-
6186
-
6191 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &sum ) const;
-
6192
-
6194
-
6199 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &sum ) const;
-
6200
-
6202
-
6207 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &sum ) const;
-
6208
-
6210
-
6215 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, float &awt_sum ) const;
-
6216
-
6218
-
6223 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, double &sum ) const;
-
6224
-
6226
-
6231 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &sum ) const;
-
6232
-
6234
-
6239 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &sum ) const;
-
6240
-
6242
-
6247 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &sum ) const;
-
6248
-
6250
-
6256 void scalePrimitiveData( const std::vector<uint> &UUIDs, const std::string &label, float scaling_factor );
-
6257
-
6259
-
6264 void scalePrimitiveData( const std::string &label, float scaling_factor );
-
6265
-
6267
-
6273 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, int increment );
-
6274
-
6276
-
6282 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, uint increment );
-
6283
-
6285
-
6291 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, float increment );
-
6292
-
6294
-
6300 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, double increment );
-
6301
-
6303
-
6309 void aggregatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_data_labels, const std::string &result_primitive_data_label );
-
6310
-
6312
-
6318 void aggregatePrimitiveDataProduct( const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_data_labels, const std::string &result_primitive_data_label );
-
6319
-
6321
-
6325 float sumPrimitiveSurfaceArea( const std::vector<uint> &UUIDs ) const;
-
6326
-
6328
-
6336 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator );
-
6337
-
6339
-
6347 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, double filter_value, const std::string &comparator );
-
6348
-
6350
-
6358 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, int filter_value, const std::string &comparator );
-
6359
-
6361
-
6369 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, uint filter_value, const std::string &comparator );
-
6370
-
6372
-
6379 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, const std::string &filter_value );
-
6380
-
6382
-
6390 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, float filter_value, const std::string &comparator );
-
6391
-
6393
-
6401 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, double filter_value, const std::string &comparator );
-
6402
-
6404
-
6412 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, int filter_value, const std::string &comparator );
-
6413
-
6415
-
6423 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, uint filter_value, const std::string &comparator );
-
6424
-
6426
-
6433 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, const std::string &filter_value );
-
6434
-
6435};
+
5896
+
5899 void writePLY( const char* filename ) const;
+
5900
+
5902
+
5906 std::vector<uint> loadOBJ(const char* filename, bool silent=false );
+
5907
+
5909
+
5918 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, bool silent=false );
+
5919
+
5921
+
5931 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, float height, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent=false );
+
5932
+
5933
+
5935
+
5945 std::vector<uint> loadOBJ(const char* filename, const vec3 &origin, const helios::vec3 &scale, const SphericalCoord &rotation, const RGBcolor &default_color, const char* upaxis, bool silent=false );
+
5946
+
5948
+
5951 void writeOBJ( const std::string &filename ) const;
+
5952
+
5954
+
5958 void writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs ) const;
+
5959
+
5961
+
5966 void writeOBJ( const std::string &filename, const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_dat_fields ) const;
+
5967
+
5969
+
5975 void setDate( int day, int month, int year );
+
5976
+
5978
+
5982 void setDate(const Date &date );
+
5983
+
5985
+
5990 void setDate( int Julian_day, int year );
+
5991
+
5993
+
5997 helios::Date getDate() const;
+
5998
+
6000
+
6004 const char* getMonthString() const;
+
6005
+
6007
+
6011 int getJulianDate() const;
+
6012
+
6014
+
6020 void setTime( int minute, int hour );
+
6021
+
6023
+
6030 void setTime( int second, int minute, int hour );
+
6031
+
6033
+
6038 void setTime(const Time &time );
+
6039
+
6041
+
6045 helios::Time getTime() const;
+
6046
+
6048
+
6051 void setLocation( const helios::Location &location );
+
6052
+
6054
+ +
6058
+
6060
+
6063 float randu();
+
6064
+
6066
+
6071 float randu( float min, float max );
+
6072
+
6074
+
6079 int randu( int min, int max );
+
6080
+
6082
+
6085 float randn();
+
6086
+
6088
+
6093 float randn( float mean, float stddev );
+
6094
+
6096
+
6100 void duplicatePrimitiveData( const char* existing_data_label, const char* copy_data_label );
+
6101
+
6103
+
6108 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, float &mean ) const;
+
6109
+
6111
+
6116 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, double &mean ) const;
+
6117
+
6119
+
6124 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &mean ) const;
+
6125
+
6127
+
6132 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &mean ) const;
+
6133
+
6135
+
6140 void calculatePrimitiveDataMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &mean ) const;
+
6141
+
6143
+
6148 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, float &awt_mean ) const;
+
6149
+
6151
+
6156 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, double &awt_mean ) const;
+
6157
+
6159
+
6164 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &awt_mean ) const;
+
6165
+
6167
+
6172 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &awt_mean ) const;
+
6173
+
6175
+
6180 void calculatePrimitiveDataAreaWeightedMean( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &awt_mean ) const;
+
6181
+
6183
+
6188 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, float &sum ) const;
+
6189
+
6191
+
6196 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, double &sum ) const;
+
6197
+
6199
+
6204 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &sum ) const;
+
6205
+
6207
+
6212 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &sum ) const;
+
6213
+
6215
+
6220 void calculatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &sum ) const;
+
6221
+
6223
+
6228 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, float &awt_sum ) const;
+
6229
+
6231
+
6236 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, double &sum ) const;
+
6237
+
6239
+
6244 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec2 &sum ) const;
+
6245
+
6247
+
6252 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec3 &sum ) const;
+
6253
+
6255
+
6260 void calculatePrimitiveDataAreaWeightedSum( const std::vector<uint> &UUIDs, const std::string &label, helios::vec4 &sum ) const;
+
6261
+
6263
+
6269 void scalePrimitiveData( const std::vector<uint> &UUIDs, const std::string &label, float scaling_factor );
+
6270
+
6272
+
6277 void scalePrimitiveData( const std::string &label, float scaling_factor );
+
6278
+
6280
+
6286 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, int increment );
+
6287
+
6289
+
6295 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, uint increment );
+
6296
+
6298
+
6304 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, float increment );
+
6305
+
6307
+
6313 void incrementPrimitiveData( const std::vector<uint> &UUIDs, const char* label, double increment );
+
6314
+
6316
+
6322 void aggregatePrimitiveDataSum( const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_data_labels, const std::string &result_primitive_data_label );
+
6323
+
6325
+
6331 void aggregatePrimitiveDataProduct( const std::vector<uint> &UUIDs, const std::vector<std::string> &primitive_data_labels, const std::string &result_primitive_data_label );
+
6332
+
6334
+
6338 float sumPrimitiveSurfaceArea( const std::vector<uint> &UUIDs ) const;
+
6339
+
6341
+
6349 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator );
+
6350
+
6352
+
6360 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, double filter_value, const std::string &comparator );
+
6361
+
6363
+
6371 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, int filter_value, const std::string &comparator );
+
6372
+
6374
+
6382 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, uint filter_value, const std::string &comparator );
+
6383
+
6385
+
6392 std::vector<uint> filterPrimitivesByData( const std::vector<uint> &UUIDs, const std::string &primitive_data_label, const std::string &filter_value );
+
6393
+
6395
+
6403 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, float filter_value, const std::string &comparator );
+
6404
+
6406
+
6414 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, double filter_value, const std::string &comparator );
+
6415
+
6417
+
6425 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, int filter_value, const std::string &comparator );
+
6426
+
6428
+
6436 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, uint filter_value, const std::string &comparator );
+
6437
+
6439
+
6446 std::vector<uint> filterObjectsByData( const std::vector<uint> &objIDs, const std::string &object_data_label, const std::string &filter_value );
+
6447
+
6448};
-
6436
-
6437}
-
6438
-
6439
-
6440
-
6441#endif
+
6449
+
6450}
+
6451
+
6452
+
6453
+
6454#endif
HeliosDataType
Data types.
Definition Context.h:41
@ HELIOS_TYPE_INT3
helios::int3 data type
Definition Context.h:59
@ HELIOS_TYPE_DOUBLE
double data type
Definition Context.h:49
@@ -2898,7 +2913,7 @@
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
PrimitiveType
Type of primitive element.
Definition Context.h:31
@ PRIMITIVE_TYPE_PATCH
< Rectangular primitive
Definition Context.h:33
-
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
+
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
@ PRIMITIVE_TYPE_TRIANGLE
< Triangular primitive
Definition Context.h:35
ObjectType
Type of compound object.
Definition Context.h:128
@ OBJECT_TYPE_BOX
Box.
Definition Context.h:136
@@ -2908,14 +2923,14 @@
@ OBJECT_TYPE_DISK
< Disk
Definition Context.h:138
@ OBJECT_TYPE_TILE
< Tile
Definition Context.h:130
@ OBJECT_TYPE_SPHERE
< Sphere
Definition Context.h:132
-
Box compound object class.
Definition Context.h:759
-
float getVolume() const
Get the volume of the box object.
Definition Context.cpp:4004
-
void setSubdivisionCount(const helios::int3 &subdiv)
Set the number of box sub-patch divisions.
Definition Context.cpp:4000
-
helios::int3 getSubdivisionCount() const
Get the number of sub-patch divisions of the box object in each Cartesian direction.
Definition Context.cpp:3996
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the box object.
Definition Context.cpp:3980
+
Box compound object class.
Definition Context.h:765
+
float getVolume() const
Get the volume of the box object.
Definition Context.cpp:4031
+
void setSubdivisionCount(const helios::int3 &subdiv)
Set the number of box sub-patch divisions.
Definition Context.cpp:4027
+
helios::int3 getSubdivisionCount() const
Get the number of sub-patch divisions of the box object in each Cartesian direction.
Definition Context.cpp:4023
+
vec3 getCenter() const
Get the Cartesian coordinates of the center of the box object.
Definition Context.cpp:4007
~Box() override=default
Box destructor.
-
Box(uint a_OID, const std::vector< uint > &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:3941
-
vec3 getSize() const
Get the dimensions of the box object in each Cartesian direction.
Definition Context.cpp:3961
+
Box(uint a_OID, const std::vector< uint > &a_UUIDs, const int3 &a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:3968
+
vec3 getSize() const
Get the dimensions of the box object in each Cartesian direction.
Definition Context.cpp:3988
uint getObjectDataSize(const char *label) const
Get the size/length of object data.
void rotate(float rotation_radians, const char *rotation_axis_xyz_string)
Method to rotate a Compound Object about the x-, y-, or z-axis.
Definition Context.cpp:2377
@@ -2934,7 +2949,7 @@
bool arePrimitivesComplete() const
Method to query whether all object primitives are in tact.
Definition Context.cpp:2536
float getArea() const
Calculate the total one-sided surface area of the Compound Object.
Definition Context.cpp:2285
void translate(const helios::vec3 &shift)
Method to translate/shift a Compound Object.
Definition Context.cpp:2353
-
bool doesObjectDataExist(const char *label) const
Check if object data 'label' exists.
+
bool doesObjectDataExist(const char *label) const
Check if object data 'label' exists.
helios::ObjectType getObjectType() const
Get an enumeration specifying the type of the object.
Definition Context.cpp:2247
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
HeliosDataType getObjectDataType(const char *label) const
Get the Helios data type of object data.
@@ -2946,230 +2961,231 @@
void useTextureColor()
For all primitives in the Compound Object, use the texture map to color the primitives rather than th...
Definition Context.cpp:2331
bool doesObjectContainPrimitive(uint UUID)
Check whether a primitive is a member of the object based on its UUID.
Definition Context.cpp:2262
helios::vec3 getObjectCenter() const
Calculate the Cartesian (x,y,z) point of the center of a bounding box for the Compound Object.
Definition Context.cpp:2268
-
Cone compound object class.
Definition Context.h:847
-
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the cone object.
Definition Context.cpp:4171
-
Cone(uint a_OID, const std::vector< uint > &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0, float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4107
-
float getNodeRadius(int node_index) const
Get the radius of a cone object node.
Definition Context.cpp:4163
-
void setSubdivisionCount(uint subdiv)
Set the number of radial sub-triangle divisions.
Definition Context.cpp:4175
-
helios::vec3 getNodeCoordinate(int node_index) const
Get the Cartesian coordinates of a cone object node.
Definition Context.cpp:4144
-
helios::vec3 getAxisUnitVector() const
Get a unit vector pointing in the direction of the cone central axis.
Definition Context.cpp:4179
-
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4130
-
void scaleLength(float S)
Method to scale the length of the cone.
Definition Context.cpp:4212
+
Cone compound object class.
Definition Context.h:853
+
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the cone object.
Definition Context.cpp:4198
+
Cone(uint a_OID, const std::vector< uint > &a_UUIDs, const vec3 &a_node0, const vec3 &a_node1, float a_radius0, float a_radius1, uint a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4134
+
float getNodeRadius(int node_index) const
Get the radius of a cone object node.
Definition Context.cpp:4190
+
void setSubdivisionCount(uint subdiv)
Set the number of radial sub-triangle divisions.
Definition Context.cpp:4202
+
helios::vec3 getNodeCoordinate(int node_index) const
Get the Cartesian coordinates of a cone object node.
Definition Context.cpp:4171
+
helios::vec3 getAxisUnitVector() const
Get a unit vector pointing in the direction of the cone central axis.
Definition Context.cpp:4206
+
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4157
+
void scaleLength(float S)
Method to scale the length of the cone.
Definition Context.cpp:4239
~Cone() override=default
Cone destructor.
-
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition Context.cpp:4261
-
float getLength() const
Get the length of the cone along the axial direction.
Definition Context.cpp:4197
-
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4159
-
float getVolume() const
Get the volume of the cone object.
Definition Context.cpp:4302
-
Stores the state associated with simulation.
Definition Context.h:1882
+
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition Context.cpp:4288
+
float getLength() const
Get the length of the cone along the axial direction.
Definition Context.cpp:4224
+
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4186
+
float getVolume() const
Get the volume of the cone object.
Definition Context.cpp:4329
+
Stores the state associated with simulation.
Definition Context.h:1888
void copyPrimitiveData(uint sourceUUID, uint destinationUUID)
copy all primitive data from one primitive to another
-
std::vector< helios::vec2 > getTileObjectTextureUV(uint ObjID) const
get the texture UV coordinates of a tile object from the context
Definition Context.cpp:8132
+
std::vector< helios::vec2 > getTileObjectTextureUV(uint ObjID) const
get the texture UV coordinates of a tile object from the context
Definition Context.cpp:8159
void setTileObjectSubdivisionCount(const std::vector< uint > &ObjectIDs, const int2 &new_subdiv)
Change the subdivision count of a tile object.
Definition Context.cpp:2982
-
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7139
-
void getPrimitiveTransformationMatrix(uint UUID, float(&T)[16]) const
Method to return the Affine transformation matrix of a Primitive.
Definition Context.cpp:7108
-
void scaleTubeLength(uint ObjID, float scale_factor)
Scale the length of a tube object by an arbitrary factor for all tube nodes.
Definition Context.cpp:8208
-
bool isObjectHidden(uint ObjID) const
Query if an object is hidden.
Definition Context.cpp:7913
+
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7166
+
void getPrimitiveTransformationMatrix(uint UUID, float(&T)[16]) const
Method to return the Affine transformation matrix of a Primitive.
Definition Context.cpp:7135
+
void scaleTubeLength(uint ObjID, float scale_factor)
Scale the length of a tube object by an arbitrary factor for all tube nodes.
Definition Context.cpp:8235
+
bool isObjectHidden(uint ObjID) const
Query if an object is hidden.
Definition Context.cpp:7940
std::vector< std::string > listTimeseriesVariables() const
List all existing timeseries variables.
Definition Context.cpp:2036
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:2897
-
float getTubeObjectSegmentVolume(uint ObjID, uint segment_index) const
get the volume of a segment within a Tube object
Definition Context.cpp:8176
+
float getTubeObjectSegmentVolume(uint ObjID, uint segment_index) const
get the volume of a segment within a Tube object
Definition Context.cpp:8203
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:7127
+
helios::RGBcolor getPrimitiveColor(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7154
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:2642
float randn()
Draw a random number from a normal distribution with mean = 0, stddev = 1.
Definition Context.cpp:1204
-
Disk * getDiskObjectPointer(uint ObjID) const
Get a pointer to a Disk Compound Object.
Definition Context.cpp:4022
-
void overrideObjectTextureColor(uint ObjID)
Override the color in the texture map for all primitives in the Compound Object, in which case the pr...
Definition Context.cpp:7978
-
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:7022
+
Disk * getDiskObjectPointer(uint ObjID) const
Get a pointer to a Disk Compound Object.
Definition Context.cpp:4049
+
void overrideObjectTextureColor(uint ObjID)
Override the color in the texture map for all primitives in the Compound Object, in which case the pr...
Definition Context.cpp:8005
+
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:7049
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
void getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single object.
Definition Context.cpp:7998
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
void getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single object.
Definition Context.cpp:8025
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
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:3954
+
Box * getBoxObjectPointer(uint ObjID) const
Get a pointer to a Box Compound Object.
Definition Context.cpp:3981
void cleanDeletedUUIDs(std::vector< uint > &UUIDs) const
Delete UUIDs from vector if primitives no longer exist (1D vector)
Definition Context.cpp:1793
-
uint getConeObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Cone object from the context
Definition Context.cpp:8250
-
helios::vec3 getDiskObjectCenter(uint ObjID) const
get the center of a Disk object from the context
Definition Context.cpp:8238
+
uint getConeObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Cone object from the context
Definition Context.cpp:8284
+
helios::vec3 getDiskObjectCenter(uint ObjID) const
get the center of a Disk object from the context
Definition Context.cpp:8272
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
int getJulianDate() const
Get simulation date by Julian day.
Definition Context.cpp:1132
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
-
helios::int3 getBoxObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Box object from the context
Definition Context.cpp:8230
-
uint getTubeObjectSubdivisionCount(uint ObjectID) const
get the subdivision count of a Tube object from the context
Definition Context.cpp:8156
-
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
-
~Context()
Context destructor.
Definition Context.cpp:6970
-
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7017
+
helios::int3 getBoxObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Box object from the context
Definition Context.cpp:8264
+
uint getTubeObjectSubdivisionCount(uint ObjectID) const
get the subdivision count of a Tube object from the context
Definition Context.cpp:8183
+
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
+
~Context()
Context destructor.
Definition Context.cpp:6997
+
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7044
std::vector< uint > getAllObjectIDs() const
Get the IDs for all Compound Objects in the Context.
Definition Context.cpp:2589
-
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4123
+
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4150
void seedRandomGenerator(uint seed)
Set seed for random generator.
Definition Context.cpp:45
void getObjectData(uint objID, const char *label, int &data) const
Get data associated with a compound object.
-
void printPrimitiveInfo(uint UUID) const
Prints primitive properties to console (useful for debugging purposes)
Definition Context.cpp:7225
+
void printPrimitiveInfo(uint UUID) const
Prints primitive properties to console (useful for debugging purposes)
Definition Context.cpp:7252
void markGeometryClean()
Mark the Context geometry as "clean", meaning that the geometry has not been modified since last set ...
Definition Context.cpp:149
void getDomainBoundingSphere(helios::vec3 &center, float &radius) const
Get the center and radius of a sphere that bounds all primitives in the domain.
Definition Context.cpp:2116
void rotateObject(uint ObjID, float rotation_radians, const char *rotation_axis_xyz)
Rotate a single compound object about the x, y, or z axis.
Definition Context.cpp:2847
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
helios::vec3 getPatchCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a patch element.
Definition Context.cpp:1693
std::vector< uint > filterPrimitivesByData(const std::vector< uint > &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator)
Filter a set of primitives based on their primitive data and a condition and float value.
-
helios::vec2 getTileObjectSize(uint ObjID) const
get the size of a tile object from the context
Definition Context.cpp:8120
-
uint getObjectPrimitiveCount(uint ObjID) const
Method to return the number of primitives contained in the object.
Definition Context.cpp:7924
+
helios::vec2 getTileObjectSize(uint ObjID) const
get the size of a tile object from the context
Definition Context.cpp:8147
+
uint getObjectPrimitiveCount(uint ObjID) const
Method to return the number of primitives contained in the object.
Definition Context.cpp:7951
std::vector< std::string > getLoadedXMLFiles()
Get names of XML files that are currently loaded.
uint getPrimitiveDataSize(uint UUID, const char *label) const
Get the size/length of primitive data.
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
void calculatePrimitiveDataSum(const std::vector< uint > &UUIDs, const std::string &label, float &sum) const
Calculate sum of primitive data values (float) for a subset of primitives.
-
helios::RGBAcolor getPrimitiveColorRGBA(uint UUID) const
Method to return the diffuse color of a Primitive with transparency.
Definition Context.cpp:7135
-
helios::vec3 getBoxObjectSize(uint ObjID) const
get the size of a Box object from the context
Definition Context.cpp:8226
-
helios::vec3 getSphereObjectCenter(uint ObjID) const
get the center of a Sphere object from the context
Definition Context.cpp:8140
+
helios::RGBAcolor getPrimitiveColorRGBA(uint UUID) const
Method to return the diffuse color of a Primitive with transparency.
Definition Context.cpp:7162
+
helios::vec3 getBoxObjectSize(uint ObjID) const
get the size of a Box object from the context
Definition Context.cpp:8260
+
helios::vec3 getSphereObjectCenter(uint ObjID) const
get the center of a Sphere object from the context
Definition Context.cpp:8167
void incrementPrimitiveData(const std::vector< uint > &UUIDs, const char *label, int increment)
Increase value of primitive data (int) by some value.
-
helios::vec3 getObjectCenter(uint ObjID) const
Method to return the Cartesian (x,y,z) point of the center of a bounding box for the object.
Definition Context.cpp:7928
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7159
+
helios::vec3 getObjectCenter(uint ObjID) const
Method to return the Cartesian (x,y,z) point of the center of a bounding box for the object.
Definition Context.cpp:7955
+
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7186
uint getObjectCount() const
Get the total number of objects that have been created in the Context.
Definition Context.cpp:2581
-
helios::vec3 getConeObjectNode(uint ObjID, int number) const
get a node of a Cone object from the context
Definition Context.cpp:8262
-
float getTubeObjectVolume(uint ObjID) const
get the volume of a Tube object from the context
Definition Context.cpp:8172
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7175
+
helios::vec3 getConeObjectNode(uint ObjID, int number) const
get a node of a Cone object from the context
Definition Context.cpp:8296
+
float getTubeObjectVolume(uint ObjID) const
get the volume of a Tube object from the context
Definition Context.cpp:8199
+
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7202
void cropDomainZ(const vec2 &zbounds)
Crop the domain in the z-direction such that all primitives lie within some specified z interval.
Definition Context.cpp:2190
-
Polymesh * getPolymeshObjectPointer(uint ObjID) const
Get a pointer to a Polygon Mesh Compound Object.
Definition Context.cpp:4081
+
Polymesh * getPolymeshObjectPointer(uint ObjID) const
Get a pointer to a Polygon Mesh Compound Object.
Definition Context.cpp:4108
void cropDomainX(const vec2 &xbounds)
Crop the domain in the x-direction such that all primitives lie within some specified x interval.
Definition Context.cpp:2144
-
helios::vec3 getSphereObjectRadius(uint ObjID) const
get the radius of a Sphere object from the context
Definition Context.cpp:8144
+
helios::vec3 getSphereObjectRadius(uint ObjID) const
get the radius of a Sphere object from the context
Definition Context.cpp:8171
void setDate(int day, int month, int year)
Set simulation date by day, month, year.
Definition Context.cpp:1059
void renamePrimitiveData(uint UUID, const char *old_label, const char *new_label)
Rename primitive data for a primitive.
-
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:6988
-
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7179
+
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7015
+
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7206
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
void usePrimitiveTextureColor(uint UUID)
Use the texture map to color the primitive rather than the constant RGB color. This is function rever...
Definition Context.cpp:7207
-
bool doesObjectContainPrimitive(uint ObjID, uint UUID)
Method to check if an Object contains a Primitive.
Definition Context.cpp:7974
+
void usePrimitiveTextureColor(uint UUID)
Use the texture map to color the primitive rather than the constant RGB color. This is function rever...
Definition Context.cpp:7234
+
bool doesObjectContainPrimitive(uint ObjID, uint UUID)
Method to check if an Object contains a Primitive.
Definition Context.cpp:8001
void duplicateObjectData(uint objID, const char *old_label, const char *new_label)
Duplicate/copy existing object data.
const char * getMonthString() const
Get a string corresponding to the month of the simulation date.
Definition Context.cpp:1103
std::vector< uint > filterObjectsByData(const std::vector< uint > &ObjIDs, const char *object_data, float threshold, const char *comparator) const
Get a vector of object IDs that meet filtering criteria based on object data.
Definition Context.cpp:2750
-
void setObjectColor(uint ObjID, const helios::RGBcolor &color)
Method to set the diffuse color of an Object.
Definition Context.cpp:7954
+
void setObjectColor(uint ObjID, const helios::RGBcolor &color)
Method to set the diffuse color of an Object.
Definition Context.cpp:7981
void setTriangleVertices(uint UUID, const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
//! Manually set the Triangle vertices
Definition Context.cpp:1722
-
void appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float radius, const RGBcolor &color)
Append a tube segment to an existing tube object.
Definition Context.cpp:8180
+
void appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float radius, const RGBcolor &color)
Append a tube segment to an existing tube object.
Definition Context.cpp:8207
bool isGeometryDirty() const
Query whether the Context geometry is "dirty", meaning has the geometry been modified since last set ...
Definition Context.cpp:157
-
helios::vec3 getTileObjectNormal(uint ObjID) const
get the normal of a tile object from the context
Definition Context.cpp:8128
+
helios::vec3 getTileObjectNormal(uint ObjID) const
get the normal of a tile object from the context
Definition Context.cpp:8155
Context()
Context default constructor.
Definition Context.cpp:20
-
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
+
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
void aggregatePrimitiveDataProduct(const std::vector< uint > &UUIDs, const std::vector< std::string > &primitive_data_labels, const std::string &result_primitive_data_label)
Multiply primitive data values for each primitive together and store result in new primitive data.
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
+
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:7011
helios::vec3 getVoxelSize(uint UUID) const
Get the size of a voxel element.
Definition Context.cpp:1741
-
std::vector< float > getTubeObjectNodeRadii(uint ObjID) const
get the node radii of a Tube object from the context
Definition Context.cpp:8164
+
std::vector< float > getTubeObjectNodeRadii(uint ObjID) const
get the node radii of a Tube object from the context
Definition Context.cpp:8191
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
void clearObjectData(uint objID, const char *label)
Clear primitive data for a single primitive based on its objID.
-
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7221
+
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7248
void translateObject(uint ObjID, const vec3 &shift)
Translate a single compound object.
Definition Context.cpp:2837
void scaleObjectAboutCenter(uint ObjID, const helios::vec3 &scalefact)
Method to scale a compound object in the x-, y- and z-directions.
Definition Context.cpp:2887
void cropDomainY(const vec2 &ybounds)
Crop the domain in the y-direction such that all primitives lie within some specified y interval.
Definition Context.cpp:2167
helios::ObjectType getObjectType(uint ObjID) const
Get an enumeration specifying the type of the object.
Definition Context.cpp:2940
-
void colorPrimitiveByDataPseudocolor(const std::vector< uint > &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors)
Overwrite primitive color based on a pseudocolor mapping of primitive data values.
Definition Context.cpp:6666
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
std::vector< RGBcolor > getTubeObjectNodeColors(uint ObjID) const
get the node colors of a Tube object from the context
Definition Context.cpp:8168
+
void colorPrimitiveByDataPseudocolor(const std::vector< uint > &UUIDs, const std::string &primitive_data, const std::string &colormap, uint Ncolors)
Overwrite primitive color based on a pseudocolor mapping of primitive data values.
Definition Context.cpp:6693
+
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
std::vector< RGBcolor > getTubeObjectNodeColors(uint ObjID) const
get the node colors of a Tube object from the context
Definition Context.cpp:8195
std::vector< std::string > listPrimitiveData(uint UUID) const
Return labels for all primitive data for this particular primitive.
std::vector< uint > getObjectPrimitiveUUIDs(uint ObjID) const
Get primitive UUIDs associated with compound object (single object ID input)
Definition Context.cpp:2907
+
void pruneTubeNodes(uint ObjID, uint node_index)
Remove a portion of the tube downstream of a specified node.
Definition Context.cpp:8242
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
-
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7167
+
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7194
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:1711
helios::Time getTime() const
Get the simulation time.
Definition Context.cpp:1166
-
helios::RGBcolor getPrimitiveColorRGB(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7131
+
helios::RGBcolor getPrimitiveColorRGB(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7158
Context(const Context &)=delete
Deleted copy constructor to prevent copying of Context.
std::vector< uint > loadOBJ(const char *filename, bool silent=false)
Load geometry contained in a Wavefront OBJ file (.obj). Model will be placed at the origin without an...
void getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const
Get a box that bounds all primitives in the domain.
Definition Context.cpp:2046
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:8246
-
void setPrimitiveTextureFile(uint UUID, const std::string &texturefile)
Set the texture map file for a primitive.
Definition Context.cpp:7163
-
std::vector< helios::vec3 > getConeObjectNodes(uint ObjID) const
get the nodes of a Cone object from the context
Definition Context.cpp:8254
+
uint getDiskObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Disk object from the context
Definition Context.cpp:8280
+
void setPrimitiveTextureFile(uint UUID, const std::string &texturefile)
Set the texture map file for a primitive.
Definition Context.cpp:7190
+
std::vector< helios::vec3 > getConeObjectNodes(uint ObjID) const
get the nodes of a Cone object from the context
Definition Context.cpp:8288
void hidePrimitive(const std::vector< uint > &UUIDs)
Hide primitives in the Context such that their UUIDs are not returned in Context::getAllUUIDs()
Definition Context.cpp:1777
Sphere * getSphereObjectPointer(uint ObjID) const
Get a pointer to a Sphere Compound Object.
Definition Context.cpp:3410
-
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:7197
+
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:7224
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.
-
helios::int2 getTileObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a tile object from the context
Definition Context.cpp:8124
+
helios::int2 getTileObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a tile object from the context
Definition Context.cpp:8151
HeliosDataType getGlobalDataType(const char *label) const
Get the Helios data type of global data.
bool isPrimitiveHidden(uint UUID) const
Query whether a primitive is hidden.
Definition Context.cpp:1786
helios::Date getDate() const
Get simulation date.
Definition Context.cpp:1099
-
void printObjectInfo(uint ObjID) const
Prints object properties to console (useful for debugging purposes)
Definition Context.cpp:7499
+
void printObjectInfo(uint ObjID) const
Prints object properties to console (useful for debugging purposes)
Definition Context.cpp:7526
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition Context.cpp:49
size_t getGlobalDataSize(const char *label) const
Get the size/length of global data.
void getGlobalData(const char *label, int &data) const
Get global data value (scalar integer)
-
void hideObject(const std::vector< uint > &ObjIDs)
Hide compound objects in the Context such that their object IDs are not returned in Context::getAllOb...
Definition Context.cpp:7901
+
void hideObject(const std::vector< uint > &ObjIDs)
Hide compound objects in the Context such that their object IDs are not returned in Context::getAllOb...
Definition Context.cpp:7928
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7187
+
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7214
float getTileObjectAreaRatio(uint ObjectID) const
Get the area ratio of a tile object (total object area / sub-patch area)
Definition Context.cpp:2944
bool doesObjectExist(uint ObjID) const
Check whether Compound Object exists in the Context.
Definition Context.cpp:2585
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
void clearGlobalData(const char *label)
Delete/clear global data.
void renameObjectData(uint objID, const char *old_label, const char *new_label)
Rename existing object data.
-
std::vector< helios::vec3 > getTubeObjectNodes(uint ObjID) const
get the nodes of a Tube object from the context
Definition Context.cpp:8160
+
std::vector< helios::vec3 > getTubeObjectNodes(uint ObjID) const
get the nodes of a Tube object from the context
Definition Context.cpp:8187
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:8116
-
void scaleTubeGirth(uint ObjID, float scale_factor)
Scale the girth for all nodes of a tube object.
Definition Context.cpp:8194
+
helios::vec3 getTileObjectCenter(uint ObjID) const
Get the Cartesian (x,y,z) center position of a tile object.
Definition Context.cpp:8143
+
void scaleTubeGirth(uint ObjID, float scale_factor)
Scale the girth for all nodes of a tube object.
Definition Context.cpp:8221
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:7217
+
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:7244
void deleteObject(uint ObjID)
Delete a single Compound Object from the context.
Definition Context.cpp:2609
-
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition Context.cpp:7920
-
std::string getObjectTextureFile(uint ObjID) const
Method to return the texture map file of an Object.
Definition Context.cpp:7932
+
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition Context.cpp:7947
+
std::string getObjectTextureFile(uint ObjID) const
Method to return the texture map file of an Object.
Definition Context.cpp:7959
void aggregatePrimitiveDataSum(const std::vector< uint > &UUIDs, const std::vector< std::string > &primitive_data_labels, const std::string &result_primitive_data_label)
Sum multiple primitive data values for each primitive together and store result in new primitive data...
-
float getPolymeshObjectVolume(uint ObjID) const
Get the volume of a Polygon Mesh object from the context.
Definition Context.cpp:8282
+
float getPolymeshObjectVolume(uint ObjID) const
Get the volume of a Polygon Mesh object from the context.
Definition Context.cpp:8316
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1491
Tube * getTubeObjectPointer(uint ObjID) const
Get a pointer to a Tube Compound Object.
Definition Context.cpp:3486
helios::vec2 getPatchSize(uint UUID) const
Get the size of a patch element.
Definition Context.cpp:1684
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:8136
+
std::vector< helios::vec3 > getTileObjectVertices(uint ObjID) const
get the vertices of a tile object from the context
Definition Context.cpp:8163
void markGeometryDirty()
Mark the Context geometry as "dirty", meaning that the geometry has been modified since last set as c...
Definition Context.cpp:153
-
void getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single primitive.
Definition Context.cpp:7057
+
void getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single primitive.
Definition Context.cpp:7084
void writeXML(const char *filename, bool quiet=false) const
Write Context geometry and data to XML file for all UUIDs in the context.
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7104
+
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7131
uint getObjectDataSize(uint objID, const char *label) const
Get the size/length of primitive data.
void calculatePrimitiveDataAreaWeightedSum(const std::vector< uint > &UUIDs, const std::string &label, float &awt_sum) const
Calculate sum of primitive data values (float) for a subset of primitives, where each value in the su...
void incrementGlobalData(const char *label, int increment)
Increase value of global data (int) by some value.
void clearPrimitiveData(uint UUID, const char *label)
Clear primitive data for a single primitive based on its UUID.
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
-
helios::vec3 getConeObjectAxisUnitVector(uint ObjID) const
get the axis unit vector of a Cone object from the context
Definition Context.cpp:8270
+
helios::vec3 getConeObjectAxisUnitVector(uint ObjID) const
get the axis unit vector of a Cone object from the context
Definition Context.cpp:8304
helios::vec3 getVoxelCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a voxel element.
Definition Context.cpp:1750
void calculatePrimitiveDataAreaWeightedMean(const std::vector< uint > &UUIDs, const std::string &label, float &awt_mean) const
Calculate mean of primitive data values (float) for a subset of primitives, where each value in the m...
-
helios::vec2 getDiskObjectSize(uint ObjID) const
get the size of a Disk object from the context
Definition Context.cpp:8242
+
helios::vec2 getDiskObjectSize(uint ObjID) const
get the size of a Disk object from the context
Definition Context.cpp:8276
bool doesPrimitiveExist(uint UUID) const
Check if primitive exists for a given UUID.
Definition Context.cpp:1659
bool areObjectPrimitivesComplete(uint objID) const
Method to query whether all object primitives are in tact.
Definition Context.cpp:2540
-
float getConeObjectLength(uint ObjID) const
get the length of a Cone object from the context
Definition Context.cpp:8274
+
float getConeObjectLength(uint ObjID) const
get the length of a Cone object from the context
Definition Context.cpp:8308
Tile * getTileObjectPointer(uint ObjID) const
Get a pointer to a Tile Compound Object.
Definition Context.cpp:3312
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:1512
-
void useObjectTextureColor(uint ObjID)
For all primitives in the Compound Object, use the texture map to color the primitives rather than th...
Definition Context.cpp:7988
-
uint getSphereObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Sphere object from the context
Definition Context.cpp:8148
+
void useObjectTextureColor(uint ObjID)
For all primitives in the Compound Object, use the texture map to color the primitives rather than th...
Definition Context.cpp:8015
+
uint getSphereObjectSubdivisionCount(uint ObjID) const
get the subdivision count of a Sphere object from the context
Definition Context.cpp:8175
static bool scanXMLForTag(const std::string &filename, const std::string &tag, const std::string &label="")
Scan a Helios XML file to check if a tag exists.
void setLocation(const helios::Location &location)
Set the location of the simulation (latitude, longitude, and UTC offset)
Definition Context.cpp:1170
std::vector< std::string > listObjectData(uint ObjID) const
Return labels for all object data for this particular object.
-
std::vector< float > getConeObjectNodeRadii(uint ObjID) const
get the node radii of a Cone object from the context
Definition Context.cpp:8258
+
std::vector< float > getConeObjectNodeRadii(uint ObjID) const
get the node radii of a Cone object from the context
Definition Context.cpp:8292
std::vector< std::string > listGlobalData() const
List the labels for all global data in the Context.
void writeXML_byobject(const char *filename, const std::vector< uint > &UUIDs, bool quiet=false) const
Write Context geometry and data to XML file for a subset of compound object IDs in the context.
-
float getBoxObjectVolume(uint ObjID) const
get the volume of a Box object from the context
Definition Context.cpp:8234
+
float getBoxObjectVolume(uint ObjID) const
get the volume of a Box object from the context
Definition Context.cpp:8268
void copyObjectData(uint source_objID, uint destination_objID)
copy all object data from one compound object to another
void setTime(int minute, int hour)
Set simulation time.
Definition Context.cpp:1136
-
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:7122
+
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:7149
void duplicateGlobalData(const char *old_label, const char *new_label)
Make a copy of global data.
-
float getSphereObjectVolume(uint ObjID) const
get the volume of a Sphere object from the context
Definition Context.cpp:8152
-
void setObjectTransformationMatrix(uint ObjID, float(&T)[16])
Method to set the Affine transformation matrix of an Object.
Definition Context.cpp:7940
+
float getSphereObjectVolume(uint ObjID) const
get the volume of a Sphere object from the context
Definition Context.cpp:8179
+
void setObjectTransformationMatrix(uint ObjID, float(&T)[16])
Method to set the Affine transformation matrix of an Object.
Definition Context.cpp:7967
void cropDomain(std::vector< uint > &UUIDs, const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds)
Crop specified UUIDs such that they lie within some specified axis-aligned box.
Definition Context.cpp:2213
void operator=(const Context &)=delete
Deleted assignment operator to prevent copying of Context.
-
void setTubeNodes(uint ObjID, const std::vector< helios::vec3 > &node_xyz)
Set tube vertex coordinates at each segment node.
Definition Context.cpp:8215
+
void setTubeNodes(uint ObjID, const std::vector< helios::vec3 > &node_xyz)
Set tube vertex coordinates at each segment node.
Definition Context.cpp:8249
helios::Location getLocation() const
Get the location of the simulation (latitude, longitude, and UTC offset)
Definition Context.cpp:1174
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
-
float getConeObjectNodeRadius(uint ObjID, int number) const
get a node radius of a Cone object from the context
Definition Context.cpp:8266
+
float getConeObjectNodeRadius(uint ObjID, int number) const
get a node radius of a Cone object from the context
Definition Context.cpp:8300
void cleanDeletedObjectIDs(std::vector< uint > &objIDs) const
Delete Object IDs from vector if objects no longer exist (1D vector)
Definition Context.cpp:2544
-
float getConeObjectVolume(uint ObjID) const
get the volume of a Cone object from the context
Definition Context.cpp:8278
-
helios::vec3 getBoxObjectCenter(uint ObjID) const
get the center of a Box object from the context
Definition Context.cpp:8222
+
float getConeObjectVolume(uint ObjID) const
get the volume of a Cone object from the context
Definition Context.cpp:8312
+
helios::vec3 getBoxObjectCenter(uint ObjID) const
get the center of a Box object from the context
Definition Context.cpp:8256
HeliosDataType getObjectDataType(uint objID, const char *label) const
Get the Helios data type of primitive data.
-
void setPrimitiveTransformationMatrix(uint UUID, float(&T)[16])
Method to set the Affine transformation matrix of a Primitive.
Definition Context.cpp:7112
+
void setPrimitiveTransformationMatrix(uint UUID, float(&T)[16])
Method to set the Affine transformation matrix of a Primitive.
Definition Context.cpp:7139
float sumPrimitiveSurfaceArea(const std::vector< uint > &UUIDs) const
Sum the one-sided surface area of a group of primitives.
-
void getObjectTransformationMatrix(uint ObjID, float(&T)[16]) const
Method to return the Affine transformation matrix of an Object.
Definition Context.cpp:7936
-
void setTubeRadii(uint ObjID, const std::vector< float > &node_radii)
Set tube radii at each segment node.
Definition Context.cpp:8201
-
bool objectHasTexture(uint ObjID) const
Method to check whether an Object has texture data.
Definition Context.cpp:7950
+
void getObjectTransformationMatrix(uint ObjID, float(&T)[16]) const
Method to return the Affine transformation matrix of an Object.
Definition Context.cpp:7963
+
void setTubeRadii(uint ObjID, const std::vector< float > &node_radii)
Set tube radii at each segment node.
Definition Context.cpp:8228
+
bool objectHasTexture(uint ObjID) const
Method to check whether an Object has texture data.
Definition Context.cpp:7977
void scaleObject(uint ObjID, const helios::vec3 &scalefact)
Method to scale a compound object in the x-, y- and z-directions.
Definition Context.cpp:2877
-
Disk compound object class.
Definition Context.h:795
-
vec2 getSize() const
Get the lateral dimensions of the disk object.
Definition Context.cpp:4029
-
int2 getSubdivisionCount() const
Get the number of sub-triangle divisions of the disk object.
Definition Context.cpp:4061
+
Disk compound object class.
Definition Context.h:801
+
vec2 getSize() const
Get the lateral dimensions of the disk object.
Definition Context.cpp:4056
+
int2 getSubdivisionCount() const
Get the number of sub-triangle divisions of the disk object.
Definition Context.cpp:4088
~Disk() override=default
Disk destructor.
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the disk object.
Definition Context.cpp:4045
-
Disk(uint a_OID, const std::vector< uint > &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4009
-
void setSubdivisionCount(int2 subdiv)
Set the number of disk sub-triangle divisions.
Definition Context.cpp:4065
-
Polymesh compound object class.
Definition Context.h:828
+
vec3 getCenter() const
Get the Cartesian coordinates of the center of the disk object.
Definition Context.cpp:4072
+
Disk(uint a_OID, const std::vector< uint > &a_UUIDs, int2 a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4036
+
void setSubdivisionCount(int2 subdiv)
Set the number of disk sub-triangle divisions.
Definition Context.cpp:4092
+
Polymesh compound object class.
Definition Context.h:834
~Polymesh() override=default
Polymesh destructor.
-
Polymesh(uint a_OID, const std::vector< uint > &a_UUIDs, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4069
-
float getVolume() const
Get the volume of the polymesh object.
Definition Context.cpp:4088
+
Polymesh(uint a_OID, const std::vector< uint > &a_UUIDs, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:4096
+
float getVolume() const
Get the volume of the polymesh object.
Definition Context.cpp:4115
Sphere compound object class.
Definition Context.h:624
uint getSubdivisionCount() const
Get the number of sub-patch divisions of the sphere object.
Definition Context.cpp:3455
helios::vec3 getRadius() const
Get the radius of the sphere.
Definition Context.cpp:3417
@@ -3178,7 +3194,6 @@
Sphere(uint a_OID, const std::vector< uint > &a_UUIDs, uint a_subdiv, const char *a_texturefile, helios::Context *a_context)
Default constructor.
Definition Context.cpp:3397
void setSubdivisionCount(uint subdiv)
Set the number of sphere tesselation divisions.
Definition Context.cpp:3459
~Sphere() override=default
Sphere destructor.
-
Texture map data structure.
Definition Context.h:67
std::string getTextureFile() const
Get the name/path of the texture map file.
Definition Context.cpp:129
bool hasTransparencyChannel() const
Check whether the texture has a transparency channel.
Definition Context.cpp:137
helios::int2 getImageResolution() const
Get the size of the texture in pixels (horizontal x vertical)
Definition Context.cpp:133
@@ -3200,6 +3215,7 @@
float getSegmentVolume(uint segment_index) const
Get the volume of a segment within the tube object.
Definition Context.cpp:3561
std::vector< float > getNodeRadii() const
Get the radius at each of the tube object nodes.
Definition Context.cpp:3508
void scaleTubeGirth(float S)
Scale the girth of the tube object.
Definition Context.cpp:3826
+
void pruneTubeNodes(uint node_index)
Remove a portion of the tube downstream of a specified node.
Definition Context.cpp:3916
void setTubeRadii(const std::vector< float > &node_radii)
Set tube radii at each segment node.
Definition Context.cpp:3846
std::vector< std::vector< helios::vec3 > > getTriangleVertices() const
Get positions of triangle vertices comprising the tube object.
Definition Context.cpp:3529
float getVolume() const
Get the volume of the tube object.
Definition Context.cpp:3547
@@ -3210,41 +3226,41 @@
void scaleTubeLength(float S)
Scale the length of the tube object.
Definition Context.cpp:3869
float getLength() const
Get the length of the tube object.
Definition Context.cpp:3537
void setTubeNodes(const std::vector< helios::vec3 > &node_xyz)
Set tube vertex coordinates at each segment node.
Definition Context.cpp:3895
-
Class for parsing XML input files.
Definition Context.h:1698
-
static int parse_data_vec3(const pugi::xml_node &node_data, std::vector< vec3 > &data)
Parse vector data of type 'vec3' within an XML tag.
-
static int parse_data_int2(const pugi::xml_node &node_data, std::vector< int2 > &data)
Parse vector data of type 'int2' within an XML tag.
+
Class for parsing XML input files.
Definition Context.h:1704
+
static int parse_data_vec3(const pugi::xml_node &node_data, std::vector< vec3 > &data)
Parse vector data of type 'vec3' within an XML tag.
+
static int parse_data_int2(const pugi::xml_node &node_data, std::vector< int2 > &data)
Parse vector data of type 'int2' within an XML tag.
static int parse_radius(const pugi::xml_node &node_data, std::vector< float > &radius)
Parse the value within a <radius> (radius at nodes of a tube or cone) tag.
-
static int parse_data_float(const pugi::xml_node &node_data, std::vector< float > &data)
Parse vector data of type 'float' within an XML tag.
+
static int parse_data_float(const pugi::xml_node &node_data, std::vector< float > &data)
Parse vector data of type 'float' within an XML tag.
static int parse_transform(const pugi::xml_node &node_data, float(&transform)[16])
Parse the value within a <transform> (transformation matrix) tag.
-
static int parse_data_uint(const pugi::xml_node &node_data, std::vector< uint > &data)
Parse vector data of type 'uint' within an XML tag.
+
static int parse_data_uint(const pugi::xml_node &node_data, std::vector< uint > &data)
Parse vector data of type 'uint' within an XML tag.
static int parse_subdivisions(const pugi::xml_node &node_data, uint &subdivisions)
Parse the value within a <subdivisions> (object sub-primitive resolution) tag.
-
static int parse_data_vec4(const pugi::xml_node &node_data, std::vector< vec4 > &data)
Parse vector data of type 'vac4' within an XML tag.
-
static int parse_data_int3(const pugi::xml_node &node_data, std::vector< int3 > &data)
Parse vector data of type 'int3' within an XML tag.
-
static int parse_data_string(const pugi::xml_node &node_data, std::vector< std::string > &data)
Parse vector data of type 'string' within an XML tag.
-
static int parse_data_int(const pugi::xml_node &node_data, std::vector< int > &data)
Parse vector data of type 'int' within an XML tag.
+
static int parse_data_vec4(const pugi::xml_node &node_data, std::vector< vec4 > &data)
Parse vector data of type 'vac4' within an XML tag.
+
static int parse_data_int3(const pugi::xml_node &node_data, std::vector< int3 > &data)
Parse vector data of type 'int3' within an XML tag.
+
static int parse_data_string(const pugi::xml_node &node_data, std::vector< std::string > &data)
Parse vector data of type 'string' within an XML tag.
+
static int parse_data_int(const pugi::xml_node &node_data, std::vector< int > &data)
Parse vector data of type 'int' within an XML tag.
static int parse_texture(const pugi::xml_node &node_data, std::string &texture)
Parse the value within an <texture> (path to image texture) tag.
-
static int parse_data_vec2(const pugi::xml_node &node_data, std::vector< vec2 > &data)
Parse vector data of type 'vec2' within an XML tag.
-
static int parse_data_double(const pugi::xml_node &node_data, std::vector< double > &data)
Parse vector data of type 'double' within an XML tag.
+
static int parse_data_vec2(const pugi::xml_node &node_data, std::vector< vec2 > &data)
Parse vector data of type 'vec2' within an XML tag.
+
static int parse_data_double(const pugi::xml_node &node_data, std::vector< double > &data)
Parse vector data of type 'double' within an XML tag.
static int parse_solid_fraction(const pugi::xml_node &node_data, float &solid_fraction)
Parse the value within a <solid_fraction> (primitive solid fraction) tag.
static int parse_objID(const pugi::xml_node &node_data, uint &objID)
Parse the value within an <objID> (object ID) tag.
static int parse_textureUV(const pugi::xml_node &node_data, std::vector< vec2 > &uvs)
Parse the value within a <textureUV> (texture coordinates) tag.
static int parse_nodes(const pugi::xml_node &node_data, std::vector< vec3 > &nodes)
Parse the value within a <nodes> (coordinates defining nodes of a tube or cone) tag.
-
static int parse_data_int4(const pugi::xml_node &node_data, std::vector< int4 > &data)
Parse vector data of type 'int4' within an XML tag.
+
static int parse_data_int4(const pugi::xml_node &node_data, std::vector< int4 > &data)
Parse vector data of type 'int4' within an XML tag.
static int parse_vertices(const pugi::xml_node &node_data, std::vector< float > &vertices)
Parse the value within a <vertices> (primitive vertex coordinates) tag.
-
uint addDiskObject(uint Ndivs, const helios::vec3 &center, const helios::vec2 &size)
Add new Disk geometric primitive to the Context given its center, and size.
Definition Context.cpp:5256
-
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:4728
-
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5426
-
std::vector< uint > addDisk(uint Ndivs, const helios::vec3 &center, const helios::vec2 &size)
Add new Disk geometric primitive to the Context given its center, and size.
Definition Context.cpp:6356
-
std::vector< uint > addBox(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:6147
-
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5000
-
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition Context.cpp:5399
-
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5646
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
-
std::vector< uint > addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone to the Context.
Definition Context.cpp:6459
-
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4310
+
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:5283
+
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:4755
+
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5453
+
std::vector< uint > addDisk(uint Ndivs, const helios::vec3 &center, const helios::vec2 &size)
Add new Disk geometric primitive to the Context given its center, and size.
Definition Context.cpp:6383
+
std::vector< uint > addBox(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:6174
+
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5027
+
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition Context.cpp:5426
+
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5673
+
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5957
+
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5836
+
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4577
+
std::vector< uint > addCone(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone to the Context.
Definition Context.cpp:6486
+
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4337
float min(const std::vector< float > &vect)
Minimum value of a vector of floats.
Definition global.cpp:1100
float max(const std::vector< float > &vect)
Maximum value of a vector of floats.
Definition global.cpp:1146
float sum(const std::vector< float > &vect)
Sum of a vector of floats.
Definition global.cpp:1069
@@ -3267,17 +3283,20 @@
R-G-B color vector.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of two elements of type 'int'.
-
Vector of three elements of type 'int'.
-
Vector of four elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
-
Vector of four elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'int'.
+
Vector of four elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
+
Vector of four elements of type 'float'.
- -
+ + diff --git a/doc/html/_context__data_8cpp.html b/doc/html/_context__data_8cpp.html index 0bbcd8204..ed6d49080 100644 --- a/doc/html/_context__data_8cpp.html +++ b/doc/html/_context__data_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Context_data.cpp File Reference
@@ -108,17 +114,20 @@

Go to the source code of this file.

Detailed Description

-

Context primitive data, object data, and global data declarations.

+

Context primitive data, object data, and global data declarations.

Copyright (C) 2016-2025 Brian Bailey

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

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

Definition in file Context_data.cpp.

- -
+ + diff --git a/doc/html/_context__data_8cpp_source.html b/doc/html/_context__data_8cpp_source.html index 8f498bf47..9e4d0173e 100644 --- a/doc/html/_context__data_8cpp_source.html +++ b/doc/html/_context__data_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Context_data.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "Context.h"
17
18using namespace helios;
@@ -131,32 +138,32 @@
39 primitive_data_types[label] = HELIOS_TYPE_DOUBLE;
40}
41
-
42void Primitive::setPrimitiveData( const char* label, const helios::vec2& data ){
+
42void Primitive::setPrimitiveData( const char* label, const helios::vec2& data ){
43 primitive_data_vec2[label] = {data};
44 primitive_data_types[label] = HELIOS_TYPE_VEC2;
45}
46
-
47void Primitive::setPrimitiveData( const char* label, const helios::vec3& data ){
+
47void Primitive::setPrimitiveData( const char* label, const helios::vec3& data ){
48 primitive_data_vec3[label] = {data};
49 primitive_data_types[label] = HELIOS_TYPE_VEC3;
50}
51
-
52void Primitive::setPrimitiveData( const char* label, const helios::vec4& data ){
+
52void Primitive::setPrimitiveData( const char* label, const helios::vec4& data ){
53 primitive_data_vec4[label] = {data};
54 primitive_data_types[label] = HELIOS_TYPE_VEC4;
55}
56
-
57void Primitive::setPrimitiveData( const char* label, const helios::int2& data ){
+
57void Primitive::setPrimitiveData( const char* label, const helios::int2& data ){
58 primitive_data_int2[label] = {data};
59 primitive_data_types[label] = HELIOS_TYPE_INT2;
60}
61
-
62void Primitive::setPrimitiveData( const char* label, const helios::int3& data ){
+
62void Primitive::setPrimitiveData( const char* label, const helios::int3& data ){
63 primitive_data_int3[label] = {data};
64 primitive_data_types[label] = HELIOS_TYPE_INT3;
65}
66
-
67void Primitive::setPrimitiveData( const char* label, const helios::int4& data ){
+
67void Primitive::setPrimitiveData( const char* label, const helios::int4& data ){
68 primitive_data_int4[label] = {data};
69 primitive_data_types[label] = HELIOS_TYPE_INT4;
70}
@@ -208,7 +215,7 @@
116
117 }else if( type==HELIOS_TYPE_VEC2 ){
118
-
119 auto* data_ptr = (vec2*)data;
+
119 auto* data_ptr = (vec2*)data;
120
121 primitive_data_vec2[label].resize(size);
122 for( size_t i=0; i<size; i++ ){
@@ -217,7 +224,7 @@
125
126 }else if( type==HELIOS_TYPE_VEC3 ){
127
-
128 auto* data_ptr = (vec3*)data;
+
128 auto* data_ptr = (vec3*)data;
129
130 primitive_data_vec3[label].resize(size);
131 for( size_t i=0; i<size; i++ ){
@@ -226,7 +233,7 @@
134
135 }else if( type==HELIOS_TYPE_VEC4 ){
136
-
137 auto* data_ptr = (vec4*)data;
+
137 auto* data_ptr = (vec4*)data;
138
139 primitive_data_vec4[label].resize(size);
140 for( size_t i=0; i<size; i++ ){
@@ -235,7 +242,7 @@
143
144 }else if( type==HELIOS_TYPE_INT2 ){
145
-
146 auto* data_ptr = (int2*)data;
+
146 auto* data_ptr = (int2*)data;
147
148 primitive_data_int2[label].resize(size);
149 for( size_t i=0; i<size; i++ ){
@@ -244,7 +251,7 @@
152
153 }else if( type==HELIOS_TYPE_INT3 ){
154
-
155 auto* data_ptr = (int3*)data;
+
155 auto* data_ptr = (int3*)data;
156
157 primitive_data_int3[label].resize(size);
158 for( size_t i=0; i<size; i++ ){
@@ -253,7 +260,7 @@
161
162 }else if( type==HELIOS_TYPE_INT4 ){
163
-
164 auto* data_ptr = (int4*)data;
+
164 auto* data_ptr = (int4*)data;
165
166 primitive_data_int4[label].resize(size);
167 for( size_t i=0; i<size; i++ ){
@@ -3546,7 +3553,7 @@
3082
3083std::vector<std::string> Context::listObjectData(uint ObjID) const{
-
3084 return getObjectPointer_private(ObjID)->listObjectData();
+
3084 return getObjectPointer_private(ObjID)->listObjectData();
3085}
3086
@@ -5270,16 +5277,16 @@
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
uint getObjectDataSize(const char *label) const
Get the size/length of object data.
std::vector< std::string > listObjectData() const
Return labels for all object data for this particular object.
-
bool doesObjectDataExist(const char *label) const
Check if object data 'label' exists.
+
bool doesObjectDataExist(const char *label) const
Check if object data 'label' exists.
HeliosDataType getObjectDataType(const char *label) const
Get the Helios data type of object data.
void clearObjectData(const char *label)
Clear the object data for this object.
void getObjectData(const char *label, int &data) const
Get data associated with a object element (integer scalar)
void setObjectData(const char *label, const int &data)
Add data value (int) associated with a object element.
void copyPrimitiveData(uint sourceUUID, uint destinationUUID)
copy all primitive data from one primitive to another
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.
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
-
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
+
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
void getObjectData(uint objID, const char *label, int &data) const
Get data associated with a compound object.
std::vector< uint > filterPrimitivesByData(const std::vector< uint > &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator)
Filter a set of primitives based on their primitive data and a condition and float value.
uint getPrimitiveDataSize(uint UUID, const char *label) const
Get the size/length of primitive data.
@@ -5288,11 +5295,11 @@
void renamePrimitiveData(uint UUID, const char *old_label, const char *new_label)
Rename primitive data for a primitive.
void duplicateObjectData(uint objID, const char *old_label, const char *new_label)
Duplicate/copy existing object data.
std::vector< uint > filterObjectsByData(const std::vector< uint > &ObjIDs, const char *object_data, float threshold, const char *comparator) const
Get a vector of object IDs that meet filtering criteria based on object data.
Definition Context.cpp:2750
-
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
+
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
void aggregatePrimitiveDataProduct(const std::vector< uint > &UUIDs, const std::vector< std::string > &primitive_data_labels, const std::string &result_primitive_data_label)
Multiply primitive data values for each primitive together and store result in new primitive data.
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
void clearObjectData(uint objID, const char *label)
Clear primitive data for a single primitive based on its objID.
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
std::vector< std::string > listPrimitiveData(uint UUID) const
Return labels for all primitive data for this particular primitive.
void renameGlobalData(const char *old_label, const char *new_label)
Rename global data.
void duplicatePrimitiveData(uint UUID, const char *old_label, const char *new_label)
Duplicate/copy primitive data.
@@ -5329,35 +5336,38 @@
vec4 make_vec4(float x, float y, float z, float w)
Make a vec4 from three floats.
int4 make_int4(int x, int y, int z, int w)
Make an int4 vector from three ints.
Structure for Global Data Entities.
Definition Context.h:102
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of four elements of type 'int'.
+
Vector of four elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int w
Fourth element in vector.
int y
Second element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
-
Vector of four elements of type 'float'.
+
Vector of four elements of type 'float'.
float y
Second element in vector.
float w
Fourth element in vector.
float z
Third element in vector.
float x
First element in vector.
- -
+ + diff --git a/doc/html/_context__file_i_o_8cpp.html b/doc/html/_context__file_i_o_8cpp.html index 0092b9bc6..85ad35aaa 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Context_fileIO.cpp File Reference
@@ -108,17 +114,20 @@

Go to the source code of this file.

Detailed Description

-

Filesystem input/output functions within the Context.

+

Filesystem input/output functions within the Context.

Copyright (C) 2016-2025 Brian Bailey

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

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

Definition in file Context_fileIO.cpp.

- -
+ + diff --git a/doc/html/_context__file_i_o_8cpp_source.html b/doc/html/_context__file_i_o_8cpp_source.html index 779c8bf15..f403d8382 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Context_fileIO.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "Context.h"
17
18using namespace helios;
@@ -2608,7 +2615,7 @@
2466 if (strcmp(data_group, "primitive") == 0) {
2467 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2468 } else if (strcmp(data_group, "object") == 0) {
-
2469 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2469 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2470 } else {
2471 getGlobalData(label.c_str(), data);
2472 }
@@ -2625,7 +2632,7 @@
2483 if (strcmp(data_group, "primitive") == 0) {
2484 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2485 } else if (strcmp(data_group, "object") == 0) {
-
2486 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2486 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2487 } else {
2488 getGlobalData(label.c_str(), data);
2489 }
@@ -2642,7 +2649,7 @@
2500 if (strcmp(data_group, "primitive") == 0) {
2501 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2502 } else if (strcmp(data_group, "object") == 0) {
-
2503 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2503 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2504 } else {
2505 getGlobalData(label.c_str(), data);
2506 }
@@ -2659,7 +2666,7 @@
2517 if (strcmp(data_group, "primitive") == 0) {
2518 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2519 } else if (strcmp(data_group, "object") == 0) {
-
2520 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2520 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2521 } else {
2522 getGlobalData(label.c_str(), data);
2523 }
@@ -2676,7 +2683,7 @@
2534 if (strcmp(data_group, "primitive") == 0) {
2535 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2536 } else if (strcmp(data_group, "object") == 0) {
-
2537 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2537 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2538 } else {
2539 getGlobalData(label.c_str(), data);
2540 }
@@ -2693,7 +2700,7 @@
2551 if (strcmp(data_group, "primitive") == 0) {
2552 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2553 } else if (strcmp(data_group, "object") == 0) {
-
2554 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2554 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2555 } else {
2556 getGlobalData(label.c_str(), data);
2557 }
@@ -2710,7 +2717,7 @@
2568 if (strcmp(data_group, "primitive") == 0) {
2569 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2570 } else if (strcmp(data_group, "object") == 0) {
-
2571 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2571 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2572 } else {
2573 getGlobalData(label.c_str(), data);
2574 }
@@ -2728,7 +2735,7 @@
2586 if (strcmp(data_group, "primitive") == 0) {
2587 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2588 } else if (strcmp(data_group, "object") == 0) {
-
2589 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2589 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2590 } else {
2591 getGlobalData(label.c_str(), data);
2592 }
@@ -2745,7 +2752,7 @@
2603 if (strcmp(data_group, "primitive") == 0) {
2604 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2605 } else if (strcmp(data_group, "object") == 0) {
-
2606 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2606 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2607 } else {
2608 getGlobalData(label.c_str(), data);
2609 }
@@ -2762,7 +2769,7 @@
2620 if (strcmp(data_group, "primitive") == 0) {
2621 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2622 } else if (strcmp(data_group, "object") == 0) {
-
2623 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2623 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2624 } else {
2625 getGlobalData(label.c_str(), data);
2626 }
@@ -2780,7 +2787,7 @@
2638 if (strcmp(data_group, "primitive") == 0) {
2639 ((Primitive *) ptr)->getPrimitiveData(label.c_str(), data);
2640 } else if (strcmp(data_group, "object") == 0) {
-
2641 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
+
2641 ((CompoundObject *) ptr)->getObjectData(label.c_str(), data);
2642 } else {
2643 getGlobalData(label.c_str(), data);
2644 }
@@ -4273,7 +4280,7 @@
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());
+
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);
@@ -4315,10 +4322,10 @@
4142 // - it would make more sense to write patches as quads rather than two triangles
4143
4144 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;
4146 return;
4147 }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;
4149 return;
4150 }
4151
@@ -5027,7 +5034,7 @@
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
PrimitiveType
Type of primitive element.
Definition Context.h:31
@ PRIMITIVE_TYPE_PATCH
< Rectangular primitive
Definition Context.h:33
-
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
+
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
@ PRIMITIVE_TYPE_TRIANGLE
< Triangular primitive
Definition Context.h:35
@ OBJECT_TYPE_BOX
Box.
Definition Context.h:136
@ OBJECT_TYPE_POLYMESH
< Triangular Mesh
Definition Context.h:140
@@ -5036,10 +5043,10 @@
@ OBJECT_TYPE_DISK
< Disk
Definition Context.h:138
@ OBJECT_TYPE_TILE
< Tile
Definition Context.h:130
@ OBJECT_TYPE_SPHERE
< Sphere
Definition Context.h:132
-
Box compound object class.
Definition Context.h:759
-
helios::int3 getSubdivisionCount() const
Get the number of sub-patch divisions of the box object in each Cartesian direction.
Definition Context.cpp:3996
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the box object.
Definition Context.cpp:3980
-
vec3 getSize() const
Get the dimensions of the box object in each Cartesian direction.
Definition Context.cpp:3961
+
Box compound object class.
Definition Context.h:765
+
helios::int3 getSubdivisionCount() const
Get the number of sub-patch divisions of the box object in each Cartesian direction.
Definition Context.cpp:4023
+
vec3 getCenter() const
Get the Cartesian coordinates of the center of the box object.
Definition Context.cpp:4007
+
vec3 getSize() const
Get the dimensions of the box object in each Cartesian direction.
Definition Context.cpp:3988
void setPrimitiveUUIDs(const std::vector< uint > &UUIDs)
Method to set the UUIDs of object child primitives.
Definition Context.cpp:2517
std::string getTextureFile() const
Method to return the texture map file of an Object.
Definition Context.cpp:2349
@@ -5049,35 +5056,35 @@
helios::ObjectType getObjectType() const
Get an enumeration specifying the type of the object.
Definition Context.cpp:2247
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
void getTransformationMatrix(float(&T)[16]) const
Method to return the Affine transformation matrix of a Compound Object.
Definition Context.cpp:2503
-
Cone compound object class.
Definition Context.h:847
-
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the cone object.
Definition Context.cpp:4171
-
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4130
-
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4159
-
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7139
+
Cone compound object class.
Definition Context.h:853
+
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the cone object.
Definition Context.cpp:4198
+
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4157
+
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4186
+
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7166
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:4022
-
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:7022
+
Disk * getDiskObjectPointer(uint ObjID) const
Get a pointer to a Disk Compound Object.
Definition Context.cpp:4049
+
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:7049
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:3954
+
Box * getBoxObjectPointer(uint ObjID) const
Get a pointer to a Box Compound Object.
Definition Context.cpp:3981
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:1536
-
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4123
+
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4150
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
std::vector< std::string > getLoadedXMLFiles()
Get names of XML files that are currently loaded.
void setDate(int day, int month, int year)
Set simulation date by day, month, year.
Definition Context.cpp:1059
-
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:6988
-
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7179
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
+
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7015
+
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7206
+
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:7011
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
-
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7221
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7248
+
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:2907
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:1166
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:3410
-
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:7197
+
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:7224
HeliosDataType getGlobalDataType(const char *label) const
Get the Helios data type of global data.
helios::Date getDate() const
Get simulation date.
Definition Context.cpp:1099
size_t getGlobalDataSize(const char *label) const
Get the size/length of global data.
@@ -5087,7 +5094,7 @@
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 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:7217
+
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:7244
Tube * getTubeObjectPointer(uint ObjID) const
Get a pointer to a Tube Compound Object.
Definition Context.cpp:3486
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.
@@ -5097,11 +5104,11 @@
static bool scanXMLForTag(const std::string &filename, const std::string &tag, const std::string &label="")
Scan a Helios XML file to check if a tag exists.
void writeXML_byobject(const char *filename, const std::vector< uint > &UUIDs, bool quiet=false) const
Write Context geometry and data to XML file for a subset of compound object IDs in the context.
void setTime(int minute, int hour)
Set simulation time.
Definition Context.cpp:1136
-
void setPrimitiveTransformationMatrix(uint UUID, float(&T)[16])
Method to set the Affine transformation matrix of a Primitive.
Definition Context.cpp:7112
-
Disk compound object class.
Definition Context.h:795
-
vec2 getSize() const
Get the lateral dimensions of the disk object.
Definition Context.cpp:4029
-
int2 getSubdivisionCount() const
Get the number of sub-triangle divisions of the disk object.
Definition Context.cpp:4061
-
vec3 getCenter() const
Get the Cartesian coordinates of the center of the disk object.
Definition Context.cpp:4045
+
void setPrimitiveTransformationMatrix(uint UUID, float(&T)[16])
Method to set the Affine transformation matrix of a Primitive.
Definition Context.cpp:7139
+
Disk compound object class.
Definition Context.h:801
+
vec2 getSize() const
Get the lateral dimensions of the disk object.
Definition Context.cpp:4056
+
int2 getSubdivisionCount() const
Get the number of sub-triangle divisions of the disk object.
Definition Context.cpp:4088
+
vec3 getCenter() const
Get the Cartesian coordinates of the center of the disk object.
Definition Context.cpp:4072
Sphere compound object class.
Definition Context.h:624
uint getSubdivisionCount() const
Get the number of sub-patch divisions of the sphere object.
Definition Context.cpp:3455
helios::vec3 getRadius() const
Get the radius of the sphere.
Definition Context.cpp:3417
@@ -5113,25 +5120,25 @@
std::vector< helios::RGBcolor > getNodeColors() const
Get the colors at each of the tube object nodes.
Definition Context.cpp:3525
std::vector< helios::vec3 > getNodes() const
Get the Cartesian coordinates of each of the tube object nodes.
Definition Context.cpp:3493
uint getSubdivisionCount() const
Get the number of sub-triangle divisions of the tube object.
Definition Context.cpp:3533
-
static int parse_data_vec3(const pugi::xml_node &node_data, std::vector< vec3 > &data)
Parse vector data of type 'vec3' within an XML tag.
-
static int parse_data_int2(const pugi::xml_node &node_data, std::vector< int2 > &data)
Parse vector data of type 'int2' within an XML tag.
+
static int parse_data_vec3(const pugi::xml_node &node_data, std::vector< vec3 > &data)
Parse vector data of type 'vec3' within an XML tag.
+
static int parse_data_int2(const pugi::xml_node &node_data, std::vector< int2 > &data)
Parse vector data of type 'int2' within an XML tag.
static int parse_radius(const pugi::xml_node &node_data, std::vector< float > &radius)
Parse the value within a <radius> (radius at nodes of a tube or cone) tag.
-
static int parse_data_float(const pugi::xml_node &node_data, std::vector< float > &data)
Parse vector data of type 'float' within an XML tag.
+
static int parse_data_float(const pugi::xml_node &node_data, std::vector< float > &data)
Parse vector data of type 'float' within an XML tag.
static int parse_transform(const pugi::xml_node &node_data, float(&transform)[16])
Parse the value within a <transform> (transformation matrix) tag.
-
static int parse_data_uint(const pugi::xml_node &node_data, std::vector< uint > &data)
Parse vector data of type 'uint' within an XML tag.
+
static int parse_data_uint(const pugi::xml_node &node_data, std::vector< uint > &data)
Parse vector data of type 'uint' within an XML tag.
static int parse_subdivisions(const pugi::xml_node &node_data, uint &subdivisions)
Parse the value within a <subdivisions> (object sub-primitive resolution) tag.
-
static int parse_data_vec4(const pugi::xml_node &node_data, std::vector< vec4 > &data)
Parse vector data of type 'vac4' within an XML tag.
-
static int parse_data_int3(const pugi::xml_node &node_data, std::vector< int3 > &data)
Parse vector data of type 'int3' within an XML tag.
-
static int parse_data_string(const pugi::xml_node &node_data, std::vector< std::string > &data)
Parse vector data of type 'string' within an XML tag.
-
static int parse_data_int(const pugi::xml_node &node_data, std::vector< int > &data)
Parse vector data of type 'int' within an XML tag.
+
static int parse_data_vec4(const pugi::xml_node &node_data, std::vector< vec4 > &data)
Parse vector data of type 'vac4' within an XML tag.
+
static int parse_data_int3(const pugi::xml_node &node_data, std::vector< int3 > &data)
Parse vector data of type 'int3' within an XML tag.
+
static int parse_data_string(const pugi::xml_node &node_data, std::vector< std::string > &data)
Parse vector data of type 'string' within an XML tag.
+
static int parse_data_int(const pugi::xml_node &node_data, std::vector< int > &data)
Parse vector data of type 'int' within an XML tag.
static int parse_texture(const pugi::xml_node &node_data, std::string &texture)
Parse the value within an <texture> (path to image texture) tag.
-
static int parse_data_vec2(const pugi::xml_node &node_data, std::vector< vec2 > &data)
Parse vector data of type 'vec2' within an XML tag.
-
static int parse_data_double(const pugi::xml_node &node_data, std::vector< double > &data)
Parse vector data of type 'double' within an XML tag.
+
static int parse_data_vec2(const pugi::xml_node &node_data, std::vector< vec2 > &data)
Parse vector data of type 'vec2' within an XML tag.
+
static int parse_data_double(const pugi::xml_node &node_data, std::vector< double > &data)
Parse vector data of type 'double' within an XML tag.
static int parse_solid_fraction(const pugi::xml_node &node_data, float &solid_fraction)
Parse the value within a <solid_fraction> (primitive solid fraction) tag.
static int parse_objID(const pugi::xml_node &node_data, uint &objID)
Parse the value within an <objID> (object ID) tag.
static int parse_textureUV(const pugi::xml_node &node_data, std::vector< vec2 > &uvs)
Parse the value within a <textureUV> (texture coordinates) tag.
static int parse_nodes(const pugi::xml_node &node_data, std::vector< vec3 > &nodes)
Parse the value within a <nodes> (coordinates defining nodes of a tube or cone) tag.
-
static int parse_data_int4(const pugi::xml_node &node_data, std::vector< int4 > &data)
Parse vector data of type 'int4' within an XML tag.
+
static int parse_data_int4(const pugi::xml_node &node_data, std::vector< int4 > &data)
Parse vector data of type 'int4' within an XML tag.
static int parse_vertices(const pugi::xml_node &node_data, std::vector< float > &vertices)
Parse the value within a <vertices> (primitive vertex coordinates) tag.
bool parse_double(const std::string &input_string, double &converted_double)
Convert a string into a double with error checking.
Definition global.cpp:779
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
@@ -5147,13 +5154,13 @@
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:3090
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:5256
-
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:4728
-
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5426
-
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5000
-
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition Context.cpp:5399
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
-
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4310
+
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:5283
+
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:4755
+
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5453
+
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5027
+
uint addPolymeshObject(const std::vector< uint > &UUIDs)
Add new Polymesh Compound Object.
Definition Context.cpp:5426
+
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4577
+
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4337
vec3 rotatePoint(const vec3 &position, const SphericalCoord &rotation)
Function to rotate a 3D vector given spherical angles elevation and azimuth.
Definition global.cpp:79
vec2 string2vec2(const char *str)
Convert a space-delimited string into a vec2 vector.
Definition global.cpp:623
int2 string2int2(const char *str)
Convert a space-delimited string into an int2 vector.
Definition global.cpp:683
@@ -5199,35 +5206,38 @@
int second
Second of minute.
int hour
Hour of day.
int minute
Minute of hour.
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of four elements of type 'int'.
+
Vector of four elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int w
Fourth element in vector.
int y
Second element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
-
Vector of four elements of type 'float'.
+
Vector of four elements of type 'float'.
float y
Second element in vector.
float w
Fourth element in vector.
float z
Third element in vector.
float x
First element in vector.
- -
+ + diff --git a/doc/html/_convert_p_l_y.html b/doc/html/_convert_p_l_y.html index 5d2ea57f5..494357d01 100644 --- a/doc/html/_convert_p_l_y.html +++ b/doc/html/_convert_p_l_y.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Converting polygon file formats to .ply using Blender
@@ -114,10 +124,12 @@

With the object selected, click on 'file' again in the upper menu bar, and navigate to 'export', then to 'Stanford (.ply)'. In the lower left, use the 'Up:' drop-down to specify 'Y Up', which will make the coordinate system consistent with that of Helios. Once that is complete, specify an appropriate filename and click 'Export PLY'.

- -
+ + diff --git a/doc/html/_dependent_software.html b/doc/html/_dependent_software.html index fc567823c..593ba8439 100644 --- a/doc/html/_dependent_software.html +++ b/doc/html/_dependent_software.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Install and Set-up
@@ -260,10 +270,12 @@

C/C++ Compiler: You will also need a C/C++ compiler installed - we recommend using the GNU compilers or the AppleClang compilers. The GNU compilers can easily be installed via the command line "brew install gcc".

- -
+ + diff --git a/doc/html/_dummy.html b/doc/html/_dummy.html index b9fb61255..d6ed18fe7 100644 --- a/doc/html/_dummy.html +++ b/doc/html/_dummy.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Dummy Model Plugin Documentation
@@ -118,10 +128,12 @@

This plugin has no dependencies.

- - + + diff --git a/doc/html/_dummy_model_8cpp.html b/doc/html/_dummy_model_8cpp.html index 2aa861e24..d58484cfa 100644 --- a/doc/html/_dummy_model_8cpp.html +++ b/doc/html/_dummy_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
DummyModel.cpp File Reference
@@ -112,10 +118,13 @@

Definition in file DummyModel.cpp.

- - + + diff --git a/doc/html/_dummy_model_8cpp_source.html b/doc/html/_dummy_model_8cpp_source.html index 7e3955fde..c6b77b906 100644 --- a/doc/html/_dummy_model_8cpp_source.html +++ b/doc/html/_dummy_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
DummyModel.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
4
5#include "DummyModel.h"
6
@@ -126,7 +133,7 @@
20 context->addVariable("dummy_variable");
21
22 //Set the value of dummy variable for all primitives to 5.0
-
23 for( uint i=0; i<context->getPrimitiveCount(); i++ ){
+
23 for( uint i=0; i<context->getPrimitiveCount(); i++ ){
24 context->setVariableValue("dummy_variable",i,5.f);
25 }
26
@@ -137,13 +144,15 @@
DummyModel(helios::Context *context)
Constructor.
Definition DummyModel.cpp:7
void run(void)
Function to run the dummy model.
-
Stores the state associated with simulation.
Definition Context.h:1882
-
uint getPrimitiveCount() const
Get the total number of Primitives in the Context.
Definition Context.cpp:1759
+
Stores the state associated with simulation.
Definition Context.h:1888
- -
+ + diff --git a/doc/html/_dummy_model_8h.html b/doc/html/_dummy_model_8h.html index 17c70d58b..05cb8b6d7 100644 --- a/doc/html/_dummy_model_8h.html +++ b/doc/html/_dummy_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -121,10 +127,13 @@

Definition in file DummyModel.h.

- -
+ + diff --git a/doc/html/_dummy_model_8h.js b/doc/html/_dummy_model_8h.js new file mode 100644 index 000000000..5b33fba78 --- /dev/null +++ b/doc/html/_dummy_model_8h.js @@ -0,0 +1,4 @@ +var _dummy_model_8h = +[ + [ "DummyModel", "class_dummy_model.html", "class_dummy_model" ] +]; \ No newline at end of file diff --git a/doc/html/_dummy_model_8h_source.html b/doc/html/_dummy_model_8h_source.html index 03110dfa7..c8895159e 100644 --- a/doc/html/_dummy_model_8h_source.html +++ b/doc/html/_dummy_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
DummyModel.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
4
5#include "Context.h"
-
6
-
8
+
6
+
8
- +
10public:
-
11
+
11
13 DummyModel( helios::Context* context );
-
14
+
14
16 void run( void );
17
18private:
-
19
+
19
21 helios::Context* context;
22
23};
-
Dummy model class.
Definition DummyModel.h:9
DummyModel(helios::Context *context)
Constructor.
Definition DummyModel.cpp:7
void run(void)
Function to run the dummy model.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
- -
+ + diff --git a/doc/html/_energy_balance_doc.html b/doc/html/_energy_balance_doc.html index 9e8debd39..9449906be 100644 --- a/doc/html/_energy_balance_doc.html +++ b/doc/html/_energy_balance_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Energy Balance Model Plugin Documentation
@@ -371,8 +377,8 @@

Context context;
// Add `Patch' primitive
-
vec3 center = make_vec3(0,0,1);
-
vec2 size = make_vec2(1,1);
+
vec3 center = make_vec3(0,0,1);
+
vec2 size = make_vec2(1,1);
uint UUID = context.addPatch( center, size );
EnergyBalanceModel energybalance(&context);
@@ -386,10 +392,12 @@

return 0;
}
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.

Unsteady model with heat storage

Additional functions are available to run the unsteady energy balance model with heat storage. If the timestep argument "dt" is passed with value greater than 0, and the heat capacity $C_p$ is greater than 0, the unsteady energy balance equation will be applied with the heat storage term included. The equation is discretized in time using a forward Euler scheme in order to solve for the surface temperature at time $t+\Delta t$

@@ -420,12 +428,12 @@

Context context;
// Add one 'Patch' primitive
-
vec3 center = make_vec3(0,0,1);
-
vec2 size = make_vec2(1,1);
+
vec3 center = make_vec3(0,0,1);
+
vec2 size = make_vec2(1,1);
uint UUID1 = context.addPatch( center, size );
// Add a second `Patch' primitive
-
center = make_vec3(2,0,1);
+
center = make_vec3(2,0,1);
uint UUID2 = context.addPatch( center, size );
// Set the heat capacity of the first patch so that the unsteady energy balance model will be run
@@ -446,10 +454,13 @@

void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.

- - + + diff --git a/doc/html/_energy_balance_model_8cpp.html b/doc/html/_energy_balance_model_8cpp.html index 648083d98..2efdf60dc 100644 --- a/doc/html/_energy_balance_model_8cpp.html +++ b/doc/html/_energy_balance_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
EnergyBalanceModel.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file EnergyBalanceModel.cpp.

- - + + diff --git a/doc/html/_energy_balance_model_8cpp_source.html b/doc/html/_energy_balance_model_8cpp_source.html index b3a2bcfaa..ae267b150 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
EnergyBalanceModel.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "EnergyBalanceModel.h"
17
18using namespace helios;
@@ -163,7 +170,7 @@
68
69 context_test.setPrimitiveData( UUIDs, "air_temperature", Tref );
70
-
71 EnergyBalanceModel energymodeltest(&context_test);
+
71 EnergyBalanceModel energymodeltest(&context_test);
72 energymodeltest.disableMessages();
73
74 energymodeltest.addRadiationBand("LW");
@@ -197,7 +204,7 @@
102
103 context_2.setPrimitiveData( UUIDs_2, "air_temperature", T );
104
-
105 EnergyBalanceModel energymodel_2(&context_2);
+
105 EnergyBalanceModel energymodel_2(&context_2);
106 energymodel_2.disableMessages();
107
108 energymodel_2.addRadiationBand("LW");
@@ -249,7 +256,7 @@
154
155 context_3.setPrimitiveData( UUID_3, "twosided_flag", uint(0) );
156
-
157 EnergyBalanceModel energymodel_3(&context_3);
+
157 EnergyBalanceModel energymodel_3(&context_3);
158 energymodel_3.disableMessages();
159
160 energymodel_3.addRadiationBand("LW");
@@ -326,7 +333,7 @@
231
232 UUID_4 = context_4.addPatch( make_vec3(1,2,3), make_vec2(3,2) );
233
-
234 EnergyBalanceModel energymodel_4(&context_4);
+
234 EnergyBalanceModel energymodel_4(&context_4);
235 energymodel_4.disableMessages();
236
237 energymodel_4.addRadiationBand("LW");
@@ -363,7 +370,7 @@
268 context_5.setPrimitiveData( UUID_5, "twosided_flag", uint(0) );
269 context_5.setPrimitiveData( UUID_5, "emissivity_SW", 0.f );
270
-
271 EnergyBalanceModel energybalance_5(&context_5);
+
271 EnergyBalanceModel energybalance_5(&context_5);
272 energybalance_5.disableMessages();
273
274 energybalance_5.addRadiationBand("SW");
@@ -468,7 +475,7 @@
362
- +
364 printDefaultValueReport(context->getAllUUIDs());
365}
366
@@ -496,63 +503,63 @@
387 for (uint UUID: UUIDs) {
388
389 //surface temperature (K)
-
390 if (!context->doesPrimitiveDataExist(UUID, "temperature") ||
-
391 context->getPrimitiveDataType(UUID, "temperature") != HELIOS_TYPE_FLOAT) {
+
390 if (!context->doesPrimitiveDataExist(UUID, "temperature") ||
+
391 context->getPrimitiveDataType(UUID, "temperature") != HELIOS_TYPE_FLOAT) {
392 assumed_default_TL++;
393 }
394
395 //air pressure (Pa)
-
396 if (!context->doesPrimitiveDataExist(UUID, "air_pressure") ||
-
397 context->getPrimitiveDataType(UUID, "air_pressure") != HELIOS_TYPE_FLOAT) {
+
396 if (!context->doesPrimitiveDataExist(UUID, "air_pressure") ||
+
397 context->getPrimitiveDataType(UUID, "air_pressure") != HELIOS_TYPE_FLOAT) {
398 assumed_default_p++;
399 }
400
401 //air temperature (K)
-
402 if (!context->doesPrimitiveDataExist(UUID, "air_temperature") ||
-
403 context->getPrimitiveDataType(UUID, "air_temperature") != HELIOS_TYPE_FLOAT) {
+
402 if (!context->doesPrimitiveDataExist(UUID, "air_temperature") ||
+
403 context->getPrimitiveDataType(UUID, "air_temperature") != HELIOS_TYPE_FLOAT) {
404 assumed_default_Ta++;
405 }
406
407 //air humidity
-
408 if (!context->doesPrimitiveDataExist(UUID, "air_humidity") ||
-
409 context->getPrimitiveDataType(UUID, "air_humidity") != HELIOS_TYPE_FLOAT) {
+
408 if (!context->doesPrimitiveDataExist(UUID, "air_humidity") ||
+
409 context->getPrimitiveDataType(UUID, "air_humidity") != HELIOS_TYPE_FLOAT) {
410 assumed_default_rh++;
411 }
412
413 //boundary-layer conductance to heat
-
414 if (!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance") || context->getPrimitiveDataType(UUID, "boundarylayer_conductance") != HELIOS_TYPE_FLOAT){
+
414 if (!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance") || context->getPrimitiveDataType(UUID, "boundarylayer_conductance") != HELIOS_TYPE_FLOAT){
415 assumed_default_gH++;
416 }
417
418 //wind speed
-
419 if (!context->doesPrimitiveDataExist(UUID, "wind_speed") || context->getPrimitiveDataType(UUID, "wind_speed") != HELIOS_TYPE_FLOAT){
+
419 if (!context->doesPrimitiveDataExist(UUID, "wind_speed") || context->getPrimitiveDataType(UUID, "wind_speed") != HELIOS_TYPE_FLOAT){
420 assumed_default_U++;
421 }
422
423 //object length
-
424 if (!context->doesPrimitiveDataExist(UUID, "object_length") || context->getPrimitiveDataType(UUID, "object_length") != HELIOS_TYPE_FLOAT){
+
424 if (!context->doesPrimitiveDataExist(UUID, "object_length") || context->getPrimitiveDataType(UUID, "object_length") != HELIOS_TYPE_FLOAT){
425 assumed_default_L++;
426 }
427
428 //moisture conductance
-
429 if (!context->doesPrimitiveDataExist(UUID, "moisture_conductance") || context->getPrimitiveDataType(UUID, "moisture_conductance") != HELIOS_TYPE_FLOAT){
+
429 if (!context->doesPrimitiveDataExist(UUID, "moisture_conductance") || context->getPrimitiveDataType(UUID, "moisture_conductance") != HELIOS_TYPE_FLOAT){
430 assumed_default_gs++;
431 }
432
433 //Heat capacity
-
434 if (!context->doesPrimitiveDataExist(UUID, "heat_capacity") || context->getPrimitiveDataType(UUID, "heat_capacity") != HELIOS_TYPE_FLOAT) {
+
434 if (!context->doesPrimitiveDataExist(UUID, "heat_capacity") || context->getPrimitiveDataType(UUID, "heat_capacity") != HELIOS_TYPE_FLOAT) {
435 assumed_default_heatcapacity++;
436 }
437
438 //"Other" heat fluxes
-
439 if (!context->doesPrimitiveDataExist(UUID, "other_surface_flux") || context->getPrimitiveDataType(UUID, "other_surface_flux") != HELIOS_TYPE_FLOAT) {
+
439 if (!context->doesPrimitiveDataExist(UUID, "other_surface_flux") || context->getPrimitiveDataType(UUID, "other_surface_flux") != HELIOS_TYPE_FLOAT) {
440 assumed_default_Qother++;
441 }
442
443 //two-sided flag
-
444 if ( context->doesPrimitiveDataExist(UUID, "twosided_flag") && context->getPrimitiveDataType(UUID, "twosided_flag") == HELIOS_TYPE_UINT) {
+
444 if ( context->doesPrimitiveDataExist(UUID, "twosided_flag") && context->getPrimitiveDataType(UUID, "twosided_flag") == HELIOS_TYPE_UINT) {
445 uint twosided;
-
446 context->getPrimitiveData(UUID, "twosided_flag", twosided);
+
446 context->getPrimitiveData(UUID, "twosided_flag", twosided);
447 if( twosided==0 ){
448 twosided_0++;
449 }else if( twosided==1 ){
@@ -563,9 +570,9 @@
454 }
455
456 //number of evaporating faces
-
457 if ( context->doesPrimitiveDataExist(UUID, "evaporating_faces") && context->getPrimitiveDataType(UUID, "evaporating_faces") == HELIOS_TYPE_UINT) {
+
457 if ( context->doesPrimitiveDataExist(UUID, "evaporating_faces") && context->getPrimitiveDataType(UUID, "evaporating_faces") == HELIOS_TYPE_UINT) {
458 uint Ne;
-
459 context->getPrimitiveData(UUID, "evaporating_faces", Ne);
+
459 context->getPrimitiveData(UUID, "evaporating_faces", Ne);
460 if( Ne==1 ){
461 Ne_1++;
462 }else if( Ne==2 ){
@@ -576,7 +583,7 @@
467 }
468
469 //Surface humidity
-
470 if (!context->doesPrimitiveDataExist(UUID, "surface_humidity") || context->getPrimitiveDataType(UUID, "surface_humidity") != HELIOS_TYPE_FLOAT) {
+
470 if (!context->doesPrimitiveDataExist(UUID, "surface_humidity") || context->getPrimitiveDataType(UUID, "surface_humidity") != HELIOS_TYPE_FLOAT) {
471 assumed_default_fs++;
472 }
473
@@ -605,7 +612,6 @@
@ HELIOS_TYPE_UINT
unsigned integer data type
Definition Context.h:45
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
-
Energy balance model class.
void printDefaultValueReport() const
Print a report detailing usage of default input values for all primitives in the Context.
void enableMessages()
Enable standard output from this plug-in (default)
void addRadiationBand(const char *band)
Add the label of a radiation band in the RadiationModel plug-in that should be used in calculation of...
@@ -614,21 +620,22 @@
void run()
Function to run the energy balance model for all primitives in the Context.
EnergyBalanceModel(helios::Context *context)
Constructor.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
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 > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
+
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
uint addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
Add new Triangle geometric primitive.
Definition Context.cpp:1328
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
- -
+ + diff --git a/doc/html/_energy_balance_model_8cu.html b/doc/html/_energy_balance_model_8cu.html index e0e6e048e..d617e3927 100644 --- a/doc/html/_energy_balance_model_8cu.html +++ b/doc/html/_energy_balance_model_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Macros | @@ -275,7 +281,7 @@

-inline +inline

+ + diff --git a/doc/html/_energy_balance_model_8cu_source.html b/doc/html/_energy_balance_model_8cu_source.html index ec4af80df..3e5eb16e3 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
EnergyBalanceModel.cu
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include <cuda_runtime.h>
17#include "EnergyBalanceModel.h"
18
@@ -209,13 +216,13 @@
117
-
119 run( context->getAllUUIDs() );
+
119 run( context->getAllUUIDs() );
120}
121
122void EnergyBalanceModel::run( float dt ){
-
123 run( context->getAllUUIDs(), dt );
+
123 run( context->getAllUUIDs(), dt );
124}
125
@@ -265,18 +272,18 @@
166
167 char str[50];
168 sprintf(str,"radiation_flux_%s",radiation_bands.at(b).c_str());
-
169 if( !context->doesPrimitiveDataExist(p,str) ) {
+
169 if( !context->doesPrimitiveDataExist(p,str) ) {
170 helios_runtime_error("ERROR (EnergyBalanceModel::run): No radiation was found in the context for band " + std::string(radiation_bands.at(b)) + ". Did you run the radiation model for this band?");
-
171 }else if( context->getPrimitiveDataType(p,str)!=HELIOS_TYPE_FLOAT ){
+
171 }else if( context->getPrimitiveDataType(p,str)!=HELIOS_TYPE_FLOAT ){
172 helios_runtime_error("ERROR (EnergyBalanceModel::run): Radiation primitive data for band " + std::string(radiation_bands.at(b)) + " does not have the correct type of ''float'");
173 }
174 float R;
-
175 context->getPrimitiveData(p,str,R);
+
175 context->getPrimitiveData(p,str,R);
176 Rn.at(u) += R;
177
178 sprintf(str,"emissivity_%s",radiation_bands.at(b).c_str());
-
179 if( context->doesPrimitiveDataExist(p,str) && context->getPrimitiveDataType(p,str)==HELIOS_TYPE_FLOAT ){
-
180 context->getPrimitiveData(p,str,emissivity.at(u));
+
179 if( context->doesPrimitiveDataExist(p,str) && context->getPrimitiveDataType(p,str)==HELIOS_TYPE_FLOAT ){
+
180 context->getPrimitiveData(p,str,emissivity.at(u));
181 }
182
183 }
@@ -345,8 +352,8 @@
246 size_t p = UUIDs.at(u);
247
248 //Initial guess for surface temperature
-
249 if( context->doesPrimitiveDataExist(p,"temperature") && context->getPrimitiveDataType(p,"temperature")==HELIOS_TYPE_FLOAT ){
-
250 context->getPrimitiveData(p,"temperature",To[u]);
+
249 if( context->doesPrimitiveDataExist(p,"temperature") && context->getPrimitiveDataType(p,"temperature")==HELIOS_TYPE_FLOAT ){
+
250 context->getPrimitiveData(p,"temperature",To[u]);
251 }else{
252 To[u] = temperature_default;
253 }
@@ -355,8 +362,8 @@
256 }
257
258 //Air temperature
-
259 if( context->doesPrimitiveDataExist(p,"air_temperature") && context->getPrimitiveDataType(p,"air_temperature")==HELIOS_TYPE_FLOAT ){
-
260 context->getPrimitiveData(p,"air_temperature",Ta[u]);
+
259 if( context->doesPrimitiveDataExist(p,"air_temperature") && context->getPrimitiveDataType(p,"air_temperature")==HELIOS_TYPE_FLOAT ){
+
260 context->getPrimitiveData(p,"air_temperature",Ta[u]);
261 if( message_flag && Ta[u]<250.f ){
262 std::cout << "WARNING (EnergyBalanceModel::run): Value of " << Ta[u] << " given in 'air_temperature' primitive data is very small. Values should be given in units of Kelvin. Assuming default value of " << air_temperature_default << std::endl;
263 Ta[u] = air_temperature_default;
@@ -367,8 +374,8 @@
268
269 //Air relative humidity
270 float hr;
-
271 if( context->doesPrimitiveDataExist(p,"air_humidity") && context->getPrimitiveDataType(p,"air_humidity")==HELIOS_TYPE_FLOAT ){
-
272 context->getPrimitiveData(p,"air_humidity",hr);
+
271 if( context->doesPrimitiveDataExist(p,"air_humidity") && context->getPrimitiveDataType(p,"air_humidity")==HELIOS_TYPE_FLOAT ){
+
272 context->getPrimitiveData(p,"air_humidity",hr);
273 if( hr>1.f ){
274 if( message_flag ){
275 std::cout << "WARNING (EnergyBalanceModel::run): Value of " << hr << " given in 'air_humidity' primitive data is large than 1. Values should be given as fractional values between 0 and 1. Assuming default value of " << air_humidity_default << std::endl;
@@ -389,8 +396,8 @@
290 ea[u] = hr*esat; // Definition of vapor pressure (see Campbell and Norman pp. 42 Eq. 3.11)
291
292 //Air pressure
-
293 if( context->doesPrimitiveDataExist(p,"air_pressure") && context->getPrimitiveDataType(p,"air_pressure")==HELIOS_TYPE_FLOAT ){
-
294 context->getPrimitiveData(p,"air_pressure",pressure[u]);
+
293 if( context->doesPrimitiveDataExist(p,"air_pressure") && context->getPrimitiveDataType(p,"air_pressure")==HELIOS_TYPE_FLOAT ){
+
294 context->getPrimitiveData(p,"air_pressure",pressure[u]);
295 if( pressure[u]<10000.f ){
296 if( message_flag ) {
297 std::cout << "WARNING (EnergyBalanceModel::run): Value of " << pressure[u] << " given in 'air_pressure' primitive data is very small. Values should be given in units of Pascals. Assuming default value of " << pressure_default << std::endl;
@@ -403,9 +410,9 @@
304
305 //Number of sides emitting radiation
306 Nsides[u] = 2; //default is 2
-
307 if( context->doesPrimitiveDataExist(p,"twosided_flag") && context->getPrimitiveDataType(p,"twosided_flag")==HELIOS_TYPE_UINT ){
+
307 if( context->doesPrimitiveDataExist(p,"twosided_flag") && context->getPrimitiveDataType(p,"twosided_flag")==HELIOS_TYPE_UINT ){
308 uint flag;
-
309 context->getPrimitiveData(p,"twosided_flag",flag);
+
309 context->getPrimitiveData(p,"twosided_flag",flag);
310 if( flag==0 ){
311 Nsides[u]=1;
312 }
@@ -413,12 +420,12 @@
314
315 //Number of evaporating/transpiring faces
316 stomatal_sidedness[u] = 0.f; //if Nsides=1, force this to be 0 (all stomata on upper surface)
-
317 if( Nsides[u]==2 && context->doesPrimitiveDataExist(p,"stomatal_sidedness") && context->getPrimitiveDataType(p,"stomatal_sidedness")==HELIOS_TYPE_FLOAT ){
-
318 context->getPrimitiveData(p,"stomatal_sidedness",stomatal_sidedness[u]);
+
317 if( Nsides[u]==2 && context->doesPrimitiveDataExist(p,"stomatal_sidedness") && context->getPrimitiveDataType(p,"stomatal_sidedness")==HELIOS_TYPE_FLOAT ){
+
318 context->getPrimitiveData(p,"stomatal_sidedness",stomatal_sidedness[u]);
319 //this is for backward compatability prior to v1.3.17
-
320 }else if( Nsides[u]==2 && context->doesPrimitiveDataExist(p,"evaporating_faces") && context->getPrimitiveDataType(p,"evaporating_faces")==HELIOS_TYPE_UINT ){
+
320 }else if( Nsides[u]==2 && context->doesPrimitiveDataExist(p,"evaporating_faces") && context->getPrimitiveDataType(p,"evaporating_faces")==HELIOS_TYPE_UINT ){
321 uint flag;
-
322 context->getPrimitiveData(p,"evaporating_faces",flag);
+
322 context->getPrimitiveData(p,"evaporating_faces",flag);
323 if( flag==1 ) { //stomata on one side
324 stomatal_sidedness[u] = 0.f;
325 }else if( flag==2 ){
@@ -427,31 +434,31 @@
328 }
329
330 //Boundary-layer conductance to heat
-
331 if( context->doesPrimitiveDataExist(p,"boundarylayer_conductance") && context->getPrimitiveDataType(p,"boundarylayer_conductance")==HELIOS_TYPE_FLOAT ){
-
332 context->getPrimitiveData(p,"boundarylayer_conductance",gH[u]);
+
331 if( context->doesPrimitiveDataExist(p,"boundarylayer_conductance") && context->getPrimitiveDataType(p,"boundarylayer_conductance")==HELIOS_TYPE_FLOAT ){
+
332 context->getPrimitiveData(p,"boundarylayer_conductance",gH[u]);
333 }else{
334
335 //Wind speed
336 float U;
-
337 if( context->doesPrimitiveDataExist(p,"wind_speed") && context->getPrimitiveDataType(p,"wind_speed")==HELIOS_TYPE_FLOAT ){
-
338 context->getPrimitiveData(p,"wind_speed",U);
+
337 if( context->doesPrimitiveDataExist(p,"wind_speed") && context->getPrimitiveDataType(p,"wind_speed")==HELIOS_TYPE_FLOAT ){
+
338 context->getPrimitiveData(p,"wind_speed",U);
339 }else{
340 U = wind_speed_default;
341 }
342
343 //Characteristic size of primitive
344 float L;
-
345 if( context->doesPrimitiveDataExist(p,"object_length") && context->getPrimitiveDataType(p,"object_length")==HELIOS_TYPE_FLOAT ){
-
346 context->getPrimitiveData(p,"object_length",L);
+
345 if( context->doesPrimitiveDataExist(p,"object_length") && context->getPrimitiveDataType(p,"object_length")==HELIOS_TYPE_FLOAT ){
+
346 context->getPrimitiveData(p,"object_length",L);
347 if( L==0 ){
-
348 L = sqrt(context->getPrimitiveArea(p));
+
348 L = sqrt(context->getPrimitiveArea(p));
349 primitive_length_used = true;
350 }
-
351 }else if( context->getPrimitiveParentObjectID(p)>0 ){
-
352 uint objID = context->getPrimitiveParentObjectID(p);
-
353 L = sqrt(context->getObjectArea(objID));
+
351 }else if( context->getPrimitiveParentObjectID(p)>0 ){
+
352 uint objID = context->getPrimitiveParentObjectID(p);
+
353 L = sqrt(context->getObjectArea(objID));
354 }else{
-
355 L = sqrt(context->getPrimitiveArea(p));
+
355 L = sqrt(context->getPrimitiveArea(p));
356 primitive_length_used = true;
357 }
358
@@ -461,29 +468,29 @@
362 }
363
364 //Moisture conductance
-
365 if( context->doesPrimitiveDataExist(p,"moisture_conductance") && context->getPrimitiveDataType(p,"moisture_conductance")==HELIOS_TYPE_FLOAT ){
-
366 context->getPrimitiveData(p,"moisture_conductance",gS[u]);
+
365 if( context->doesPrimitiveDataExist(p,"moisture_conductance") && context->getPrimitiveDataType(p,"moisture_conductance")==HELIOS_TYPE_FLOAT ){
+
366 context->getPrimitiveData(p,"moisture_conductance",gS[u]);
367 }else{
368 gS[u] = gS_default;
369 }
370
371 //Other fluxes
-
372 if( context->doesPrimitiveDataExist(p,"other_surface_flux") && context->getPrimitiveDataType(p,"other_surface_flux")==HELIOS_TYPE_FLOAT ){
-
373 context->getPrimitiveData(p,"other_surface_flux",Qother[u]);
+
372 if( context->doesPrimitiveDataExist(p,"other_surface_flux") && context->getPrimitiveDataType(p,"other_surface_flux")==HELIOS_TYPE_FLOAT ){
+
373 context->getPrimitiveData(p,"other_surface_flux",Qother[u]);
374 }else{
375 Qother[u] = Qother_default;
376 }
377
378 //Object heat capacity
-
379 if( context->doesPrimitiveDataExist(p,"heat_capacity") && context->getPrimitiveDataType(p,"heat_capacity")==HELIOS_TYPE_FLOAT ){
-
380 context->getPrimitiveData(p,"heat_capacity",heatcapacity[u]);
+
379 if( context->doesPrimitiveDataExist(p,"heat_capacity") && context->getPrimitiveDataType(p,"heat_capacity")==HELIOS_TYPE_FLOAT ){
+
380 context->getPrimitiveData(p,"heat_capacity",heatcapacity[u]);
381 }else{
382 heatcapacity[u] = heatcapacity_default;
383 }
384
385 //Surface humidity
-
386 if( context->doesPrimitiveDataExist(p,"surface_humidity") && context->getPrimitiveDataType(p,"surface_humidity")==HELIOS_TYPE_FLOAT ){
-
387 context->getPrimitiveData(p,"surface_humidity",surfacehumidity[u]);
+
386 if( context->doesPrimitiveDataExist(p,"surface_humidity") && context->getPrimitiveDataType(p,"surface_humidity")==HELIOS_TYPE_FLOAT ){
+
387 context->getPrimitiveData(p,"surface_humidity",surfacehumidity[u]);
388 }else{
389 surfacehumidity[u] = surface_humidity_default;
390 }
@@ -546,10 +553,10 @@
447 T[u] = temperature_default;
448 }
449
-
450 context->setPrimitiveData(p,"temperature",T[u]);
+
450 context->setPrimitiveData(p,"temperature",T[u]);
451
452 float QH = 29.25*gH[u]*(T[u]-Ta[u]);
-
453 context->setPrimitiveData(p,"sensible_flux",QH);
+
453 context->setPrimitiveData(p,"sensible_flux",QH);
454
455 float es = 611.f*exp(17.502f*(T[u]-273.f)/((T[u]-273.f)+240.97f));
456 float gM = 1.08f*gH[u]*gS[u]*(stomatal_sidedness[u]/(1.08f*gH[u]+gS[u]*stomatal_sidedness[u]) + (1.f-stomatal_sidedness[u])/(1.08f*gH[u]+gS[u]*(1.f-stomatal_sidedness[u])));
@@ -557,20 +564,20 @@
458 gM = 0;
459 }
460 float QL = 44000*gM*(es-ea[u])/pressure[u];
-
461 context->setPrimitiveData(p,"latent_flux",QL);
+
461 context->setPrimitiveData(p,"latent_flux",QL);
462
463 float storage=0.f;
464 if ( dt>0){
465 storage=heatcapacity[u]*(T[u]-To[u])/dt;
466 }
-
467 context->setPrimitiveData(p,"storage_flux", storage);
+
467 context->setPrimitiveData(p,"storage_flux", storage);
468
469 for( int i=0; i<output_prim_data.size(); i++ ){
470 if( output_prim_data.at(i) == "boundarylayer_conductance_out" ){
-
471 context->setPrimitiveData(p,"boundarylayer_conductance_out",gH[u]);
+
471 context->setPrimitiveData(p,"boundarylayer_conductance_out",gH[u]);
472 }else if( output_prim_data.at(i) == "vapor_pressure_deficit" ){
473 float vpd = (es-ea[u])/pressure[u];
-
474 context->setPrimitiveData(p,"vapor_pressure_deficit",vpd);
+
474 context->setPrimitiveData(p,"vapor_pressure_deficit",vpd);
475 }
476 }
477
@@ -619,20 +626,15 @@
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
void run()
Function to run the energy balance model for all primitives in the Context.
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
-
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
-
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7017
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
-
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition Context.cpp:7920
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
- -
+ + diff --git a/doc/html/_energy_balance_model_8h.html b/doc/html/_energy_balance_model_8h.html index 86965c5e7..c8af8273a 100644 --- a/doc/html/_energy_balance_model_8h.html +++ b/doc/html/_energy_balance_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -124,10 +130,13 @@

Definition in file EnergyBalanceModel.h.

- -
+ + diff --git a/doc/html/_energy_balance_model_8h.js b/doc/html/_energy_balance_model_8h.js new file mode 100644 index 000000000..60ca6de10 --- /dev/null +++ b/doc/html/_energy_balance_model_8h.js @@ -0,0 +1,4 @@ +var _energy_balance_model_8h = +[ + [ "EnergyBalanceModel", "class_energy_balance_model.html", "class_energy_balance_model" ] +]; \ No newline at end of file diff --git a/doc/html/_energy_balance_model_8h_source.html b/doc/html/_energy_balance_model_8h_source.html index c2dbdd94f..eefb60ca5 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
EnergyBalanceModel.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef ENERGYBALANCEMODEL
17#define ENERGYBALANCEMODEL
18
19#include "Context.h"
-
20
-
22
+
20
+
22
- +
24public:
-
25
-
27
+
25
+
27
-
31
-
33
+
31
+
33
36 int selfTest();
-
37
+
37
39 void enableMessages();
-
40
+
40
42 void disableMessages();
-
43
+
43
45 void run() ;
-
46
-
48
+
46
+
48
51 void run( float dt ) ;
-
52
-
54
+
52
+
54
57 void run( const std::vector<uint> &UUIDs );
-
58
-
60
+
58
+
60
64 void run( const std::vector<uint> &UUIDs, float dt );
-
65
-
67
+
65
+
67
70 void addRadiationBand( const char* band );
-
71
-
73
+
71
+
73
76 void addRadiationBand( const std::vector<std::string> &bands );
-
77
-
79
+
77
+
79
82 void optionalOutputPrimitiveData( const char* label );
-
83
+
83
85 void printDefaultValueReport() const;
-
86
-
88
+
86
+
88
91 void printDefaultValueReport(const std::vector<uint> &UUIDs) const;
92
93private:
-
94
+
94
96 helios::Context* context;
-
97
+
97
99 float temperature_default;
-
100
+
100
102 float wind_speed_default;
-
103
+
103
105 float air_temperature_default;
-
106
+
106
108 float air_humidity_default;
-
109
+
109
111 float pressure_default;
-
112
+
112
114 float gS_default;
-
115
+
115
117 float heatcapacity_default;
-
118
+
118
120 float Qother_default;
-
121
+
121
123 float surface_humidity_default;
124
125 bool message_flag;
-
126
+
126
128 std::vector<std::string> radiation_bands;
-
129
+
129
131 std::vector<std::string> output_prim_data;
132
133};
@@ -183,7 +190,6 @@
134
135#endif
-
Energy balance model class.
void printDefaultValueReport() const
Print a report detailing usage of default input values for all primitives in the Context.
void enableMessages()
Enable standard output from this plug-in (default)
void addRadiationBand(const char *band)
Add the label of a radiation band in the RadiationModel plug-in that should be used in calculation of...
@@ -192,12 +198,15 @@
void run()
Function to run the energy balance model for all primitives in the Context.
EnergyBalanceModel(helios::Context *context)
Constructor.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
- -
+ + diff --git a/doc/html/_i_o.html b/doc/html/_i_o.html index b531ef0ff..a76a5a4d0 100644 --- a/doc/html/_i_o.html +++ b/doc/html/_i_o.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
File Input/Output
@@ -217,21 +227,23 @@

context.loadTabularTimeseriesData("../input/weatherfile.csv", {"date", "hour", "temperature"}, ",", "MMDDYYYY", 1);
-
Date date = make_Date( 2, 1, 2020 );
-
Time time = make_Time( 13, 00, 00 );
+
Date date = make_Date( 2, 1, 2020 );
+
Time time = make_Time( 13, 00, 00 );
float T = context.queryTimeseriesData( "temperature", date, time );
}
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
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:1894
+
Time make_Time(int hour, int minute)
Make a Time vector.
+
Date make_Date(int day, int month, int year)
Make a Date vector.

The above example would read the comma-delimited file "../input/weatherfile.csv". Timeseries data would be added to the Context for values of "temperature", which could be queried based on this label.

Reading XML Files

-

XML files can be read by the Context via the function 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.

#include "Context.h"
+

XML files can be read by the Context via the function 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.

#include "Context.h"
using namespace helios;
int main(){
@@ -272,7 +284,7 @@

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'.
+
Vector of three elements of type 'float'.

There are other forms of the loadPLY function that allow for translation, rotation, and scaling of the entire PLY model.

Different applications may utilize different coordinate axes in .ply files. In computer graphics applications, it is common to define the y-axis as the up direction. Helios uses a z-up coordinate system. By default helios::Context::loadPLY() assumes that the coordinate system used when creating the .ply file is y-up. There is an optional argument helios::Context::loadPLY() that can allow you to easily define the up-axis.

The Blender software package (www.blender.org) can easily modify and convert most polygon file formats to .ply format. This page gives a tutorial on how to perform such conversions using Blender.

@@ -307,10 +319,12 @@

Context context;
-
context.loadOBJ("relative/path/to/someobjfile.obj", make_vec3(0,0,0), 0, nullrotation, RGB::red );
+
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...
+
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.

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.

@@ -347,7 +361,7 @@

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.

+

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

An XML file can be written as follows:

#include "Context.h"
using namespace helios;
@@ -401,10 +415,12 @@

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 c1dd8ab80..0ffdf66e0 100644 --- a/doc/html/_input_output_8cpp.html +++ b/doc/html/_input_output_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
@@ -143,10 +149,13 @@

+ + diff --git a/doc/html/_input_output_8cpp_source.html b/doc/html/_input_output_8cpp_source.html index 0f7783e5c..898622e0e 100644 --- a/doc/html/_input_output_8cpp_source.html +++ b/doc/html/_input_output_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
InputOutput.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "PlantArchitecture.h"
17
18using namespace helios;
@@ -402,7 +409,7 @@
310 std::string leaf_delimiter = "Leaf(";
311 bool base_shoot = true;
312 uint baseID;
-
313 AxisRotation shoot_base_rotation;
+
313 AxisRotation shoot_base_rotation;
314
315 //parse shoot arguments
316 if( LString_shoot.front() != '{' ){
@@ -502,7 +509,7 @@
410 helios_runtime_error("ERROR (PlantArchitecture::generatePlantFromString): First character of string must be '{'");
411 }
412
-
413 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
413 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
414 shoot_parameters.max_nodes = 200;
415 shoot_parameters.vegetative_bud_break_probability_min = 0;
416 shoot_parameters.vegetative_bud_break_time = 0;
@@ -658,7 +665,7 @@
566
567 // base position
568 node_string = "base_position";
-
569 vec3 base_position = parse_xml_tag_vec3(plant.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
569 vec3 base_position = parse_xml_tag_vec3(plant.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
570
571 // plant age
572 node_string = "plant_age";
@@ -692,8 +699,8 @@
600
601 // base rotation
602 node_string = "base_rotation";
-
603 vec3 base_rot = parse_xml_tag_vec3(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
-
604 AxisRotation base_rotation(deg2rad(base_rot.x), deg2rad(base_rot.y), deg2rad(base_rot.z));
+
603 vec3 base_rot = parse_xml_tag_vec3(shoot.child(node_string.c_str()), node_string, "PlantArchitecture::readPlantStructureXML");
+
604 AxisRotation base_rotation(deg2rad(base_rot.x), deg2rad(base_rot.y), deg2rad(base_rot.z));
605
606 for (pugi::xml_node phytomer = shoot.child("phytomer"); phytomer; phytomer = phytomer.next_sibling("phytomer")) {
607
@@ -776,7 +783,7 @@
684 }
685
686
-
687 ShootParameters shoot_parameters = getCurrentShootParameters(shoot_type_label);
+
687 ShootParameters shoot_parameters = getCurrentShootParameters(shoot_type_label);
688
689 shoot_parameters.phytomer_parameters.phytomer_creation_function = nullptr;
690
@@ -835,13 +842,12 @@
743
744}
-
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 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 ...
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:49
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:954
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:978
std::string getFileExtension(const std::string &filepath)
Parse a file string to get the extension.
Definition global.cpp:3075
@@ -857,15 +863,17 @@
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)
-
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/_leaf_optics_8cpp.html b/doc/html/_leaf_optics_8cpp.html index 3c731bcb9..8e3df7cbf 100644 --- a/doc/html/_leaf_optics_8cpp.html +++ b/doc/html/_leaf_optics_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
LeafOptics.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file LeafOptics.cpp.

- - + + diff --git a/doc/html/_leaf_optics_8cpp_source.html b/doc/html/_leaf_optics_8cpp_source.html index c5893fd1f..ded6173a5 100644 --- a/doc/html/_leaf_optics_8cpp_source.html +++ b/doc/html/_leaf_optics_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
LeafOptics.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "LeafOptics.h"
17using namespace std;
18using namespace helios;
@@ -122,10 +129,10 @@
29
30 // Load leaf refraction index - refractiveindex (n)
31 std::vector<helios::vec2> data;
-
32 if( !context->doesGlobalDataExist("refraction_index" ) ){
+
32 if( !context->doesGlobalDataExist("refraction_index" ) ){
33 helios_runtime_error("Refraction index data was not loaded properly from the prospect_spectral_library.xml file.");
34 }
-
35 context->getGlobalData("refraction_index", data);
+
35 context->getGlobalData("refraction_index", data);
36 if( data.size() != nw ){
37 helios_runtime_error("Size of refraction index data loaded from the prospect_spectral_library.xml file was not correct.");
38 }
@@ -136,10 +143,10 @@
43 wave_length.at(i) = data.at(i).x;
44 }
45 // Load specific absorption coefficient (per elementary layer depth) for total chlorophyll - absorption_chlorophyll (cm^2/micro_g)
-
46 if( !context->doesGlobalDataExist("absorption_chlorophyll" ) ){
+
46 if( !context->doesGlobalDataExist("absorption_chlorophyll" ) ){
47 helios_runtime_error("Chlorophyll absorption spectral data was not loaded properly from the prospect_spectral_library.xml file.");
48 }
-
49 context->getGlobalData("absorption_chlorophyll", data);
+
49 context->getGlobalData("absorption_chlorophyll", data);
50 if( data.size() != nw ){
51 helios_runtime_error("Size of chlorophyll absorption spectral data loaded from the prospect_spectral_library.xml file was not correct.");
52 }
@@ -149,10 +156,10 @@
56 }
57
58 // Load specific absorption coefficient for total carotenoids - absorption_carotenoid (cm^2/micro_g)
-
59 if( !context->doesGlobalDataExist("absorption_carotenoid" ) ){
+
59 if( !context->doesGlobalDataExist("absorption_carotenoid" ) ){
60 helios_runtime_error("Carotenoid absorption spectral data was not loaded properly from the prospect_spectral_library.xml file.");
61 }
-
62 context->getGlobalData("absorption_carotenoid", data);
+
62 context->getGlobalData("absorption_carotenoid", data);
63 if( data.size() != nw ){
64 helios_runtime_error("Size of carotenoid absorption spectral data loaded from the prospect_spectral_library.xml file was not correct.");
65 }
@@ -162,10 +169,10 @@
69 }
70
71 // Load specific absorption coefficient for anthocyanins - sac_an (cm^2/micro_g)
-
72 if( !context->doesGlobalDataExist("absorption_anthocyanin" ) ){
+
72 if( !context->doesGlobalDataExist("absorption_anthocyanin" ) ){
73 helios_runtime_error("Anothocyanin absorption spectral data was not loaded properly from the prospect_spectral_library.xml file.");
74 }
-
75 context->getGlobalData("absorption_anthocyanin", data);
+
75 context->getGlobalData("absorption_anthocyanin", data);
76 if( data.size() != nw ){
77 helios_runtime_error("Size of anthocyanin absorption spectral data loaded from the prospect_spectral_library.xml file was not correct.");
78 }
@@ -175,10 +182,10 @@
82 }
83
84 // Load specific absorption coefficient for specific brown pigments (phenols during leaf death) - absorption_brown (arbitrary unit)
-
85 if( !context->doesGlobalDataExist("absorption_brown" ) ){
+
85 if( !context->doesGlobalDataExist("absorption_brown" ) ){
86 helios_runtime_error("Brown pigment absorption spectral data was not loaded properly from the prospect_spectral_library.xml file.");
87 }
-
88 context->getGlobalData("absorption_brown", data);
+
88 context->getGlobalData("absorption_brown", data);
89 if( data.size() != nw ){
90 helios_runtime_error("Size of brown pigment absorption spectral data loaded from the prospect_spectral_library.xml file was not correct.");
91 }
@@ -188,10 +195,10 @@
95 }
96
97 // Load specific absorption coefficient for mass of water per leaf area (EWT)- absorption_water (1/cm or cm^2/g)
-
98 if( !context->doesGlobalDataExist("absorption_water" ) ){
+
98 if( !context->doesGlobalDataExist("absorption_water" ) ){
99 helios_runtime_error("Water absorption spectral data was not loaded properly from the prospect_spectral_library.xml file.");
100 }
-
101 context->getGlobalData("absorption_water", data);
+
101 context->getGlobalData("absorption_water", data);
102 if( data.size() != nw ){
103 helios_runtime_error("Size of water absorption spectral data loaded from the prospect_spectral_library.xml file was not correct.");
104 }
@@ -201,10 +208,10 @@
108 }
109
110 // Load specific absorption coefficient for dry mass per leaf area (LMA)- absorption_drymass (cm^2/g)
-
111 if( !context->doesGlobalDataExist("absorption_drymass" ) ){
+
111 if( !context->doesGlobalDataExist("absorption_drymass" ) ){
112 helios_runtime_error("Dry mass absorption spectral data was not loaded properly from the prospect_spectral_library.xml file.");
113 }
-
114 context->getGlobalData("absorption_drymass", data);
+
114 context->getGlobalData("absorption_drymass", data);
115 if( data.size() != nw ){
116 helios_runtime_error("Size of dry mass absorption spectral data loaded from the prospect_spectral_library.xml file was not correct.");
117 }
@@ -214,10 +221,10 @@
121 }
122
123 // Load specific absorption coefficient for proteins- absorption_proteins (cm2.g-1)
-
124 if( !context->doesGlobalDataExist("absorption_proteins" ) ){
+
124 if( !context->doesGlobalDataExist("absorption_proteins" ) ){
125 helios_runtime_error("Protein absorption spectral data was not loaded properly from the prospect_spectral_library.xml file.");
126 }
-
127 context->getGlobalData("absorption_proteins", data);
+
127 context->getGlobalData("absorption_proteins", data);
128 if( data.size() != nw ){
129 helios_runtime_error("Size of protein absorption spectral data loaded from the prospect_spectral_library.xml file was not correct.");
130 }
@@ -227,10 +234,10 @@
134 }
135
136 // Load specific absorption coefficient for carbon based constituents- absorption_carbonconstituents (cm^2/g)
-
137 if( !context->doesGlobalDataExist("absorption_carbonconstituents" ) ){
+
137 if( !context->doesGlobalDataExist("absorption_carbonconstituents" ) ){
138 helios_runtime_error("Carbon constituent absorption spectral data was not loaded properly from the prospect_spectral_library.xml file.");
139 }
-
140 context->getGlobalData("absorption_carbonconstituents", data);
+
140 context->getGlobalData("absorption_carbonconstituents", data);
141 if( data.size() != nw ){
142 helios_runtime_error("Size of carbon constituent absorption spectral data loaded from the prospect_spectral_library.xml file was not correct.");
143 }
@@ -257,7 +264,7 @@
162
163 Context context_test;
164
-
165 LeafOptics leafoptics(&context_test);
+
165 LeafOptics leafoptics(&context_test);
166 leafoptics.disableMessages();
167
168 LeafOpticsProperties leafproperties;
@@ -277,11 +284,11 @@
180
181 std::string leaf_reflectivity_label = "leaf_reflectivity_"+label;
182 std::string leaf_transmissivity_label = "leaf_transmissivity_"+label;
-
183 context->setGlobalData(leaf_reflectivity_label.c_str(),HELIOS_TYPE_VEC2,reflectivities_fit.size(),&reflectivities_fit[0]);
-
184 context->setGlobalData(leaf_transmissivity_label.c_str(),HELIOS_TYPE_VEC2,transmissivities_fit.size(),&transmissivities_fit[0]);
+
183 context->setGlobalData(leaf_reflectivity_label.c_str(),HELIOS_TYPE_VEC2,reflectivities_fit.size(),&reflectivities_fit[0]);
+
184 context->setGlobalData(leaf_transmissivity_label.c_str(),HELIOS_TYPE_VEC2,transmissivities_fit.size(),&transmissivities_fit[0]);
185
-
186 context->setPrimitiveData( UUIDs, "reflectivity_spectrum", leaf_reflectivity_label);
-
187 context->setPrimitiveData( UUIDs, "transmissivity_spectrum", leaf_transmissivity_label);
+
186 context->setPrimitiveData( UUIDs, "reflectivity_spectrum", leaf_reflectivity_label);
+
187 context->setPrimitiveData( UUIDs, "transmissivity_spectrum", leaf_transmissivity_label);
188 setProperties(UUIDs, leafproperties);
189}
@@ -294,8 +301,8 @@
195
196 std::string leaf_reflectivity_label = "leaf_reflectivity_"+label;
197 std::string leaf_transmissivity_label = "leaf_transmissivity_"+label;
-
198 context->setGlobalData(leaf_reflectivity_label.c_str(),HELIOS_TYPE_VEC2,reflectivities_fit.size(),&reflectivities_fit[0]);
-
199 context->setGlobalData(leaf_transmissivity_label.c_str(),HELIOS_TYPE_VEC2,transmissivities_fit.size(),&transmissivities_fit[0]);
+
198 context->setGlobalData(leaf_reflectivity_label.c_str(),HELIOS_TYPE_VEC2,reflectivities_fit.size(),&reflectivities_fit[0]);
+
199 context->setGlobalData(leaf_transmissivity_label.c_str(),HELIOS_TYPE_VEC2,transmissivities_fit.size(),&transmissivities_fit[0]);
200
201}
@@ -482,19 +489,19 @@
383void LeafOptics::setProperties(const std::vector<uint> &UUIDs, const LeafOpticsProperties &leafproperties) {
384
-
385 context->setPrimitiveData(UUIDs, "chlorophyll", leafproperties.chlorophyllcontent);
-
386 context->setPrimitiveData(UUIDs, "carotenoid", leafproperties.carotenoidcontent);
-
387 context->setPrimitiveData(UUIDs, "anthocyanin", leafproperties.anthocyancontent);
+
385 context->setPrimitiveData(UUIDs, "chlorophyll", leafproperties.chlorophyllcontent);
+
386 context->setPrimitiveData(UUIDs, "carotenoid", leafproperties.carotenoidcontent);
+
387 context->setPrimitiveData(UUIDs, "anthocyanin", leafproperties.anthocyancontent);
388 if (leafproperties.brownpigments > 0.0){
-
389 context->setPrimitiveData(UUIDs, "brown", leafproperties.brownpigments);
+
389 context->setPrimitiveData(UUIDs, "brown", leafproperties.brownpigments);
390 }
-
391 context->setPrimitiveData(UUIDs, "water", leafproperties.watermass);
+
391 context->setPrimitiveData(UUIDs, "water", leafproperties.watermass);
392 if (leafproperties.drymass > 0.0) {
-
393 context->setPrimitiveData(UUIDs, "drymass", leafproperties.drymass);
+
393 context->setPrimitiveData(UUIDs, "drymass", leafproperties.drymass);
394 }
395 else {
-
396 context->setPrimitiveData(UUIDs, "protein", leafproperties.protein);
-
397 context->setPrimitiveData(UUIDs, "cellulose", leafproperties.carbonconstituents);
+
396 context->setPrimitiveData(UUIDs, "protein", leafproperties.protein);
+
397 context->setPrimitiveData(UUIDs, "cellulose", leafproperties.carbonconstituents);
398 }
399}
@@ -513,7 +520,6 @@
408
@ HELIOS_TYPE_VEC2
helios::vec2 data type
Definition Context.h:51
-
static int selfTest()
Self-test.
void getLeafSpectra(const LeafOpticsProperties &leafproperties, std::vector< helios::vec2 > &reflectivities_fit, std::vector< helios::vec2 > &transmissivities_fit)
Get the leaf spectra.
void run(const std::vector< uint > &UUIDs, const LeafOpticsProperties &leafproperties, const std::string &label)
Run the LeafOptics model to generate reflectivity and transmissivity spectra, create associated globa...
@@ -522,20 +528,19 @@
void enableMessages()
Enable command-line output messages from this plug-in.
void setProperties(const std::vector< uint > &UUIDs, const LeafOpticsProperties &leafproperties)
Set leaf optical properties for a set of primitives.
void disableMessages()
Disable command-line output messages from this plug-in.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
std::vector< uint > loadXML(const char *filename, bool quiet=false)
Load inputs specified in an XML file.
-
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
-
void getGlobalData(const char *label, int &data) const
Get global data value (scalar integer)
-
void setGlobalData(const char *label, const int &data)
Add global data value (int)
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
LeafOptics model class.
Definition LeafOptics.h:21
- - + + diff --git a/doc/html/_leaf_optics_8h.html b/doc/html/_leaf_optics_8h.html index 76fc40417..fd5f8b199 100644 --- a/doc/html/_leaf_optics_8h.html +++ b/doc/html/_leaf_optics_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
@@ -126,10 +132,13 @@

Definition in file LeafOptics.h.

- - + + diff --git a/doc/html/_leaf_optics_8h.js b/doc/html/_leaf_optics_8h.js new file mode 100644 index 000000000..f96050a21 --- /dev/null +++ b/doc/html/_leaf_optics_8h.js @@ -0,0 +1,5 @@ +var _leaf_optics_8h = +[ + [ "LeafOpticsProperties", "struct_leaf_optics_properties.html", null ], + [ "LeafOptics", "class_leaf_optics.html", "class_leaf_optics" ] +]; \ No newline at end of file diff --git a/doc/html/_leaf_optics_8h_source.html b/doc/html/_leaf_optics_8h_source.html index 5336f663d..df4f3e7f8 100644 --- a/doc/html/_leaf_optics_8h_source.html +++ b/doc/html/_leaf_optics_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
LeafOptics.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "Context.h"
-
17
-
19
+
17
+
19
+
20
- +
21struct LeafOpticsProperties{
22
23 float numberlayers = 1.5;
24 float brownpigments = 0.f;
@@ -127,49 +135,49 @@
36 //Default values for Prospect-PRO
37 // float N=1.5; float CHL= 40.0 ; float CAR = 10.0; float ANT = 0.5; float Brown=0.0; float EWT= 0.015; float pro = 0.001; float carbon = 0.009;
38
- +
39 LeafOpticsProperties(){};
40
-
41 LeafOpticsProperties(float chlorophyllcontent, float carotenoidcontent, float anthocyancontent, float watermass, float drymass, float protein,
+
41 LeafOpticsProperties(float chlorophyllcontent, float carotenoidcontent, float anthocyancontent, float watermass, float drymass, float protein,
42 float carbonconstituents): chlorophyllcontent(chlorophyllcontent), carotenoidcontent(carotenoidcontent),
43 anthocyancontent(anthocyancontent), watermass(watermass), drymass(drymass), protein(protein), carbonconstituents(carbonconstituents){}
44};
45
- +
47public:
-
48
+
48
50 LeafOptics( helios::Context* a_context );
-
51
-
53
+
51
+
53
56 static int selfTest();
-
57
-
59
+
57
+
59
64 void run(const std::vector<uint> &UUIDs, const LeafOpticsProperties &leafproperties, const std::string &label);
-
65
-
67
+
65
+
67
71 void run(const LeafOpticsProperties &leafproperties, const std::string &label);
-
72
-
74
+
72
+
74
85 void PROSPECT(float numberlayers, float Chlorophyllcontent, float carotenoidcontent, float anthocyancontent,
86 float brownpigments, float watermass, float drymass, float protein, float carbonconstituents, std::vector<float> &reflectivities_fit, std::vector<float> &transmissivities_fit );
-
87
-
89
+
87
+
89
94 void getLeafSpectra(const LeafOpticsProperties &leafproperties, std::vector<helios::vec2> &reflectivities_fit, std::vector<helios::vec2> &transmissivities_fit);
-
95
-
97
+
95
+
97
101 void setProperties(const std::vector<uint> &UUIDs, const LeafOpticsProperties &leafproperties);
-
102
+
102
104 void disableMessages();
-
105
+
105
107 void enableMessages();
108
109private:
110
111 std::vector<float> R_spec_normal, R_spec_diffuse, wave_length, Rtotal, Ttotal ;
-
112
+
112
114 const uint nw = 2101;
-
115
+
115
117 helios::Context* context;
120 float chlorophyll_default = 43.0;
121 float chlorophyll_default_grass = 57.0;
@@ -198,7 +206,6 @@
144};
-
static int selfTest()
Self-test.
void getLeafSpectra(const LeafOpticsProperties &leafproperties, std::vector< helios::vec2 > &reflectivities_fit, std::vector< helios::vec2 > &transmissivities_fit)
Get the leaf spectra.
void run(const std::vector< uint > &UUIDs, const LeafOpticsProperties &leafproperties, const std::string &label)
Run the LeafOptics model to generate reflectivity and transmissivity spectra, create associated globa...
@@ -207,13 +214,16 @@
void enableMessages()
Enable command-line output messages from this plug-in.
void setProperties(const std::vector< uint > &UUIDs, const LeafOpticsProperties &leafproperties)
Set leaf optical properties for a set of primitives.
void disableMessages()
Disable command-line output messages from this plug-in.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
LeafOptics model class.
Definition LeafOptics.h:21
- -
+ + diff --git a/doc/html/_li_d_a_r_8cpp.html b/doc/html/_li_d_a_r_8cpp.html index 0ff4effdb..0e4f5b369 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
@@ -172,10 +178,13 @@

+ + diff --git a/doc/html/_li_d_a_r_8cpp_source.html b/doc/html/_li_d_a_r_8cpp_source.html index cd12887e7..88fe5aae0 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
LiDAR.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "LiDAR.h"
17
18using namespace std;
@@ -324,10 +331,10 @@
212 helios_runtime_error("ERROR (LiDARcloud::addHitPoint): Hit point cannot be added to scan #" + std::to_string(scanID) + " because there have only been " + std::to_string(scans.size()) + " scans added.");
213 }
214
-
215 ScanMetadata scan = scans.at(scanID);
-
216 int2 row_column = scan.direction2rc( direction );
+
215 ScanMetadata scan = scans.at(scanID);
+
216 int2 row_column = scan.direction2rc( direction );
217
-
218 HitPoint hit( scanID, xyz, direction, row_column, color, data );
+
218 HitPoint hit( scanID, xyz, direction, row_column, color, data );
219
220 hits.push_back(hit);
221
@@ -337,10 +344,10 @@
225 const int2 &row_column, const RGBcolor &color,
226 const map<string, double> &data ){
227
-
228 ScanMetadata scan = scans.at(scanID);
-
229 SphericalCoord direction = scan.rc2direction( row_column.x, row_column.y );
+
228 ScanMetadata scan = scans.at(scanID);
+
229 SphericalCoord direction = scan.rc2direction( row_column.x, row_column.y );
230
-
231 HitPoint hit( scanID, xyz, direction, row_column, color, data );
+
231 HitPoint hit( scanID, xyz, direction, row_column, color, data );
232
233 hits.push_back(hit);
234
@@ -2276,7 +2283,7 @@
2028
2029void LiDARcloud::floodfill( size_t t, std::vector<Triangulation> &cloud_triangles, std::vector<int> &fill_flag, std::vector<std::vector<int> > &nodes, int tag, int depth, int maxdepth ){
2030
-
2031 Triangulation tri = cloud_triangles.at(t);
+
2031 Triangulation tri = cloud_triangles.at(t);
2032
2033 int verts[3] = {tri.ID0, tri.ID1, tri.ID2};
2034
@@ -2545,9 +2552,9 @@
2293
2294 size_t Ntri = 0;
2295 for( size_t t=0; t< getTriangleCount(); t++ ){
-
2296 Triangulation tri = getTriangle(t);
+
2296 Triangulation tri = getTriangle(t);
2297 if( tri.gridcell == v ){
-
2298 helios::vec3 normal = cross( tri.vertex1-tri.vertex0, tri.vertex2-tri.vertex0 );
+
2298 helios::vec3 normal = cross( tri.vertex1-tri.vertex0, tri.vertex2-tri.vertex0 );
2299 tri_rots.push_back( make_SphericalCoord(cart2sphere(normal).zenith,cart2sphere(normal).azimuth) );
2300 }
2301 }
@@ -2556,11 +2563,11 @@
2304
2305 int randi = round(randu()*(tri_rots.size()-1));
2306
-
2307 helios::vec3 cellsize = getCellSize(v);
-
2308 helios::vec3 cellcenter = getCellCenter(v);
+
2307 helios::vec3 cellsize = getCellSize(v);
+
2308 helios::vec3 cellcenter = getCellCenter(v);
2309 float rotation = getCellRotation(v);
2310
-
2311 helios::vec3 shift = cellcenter + rotatePoint(helios::make_vec3( (randu()-0.5)*cellsize.x, (randu()-0.5)*cellsize.y, (randu()-0.5)*cellsize.z ),0,rotation);
+
2311 helios::vec3 shift = cellcenter + rotatePoint(helios::make_vec3( (randu()-0.5)*cellsize.x, (randu()-0.5)*cellsize.y, (randu()-0.5)*cellsize.z ),0,rotation);
2312
2313 reconstructed_alphamasks_center.push_back( shift );
2314 reconstructed_alphamasks_size.push_back( reconstructed_alphamasks_size.front() );
@@ -2595,13 +2602,13 @@
2343
2344 int group_index = group_gridcell.at(v).at(randi);
2345
-
2346 helios::vec3 cellsize = getCellSize(v);
-
2347 helios::vec3 cellcenter = getCellCenter(v);
+
2346 helios::vec3 cellsize = getCellSize(v);
+
2347 helios::vec3 cellcenter = getCellCenter(v);
2348 float rotation = getCellRotation(v);
-
2349 helios::vec3 cellanchor = getCellGlobalAnchor(v);
+
2349 helios::vec3 cellanchor = getCellGlobalAnchor(v);
2350
2351 //helios::vec3 shift = reconstructed_alphamasks_center.at(group_index) + helios::make_vec3( 0.45*(randu()-0.5)*cellsize.x, 0.45*(randu()-0.5)*cellsize.y, 0.45*(randu()-0.5)*cellsize.z ); //uniform shift about group
-
2352 helios::vec3 shift = reconstructed_alphamasks_center.at(group_index) + helios::make_vec3( 0.25*randn(generator)*cellsize.x, 0.25*randn(generator)*cellsize.y, 0.25*randn(generator)*cellsize.z ); //Gaussian shift about group
+
2352 helios::vec3 shift = reconstructed_alphamasks_center.at(group_index) + helios::make_vec3( 0.25*randn(generator)*cellsize.x, 0.25*randn(generator)*cellsize.y, 0.25*randn(generator)*cellsize.z ); //Gaussian shift about group
2353 //helios::vec3 shift = cellcenter + helios::make_vec3( (randu()-0.5)*cellsize.x, (randu()-0.5)*cellsize.y, (randu()-0.5)*cellsize.z ); //uniform shift within voxel
2354 shift = rotatePointAboutLine(shift,cellanchor,make_vec3(0,0,1),rotation);
2355
@@ -2695,10 +2702,10 @@
2443
2444 int gridcell = reconstructed_triangles.at(g).at(t).gridcell;
2445
-
2446 helios::vec3 normal = cross( reconstructed_triangles.at(g).at(t).vertex1-reconstructed_triangles.at(g).at(t).vertex0, reconstructed_triangles.at(g).at(t).vertex2-reconstructed_triangles.at(g).at(t).vertex0 );
+
2446 helios::vec3 normal = cross( reconstructed_triangles.at(g).at(t).vertex1-reconstructed_triangles.at(g).at(t).vertex0, reconstructed_triangles.at(g).at(t).vertex2-reconstructed_triangles.at(g).at(t).vertex0 );
2447 normal.z = fabs(normal.z); //keep in upper hemisphere
2448
-
2449 helios::SphericalCoord normal_dir = cart2sphere(normal);
+
2449 helios::SphericalCoord normal_dir = cart2sphere(normal);
2450
2451 int bin_theta = floor(normal_dir.zenith/db_theta);
2452 if( bin_theta>=Nbins ){
@@ -2891,31 +2898,31 @@
void disableMessages()
Disable all print messages to the screen except for fatal error messages.
Definition LiDAR.cpp:100
void addGridWireFrametoVisualizer(Visualizer *visualizer) const
Add wire frame of the grid to the visualizer plug-in.
Definition LiDAR.cpp:716
Class for visualization of simulation results.
Definition Visualizer.h:275
-
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
+
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
void addPoint(const helios::vec3 &position, const helios::RGBcolor &color, uint pointsize, CoordinateSystem coordFlag)
Add a point by giving its coordinates and size.
void addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a triangle by giving the coordinates of its three vertices.
void addLine(const helios::vec3 &start, const helios::vec3 &end, const helios::RGBcolor &color, uint linewidth, CoordinateSystem coordFlag)
Add Lines by giving the coordinates of points along the Lines.
void addVoxelByCenter(const helios::vec3 &center, const helios::vec3 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a voxel by giving the coordinates of its center.
void addRectangleByCenter(const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a rectangle by giving the coordinates of its center.
-
Colormap getCurrentColormap() const
Get the current colormap used in Colorbar/visualization.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Colormap getCurrentColormap() const
Get the current colormap used in Colorbar/visualization.
+
Stores the state associated with simulation.
Definition Context.h:1888
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
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:1536
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1491
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7104
+
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7131
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
-
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:7122
+
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:7149
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
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
std::vector< std::vector< bool > > readPNGAlpha(const std::string &filename)
Function to read the alpha channel from a PNG image.
Definition global.cpp:1488
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
+
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5836
float randu()
Random number from a uniform distribution between 0 and 1.
Definition global.cpp:223
vec3 rotatePoint(const vec3 &position, const SphericalCoord &rotation)
Function to rotate a 3D vector given spherical angles elevation and azimuth.
Definition global.cpp:79
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
@@ -2937,7 +2944,7 @@
Structure containing metadata for a terrestrial scan.
Definition LiDAR.h:188
float phiMin
Minimum azimuthal angle of scan in radians.
Definition LiDAR.h:227
-
float thetaMin
Minimum zenithal angle of scan in radians
Definition LiDAR.h:214
+
float thetaMin
Minimum zenithal angle of scan in radians.
Definition LiDAR.h:214
helios::vec3 origin
(x,y,z) coordinate of scanner location
Definition LiDAR.h:235
float thetaMax
Maximum zenithal angle of scan in radians.
Definition LiDAR.h:219
float phiMax
Maximum azimuthal angle of scan in radians.
Definition LiDAR.h:232
@@ -2960,26 +2967,29 @@
Vector of spherical coordinates (elevation,azimuth)
const float & zenith
Zenithal angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
float magnitude() const
Compute the vector magnitude.
- -
+ + diff --git a/doc/html/_li_d_a_r_8cu.html b/doc/html/_li_d_a_r_8cu.html index 3a9bd559a..aff341085 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
LiDAR.cu File Reference
@@ -116,10 +122,13 @@

Definition in file LiDAR.cu.

- - + + diff --git a/doc/html/_li_d_a_r_8cu_source.html b/doc/html/_li_d_a_r_8cu_source.html index 3ced58e2d..6b80e3b42 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
LiDAR.cu
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "LiDAR.cuh"
17#include "LiDAR.h"
18
@@ -386,13 +393,13 @@
293 CUDA_CHECK_ERROR( cudaMemcpy(d_hit_xyz, hit_xyz, N*sizeof(float3), cudaMemcpyHostToDevice) );
294
295 // ---- Grid Cells ---- //
-
296
+
296
298 float3* d_grid_center;
-
299
+
299
301 float3* d_grid_anchor;
-
302
+
302
304 float3* d_grid_size;
-
305
+
305
307 float* d_grid_rotation;
308
309 const uint Ncells = getGridCellCount();
@@ -497,13 +504,13 @@
407 CUDA_CHECK_ERROR( cudaMemcpy(d_hit_xyz, hit_xyz, N*sizeof(float3), cudaMemcpyHostToDevice) );
408
409 // ---- Grid Cells ---- //
-
410
+
410
412 float3* d_grid_center;
-
413
+
413
415 float3* d_grid_anchor;
-
416
+
416
418 float3* d_grid_size;
-
419
+
419
421 float* d_grid_rotation;
422
423 const uint Ncells = getGridCellCount();
@@ -839,12 +846,12 @@
748 getGridBoundingBox(boxmin, boxmax); // axis aligned bounding box of all grid cells
749 grid_vertices.push_back(boxmin);
750 grid_vertices.push_back(boxmax);
-
751 grid_vertices.push_back(helios::make_vec3(boxmin.x, boxmin.y, boxmax.z));
-
752 grid_vertices.push_back(helios::make_vec3(boxmax.x, boxmax.y, boxmin.z));
-
753 grid_vertices.push_back(helios::make_vec3(boxmin.x, boxmax.y, boxmin.z));
-
754 grid_vertices.push_back(helios::make_vec3(boxmin.x, boxmax.y, boxmax.z));
-
755 grid_vertices.push_back(helios::make_vec3(boxmax.x, boxmin.y, boxmin.z));
-
756 grid_vertices.push_back(helios::make_vec3(boxmax.x, boxmin.y, boxmax.z));
+
751 grid_vertices.push_back(helios::make_vec3(boxmin.x, boxmin.y, boxmax.z));
+
752 grid_vertices.push_back(helios::make_vec3(boxmax.x, boxmax.y, boxmin.z));
+
753 grid_vertices.push_back(helios::make_vec3(boxmin.x, boxmax.y, boxmin.z));
+
754 grid_vertices.push_back(helios::make_vec3(boxmin.x, boxmax.y, boxmax.z));
+
755 grid_vertices.push_back(helios::make_vec3(boxmax.x, boxmin.y, boxmin.z));
+
756 grid_vertices.push_back(helios::make_vec3(boxmax.x, boxmin.y, boxmax.z));
757
758 float max_theta = 0;
759 float min_theta = M_PI;
@@ -1000,7 +1007,7 @@
905 }
906
907 if( !triangulationcomputed ){
-
908 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
+
908 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
909 }
910
911 if( !hitgridcellcomputed ){
@@ -1460,7 +1467,7 @@
1363 }
1364
1365 if( !triangulationcomputed ){
-
1366 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
+
1366 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
1367 }
1368
1369 if( !hitgridcellcomputed ){
@@ -1798,7 +1805,7 @@
1699 }
1700
1701 if( !triangulationcomputed ){
-
1702 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU_synthetic): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
+
1702 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU_synthetic): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
1703 }
1704
1705 if( !hitgridcellcomputed ){
@@ -1847,7 +1854,7 @@
1748 // so when accessing the things using getHitData(), getHitXYZ(), etc,
1749 // for only one of the scans (this_scan),
1750 // need to use getHitData(this_scan_index[i]) not getHitData(i)
-
1751
+
1751
1753 for( uint s=0; s<Nscans; s++ ){
1754
1755 if( printmessages ){
@@ -1938,7 +1945,7 @@
1840 uint* d_hit_location;
1841 CUDA_CHECK_ERROR( cudaMalloc((uint**)&d_hit_location, Nhits*sizeof(uint)) );
1842
-
1843
+
1843
1845 // now loop through each voxel
1846 for( uint c=0; c<Ncells; c++ ){
1847
@@ -2020,7 +2027,7 @@
1924 float W = 0;
1925 float drr = 0;
1926 float last_drr = 0;
-
1927
+
1927
1929 for(int j = 0; j < beam_array.at(k).size(); j++){
1930
1931 // pull out the index of the current scan's current beam's current hit (which is used to access the overall hit index r through this_scan_index[i])
@@ -2069,7 +2076,7 @@
1974 // output info about the current beam to file
1975 file_beam << s << "," << c << "," << k << "," << R_before << "," << R_inside << "," << R_after << "," << R_miss << "," << E_before << "," << E_inside << "," << E_after << "," << E_miss << "," << sin_theta << "," << drrx << "," << last_drr << "," << I_before << "," << I_inside << "," << I_after << "," << I_miss << std::endl;
1976 }
-
1977
+
1977
1979 // calculate terms for different P methods
1980
1981 // P_exact
@@ -2167,7 +2174,7 @@
2073 std::vector<float> P_exact(Ncells);
2074 std::vector<uint> voxel_beam_count_tot(Ncells);
2075 std::vector<float> dr_bar(Ncells);
-
2076
+
2076
2078 // now aggregate over all scans
2079 for( uint c=0; c<Ncells; c++ ){
2080
@@ -2813,13 +2820,13 @@
2719
2720 if( t>=t0 ){ //hit lies within or beyond the volume
2721
-
2722 atomicAdd( hit_after, sin(acos_safe(dz))*d_scan_weight[idx] );
+
2722 atomicAdd( hit_after, sin(acos_safe(dz))*d_scan_weight[idx] );
2723
2724 d_dr[ idx ] = fabs(t1-t0);
2725
2726 }else if( t<t0 ){ //hit lies before the volume
2727
-
2728 atomicAdd( hit_before, sin(acos_safe(dz))*d_scan_weight[idx] );
+
2728 atomicAdd( hit_before, sin(acos_safe(dz))*d_scan_weight[idx] );
2729
2730 }
2731
@@ -2910,7 +2917,7 @@
2816 float t = magnitude( scan_xyz_rot - origin_rot ); //t-distance to hit point
2817
2818 if( t>=t0 && t<= t1 ){ //hit lies within the volume
-
2819 atomicAdd( hit_after, sin(acos_safe(dz))*d_scan_weight[idx] );
+
2819 atomicAdd( hit_after, sin(acos_safe(dz))*d_scan_weight[idx] );
2820 d_hit_location[ idx ] = 2;
2821 d_dr[ idx ] = fabs(t1-t0);
2822 }else if( t > t1 && t < scanner_range){ //hit lies after the volume (but not a miss)
@@ -2921,7 +2928,7 @@
2827 d_dr[ idx ] = fabs(t1-t0);
2828 }else if( t<t0 ){ //hit lies before the volume
2829 d_hit_location[ idx ] = 1;
-
2830 atomicAdd( hit_before, sin(acos_safe(dz))*d_scan_weight[idx] );
+
2830 atomicAdd( hit_before, sin(acos_safe(dz))*d_scan_weight[idx] );
2831
2832 }
2833
@@ -3268,7 +3275,7 @@
3165 //figure out how many patches
3166 size_t Npatches = 0;
3167 for( int p=0; p<UUIDs_all.size(); p++ ){
-
3168 if( context->getPrimitiveType(UUIDs_all.at(p)) == helios::PRIMITIVE_TYPE_PATCH ){
+
3168 if( context->getPrimitiveType(UUIDs_all.at(p)) == helios::PRIMITIVE_TYPE_PATCH ){
3169 Npatches++;
3170 }
3171 }
@@ -3282,7 +3289,7 @@
3179 c=0;
3180 for( int p=0; p<UUIDs_all.size(); p++ ){
3181 uint UUID = UUIDs_all.at(p);
-
3182 if( context->getPrimitiveType(UUID) == helios::PRIMITIVE_TYPE_PATCH ){
+
3182 if( context->getPrimitiveType(UUID) == helios::PRIMITIVE_TYPE_PATCH ){
3183 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUID);
3184 patch_vertex[4*c] = vec3tofloat3(verts.at(0));
3185 patch_vertex[4*c+1] = vec3tofloat3(verts.at(1));
@@ -3337,7 +3344,7 @@
3234 //figure out how many triangles
3235 size_t Ntriangles = 0;
3236 for( int p=0; p<UUIDs_all.size(); p++ ){
-
3237 if( context->getPrimitiveType(UUIDs_all.at(p)) == helios::PRIMITIVE_TYPE_TRIANGLE ){
+
3237 if( context->getPrimitiveType(UUIDs_all.at(p)) == helios::PRIMITIVE_TYPE_TRIANGLE ){
3238 Ntriangles++;
3239 }
3240 }
@@ -3351,7 +3358,7 @@
3248 c=0;
3249 for( int p=0; p<UUIDs_all.size(); p++ ){
3250 uint UUID = UUIDs_all.at(p);
-
3251 if( context->getPrimitiveType(UUID) == helios::PRIMITIVE_TYPE_TRIANGLE ){
+
3251 if( context->getPrimitiveType(UUID) == helios::PRIMITIVE_TYPE_TRIANGLE ){
3252 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUID);
3253 tri_vertex[3*c] = vec3tofloat3(verts.at(0));
3254 tri_vertex[3*c+1] = vec3tofloat3(verts.at(1));
@@ -3465,7 +3472,7 @@
3362 for (uint i=0; i<Ntheta; i++ ){
3363 float theta_z = thetamin+float(i)*(thetamax-thetamin)/float(Ntheta);
3364 float theta_elev = 0.5f*M_PI-theta_z;
-
3365 helios::vec3 dir = sphere2cart(helios::make_SphericalCoord(1.f,theta_elev,phi));
+
3365 helios::vec3 dir = sphere2cart(helios::make_SphericalCoord(1.f,theta_elev,phi));
3366 raydir.at(Ntheta*j+i) = dir;
3367 }
3368 }
@@ -3749,13 +3756,13 @@
3646
3647 color = context->getPrimitiveColor(uint(UUID));
3648
-
3649 if( context->doesPrimitiveDataExist(uint(UUID),"object_label") && context->getPrimitiveDataType(uint(UUID),"object_label")==helios::HELIOS_TYPE_INT ){
+
3649 if( context->doesPrimitiveDataExist(uint(UUID),"object_label") && context->getPrimitiveDataType(uint(UUID),"object_label")==helios::HELIOS_TYPE_INT ){
3650 int label;
3651 context->getPrimitiveData(uint(UUID),"object_label",label);
3652 data["object_label"] = double(label);
3653 }
3654
-
3655 if( context->doesPrimitiveDataExist(uint(UUID),"reflectivity_lidar") && context->getPrimitiveDataType(uint(UUID),"reflectivity_lidar")==helios::HELIOS_TYPE_FLOAT ){
+
3655 if( context->doesPrimitiveDataExist(uint(UUID),"reflectivity_lidar") && context->getPrimitiveDataType(uint(UUID),"reflectivity_lidar")==helios::HELIOS_TYPE_FLOAT ){
3656 float rho;
3657 context->getPrimitiveData(uint(UUID),"reflectivity_lidar",rho);
3658 data.at("intensity")*=rho;
@@ -3763,8 +3770,8 @@
3660
3661 }
3662
-
3663 helios::vec3 dir = helios::make_vec3(direction[r].x,direction[r].y,direction[r].z);
-
3664 helios::vec3 origin = helios::make_vec3(scan_origin.x,scan_origin.y,scan_origin.z);
+
3663 helios::vec3 dir = helios::make_vec3(direction[r].x,direction[r].y,direction[r].z);
+
3664 helios::vec3 origin = helios::make_vec3(scan_origin.x,scan_origin.y,scan_origin.z);
3665 helios::vec3 p = origin+dir*t_hit.at(hit).at(0);
3666 addHitPoint( s, p, helios::cart2sphere(dir), color, data );
3667
@@ -3835,13 +3842,13 @@
3730 CUDA_CHECK_ERROR( cudaMemcpy(d_prim_xyz, prim_xyz, N*sizeof(float3), cudaMemcpyHostToDevice) );
3731
3732 // ---- Grid Cells ---- //
-
3733
+
3733
3735 float3* d_grid_center;
-
3736
+
3736
3738 float3* d_grid_anchor;
-
3739
+
3739
3741 float3* d_grid_size;
-
3742
+
3742
3744 float* d_grid_rotation;
3745
3746 const uint Ncells = getGridCellCount();
@@ -3898,7 +3905,7 @@
3797 if( prim_vol[p]>=0 ){
3798 uint gridcell = prim_vol[p];
3799 total_area.at(gridcell) += context->getPrimitiveArea(UUIDs_all.at(p));
-
3800 context->setPrimitiveData(UUIDs_all.at(p),"gridCell",helios::HELIOS_TYPE_UINT,1,&gridcell);
+
3800 context->setPrimitiveData(UUIDs_all.at(p),"gridCell",helios::HELIOS_TYPE_UINT,1,&gridcell);
3801 }
3802 }
3803
@@ -3946,7 +3953,7 @@
3844
3845 float3 raydir = d_sphere2cart( 1.f, 0.5*M_PI-0.5*beam_divergence*rnd(seed), 2.f*M_PI*rnd(seed) );
3846
-
3847 float zenith = acos_safe( d_raydir[idx].z/sqrt(d_raydir[idx].x*d_raydir[idx].x+d_raydir[idx].y*d_raydir[idx].y+d_raydir[idx].z*d_raydir[idx].z) );
+
3847 float zenith = acos_safe( d_raydir[idx].z/sqrt(d_raydir[idx].x*d_raydir[idx].x+d_raydir[idx].y*d_raydir[idx].y+d_raydir[idx].z*d_raydir[idx].z) );
3848 float azimuth = atan2_2pi( d_raydir[idx].x, d_raydir[idx].y );
3849 raydir = d_rotatePoint( raydir, zenith, 0.5*M_PI-azimuth );
3850
@@ -4045,7 +4052,7 @@
3943
3944 float3 raydir = d_sphere2cart( 1.f, 0.5*M_PI-0.5*beam_divergence*rnd(seed), 2.f*M_PI*rnd(seed) );
3945
-
3946 float zenith = acos_safe( d_raydir[idx].z/sqrt(d_raydir[idx].x*d_raydir[idx].x+d_raydir[idx].y*d_raydir[idx].y+d_raydir[idx].z*d_raydir[idx].z) );
+
3946 float zenith = acos_safe( d_raydir[idx].z/sqrt(d_raydir[idx].x*d_raydir[idx].x+d_raydir[idx].y*d_raydir[idx].y+d_raydir[idx].z*d_raydir[idx].z) );
3947 float azimuth = atan2_2pi( d_raydir[idx].x, d_raydir[idx].y );
3948 raydir = d_rotatePoint( raydir, zenith, 0.5*M_PI-azimuth );
3949
@@ -4140,7 +4147,7 @@
4037 }
4038
4039 if( !triangulationcomputed ){
-
4040 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
+
4040 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
4041 }
4042
4043 if( !hitgridcellcomputed ){
@@ -4181,7 +4188,7 @@
4078 // so when accessing the things using getHitData(), getHitXYZ(), etc,
4079 // for only one of the scans (this_scan),
4080 // need to use getHitData(this_scan_index[i]) not getHitData(i)
-
4081
+
4081
4083 for( uint s=0; s<Nscans; s++ ){
4084
4085 if( printmessages ){
@@ -4272,7 +4279,7 @@
4170 uint* d_hit_location;
4171 CUDA_CHECK_ERROR( cudaMalloc((uint**)&d_hit_location, Nhits*sizeof(uint)) );
4172
-
4173
+
4173
4175 // now loop through each voxel
4176 for( uint c=0; c<Ncells; c++ ){
4177
@@ -4336,7 +4343,7 @@
4236 // float W = 0;
4237 float drr = 0;
4238 float last_drr = 0;
-
4239
+
4239
4241 for(int j = 0; j < beam_array.at(k).size(); j++){
4242
4243 // pull out the index of the current scan's current beam's current hit (which is used to access the overall hit index r through this_scan_index[i])
@@ -4377,7 +4384,7 @@
4278 // output info about the current beam to file
4279 file_beam << s << "," << c << "," << k << "," << E_before << "," << E_inside << "," << E_after << "," << E_miss << "," << sin_theta << "," << drrx << "," << last_drr << std::endl;
4280 }
-
4281
+
4281
4283 // calculate terms equal weighting P method
4284
4285 // P_equal
@@ -4426,7 +4433,7 @@
4328 std::vector<float> P_equal(Ncells);
4329 std::vector<uint> voxel_beam_count_tot(Ncells);
4330 std::vector<float> dr_bar(Ncells);
-
4331
+
4331
4333 // now aggregate over all scans
4334 for( uint c=0; c<Ncells; c++ ){
4335
@@ -4460,7 +4467,7 @@
4363 }
4364 } //end of loop through cells to aggregate all scans
4365
-
4366
+
4366
4368 //----------- Calculate number of hits in voxels -------------- //
4369
4370 //figure out hits for all scans
@@ -4589,7 +4596,7 @@
4491 }
4492
4493 if( !triangulationcomputed ){
-
4494 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
+
4494 helios::helios_runtime_error("ERROR (LiDARcloud::calculateLeafAreaGPU): Triangulation must be performed prior to leaf area calculation. See triangulateHitPoints().");
4495 }
4496
4497 if( !hitgridcellcomputed ){
@@ -4630,7 +4637,7 @@
4532 // so when accessing the things using getHitData(), getHitXYZ(), etc,
4533 // for only one of the scans (this_scan),
4534 // need to use getHitData(this_scan_index[i]) not getHitData(i)
-
4535
+
4535
4537 for( uint s=0; s<Nscans; s++ ){
4538
4539 if( printmessages ){
@@ -4721,7 +4728,7 @@
4624 uint* d_hit_location;
4625 CUDA_CHECK_ERROR( cudaMalloc((uint**)&d_hit_location, Nhits*sizeof(uint)) );
4626
-
4627
+
4627
4629 // now loop through each voxel
4630 for( uint c=0; c<Ncells; c++ ){
4631
@@ -4785,7 +4792,7 @@
4690 // float W = 0;
4691 float drr = 0;
4692 float last_drr = 0;
-
4693
+
4693
4695 for(int j = 0; j < beam_array.at(k).size(); j++){
4696
4697 // pull out the index of the current scan's current beam's current hit (which is used to access the overall hit index r through this_scan_index[i])
@@ -4826,7 +4833,7 @@
4732 // output info about the current beam to file
4733 file_beam << s << "," << c << "," << k << "," << E_before << "," << E_inside << "," << E_after << "," << E_miss << "," << sin_theta << "," << drrx << "," << last_drr << std::endl;
4734 }
-
4735
+
4735
4737 // calculate terms equal weighting P method
4738
4739 // P_equal
@@ -4875,7 +4882,7 @@
4782 std::vector<float> P_equal(Ncells);
4783 std::vector<uint> voxel_beam_count_tot(Ncells);
4784 std::vector<float> dr_bar(Ncells);
-
4785
+
4785
4787 // now aggregate over all scans
4788 for( uint c=0; c<Ncells; c++ ){
4789
@@ -4909,7 +4916,7 @@
4817 }
4818 } //end of loop through cells to aggregate all scans
4819
-
4820
+
4820
4822 //----------- Calculate number of hits in voxels -------------- //
4823
4824 //figure out hits for all scans
@@ -5143,6 +5150,11 @@
5049
5050
5051
+
@ HELIOS_TYPE_INT
integer data type
Definition Context.h:43
+
@ HELIOS_TYPE_UINT
unsigned integer data type
Definition Context.h:45
+
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
+
@ PRIMITIVE_TYPE_PATCH
< Rectangular primitive
Definition Context.h:33
+
@ PRIMITIVE_TYPE_TRIANGLE
< Triangular primitive
Definition Context.h:35
__device__ float3 d_rotatePoint(const float3 &position, const float &theta, const float &phi)
void getGridBoundingBox(helios::vec3 &boxmin, helios::vec3 &boxmax) const
Form an axis-aligned bounding box for all grid cells in the point cloud.
Definition LiDAR.cpp:988
@@ -5185,32 +5197,34 @@
std::vector< uint > peakFinder(std::vector< float > signal)
find the indices of the peaks of a vector of floats
Definition LiDAR.cu:4984
helios::vec3 getCellGlobalAnchor(uint index) const
Get the (x,y,z) coordinate of a grid global anchor by its index.
Definition LiDAR.cpp:1819
void calculateLeafAreaGPU()
Calculate the leaf area for each grid volume.
Definition LiDAR.cu:897
-
Stores the state associated with simulation.
Definition Context.h:1882
-
helios::RGBcolor getPrimitiveColor(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7127
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
Stores the state associated with simulation.
Definition Context.h:1888
+
helios::RGBcolor getPrimitiveColor(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7154
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7159
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7175
-
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7179
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7167
+
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7186
+
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7202
+
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7206
+
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:7011
+
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
helios::int2 getPrimitiveTextureSize(uint UUID) const
Get the size (number of pixels) of primitive texture map image.
Definition Context.cpp:7194
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:2046
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7187
+
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7214
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
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:1659
-
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:7122
+
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:7149
+
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
float atan2_2pi(float y, float x)
Four quadrant arc tangent between 0 and 2*pi.
Definition global.cpp:584
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
-
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
float mean(const std::vector< float > &vect)
Mean value of a vector of floats.
Definition global.cpp:1084
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.
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor vector.
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
vec3 cross(const vec3 &a, const vec3 &b)
Cross product of two vec3 vectors.
+
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
R-G-B color vector.
@@ -5220,23 +5234,26 @@
Vector of spherical coordinates (elevation,azimuth)
const float & zenith
Zenithal angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
float magnitude() const
Compute the vector magnitude.
- -
+ + diff --git a/doc/html/_li_d_a_r_8h.html b/doc/html/_li_d_a_r_8h.html index b6a9a92a4..a72e85d81 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Data Structures | @@ -192,10 +198,13 @@

+ + diff --git a/doc/html/_li_d_a_r_8h.js b/doc/html/_li_d_a_r_8h.js new file mode 100644 index 000000000..526faaaeb --- /dev/null +++ b/doc/html/_li_d_a_r_8h.js @@ -0,0 +1,9 @@ +var _li_d_a_r_8h = +[ + [ "HitTable< datatype >", "class_hit_table.html", null ], + [ "HitPoint", "struct_hit_point.html", null ], + [ "Triangulation", "struct_triangulation.html", null ], + [ "GridCell", "struct_grid_cell.html", null ], + [ "ScanMetadata", "struct_scan_metadata.html", "struct_scan_metadata" ], + [ "LiDARcloud", "class_li_d_a_rcloud.html", "class_li_d_a_rcloud" ] +]; \ No newline at end of file diff --git a/doc/html/_li_d_a_r_8h_source.html b/doc/html/_li_d_a_r_8h_source.html index 5c754aacb..0bd54151a 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
LiDAR.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef LIDARPLUGIN
17#define LIDARPLUGIN
18
@@ -114,16 +121,16 @@
22#include "s_hull_pro.h"
23
-
24template <class datatype> class HitTable {
+
24template <class datatype> class HitTable {
25public:
26
27 uint Ntheta, Nphi;
28
-
29 HitTable( void ){
+
29 HitTable( void ){
30 Ntheta = 0;
31 Nphi = 0;
32 }
-
33 HitTable( const int nx, const int ny ){
+
33 HitTable( const int nx, const int ny ){
34 Ntheta=nx;
35 Nphi=ny;
36 data.resize(Nphi);
@@ -131,7 +138,7 @@
38 data.at(j).resize(Ntheta);
39 }
40 }
-
41 HitTable( const int nx, const int ny, const datatype initval ){
+
41 HitTable( const int nx, const int ny, const datatype initval ){
42 Ntheta=nx;
43 Nphi=ny;
44 data.resize(Nphi);
@@ -176,7 +183,7 @@
83
-
84struct HitPoint{
+
84struct HitPoint{
85 helios::vec3 position;
86 helios::SphericalCoord direction;
87 helios::int2 row_column;
@@ -184,15 +191,15 @@
89 std::map<std::string, double> data;
90 int gridcell;
91 int scanID;
-
92 HitPoint(void){
-
93 position = helios::make_vec3(0,0,0);
-
94 direction = helios::make_SphericalCoord(0,0);
+
92 HitPoint(void){
+
93 position = helios::make_vec3(0,0,0);
+
94 direction = helios::make_SphericalCoord(0,0);
95 row_column = helios::make_int2(0,0);
96 color = helios::RGB::red;
97 gridcell = -2;
98 scanID = -1;
99 }
-
100 HitPoint( int __scanID, helios::vec3 __position, helios::SphericalCoord __direction, helios::int2 __row_column, helios::RGBcolor __color, std::map<std::string, double> __data ){
+
100 HitPoint( int __scanID, helios::vec3 __position, helios::SphericalCoord __direction, helios::int2 __row_column, helios::RGBcolor __color, std::map<std::string, double> __data ){
101 scanID = __scanID;
102 position = __position;
103 direction = __direction;
@@ -204,17 +211,17 @@
109
- +
110struct Triangulation{
111 helios::vec3 vertex0, vertex1, vertex2;
112 int ID0, ID1, ID2;
113 int scanID;
114 int gridcell;
115 helios::RGBcolor color;
116 float area;
-
117 Triangulation(void){
-
118 vertex0 = helios::make_vec3(0,0,0);
-
119 vertex1 = helios::make_vec3(0,0,0);
-
120 vertex2 = helios::make_vec3(0,0,0);
+
117 Triangulation(void){
+
118 vertex0 = helios::make_vec3(0,0,0);
+
119 vertex1 = helios::make_vec3(0,0,0);
+
120 vertex2 = helios::make_vec3(0,0,0);
121 ID0 = 0;
122 ID1 = 0;
123 ID2 = 0;
@@ -223,7 +230,7 @@
126 color = helios::RGB::green;
127 area = 0;
128 }
-
129 Triangulation( int __scanID, helios::vec3 __vertex0, helios::vec3 __vertex1, helios::vec3 __vertex2, int __ID0, int __ID1, int __ID2, helios::RGBcolor __color, int __gridcell ){
+
129 Triangulation( int __scanID, helios::vec3 __vertex0, helios::vec3 __vertex1, helios::vec3 __vertex2, int __ID0, int __ID1, int __ID2, helios::RGBcolor __color, int __gridcell ){
130 scanID = __scanID;
131 vertex0 = __vertex0;
132 vertex1 = __vertex1;
@@ -251,7 +258,7 @@
154
-
155struct GridCell{
+
155struct GridCell{
156 helios::vec3 center;
157 helios::vec3 global_anchor;
158 helios::vec3 size;
@@ -264,7 +271,7 @@
165 float ground_height;
166 float vegetation_height;
167 float maximum_height;
-
168 GridCell( helios::vec3 __center, helios::vec3 __global_anchor, helios::vec3 __size, helios::vec3 __global_size, float __azimuthal_rotation, helios::int3 __global_ijk, helios::int3 __global_count ){
+
168 GridCell( helios::vec3 __center, helios::vec3 __global_anchor, helios::vec3 __size, helios::vec3 __global_size, float __azimuthal_rotation, helios::int3 __global_ijk, helios::int3 __global_count ){
169 center = __center;
170 global_anchor = __global_anchor;
171 size = __size;
@@ -280,51 +287,51 @@
181 }
182};
-
183
-
185
+
183
+
185
- -
189
+ +
189
191 ScanMetadata();
-
192
-
194
+
192
+
194
203 ScanMetadata( const helios::vec3 &a_origin, uint a_Ntheta, float a_thetaMin, float a_thetaMax, uint a_Nphi, float a_phiMin, float a_phiMax, float a_exitDiameter, float a_beamDivergence, const std::vector<std::string> &a_columnFormat);
-
204
+
204
206 std::string data_file;
207
209 uint Ntheta;
-
211
+
211
214 float thetaMin;
-
216
+
216
219 float thetaMax;
220
222 uint Nphi;
-
224
+
224
227 float phiMin;
-
229
+
229
232 float phiMax;
233
-
236
-
238
+
236
+
238
-
242
-
244
+
242
+
244
-
248
+
248
250 std::vector<std::string> columnFormat;
-
251
-
253
+
251
+
253
258 helios::SphericalCoord rc2direction(uint row, uint column ) const;
-
259
-
261
+
259
+
261
265 helios::int2 direction2rc(const helios::SphericalCoord &direction ) const;
266
267};
-
268
+
268
- +
271 private:
272
273 size_t Nhits;
@@ -336,18 +343,18 @@
279 std::vector<GridCell> grid_cells;
280
281 std::vector<Triangulation> triangles;
-
282
+
282
284 std::vector< HitTable<int> > hit_tables;
285
287 bool hitgridcellcomputed;
288
290 bool triangulationcomputed;
-
291
+
291
293 bool printmessages;
294
295 // -------- I/O --------- //
-
296
-
298
+
296
+
298
303 size_t loadASCIIFile( uint scanID, ScanMetadata &scandata );
304
305 // -------- RECONSTRUCTION --------- //
@@ -373,378 +380,379 @@
325 void floodfill( size_t t, std::vector<Triangulation> &cloud_triangles, std::vector<int> &fill_flag, std::vector<std::vector<int> > &nodes, int tag, int depth, int maxdepth );
326
327 void sourcesInsideGridCellGPU();
-
328
-
330
+
328
+
330
336 std::vector<float> LAD_inversion(std::vector<float> &P, std::vector<float> &Gtheta, std::vector<std::vector<float>> &dr_array, bool fillAnalytic);
337
338 public:
-
339
+
339
341 LiDARcloud();
-
342
+
342
-
345
+
345
347 int selfTest();
348
349 void validateRayDirections();
-
350
+
350
352 void disableMessages();
-
353
+
353
355 void enableMessages();
356
357 // ------- SCANS -------- //
-
358
+
358
360 uint getScanCount();
-
361
-
363
+
361
+
363
367 uint addScan(ScanMetadata &newscan );
368
-
370
+
370
376 void addHitPoint( uint scanID, const helios::vec3 &xyz, const helios::SphericalCoord &direction );
-
377
-
379
+
377
+
379
386 void addHitPoint( uint scanID, const helios::vec3 &xyz, const helios::SphericalCoord &direction, const helios::RGBcolor &color );
-
387
-
389
+
387
+
389
395 void addHitPoint(uint scanID, const helios::vec3 &xyz, const helios::SphericalCoord &direction, const std::map<std::string, double> &data );
396
-
398
+
398
405 void addHitPoint( uint scanID, const helios::vec3 &xyz, const helios::SphericalCoord &direction, const helios::RGBcolor &color, const std::map<std::string, double> &data );
406
-
408
+
408
415 void addHitPoint( uint scanID, const helios::vec3 &xyz, const helios::int2 &row_column, const helios::RGBcolor &color, const std::map<std::string, double> &data );
-
416
-
418
+
416
+
418
421 void deleteHitPoint( uint index );
-
422
+
422
424 uint getHitCount() const;
425
-
427
+
427
430 helios::vec3 getScanOrigin( uint scanID ) const;
-
431
-
433
+
431
+
433
436 uint getScanSizeTheta( uint scanID ) const;
-
437
-
439
+
437
+
439
442 uint getScanSizePhi( uint scanID ) const;
443
-
445
+
445
449 helios::vec2 getScanRangeTheta( uint scanID ) const;
-
450
-
452
+
450
+
452
456 helios::vec2 getScanRangePhi( uint scanID ) const;
-
457
-
459
+
457
+
459
463 float getScanBeamExitDiameter( uint scanID ) const;
-
464
-
466
+
464
+
466
469 std::vector<std::string> getScanColumnFormat( uint scanID ) const;
-
470
-
472
+
470
+
472
476 float getScanBeamDivergence( uint scanID ) const;
-
477
-
479
+
477
+
479
482 helios::vec3 getHitXYZ( uint index ) const;
-
483
-
485
+
483
+
485
488 helios::SphericalCoord getHitRaydir( uint index ) const;
-
489
-
491
+
489
+
491
496 double getHitData( uint index, const char* label ) const;
-
497
-
499
+
497
+
499
503 void setHitData(uint index, const char* label, double value );
-
504
-
506
+
504
+
506
510 bool doesHitDataExist( uint index, const char* label ) const;
511
-
513
+
513
516 helios::RGBcolor getHitColor( uint index ) const;
-
517
-
519
+
517
+
519
522 int getHitScanID( uint index ) const;
523
-
525
+
525
531 int getHitIndex( uint scanID, uint row, uint column ) const;
532
-
534
+
534
539 int getHitGridCell( uint index ) const;
-
540
-
542
+
540
+
542
546 void setHitGridCell(uint index, int cell );
-
547
-
549
+
547
+
549
552 void coordinateShift(const helios::vec3 &shift );
-
553
-
555
+
553
+
555
559 void coordinateShift( uint scanID, const helios::vec3 &shift );
-
560
-
562
+
560
+
562
565 void coordinateRotation( const helios::SphericalCoord &rotation );
-
566
-
568
+
566
+
568
572 void coordinateRotation( uint scanID, const helios::SphericalCoord &rotation );
-
573
-
575
+
573
+
575
580 void coordinateRotation( float rotation, const helios::vec3 &line_base, const helios::vec3 &line_direction );
581
583 uint getTriangleCount() const;
584
-
586
+
586
590 Triangulation getTriangle( uint index ) const;
591
592 // ------- FILE I/O --------- //
-
593
-
595
+
593
+
595
598 void loadXML( const char* filename );
-
599
-
601
+
599
+
601
605 void loadXML( const char* filename, bool load_grid_only );
-
606
-
608
+
606
+
608
611 void exportTriangleNormals( const char* filename );
-
612
-
614
+
612
+
614
618 void exportTriangleNormals( const char* filename, int gridcell );
-
619
-
621
+
619
+
621
624 void exportTriangleAreas( const char* filename );
-
625
-
627
+
625
+
627
631 void exportTriangleAreas( const char* filename, int gridcell );
-
632
-
634
+
632
+
634
638 void exportTriangleInclinationDistribution( const char* filename, uint Nbins );
-
639
-
641
-
644 void exportLeafAreas( const char* filename );
-
645
-
647
-
650 void exportLeafAreaDensities( const char* filename );
-
651
-
653
-
656 void exportGtheta( const char* filename );
-
657
-
659
-
663 void exportPointCloud( const char* filename );
-
664
-
666
-
670 void exportPointCloud( const char* filename, uint scanID );
-
671
-
673
-
677 void exportPointCloudPTX( const char* filename, uint scanID );
-
678
-
679 // ------- VISUALIZER --------- //
-
680
-
682
-
686 void addHitsToVisualizer( Visualizer* visualizer, uint pointsize ) const;
+
639
+
641
+
645 void exportTriangleAzimuthDistribution( const char* filename, uint Nbins );
+
646
+
648
+
651 void exportLeafAreas( const char* filename );
+
652
+
654
+
657 void exportLeafAreaDensities( const char* filename );
+
658
+
660
+
663 void exportGtheta( const char* filename );
+
664
+
666
+
670 void exportPointCloud( const char* filename );
+
671
+
673
+
677 void exportPointCloud( const char* filename, uint scanID );
+
678
+
680
+
684 void exportPointCloudPTX( const char* filename, uint scanID );
+
685
+
686 // ------- VISUALIZER --------- //
687
-
689
-
694 void addHitsToVisualizer( Visualizer* visualizer, uint pointsize, const char* color_value ) const;
-
695
-
697
-
700 void addGridToVisualizer( Visualizer* visualizer ) const;
-
701
-
703
-
706 void addGridWireFrametoVisualizer( Visualizer* visualizer ) const;
-
707
-
709
-
715 void addGrid(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &ndiv, float rotation);
-
716
-
718
-
721 void addTrianglesToVisualizer( Visualizer* visualizer ) const;
-
722
-
724
-
728 void addTrianglesToVisualizer( Visualizer* visualizer, uint gridcell ) const;
-
729
-
731
-
734 void addLeafReconstructionToVisualizer( Visualizer* visualizer ) const;
-
735
-
737
-
740 void addTrunkReconstructionToVisualizer( Visualizer* visualizer ) const;
-
741
-
743
-
747 void addTrunkReconstructionToVisualizer( Visualizer* visualizer, const helios::RGBcolor &trunk_color ) const;
-
748
-
750
-
754 std::vector<uint> addLeafReconstructionToContext( helios::Context* context ) const;
-
755
-
757
-
762 std::vector<uint> addLeafReconstructionToContext( helios::Context* context, const helios::int2 &subpatches ) const;
-
763
-
765
-
769 std::vector<uint> addReconstructedTriangleGroupsToContext( helios::Context* context ) const;
-
770
-
772
-
775 std::vector<uint> addTrunkReconstructionToContext( helios::Context* context ) const;
-
776
-
778
-
782 void getHitBoundingBox( helios::vec3& boxmin, helios::vec3& boxmax ) const;
-
783
-
785
-
789 void getGridBoundingBox( helios::vec3& boxmin, helios::vec3& boxmax ) const;
-
790
-
791 // --------- POINT FILTERING ----------- //
-
792
-
794
-
797 void distanceFilter( float maxdistance );
-
798
-
800
-
809 void xyzFilter( float xmin, float xmax, float ymin, float ymax, float zmin, float zmax );
-
810
-
812
-
822 void xyzFilter( float xmin, float xmax, float ymin, float ymax, float zmin, float zmax, bool deleteOutside );
-
823
-
824
-
826
-
830 void reflectanceFilter( float minreflectance );
-
831
-
833
-
839 void scalarFilter( const char* scalar_field, float threshold, const char* comparator );
-
840
-
842
-
846 void maxPulseFilter( const char* scalar );
-
847
-
849
-
853 void minPulseFilter( const char* scalar );
-
854
-
856
-
859 void firstHitFilter();
-
860
-
862
-
865 void lastHitFilter();
-
866
-
867 // ------- TRIANGULATION --------- //
-
868
-
870
-
874 void triangulateHitPoints( float Lmax, float max_aspect_ratio );
-
875
-
876 //ERK
-
878
-
886 void triangulateHitPoints( float Lmax, float max_aspect_ratio, const char* scalar_field, float threshold, const char* comparator );
-
887
-
888
-
890
-
893 void addTrianglesToContext( helios::Context* context ) const;
-
894
-
895 // -------- GRID ----------- //
-
896
-
898 uint getGridCellCount() const;
-
899
+
689
+
693 void addHitsToVisualizer( Visualizer* visualizer, uint pointsize ) const;
+
694
+
696
+
701 void addHitsToVisualizer( Visualizer* visualizer, uint pointsize, const char* color_value ) const;
+
702
+
704
+
707 void addGridToVisualizer( Visualizer* visualizer ) const;
+
708
+
710
+
713 void addGridWireFrametoVisualizer( Visualizer* visualizer ) const;
+
714
+
716
+
722 void addGrid(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &ndiv, float rotation);
+
723
+
725
+
728 void addTrianglesToVisualizer( Visualizer* visualizer ) const;
+
729
+
731
+
735 void addTrianglesToVisualizer( Visualizer* visualizer, uint gridcell ) const;
+
736
+
738
+
741 void addLeafReconstructionToVisualizer( Visualizer* visualizer ) const;
+
742
+
744
+
747 void addTrunkReconstructionToVisualizer( Visualizer* visualizer ) const;
+
748
+
750
+
754 void addTrunkReconstructionToVisualizer( Visualizer* visualizer, const helios::RGBcolor &trunk_color ) const;
+
755
+
757
+
761 std::vector<uint> addLeafReconstructionToContext( helios::Context* context ) const;
+
762
+
764
+
769 std::vector<uint> addLeafReconstructionToContext( helios::Context* context, const helios::int2 &subpatches ) const;
+
770
+
772
+
776 std::vector<uint> addReconstructedTriangleGroupsToContext( helios::Context* context ) const;
+
777
+
779
+
782 std::vector<uint> addTrunkReconstructionToContext( helios::Context* context ) const;
+
783
+
785
+
789 void getHitBoundingBox( helios::vec3& boxmin, helios::vec3& boxmax ) const;
+
790
+
792
+
796 void getGridBoundingBox( helios::vec3& boxmin, helios::vec3& boxmax ) const;
+
797
+
798 // --------- POINT FILTERING ----------- //
+
799
+
801
+
804 void distanceFilter( float maxdistance );
+
805
+
807
+
816 void xyzFilter( float xmin, float xmax, float ymin, float ymax, float zmin, float zmax );
+
817
+
819
+
829 void xyzFilter( float xmin, float xmax, float ymin, float ymax, float zmin, float zmax, bool deleteOutside );
+
830
+
831
+
833
+
837 void reflectanceFilter( float minreflectance );
+
838
+
840
+
846 void scalarFilter( const char* scalar_field, float threshold, const char* comparator );
+
847
+
849
+
853 void maxPulseFilter( const char* scalar );
+
854
+
856
+
860 void minPulseFilter( const char* scalar );
+
861
+
863
+
866 void firstHitFilter();
+
867
+
869
+
872 void lastHitFilter();
+
873
+
874 // ------- TRIANGULATION --------- //
+
875
+
877
+
881 void triangulateHitPoints( float Lmax, float max_aspect_ratio );
+
882
+
883 //ERK
+
885
+
893 void triangulateHitPoints( float Lmax, float max_aspect_ratio, const char* scalar_field, float threshold, const char* comparator );
+
894
+
895
+
897
+
900 void addTrianglesToContext( helios::Context* context ) const;
901
-
906 void addGridCell( const helios::vec3 &center, const helios::vec3 &size, float rotation );
-
907
-
909
-
918 void addGridCell( const helios::vec3 &center, const helios::vec3 &global_anchor, const helios::vec3 &size, const helios::vec3 &global_size, float rotation, const helios::int3 &global_ijk, const helios::int3 &global_count );
-
919
-
921
-
924 helios::vec3 getCellCenter( uint index ) const;
-
925
-
927
-
930 helios::vec3 getCellGlobalAnchor( uint index ) const;
-
931
-
933
-
937 helios::vec3 getCellSize( uint index ) const;
-
938
-
940
-
943 float getCellRotation(uint index ) const;
-
944
-
946
- -
950
-
951 // ------- SYNTHETIC SCAN ------ //
-
952
-
954
-
957 void syntheticScan( helios::Context* context );
-
958
-
960
-
966 void syntheticScan( helios::Context* context, bool scan_grid_only, bool record_misses );
-
967
-
969
-
976 void syntheticScan( helios::Context* context, int rays_per_pulse, float pulse_distance_threshold );
-
977
-
979
-
987 void syntheticScan( helios::Context* context, int rays_per_pulse, float pulse_distance_threshold, bool scan_grid_only, bool record_misses );
-
988
-
990
-
993 std::vector<float> calculateSyntheticLeafArea( helios::Context* context );
-
994
-
996
-
999 std::vector<float> calculateSyntheticGtheta( helios::Context* context );
-
1000
-
1001 // -------- LEAF AREA -------- //
-
1002
-
1004
-
1008 void setCellLeafArea( float area, uint index );
-
1009
-
1011
-
1014 float getCellLeafArea( uint index ) const;
-
1015
-
1017
-
1020 float getCellLeafAreaDensity( uint index ) const;
-
1021
-
1023
-
1027 void setCellGtheta( float Gtheta, uint index );
-
1028
-
1030
-
1033 float getCellGtheta( uint index ) const;
-
1034
-
1036
-
1039 std::vector<helios::vec3> gapfillMisses();
-
1040
-
1042
-
1046 std::vector<helios::vec3> gapfillMisses( uint scanID );
-
1047
-
1049
-
1055 std::vector<helios::vec3> gapfillMisses( uint scanID, const bool gapfill_grid_only, const bool add_flags );
-
1056
-
1057
-
1059 void calculateLeafAreaGPU();
-
1060
-
1062
-
1066 void calculateLeafAreaGPU( int min_voxel_hits );
-
1067
-
1069
-
1072 void calculateLeafAreaGPU_testing( int min_voxel_hits );
-
1073
-
1075
-
1081 void calculateLeafAreaGPU_synthetic( helios::Context* context, bool beamoutput, bool fillAnalytic );
-
1082
-
1084
-
1089 void calculateLeafAreaGPU_equal_weighting( bool beamoutput, bool fillAnalytic );
-
1090
-
1092
-
1098 void calculateLeafAreaGPU_equal_weighting( bool beamoutput, bool fillAnalytic, std::vector<float> constant_G );
-
1099
-
1100
-
1101 // -------- RECONSTRUCTION --------- //
-
1102
-
1104
-
1110 void leafReconstructionAlphaMask( float minimum_leaf_group_area, float maximum_leaf_group_area, float leaf_aspect_ratio, const char* mask_file );
-
1111
-
1113
-
1120 void leafReconstructionAlphaMask( float minimum_leaf_group_area, float maximum_leaf_group_area, float leaf_aspect_ratio, float leaf_length_constant, const char* mask_file );
-
1121
-
1123
-
1129 void trunkReconstruction( const helios::vec3 &box_center, const helios::vec3 &box_size, float Lmax, float max_aspect_ratio );
-
1130
-
1132
-
1135 void cropBeamsToGridAngleRange(uint source);
-
1136
-
1138
-
1141 std::vector<uint> peakFinder(std::vector<float> signal);
-
1142
-
1143};
+
902 // -------- GRID ----------- //
+
903
+
905 uint getGridCellCount() const;
+
906
+
908
+
913 void addGridCell( const helios::vec3 &center, const helios::vec3 &size, float rotation );
+
914
+
916
+
925 void addGridCell( const helios::vec3 &center, const helios::vec3 &global_anchor, const helios::vec3 &size, const helios::vec3 &global_size, float rotation, const helios::int3 &global_ijk, const helios::int3 &global_count );
+
926
+
928
+
931 helios::vec3 getCellCenter( uint index ) const;
+
932
+
934
+
937 helios::vec3 getCellGlobalAnchor( uint index ) const;
+
938
+
940
+
944 helios::vec3 getCellSize( uint index ) const;
+
945
+
947
+
950 float getCellRotation(uint index ) const;
+
951
+
953
+ +
957
+
958 // ------- SYNTHETIC SCAN ------ //
+
959
+
961
+
964 void syntheticScan( helios::Context* context );
+
965
+
967
+
973 void syntheticScan( helios::Context* context, bool scan_grid_only, bool record_misses );
+
974
+
976
+
983 void syntheticScan( helios::Context* context, int rays_per_pulse, float pulse_distance_threshold );
+
984
+
986
+
994 void syntheticScan( helios::Context* context, int rays_per_pulse, float pulse_distance_threshold, bool scan_grid_only, bool record_misses );
+
995
+
997
+
1000 std::vector<float> calculateSyntheticLeafArea( helios::Context* context );
+
1001
+
1003
+
1006 std::vector<float> calculateSyntheticGtheta( helios::Context* context );
+
1007
+
1008 // -------- LEAF AREA -------- //
+
1009
+
1011
+
1015 void setCellLeafArea( float area, uint index );
+
1016
+
1018
+
1021 float getCellLeafArea( uint index ) const;
+
1022
+
1024
+
1027 float getCellLeafAreaDensity( uint index ) const;
+
1028
+
1030
+
1034 void setCellGtheta( float Gtheta, uint index );
+
1035
+
1037
+
1040 float getCellGtheta( uint index ) const;
+
1041
+
1043
+
1046 std::vector<helios::vec3> gapfillMisses();
+
1047
+
1049
+
1053 std::vector<helios::vec3> gapfillMisses( uint scanID );
+
1054
+
1056
+
1062 std::vector<helios::vec3> gapfillMisses( uint scanID, const bool gapfill_grid_only, const bool add_flags );
+
1063
+
1064
+
1066 void calculateLeafAreaGPU();
+
1067
+
1069
+
1073 void calculateLeafAreaGPU( int min_voxel_hits );
+
1074
+
1076
+
1079 void calculateLeafAreaGPU_testing( int min_voxel_hits );
+
1080
+
1082
+
1088 void calculateLeafAreaGPU_synthetic( helios::Context* context, bool beamoutput, bool fillAnalytic );
+
1089
+
1091
+
1096 void calculateLeafAreaGPU_equal_weighting( bool beamoutput, bool fillAnalytic );
+
1097
+
1099
+
1105 void calculateLeafAreaGPU_equal_weighting( bool beamoutput, bool fillAnalytic, std::vector<float> constant_G );
+
1106
+
1107
+
1108 // -------- RECONSTRUCTION --------- //
+
1109
+
1111
+
1117 void leafReconstructionAlphaMask( float minimum_leaf_group_area, float maximum_leaf_group_area, float leaf_aspect_ratio, const char* mask_file );
+
1118
+
1120
+
1127 void leafReconstructionAlphaMask( float minimum_leaf_group_area, float maximum_leaf_group_area, float leaf_aspect_ratio, float leaf_length_constant, const char* mask_file );
+
1128
+
1130
+
1136 void trunkReconstruction( const helios::vec3 &box_center, const helios::vec3 &box_size, float Lmax, float max_aspect_ratio );
+
1137
+
1139
+
1142 void cropBeamsToGridAngleRange(uint source);
+
1143
+
1145
+
1148 std::vector<uint> peakFinder(std::vector<float> signal);
+
1149
+
1150};
-
1144
-
1145bool sortcol0( const std::vector<double>& v0, const std::vector<double>& v1 );
-
1146
-
1147bool sortcol1( const std::vector<double>& v0, const std::vector<double>& v1 );
-
1148
-
1149#endif
+
1151
+
1152bool sortcol0( const std::vector<double>& v0, const std::vector<double>& v1 );
+
1153
+
1154bool sortcol1( const std::vector<double>& v0, const std::vector<double>& v1 );
+
1155
+
1156#endif
- -
Primary class for terrestrial LiDAR scan.
Definition LiDAR.h:270
void getGridBoundingBox(helios::vec3 &boxmin, helios::vec3 &boxmax) const
Form an axis-aligned bounding box for all grid cells in the point cloud.
Definition LiDAR.cpp:988
void addTrianglesToVisualizer(Visualizer *visualizer) const
Add all triangles to the visualizer plug-in, and color them by their r-g-b color.
Definition LiDAR.cpp:638
void setHitGridCell(uint index, int cell)
Set the grid cell in which the hit point resides.
Definition LiDAR.cpp:426
@@ -757,7 +765,7 @@
double getHitData(uint index, const char *label) const
Set floating point data value associated with a hit point.
Definition LiDAR.cpp:345
uint getGridCellCount() const
Get the number of cells in the grid.
Definition LiDAR.cpp:1791
void addGridToVisualizer(Visualizer *visualizer) const
Add all grid cells to the visualizer plug-in.
Definition LiDAR.cpp:585
-
void exportPointCloud(const char *filename)
Export to file all points in the point cloud to an ASCII text file following the column format specif...
Definition fileIO.cpp:728
+
void exportPointCloud(const char *filename)
Export to file all points in the point cloud to an ASCII text file following the column format specif...
Definition fileIO.cpp:800
void enableMessages()
Enable all print messages to the screen.
Definition LiDAR.cpp:104
void setCellLeafArea(float area, uint index)
Set the leaf area of a grid cell in m^2.
Definition LiDAR.cpp:1918
int getHitIndex(uint scanID, uint row, uint column) const
Get the index of a scan point based on its row and column in the hit table.
Definition LiDAR.cpp:395
@@ -778,7 +786,7 @@
uint getHitCount() const
Get the number of hit points in the point cloud.
Definition LiDAR.cpp:254
void loadXML(const char *filename)
Read an XML file containing scan information.
Definition fileIO.cpp:22
helios::vec3 getCellCenter(uint index) const
Get the (x,y,z) coordinate of a grid cell by its index.
Definition LiDAR.cpp:1809
-
void exportLeafAreaDensities(const char *filename)
Export to file the leaf area density within each grid cell. Lines of the file correspond to each grid...
Definition fileIO.cpp:688
+
void exportLeafAreaDensities(const char *filename)
Export to file the leaf area density within each grid cell. Lines of the file correspond to each grid...
Definition fileIO.cpp:760
void addHitPoint(uint scanID, const helios::vec3 &xyz, const helios::SphericalCoord &direction)
Specify a scan point as a hit by providing the (x,y,z) coordinates and scan ray direction.
Definition LiDAR.cpp:171
void coordinateShift(const helios::vec3 &shift)
Apply a translation to all points in the point cloud.
Definition LiDAR.cpp:436
void addGrid(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &ndiv, float rotation)
Add a grid to point cloud instead of reading in from an xml file.
Definition LiDAR.cpp:674
@@ -788,7 +796,7 @@
~LiDARcloud()
LiDAR point cloud destructor.
void cropBeamsToGridAngleRange(uint source)
Delete hitpoints that do not pass through / intersect the voxel grid.
Definition LiDAR.cpp:2494
void firstHitFilter()
Filter full-waveform data to include only the first hit per laser pulse. The resulting point cloud wi...
Definition LiDAR.cpp:1296
-
void exportLeafAreas(const char *filename)
Export to file the leaf area within each grid cell. Lines of the file correspond to each grid cell.
Definition fileIO.cpp:668
+
void exportLeafAreas(const char *filename)
Export to file the leaf area within each grid cell. Lines of the file correspond to each grid cell.
Definition fileIO.cpp:740
std::vector< float > calculateSyntheticGtheta(helios::Context *context)
Calculate the G(theta) of all primitives in the context.
Definition LiDAR.cpp:1849
void addLeafReconstructionToVisualizer(Visualizer *visualizer) const
Add reconstructed leaves (triangles or alpha masks) to the visualizer plug-in.
Definition LiDAR.cpp:751
float getScanBeamDivergence(uint scanID) const
Divergence angle of the laser beam in radians.
Definition LiDAR.cpp:300
@@ -811,13 +819,14 @@
void calculateHitGridCellGPU()
Determine the grid cell in which each hit point resides for the whole point cloud - GPU accelerated v...
Definition LiDAR.cu:268
helios::vec2 getScanRangePhi(uint scanID) const
Get the range of scan directions in the phi (azimuthal) direction.
Definition LiDAR.cpp:286
void lastHitFilter()
Filter full-waveform data to include only the last hit per laser pulse. The resulting point cloud wil...
Definition LiDAR.cpp:1336
+
void exportTriangleAzimuthDistribution(const char *filename, uint Nbins)
Export to file discrete azimuthal angle probability distribution based on the triangulation....
Definition fileIO.cpp:671
void leafReconstructionAlphaMask(float minimum_leaf_group_area, float maximum_leaf_group_area, float leaf_aspect_ratio, const char *mask_file)
Perform a leaf reconstruction based on texture-masked Patches within each gridcell....
Definition LiDAR.cpp:2074
float getScanBeamExitDiameter(uint scanID) const
Get the diameter of the laser beam at exit from the instrument.
Definition LiDAR.cpp:293
uint addScan(ScanMetadata &newscan)
Add a LiDAR scan to the point cloud.
Definition LiDAR.cpp:139
std::vector< std::string > getScanColumnFormat(uint scanID) const
Get the labels for columns in ASCII input/output file.
Definition LiDAR.cpp:307
uint getTriangleCount() const
Get the number of triangles formed by the triangulation.
Definition LiDAR.cpp:508
void xyzFilter(float xmin, float xmax, float ymin, float ymax, float zmin, float zmax)
overloaded version of xyzFilter that defaults to deleting points outside the provided bounding box
Definition LiDAR.cpp:1105
-
void exportPointCloudPTX(const char *filename, uint scanID)
Export to file all points from a given scan to PTX file.
Definition fileIO.cpp:843
+
void exportPointCloudPTX(const char *filename, uint scanID)
Export to file all points from a given scan to PTX file.
Definition fileIO.cpp:915
void triangulateHitPoints(float Lmax, float max_aspect_ratio)
Perform triangulation on all hit points in point cloud.
Definition LiDAR.cpp:1382
helios::vec3 getHitXYZ(uint index) const
Get (x,y,z) coordinate of hit point by index.
Definition LiDAR.cpp:314
void calculateLeafAreaGPU_synthetic(helios::Context *context, bool beamoutput, bool fillAnalytic)
Calculate the leaf area for each grid volume in a synthetic scan using several different method for e...
Definition LiDAR.cu:1690
@@ -832,17 +841,17 @@
void addHitPoint(uint scanID, const helios::vec3 &xyz, const helios::SphericalCoord &direction, const std::map< std::string, double > &data)
Specify a scan point as a hit by providing the (x,y,z) coordinates and scan ray direction.
void distanceFilter(float maxdistance)
Filter scan by imposing a maximum distance from the scanner.
Definition LiDAR.cpp:1035
void disableMessages()
Disable all print messages to the screen except for fatal error messages.
Definition LiDAR.cpp:100
-
void exportGtheta(const char *filename)
Export to file the G(theta) value within each grid cell. Lines of the file correspond to each grid ce...
Definition fileIO.cpp:708
+
void exportGtheta(const char *filename)
Export to file the G(theta) value within each grid cell. Lines of the file correspond to each grid ce...
Definition fileIO.cpp:780
void addGridWireFrametoVisualizer(Visualizer *visualizer) const
Add wire frame of the grid to the visualizer plug-in.
Definition LiDAR.cpp:716
void calculateLeafAreaGPU()
Calculate the leaf area for each grid volume.
Definition LiDAR.cu:897
Class for visualization of simulation results.
Definition Visualizer.h:275
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
int2 make_int2(int x, int y)
Make an int2 vector from two ints.
- - +
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
+
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
Structure containing metadata for a terrestrial scan.
Definition LiDAR.h:188
float phiMin
Minimum azimuthal angle of scan in radians.
Definition LiDAR.h:227
-
float thetaMin
Minimum zenithal angle of scan in radians
Definition LiDAR.h:214
+
float thetaMin
Minimum zenithal angle of scan in radians.
Definition LiDAR.h:214
helios::vec3 origin
(x,y,z) coordinate of scanner location
Definition LiDAR.h:235
float thetaMax
Maximum zenithal angle of scan in radians.
Definition LiDAR.h:219
float phiMax
Maximum azimuthal angle of scan in radians.
Definition LiDAR.h:232
@@ -859,16 +868,19 @@
R-G-B color vector.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of two elements of type 'int'.
-
Vector of three elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
float magnitude() const
Compute the vector magnitude.
- -
+ + diff --git a/doc/html/_li_d_a_r_doc.html b/doc/html/_li_d_a_r_doc.html index 928fae3f8..e388df16a 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
LiDAR Point Cloud Plugin Documentation
@@ -486,7 +492,7 @@

}
void leafReconstructionAlphaMask(float minimum_leaf_group_area, float maximum_leaf_group_area, float leaf_aspect_ratio, const char *mask_file)
Perform a leaf reconstruction based on texture-masked Patches within each gridcell....
Definition LiDAR.cpp:2074
std::vector< uint > addLeafReconstructionToContext(helios::Context *context) const
Add reconstructed leaves (texture-masked patches) to the Context.
Definition LiDAR.cpp:845
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888

Generating Synthetic (Simulated) LiDAR Data

The LiDAR plug-in can simulate the measurements of discrete-return and full-waveform instruments based on the geometry in the Context. Ray-tracing is used to simulate the emission of radiation from the instrument, and based on ray-object intersection tests with primitive geometry in the model domain, the simulated hit points can be determined. Currently, only a rectangular scan pattern is supported.

@@ -533,7 +539,7 @@

pointcloud.exportPointCloud( "/path/to/file.xyz" ); //write to ASCII file
}
-
void exportPointCloud(const char *filename)
Export to file all points in the point cloud to an ASCII text file following the column format specif...
Definition fileIO.cpp:728
+
void exportPointCloud(const char *filename)
Export to file all points in the point cloud to an ASCII text file following the column format specif...
Definition fileIO.cpp:800
void syntheticScan(helios::Context *context)
Run a discrete return synthetic LiDAR scan based on scan parameters given in an XML file (returns onl...
Definition LiDAR.cu:3093
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212

@@ -671,15 +677,18 @@

}
uint getGridCellCount() const
Get the number of cells in the grid.
Definition LiDAR.cpp:1791
void exportTriangleAreas(const char *filename)
Export to file the area of all triangles formed.
Definition fileIO.cpp:562
-
void exportLeafAreaDensities(const char *filename)
Export to file the leaf area density within each grid cell. Lines of the file correspond to each grid...
Definition fileIO.cpp:688
-
void exportLeafAreas(const char *filename)
Export to file the leaf area within each grid cell. Lines of the file correspond to each grid cell.
Definition fileIO.cpp:668
+
void exportLeafAreaDensities(const char *filename)
Export to file the leaf area density within each grid cell. Lines of the file correspond to each grid...
Definition fileIO.cpp:760
+
void exportLeafAreas(const char *filename)
Export to file the leaf area within each grid cell. Lines of the file correspond to each grid cell.
Definition fileIO.cpp:740
void exportTriangleNormals(const char *filename)
Export to file the normal vectors (nx,ny,nz) for all triangles formed.
Definition fileIO.cpp:499

- - + + diff --git a/doc/html/_making_masks.html b/doc/html/_making_masks.html index c24fe9906..a5490f46d 100644 --- a/doc/html/_making_masks.html +++ b/doc/html/_making_masks.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Making texture mask files with transparency using GIMP
@@ -131,10 +141,12 @@

I have found the "Scissors Select Tool" in the toolbox to be useful in tracing around the edges of objects when the background does not have a constant color.

- - + + diff --git a/doc/html/_overview.html b/doc/html/_overview.html index 3b5028ee6..4ebf16213 100644 --- a/doc/html/_overview.html +++ b/doc/html/_overview.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Overview
@@ -164,10 +174,12 @@

To continue from here, you may prefer to learn by example using the Tutorials. More detailed explanations of Helios features can be found throughout the User's Guide.

- - + + diff --git a/doc/html/_p_c_g_p_u_timeout.html b/doc/html/_p_c_g_p_u_timeout.html index dcd2df5e2..c74e1edaa 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Increasing graphics driver timeout
@@ -114,10 +124,12 @@
- - + + diff --git a/doc/html/_photosynthesis_doc.html b/doc/html/_photosynthesis_doc.html index 4503c4ccf..e0cb28480 100644 --- a/doc/html/_photosynthesis_doc.html +++ b/doc/html/_photosynthesis_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Photosynthesis Model Plugin Documentation
@@ -308,12 +314,11 @@

Temperature response of model parameters

Two different temperature response functions are commonly used in photosynthetic modeling and supported in the Photosynthesis Plugin. One is an Arrhenius equation, which is exponentially increasing with no decline in the region of use. The other is a modified Arrhenius equation with a peak or temperature optimum, beyond which there is a decline in the value of the function, representing a denaturing of an enzyme and subsequent reduction of its activity.

-\[
- \begin{aligned}
+<img class= +\]" src="form_111.png" width="398" height="81"/>

In this form, the model is conveniently parameterized by the commonly used standard reference rate at 25 $^\circ$C, $k_{25}$, as well as the energy of activation, $A = \Delta H_a = dH_a$ of the Arrhenius equation, but also by the observable temperature optimum, $T_{opt}$ and one additional fitted parameter, the energy of deactivation, $D = \Delta H _d = dH_d$, related to the rate of decline from the optimum.

As $T_{opt}$ $\to \infty$, then the peaked form approaches the standard, unpeaked Arrhenius equation, allowing for mathematical backwards compatibility for parameters obtained from fitting to the standard unpeaked form.

@@ -336,14 +341,13 @@

Additional temperature parameters that are not typically fit to use the standard Arrhenius form with the parameters obtained by Bernacchi et al. (2001), and are given by the following equations

-\[
- \begin{aligned}
+<img class= +\]" src="form_124.png" width="266" height="165"/>

Summary of FvCB Model Independent Variables

@@ -526,10 +530,13 @@

- - + + diff --git a/doc/html/_photosynthesis_model_8cpp.html b/doc/html/_photosynthesis_model_8cpp.html index 1de01f528..902f6767b 100644 --- a/doc/html/_photosynthesis_model_8cpp.html +++ b/doc/html/_photosynthesis_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
PhotosynthesisModel.cpp File Reference
@@ -116,10 +122,13 @@

Definition in file PhotosynthesisModel.cpp.

- - + + diff --git a/doc/html/_photosynthesis_model_8cpp_source.html b/doc/html/_photosynthesis_model_8cpp_source.html index 296462e45..36b4b43c2 100644 --- a/doc/html/_photosynthesis_model_8cpp_source.html +++ b/doc/html/_photosynthesis_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
PhotosynthesisModel.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include <complex>
17#include "PhotosynthesisModel.h"
18
@@ -134,13 +141,13 @@
40 std::cout << "Running photosynthesis model self-test..." << std::flush;
41 }
42
-
43 Context context_test;
+
43 Context context_test;
44
45 float errtol = 0.001f;
46
47 uint UUID = context_test.addPatch(make_vec3(0, 0, 0), make_vec2(1, 1));
48
-
49 PhotosynthesisModel photomodel(&context_test);
+
49 PhotosynthesisModel photomodel(&context_test);
50
51 std::vector<float> A;
52
@@ -157,7 +164,7 @@
63
64//Generate a light response curve using Farquhar model
65
-
66 FarquharModelCoefficients fcoeffs; //these are prior default model parameters, which is what was used for this test
+
66 FarquharModelCoefficients fcoeffs; //these are prior default model parameters, which is what was used for this test
67
68 fcoeffs.setVcmax(78.5);
69 fcoeffs.setJmax(150, 43.54);
@@ -460,7 +467,7 @@
346
-
348 run(context->getAllUUIDs());
+
348 run(context->getAllUUIDs());
349}
350
@@ -470,9 +477,9 @@
353 for (uint UUID: lUUIDs) {
354
355 float i_PAR;
-
356 if (context->doesPrimitiveDataExist(UUID, "radiation_flux_PAR") &&
-
357 context->getPrimitiveDataType(UUID, "radiation_flux_PAR") == HELIOS_TYPE_FLOAT) {
-
358 context->getPrimitiveData(UUID, "radiation_flux_PAR", i_PAR);
+
356 if (context->doesPrimitiveDataExist(UUID, "radiation_flux_PAR") &&
+
357 context->getPrimitiveDataType(UUID, "radiation_flux_PAR") == HELIOS_TYPE_FLOAT) {
+
358 context->getPrimitiveData(UUID, "radiation_flux_PAR", i_PAR);
359 i_PAR = i_PAR *
360 4.57f; //umol/m^2-s (ref https://www.controlledenvironments.org/wp-content/uploads/sites/6/2017/06/Ch01.pdf)
361 if (i_PAR < 0) {
@@ -486,9 +493,9 @@
369 }
370
371 float TL;
-
372 if (context->doesPrimitiveDataExist(UUID, "temperature") &&
-
373 context->getPrimitiveDataType(UUID, "temperature") == HELIOS_TYPE_FLOAT) {
-
374 context->getPrimitiveData(UUID, "temperature", TL);
+
372 if (context->doesPrimitiveDataExist(UUID, "temperature") &&
+
373 context->getPrimitiveDataType(UUID, "temperature") == HELIOS_TYPE_FLOAT) {
+
374 context->getPrimitiveData(UUID, "temperature", TL);
375 if (TL < 200) {
376 if( message_flag ) {
377 std::cout << "WARNING (PhotosynthesisModel::run): Primitive temperature value was very low (" << TL << "K). Assuming. Are you using absolute temperature units?" << std::endl;
@@ -500,9 +507,9 @@
383 }
384
385 float CO2;
-
386 if (context->doesPrimitiveDataExist(UUID, "air_CO2") &&
-
387 context->getPrimitiveDataType(UUID, "air_CO2") == HELIOS_TYPE_FLOAT) {
-
388 context->getPrimitiveData(UUID, "air_CO2", CO2);
+
386 if (context->doesPrimitiveDataExist(UUID, "air_CO2") &&
+
387 context->getPrimitiveDataType(UUID, "air_CO2") == HELIOS_TYPE_FLOAT) {
+
388 context->getPrimitiveData(UUID, "air_CO2", CO2);
389 if (CO2 < 0) {
390 CO2 = 0;
391 if( message_flag ) {
@@ -514,9 +521,9 @@
397 }
398
399 float gM;
-
400 if (context->doesPrimitiveDataExist(UUID, "moisture_conductance") &&
-
401 context->getPrimitiveDataType(UUID, "moisture_conductance") == HELIOS_TYPE_FLOAT) {
-
402 context->getPrimitiveData(UUID, "moisture_conductance", gM);
+
400 if (context->doesPrimitiveDataExist(UUID, "moisture_conductance") &&
+
401 context->getPrimitiveDataType(UUID, "moisture_conductance") == HELIOS_TYPE_FLOAT) {
+
402 context->getPrimitiveData(UUID, "moisture_conductance", gM);
403 if (gM < 0) {
404 gM = 0;
405 if( message_flag ) {
@@ -529,26 +536,26 @@
412
413 //Number of sides
414 uint Nsides = 2; //default is 2
-
415 if( context->doesPrimitiveDataExist(UUID,"twosided_flag") && context->getPrimitiveDataType(UUID,"twosided_flag")==HELIOS_TYPE_UINT ){
+
415 if( context->doesPrimitiveDataExist(UUID,"twosided_flag") && context->getPrimitiveDataType(UUID,"twosided_flag")==HELIOS_TYPE_UINT ){
416 uint flag;
-
417 context->getPrimitiveData(UUID,"twosided_flag",flag);
+
417 context->getPrimitiveData(UUID,"twosided_flag",flag);
418 if( flag==0 ){
419 Nsides=1;
420 }
421 }
422
423 float stomatal_sidedness = 0.f; //default all stomata on one side (hypostomatous)
-
424 if( Nsides==2 && context->doesPrimitiveDataExist(UUID,"stomatal_sidedness") && context->getPrimitiveDataType(UUID,"stomatal_sidedness")==HELIOS_TYPE_FLOAT ){
-
425 context->getPrimitiveData(UUID,"stomatal_sidedness",stomatal_sidedness);
+
424 if( Nsides==2 && context->doesPrimitiveDataExist(UUID,"stomatal_sidedness") && context->getPrimitiveDataType(UUID,"stomatal_sidedness")==HELIOS_TYPE_FLOAT ){
+
425 context->getPrimitiveData(UUID,"stomatal_sidedness",stomatal_sidedness);
426 }
427
428 float gH;
-
429 if (context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance") &&
-
430 context->getPrimitiveDataType(UUID, "boundarylayer_conductance") == HELIOS_TYPE_FLOAT) {
-
431 context->getPrimitiveData(UUID, "boundarylayer_conductance", gH);
-
432 } else if (context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance_out") &&
-
433 context->getPrimitiveDataType(UUID, "boundarylayer_conductance_out") == HELIOS_TYPE_FLOAT) {
-
434 context->getPrimitiveData(UUID, "boundarylayer_conductance_out", gH);
+
429 if (context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance") &&
+
430 context->getPrimitiveDataType(UUID, "boundarylayer_conductance") == HELIOS_TYPE_FLOAT) {
+
431 context->getPrimitiveData(UUID, "boundarylayer_conductance", gH);
+
432 } else if (context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance_out") &&
+
433 context->getPrimitiveDataType(UUID, "boundarylayer_conductance_out") == HELIOS_TYPE_FLOAT) {
+
434 context->getPrimitiveData(UUID, "boundarylayer_conductance_out", gH);
435 } else {
436 gH = gH_default;
437 }
@@ -600,15 +607,15 @@
483 }
484 }
485
-
486 context->setPrimitiveData(UUID, "net_photosynthesis", HELIOS_TYPE_FLOAT, 1, &A);
+
486 context->setPrimitiveData(UUID, "net_photosynthesis", HELIOS_TYPE_FLOAT, 1, &A);
487
488 for (const auto &data: output_prim_data) {
489 if (data == "Ci" && model == "farquhar") {
-
490 context->setPrimitiveData(UUID, "Ci", Ci);
+
490 context->setPrimitiveData(UUID, "Ci", Ci);
491 } else if (data == "limitation_state" && model == "farquhar") {
-
492 context->setPrimitiveData(UUID, "limitation_state", limitation_state);
+
492 context->setPrimitiveData(UUID, "limitation_state", limitation_state);
493 } else if (data == "Gamma_CO2" && model == "farquhar") {
-
494 context->setPrimitiveData(UUID, "Gamma_CO2", Gamma);
+
494 context->setPrimitiveData(UUID, "Gamma_CO2", Gamma);
495 }
496 }
497
@@ -702,7 +709,7 @@
584
585float PhotosynthesisModel::evaluateCi_Farquhar(float Ci, std::vector<float> &variables, const void *parameters) {
586
-
587 const FarquharModelCoefficients modelcoeffs = *reinterpret_cast<const FarquharModelCoefficients *>(parameters);
+
587 const FarquharModelCoefficients modelcoeffs = *reinterpret_cast<const FarquharModelCoefficients *>(parameters);
588
589 float Vcmax, Jmax, TPU, Rd, alpha, theta;
590
@@ -900,7 +907,7 @@
772
- +
774 printDefaultValueReport(context->getAllUUIDs());
775}
776
@@ -917,34 +924,34 @@
786
787 for (uint UUID: UUIDs) {
788
-
789 if (!context->doesPrimitiveDataExist(UUID, "radiation_flux_PAR") ||
-
790 context->getPrimitiveDataType(UUID, "radiation_flux_PAR") != HELIOS_TYPE_FLOAT) {
+
789 if (!context->doesPrimitiveDataExist(UUID, "radiation_flux_PAR") ||
+
790 context->getPrimitiveDataType(UUID, "radiation_flux_PAR") != HELIOS_TYPE_FLOAT) {
791 assumed_default_i++;
792 }
793
794 //surface temperature (K)
-
795 if (!context->doesPrimitiveDataExist(UUID, "temperature") ||
-
796 context->getPrimitiveDataType(UUID, "temperature") != HELIOS_TYPE_FLOAT) {
+
795 if (!context->doesPrimitiveDataExist(UUID, "temperature") ||
+
796 context->getPrimitiveDataType(UUID, "temperature") != HELIOS_TYPE_FLOAT) {
797 assumed_default_TL++;
798 }
799
800 //boundary-layer conductance to heat
-
801 if ((!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance") ||
-
802 context->getPrimitiveDataType(UUID, "boundarylayer_conductance") != HELIOS_TYPE_FLOAT) &&
-
803 (!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance_out") ||
-
804 context->getPrimitiveDataType(UUID, "boundarylayer_conductance_out") != HELIOS_TYPE_FLOAT)) {
+
801 if ((!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance") ||
+
802 context->getPrimitiveDataType(UUID, "boundarylayer_conductance") != HELIOS_TYPE_FLOAT) &&
+
803 (!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance_out") ||
+
804 context->getPrimitiveDataType(UUID, "boundarylayer_conductance_out") != HELIOS_TYPE_FLOAT)) {
805 assumed_default_gH++;
806 }
807
808 //stomatal conductance
-
809 if (!context->doesPrimitiveDataExist(UUID, "moisture_conductance") ||
-
810 context->getPrimitiveDataType(UUID, "moisture_conductance") != HELIOS_TYPE_FLOAT) {
+
809 if (!context->doesPrimitiveDataExist(UUID, "moisture_conductance") ||
+
810 context->getPrimitiveDataType(UUID, "moisture_conductance") != HELIOS_TYPE_FLOAT) {
811 assumed_default_gM++;
812 }
813
814 //ambient air CO2
-
815 if (!context->doesPrimitiveDataExist(UUID, "air_CO2") ||
-
816 context->getPrimitiveDataType(UUID, "air_CO2") != HELIOS_TYPE_FLOAT) {
+
815 if (!context->doesPrimitiveDataExist(UUID, "air_CO2") ||
+
816 context->getPrimitiveDataType(UUID, "air_CO2") != HELIOS_TYPE_FLOAT) {
817 assumed_default_CO2++;
818 }
819
@@ -971,7 +978,6 @@
@ HELIOS_TYPE_UINT
unsigned integer data type
Definition Context.h:45
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
-
PhotosynthesisModel(helios::Context *a_context)
Default constructor.
void setFarquharCoefficientsFromLibrary(const std::string &species)
Set the Farquhar-von Caemmerer-Berry model coefficients for all primitives based on a species from th...
void disableMessages()
Disable output messages to the standard output.
@@ -985,11 +991,8 @@
FarquharModelCoefficients getFarquharCoefficientsFromLibrary(const std::string &species)
Get Farquhar-von Caemmerer-Berry model coefficients for a species from the library.
void setModelType_Empirical()
Sets photosynthesis to be calculated according to the empirical model.
FarquharModelCoefficients getFarquharModelCoefficients(uint UUID)
Get the current model coefficients for the Farquhar-von Caemmerer-Berry model.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
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 > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
float fzero(float(*function)(float value, std::vector< float > &variables, const void *parameters), std::vector< float > &variables, const void *parameters, float init_guess, float err_tol=0.0001f, int max_iterations=100)
Use Newton-Raphson method to find the zero of a function.
Definition global.cpp:2977
anytype clamp(anytype value, anytype min, anytype max)
Clamp value to be within some specified bounds.
Definition global.cpp:1055
@@ -1000,10 +1003,13 @@
- -
+ + diff --git a/doc/html/_photosynthesis_model_8h.html b/doc/html/_photosynthesis_model_8h.html index b1e3bb70f..916816bae 100644 --- a/doc/html/_photosynthesis_model_8h.html +++ b/doc/html/_photosynthesis_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -129,10 +135,13 @@

Definition in file PhotosynthesisModel.h.

- - + + diff --git a/doc/html/_photosynthesis_model_8h.js b/doc/html/_photosynthesis_model_8h.js new file mode 100644 index 000000000..65b5c7853 --- /dev/null +++ b/doc/html/_photosynthesis_model_8h.js @@ -0,0 +1,7 @@ +var _photosynthesis_model_8h = +[ + [ "PhotosyntheticTemperatureResponseParameters", "struct_photosynthetic_temperature_response_parameters.html", null ], + [ "EmpiricalModelCoefficients", "struct_empirical_model_coefficients.html", null ], + [ "FarquharModelCoefficients", "struct_farquhar_model_coefficients.html", null ], + [ "PhotosynthesisModel", "class_photosynthesis_model.html", "class_photosynthesis_model" ] +]; \ No newline at end of file diff --git a/doc/html/_photosynthesis_model_8h_source.html b/doc/html/_photosynthesis_model_8h_source.html index 94f1cc648..6630cdfd6 100644 --- a/doc/html/_photosynthesis_model_8h_source.html +++ b/doc/html/_photosynthesis_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
PhotosynthesisModel.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef PHOTOSYNTHESIS_MODEL
17#define PHOTOSYNTHESIS_MODEL
18
19#include "Context.h"
20
- - +
21struct PhotosyntheticTemperatureResponseParameters {
+
22 PhotosyntheticTemperatureResponseParameters() {
23 value_at_25C = 100.0f;
24 dHa = 2.0f;
25 dHd = 2.0f;
26 Topt = 273.15f + 38.f;
27 }
28
- +
29 PhotosyntheticTemperatureResponseParameters(float value_at_25C) {
30 this->value_at_25C = value_at_25C;
31 this->dHa = 60.f;
32 this->dHd = 1000.f;
33 this->Topt = 10000.f;
34 }
35
-
36 PhotosyntheticTemperatureResponseParameters(float value_at_25C, float rate_of_increase_dHa) {
+
36 PhotosyntheticTemperatureResponseParameters(float value_at_25C, float rate_of_increase_dHa) {
37 this->value_at_25C = value_at_25C;
38 this->dHa = rate_of_increase_dHa;
39 if (rate_of_increase_dHa > 0.f) {
@@ -137,7 +144,7 @@
44 this->Topt = 10000.f;
45 }
46
-
47 PhotosyntheticTemperatureResponseParameters(float value_at_25C, float rate_of_increase_dHa,
+
47 PhotosyntheticTemperatureResponseParameters(float value_at_25C, float rate_of_increase_dHa,
48 float optimum_temperature_in_C) {
49 this->value_at_25C = value_at_25C;
50 this->dHa = rate_of_increase_dHa;
@@ -149,7 +156,7 @@
56 this->Topt = 273.15f + optimum_temperature_in_C;
57 }
58
-
59 PhotosyntheticTemperatureResponseParameters(float value_at_25C, float rate_of_increase_dHa,
+
59 PhotosyntheticTemperatureResponseParameters(float value_at_25C, float rate_of_increase_dHa,
60 float optimum_temperature_in_C, float rate_of_decrease_dHd) {
61 this->value_at_25C = value_at_25C;
62 this->dHa = rate_of_increase_dHa;
@@ -167,9 +174,9 @@
73
74
- +
75struct EmpiricalModelCoefficients {
76
- +
77 EmpiricalModelCoefficients() {
78 Tref = 298; //K
79 Ci_ref = 290; //umol CO2/mol air
80 Asat = 18.18; //umol/m^2-s
@@ -206,9 +213,9 @@
111
- +
112struct FarquharModelCoefficients {
113public:
- +
114 FarquharModelCoefficients() {
115
116 //parameters (at TL = 25C)
117 Vcmax = -1.f; //umol/m^2/s
@@ -337,74 +344,74 @@
241
242
-
243 friend class PhotosynthesisModel;
+
243 friend class PhotosynthesisModel;
244};
245
246
- +
248public:
-
249
-
251
+
249
+
251
254 explicit PhotosynthesisModel(helios::Context *a_context);
255
256 int selfTest();
-
257
+
257
-
260
+
260
-
263
-
265
+
263
+
265
269 void setModelCoefficients(const EmpiricalModelCoefficients &modelcoefficients);
-
270
-
272
+
270
+
272
277 void setModelCoefficients(const EmpiricalModelCoefficients &modelcoefficients, const std::vector<uint> &UUIDs);
-
278
-
280
+
278
+
280
284 void setModelCoefficients(const FarquharModelCoefficients &modelcoefficients);
-
285
-
287
+
285
+
287
292 void setModelCoefficients(const FarquharModelCoefficients &modelcoefficients, const std::vector<uint> &UUIDs);
-
293
-
295
+
293
+
295
300 void setModelCoefficients(const std::vector<FarquharModelCoefficients> &modelcoefficients, const std::vector<uint> &UUIDs);
-
301
-
303
+
301
+
303
306 void setFarquharCoefficientsFromLibrary(const std::string &species);
-
307
-
309
+
307
+
309
313 void setFarquharCoefficientsFromLibrary(const std::string &species, const std::vector<uint> &UUIDs);
-
314
-
316
+
314
+
316
321
-
322
+
322
324 void run();
-
325
-
327
+
325
+
327
330 void run(const std::vector<uint> &lUUIDs);
-
331
-
333
+
331
+
333
-
338
-
340
+
338
+
340
-
345
+
345
347 void disableMessages();
-
348
+
348
350 void enableMessages();
-
351
-
353
+
351
+
353
356 void optionalOutputPrimitiveData(const char *label);
-
357
+
357
359 void printDefaultValueReport() const;
-
360
-
362
+
360
+
362
365 void printDefaultValueReport(const std::vector<uint> &UUIDs) const;
366
367private:
-
368
+
368
370 helios::Context *context;
371
372 std::string model;
@@ -434,7 +441,7 @@
396 float gH_default;
397
398 bool message_flag = true;
-
399
+
399
401 std::vector<std::string> output_prim_data;
402
403};
@@ -442,7 +449,6 @@
404
405#endif
-
PhotosynthesisModel(helios::Context *a_context)
Default constructor.
void setFarquharCoefficientsFromLibrary(const std::string &species)
Set the Farquhar-von Caemmerer-Berry model coefficients for all primitives based on a species from th...
void disableMessages()
Disable output messages to the standard output.
@@ -456,15 +462,18 @@
FarquharModelCoefficients getFarquharCoefficientsFromLibrary(const std::string &species)
Get Farquhar-von Caemmerer-Berry model coefficients for a species from the library.
void setModelType_Empirical()
Sets photosynthesis to be calculated according to the empirical model.
FarquharModelCoefficients getFarquharModelCoefficients(uint UUID)
Get the current model coefficients for the Farquhar-von Caemmerer-Berry model.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
- -
+ + diff --git a/doc/html/_plant_architecture_8cpp.html b/doc/html/_plant_architecture_8cpp.html index 7d5cdf51b..22757e6fa 100644 --- a/doc/html/_plant_architecture_8cpp.html +++ b/doc/html/_plant_architecture_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -228,15 +234,18 @@

-

Definition at line 3098 of file PlantArchitecture.cpp.

+

Definition at line 3342 of file PlantArchitecture.cpp.

- -
+ + diff --git a/doc/html/_plant_architecture_8cpp.js b/doc/html/_plant_architecture_8cpp.js new file mode 100644 index 000000000..ebb3b518c --- /dev/null +++ b/doc/html/_plant_architecture_8cpp.js @@ -0,0 +1,5 @@ +var _plant_architecture_8cpp = +[ + [ "interpolateTube", "_plant_architecture_8cpp.html#a3d09d2e054283f9202ad662a2c131018", null ], + [ "interpolateTube", "_plant_architecture_8cpp.html#a2d10c56b3c11e46ebfd346ce37f38612", null ] +]; \ No newline at end of file diff --git a/doc/html/_plant_architecture_8cpp_source.html b/doc/html/_plant_architecture_8cpp_source.html index e00aec560..9bbadd88c 100644 --- a/doc/html/_plant_architecture_8cpp_source.html +++ b/doc/html/_plant_architecture_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
PlantArchitecture.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "PlantArchitecture.h"
17
18#include <utility>
@@ -174,7 +181,7 @@
78
79PlantArchitecture::PlantArchitecture(helios::Context *context_ptr) : context_ptr(context_ptr) {
-
80 generator = context_ptr->getRandomGenerator();
+
80 generator = context_ptr->getRandomGenerator();
81
82 output_object_data["age"] = false;
83 output_object_data["rank"] = false;
@@ -213,7 +220,7 @@
114
117
@@ -271,7 +278,7 @@
168
171
@@ -300,7 +307,7 @@
193
194 phyllochron_min.initialize(2, generator);
195
-
196 elongation_rate.initialize(0.2, generator);
+
196 elongation_rate_max.initialize(0.2, generator);
197 girth_area_factor.initialize(0, generator);
198
199 vegetative_bud_break_time.initialize(5, generator);
@@ -344,7 +351,7 @@
235 plantIDs.reserve(plant_count_xy.x*plant_count_xy.y);
236 for( int j=0; j<plant_count_xy.y; j++ ){
237 for( int i=0; i<plant_count_xy.x; i++ ){
-
238 if( context_ptr->randu()<germination_rate ) {
+
238 if( context_ptr->randu()<germination_rate ) {
239 plantIDs.push_back( buildPlantInstanceFromLibrary(canopy_center_position + make_vec3(-0.5f * canopy_extent.x + float(i) * plant_spacing_xy.x, -0.5f * canopy_extent.y + float(j) * plant_spacing_xy.y, 0), age) );
240 }
241 }
@@ -375,9 +382,9 @@
263}
264
265std::vector<float> Phytomer::getInternodeNodeRadii() const {
-
266 std::vector<float> node_radii = parent_shoot_ptr->shoot_internode_radii.at(shoot_index.x);
-
267 if (shoot_index.x > 0) {
-
268 int p_minus = shoot_index.x - 1;
+
266 std::vector<float> node_radii = parent_shoot_ptr->shoot_internode_radii.at(shoot_index.x);
+
267 if (shoot_index.x > 0) {
+
268 int p_minus = shoot_index.x - 1;
269 int s_minus = parent_shoot_ptr->shoot_internode_radii.at(p_minus).size() - 1;
270 node_radii.insert(node_radii.begin(), parent_shoot_ptr->shoot_internode_radii.at(p_minus).at(s_minus));
271 }
@@ -408,17 +415,17 @@
296 frac_plus = stem_fraction;
297 }
298
-
299 vec3 node_minus = interpolateTube(axis_vertices, frac_minus);
-
300 vec3 node_plus = interpolateTube(axis_vertices, frac_plus);
+
299 vec3 node_minus = interpolateTube(axis_vertices, frac_minus);
+
300 vec3 node_plus = interpolateTube(axis_vertices, frac_plus);
301
-
302 vec3 norm = node_plus - node_minus;
+
302 vec3 norm = node_plus - node_minus;
303 norm.normalize();
304
305 return norm;
306}
307
308float Phytomer::getInternodeRadius() const {
-
309 return parent_shoot_ptr->shoot_internode_radii.at(shoot_index.x).front();
+
309 return parent_shoot_ptr->shoot_internode_radii.at(shoot_index.x).front();
310}
311
312float Phytomer::getInternodeLength() const {
@@ -436,7 +443,7 @@
324}
325
326float Phytomer::getInternodeRadius(float stem_fraction) const {
-
327 return interpolateTube(parent_shoot_ptr->shoot_internode_radii.at(shoot_index.x), stem_fraction);
+
327 return interpolateTube(parent_shoot_ptr->shoot_internode_radii.at(shoot_index.x), stem_fraction);
328}
329
330float Phytomer::getLeafArea() const {
@@ -444,8 +451,8 @@
332 float leaf_area = 0;
333 for (auto &petiole: leaf_objIDs ) {
334 for ( auto& objID : petiole ) {
-
335 if ( context_ptr->doesObjectExist(objID) ) {
-
336 leaf_area += context_ptr->getObjectArea(objID)/current_leaf_scale_factor/current_leaf_scale_factor;
+
335 if ( context_ptr->doesObjectExist(objID) ) {
+
336 leaf_area += context_ptr->getObjectArea(objID)/current_leaf_scale_factor/current_leaf_scale_factor;
337 }
338 }
339 }
@@ -506,2933 +513,3168 @@
394 }
395
396 // Calculate carbon cost
-
397 if( state == BUD_FLOWER_CLOSED || (fbud.state == BUD_ACTIVE && state == BUD_FLOWER_OPEN ) ){ //state went from active to closed flower or open flower
-
398 float flower_cost = calculateFlowerConstructionCosts(fbud);
-
399 plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(this->parent_shoot_ID)->carbohydrate_pool_molC -= flower_cost;
-
400 }else if( state == BUD_FRUITING ){ //adding a fruit
-
401 float fruit_cost = calculateFruitConstructionCosts(fbud);
-
402 plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(this->parent_shoot_ID)->carbohydrate_pool_molC -= fruit_cost;
-
403 }
-
404
-
405 // Delete geometry from previous reproductive state (if present)
-
406 context_ptr->deleteObject(fbud.inflorescence_objIDs);
-
407 fbud.inflorescence_objIDs.resize(0);
-
408 fbud.inflorescence_bases.resize(0);
-
409
-
410 if (plantarchitecture_ptr->build_context_geometry_peduncle) {
-
411 context_ptr->deleteObject(fbud.peduncle_objIDs);
-
412 fbud.peduncle_objIDs.resize(0);
-
413 }
-
414
-
415 fbud.state = state;
+
397 if( plantarchitecture_ptr->carbon_model_enabled ){
+
398 if( state == BUD_FLOWER_CLOSED || (fbud.state == BUD_ACTIVE && state == BUD_FLOWER_OPEN ) ){ //state went from active to closed flower or open flower
+
399 float flower_cost = calculateFlowerConstructionCosts(fbud);
+
400 plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(this->parent_shoot_ID)->carbohydrate_pool_molC -= flower_cost;
+
401 }else if( state == BUD_FRUITING ){ //adding a fruit
+
402 float fruit_cost = calculateFruitConstructionCosts(fbud);
+
403 plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(this->parent_shoot_ID)->carbohydrate_pool_molC -= fruit_cost;
+
404 }
+
405 }
+
406
+
407 // Delete geometry from previous reproductive state (if present)
+
408 context_ptr->deleteObject(fbud.inflorescence_objIDs);
+
409 fbud.inflorescence_objIDs.resize(0);
+
410 fbud.inflorescence_bases.resize(0);
+
411
+
412 if (plantarchitecture_ptr->build_context_geometry_peduncle) {
+
413 context_ptr->deleteObject(fbud.peduncle_objIDs);
+
414 fbud.peduncle_objIDs.resize(0);
+
415 }
416
-
417 if(state != BUD_DEAD ) { //add new reproductive organs
+
417 fbud.state = state;
418
-
419 updateInflorescence(fbud);
-
420 fbud.time_counter = 0;
-
421 if (fbud.state == BUD_FRUITING) {
-
422 setInflorescenceScaleFraction(fbud, 0.25);
-
423 }
-
424 }
-
425}
-
426
-
-
427int Shoot::appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const PhytomerParameters &phytomer_parameters) {
+
419 if(state != BUD_DEAD ) { //add new reproductive organs
+
420
+
421 updateInflorescence(fbud);
+
422 fbud.time_counter = 0;
+
423 if (fbud.state == BUD_FRUITING) {
+
424 setInflorescenceScaleFraction(fbud, 0.25);
+
425 }
+
426 }
+
427}
428
-
429 auto shoot_tree_ptr = &plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree;
+
+
429int Shoot::appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const PhytomerParameters &phytomer_parameters) {
430
-
431 //Determine the parent internode and petiole axes for rotation of the new phytomer
-
432 vec3 parent_internode_axis;
-
433 vec3 parent_petiole_axis;
-
434 vec3 internode_base_position;
-
435 if( phytomers.empty() ) { //very first phytomer on shoot
-
436 if(parent_shoot_ID == -1 ) { //very first shoot of the plant
-
437 parent_internode_axis = make_vec3(0, 0, 1);
-
438 parent_petiole_axis = make_vec3(0, -1, 0);
-
439 }else{ //first phytomer of a new shoot
-
440 assert(parent_shoot_ID < shoot_tree_ptr->size() && parent_node_index < shoot_tree_ptr->at(parent_shoot_ID)->phytomers.size() );
-
441 parent_internode_axis = shoot_tree_ptr->at(parent_shoot_ID)->phytomers.at(parent_node_index)->getInternodeAxisVector(1.f);
-
442 parent_petiole_axis = shoot_tree_ptr->at(parent_shoot_ID)->phytomers.at(parent_node_index)->getPetioleAxisVector(0.f, parent_petiole_index);
-
443 }
-
444 internode_base_position = base_position;
-
445 }else{ //additional phytomer being added to an existing shoot
-
446 parent_internode_axis = phytomers.back()->getInternodeAxisVector(1.f);
-
447 parent_petiole_axis = phytomers.back()->getPetioleAxisVector(0.f, 0);
-
448 internode_base_position = shoot_internode_vertices.back().back();
-
449 }
-
450
-
451 std::shared_ptr<Phytomer> phytomer = std::make_shared<Phytomer>(phytomer_parameters, this, phytomers.size(), parent_internode_axis, parent_petiole_axis, internode_base_position, this->base_rotation, internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, rank, plantarchitecture_ptr, context_ptr);
-
452 shoot_tree_ptr->at(ID)->phytomers.push_back(phytomer);
-
453 phytomer = shoot_tree_ptr->at(ID)->phytomers.back(); //change to point to phytomer stored in shoot
-
454
-
455 //Initialize phytomer vegetative bud types and state
-
456 for (auto &petiole: phytomer->axillary_vegetative_buds) {
-
457
-
458 //sample the bud shoot type
-
459 std::string child_shoot_type_label = sampleChildShootType();
-
460 for (auto &vbud: petiole) {
-
461 phytomer->setVegetativeBudState(BUD_DORMANT, vbud);
-
462 vbud.shoot_type_label = child_shoot_type_label;
-
463
-
464 // if the shoot type does not require dormancy, bud should be set to active
-
465 if (!shoot_parameters.growth_requires_dormancy ) {
-
466 if ( sampleVegetativeBudBreak(phytomer->shoot_index.x) ) { //randomly sample bud
-
467 phytomer->setVegetativeBudState(BUD_ACTIVE, vbud);
-
468 }else {
-
469 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
-
470 }
-
471 }
-
472 }
-
473 }
-
474
-
475 //Initialize phytomer floral bud types and state
-
476 uint petiole_index = 0;
-
477 for (auto &petiole: phytomer->floral_buds) {
-
478 uint bud_index = 0;
-
479 for (auto &fbud: petiole) {
-
480 //Set state of phytomer buds
-
481 phytomer->setFloralBudState(BUD_DORMANT, fbud);
-
482
-
483 // if the shoot type does not require dormancy, bud should be set to active
-
484 if (!shoot_parameters.flowers_require_dormancy && fbud.state != BUD_DEAD) {
-
485 phytomer->setFloralBudState(BUD_ACTIVE, fbud);
-
486 }
-
487
-
488 fbud.parent_index = petiole_index;
-
489 fbud.bud_index = bud_index;
-
490
-
491 bud_index++;
-
492 }
-
493 petiole_index++;
-
494 }
-
495
-
496 //Update the downstream leaf area for all upstream phytomers
-
497 propagateDownstreamLeafArea( this, phytomer->shoot_index.x, phytomer->getLeafArea());
-
498
-
499 //Set output object data 'age'
-
500 phytomer->age = 0;
-
501 if (plantarchitecture_ptr->build_context_geometry_internode && context_ptr->doesObjectExist(internode_tube_objID)) {
-
502 //\todo This really only needs to be done once when the shoot is first created.
-
503 if (plantarchitecture_ptr->output_object_data.at("age")) {
-
504 context_ptr->setObjectData(internode_tube_objID, "age", phytomer->age);
-
505 }
-
506 if (plantarchitecture_ptr->output_object_data.at("rank")) {
-
507 context_ptr->setObjectData(internode_tube_objID, "rank", rank);
-
508 }
-
509 if (plantarchitecture_ptr->output_object_data.at("plantID")) {
-
510 context_ptr->setObjectData(internode_tube_objID, "plantID", (int) plantID);
-
511 }
-
512 }
-
513 if (plantarchitecture_ptr->build_context_geometry_petiole) {
-
514 if (plantarchitecture_ptr->output_object_data.at("age")) {
-
515 context_ptr->setObjectData(phytomer->petiole_objIDs, "age", phytomer->age);
-
516 }
-
517 if (plantarchitecture_ptr->output_object_data.at("rank")) {
-
518 context_ptr->setObjectData(phytomer->petiole_objIDs, "rank", phytomer->rank);
-
519 }
-
520 if (plantarchitecture_ptr->output_object_data.at("plantID")) {
-
521 context_ptr->setObjectData(phytomer->petiole_objIDs, "plantID", (int) plantID);
-
522 }
-
523 }
-
524 if (plantarchitecture_ptr->output_object_data.at("age")) {
-
525 context_ptr->setObjectData(phytomer->leaf_objIDs, "age", phytomer->age);
-
526 }
-
527 if (plantarchitecture_ptr->output_object_data.at("rank")) {
-
528 context_ptr->setObjectData(phytomer->leaf_objIDs, "rank", phytomer->rank);
-
529 }
-
530 if (plantarchitecture_ptr->output_object_data.at("plantID")) {
-
531 context_ptr->setObjectData(phytomer->leaf_objIDs, "plantID", (int) plantID);
-
532 }
-
533
-
534 if (plantarchitecture_ptr->output_object_data.at("leafID")) {
-
535 for (auto &petiole: phytomer->leaf_objIDs) {
-
536 for (uint objID: petiole) {
-
537 context_ptr->setObjectData(objID, "leafID", (int) objID);
-
538 }
-
539 }
-
540 }
-
541
-
542 if( phytomer_parameters.phytomer_creation_function != nullptr ) {
-
543 phytomer_parameters.phytomer_creation_function(phytomer, current_node_number, this->parent_node_index, shoot_parameters.max_nodes.val(), plantarchitecture_ptr->plant_instances.at(plantID).current_age);
-
544 }
-
545
-
546 //calculate fully expanded/elongated carbon costs
-
547 this->carbohydrate_pool_molC -= phytomer->calculatePhytomerConstructionCosts();
-
548
-
549 return (int) phytomers.size() - 1;
-
550}
-
-
551
-
552void Shoot::breakDormancy() {
-
553
-
554 isdormant = false;
+
431 auto shoot_tree_ptr = &plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree;
+
432
+
433 //Determine the parent internode and petiole axes for rotation of the new phytomer
+
434 vec3 parent_internode_axis;
+
435 vec3 parent_petiole_axis;
+
436 vec3 internode_base_position;
+
437 if( phytomers.empty() ) { //very first phytomer on shoot
+
438 if(parent_shoot_ID == -1 ) { //very first shoot of the plant
+
439 parent_internode_axis = make_vec3(0, 0, 1);
+
440 parent_petiole_axis = make_vec3(0, -1, 0);
+
441 }else{ //first phytomer of a new shoot
+
442 assert(parent_shoot_ID < shoot_tree_ptr->size() && parent_node_index < shoot_tree_ptr->at(parent_shoot_ID)->phytomers.size() );
+
443 parent_internode_axis = shoot_tree_ptr->at(parent_shoot_ID)->phytomers.at(parent_node_index)->getInternodeAxisVector(1.f);
+
444 parent_petiole_axis = shoot_tree_ptr->at(parent_shoot_ID)->phytomers.at(parent_node_index)->getPetioleAxisVector(0.f, parent_petiole_index);
+
445 }
+
446 internode_base_position = base_position;
+
447 }else{ //additional phytomer being added to an existing shoot
+
448 parent_internode_axis = phytomers.back()->getInternodeAxisVector(1.f);
+
449 parent_petiole_axis = phytomers.back()->getPetioleAxisVector(0.f, 0);
+
450 internode_base_position = shoot_internode_vertices.back().back();
+
451 }
+
452
+
453 std::shared_ptr<Phytomer> phytomer = std::make_shared<Phytomer>(phytomer_parameters, this, phytomers.size(), parent_internode_axis, parent_petiole_axis, internode_base_position, this->base_rotation, internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, rank, plantarchitecture_ptr, context_ptr);
+
454 shoot_tree_ptr->at(ID)->phytomers.push_back(phytomer);
+
455 phytomer = shoot_tree_ptr->at(ID)->phytomers.back(); //change to point to phytomer stored in shoot
+
456
+
457 //Initialize phytomer vegetative bud types and state
+
458 for (auto &petiole: phytomer->axillary_vegetative_buds) {
+
459
+
460 //sample the bud shoot type
+
461 std::string child_shoot_type_label = sampleChildShootType();
+
462 for (auto &vbud: petiole) {
+
463 phytomer->setVegetativeBudState(BUD_DORMANT, vbud);
+
464 vbud.shoot_type_label = child_shoot_type_label;
+
465
+
466 // if the shoot type does not require dormancy, bud should be set to active
+
467 if (!shoot_parameters.growth_requires_dormancy ) {
+
468 if ( sampleVegetativeBudBreak(phytomer->shoot_index.x) ) { //randomly sample bud
+
469 phytomer->setVegetativeBudState(BUD_ACTIVE, vbud);
+
470 }else {
+
471 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
+
472 }
+
473 }
+
474 }
+
475 }
+
476
+
477 //Initialize phytomer floral bud types and state
+
478 uint petiole_index = 0;
+
479 for (auto &petiole: phytomer->floral_buds) {
+
480 uint bud_index = 0;
+
481 for (auto &fbud: petiole) {
+
482 //Set state of phytomer buds
+
483 phytomer->setFloralBudState(BUD_DORMANT, fbud);
+
484
+
485 // if the shoot type does not require dormancy, bud should be set to active
+
486 if (!shoot_parameters.flowers_require_dormancy && fbud.state != BUD_DEAD) {
+
487 phytomer->setFloralBudState(BUD_ACTIVE, fbud);
+
488 }
+
489
+
490 fbud.parent_index = petiole_index;
+
491 fbud.bud_index = bud_index;
+
492
+
493 bud_index++;
+
494 }
+
495 petiole_index++;
+
496 }
+
497
+
498 //Update the downstream leaf area for all upstream phytomers
+
499 propagateDownstreamLeafArea( this, phytomer->shoot_index.x, phytomer->getLeafArea());
+
500
+
501 //Set output object data 'age'
+
502 phytomer->age = 0;
+
503 if (plantarchitecture_ptr->build_context_geometry_internode && context_ptr->doesObjectExist(internode_tube_objID)) {
+
504 //\todo This really only needs to be done once when the shoot is first created.
+
505 if (plantarchitecture_ptr->output_object_data.at("age")) {
+
506 context_ptr->setObjectData(internode_tube_objID, "age", phytomer->age);
+
507 }
+
508 if (plantarchitecture_ptr->output_object_data.at("rank")) {
+
509 context_ptr->setObjectData(internode_tube_objID, "rank", rank);
+
510 }
+
511 if (plantarchitecture_ptr->output_object_data.at("plantID")) {
+
512 context_ptr->setObjectData(internode_tube_objID, "plantID", (int) plantID);
+
513 }
+
514 }
+
515 if (plantarchitecture_ptr->build_context_geometry_petiole) {
+
516 if (plantarchitecture_ptr->output_object_data.at("age")) {
+
517 context_ptr->setObjectData(phytomer->petiole_objIDs, "age", phytomer->age);
+
518 }
+
519 if (plantarchitecture_ptr->output_object_data.at("rank")) {
+
520 context_ptr->setObjectData(phytomer->petiole_objIDs, "rank", phytomer->rank);
+
521 }
+
522 if (plantarchitecture_ptr->output_object_data.at("plantID")) {
+
523 context_ptr->setObjectData(phytomer->petiole_objIDs, "plantID", (int) plantID);
+
524 }
+
525 }
+
526 if (plantarchitecture_ptr->output_object_data.at("age")) {
+
527 context_ptr->setObjectData(phytomer->leaf_objIDs, "age", phytomer->age);
+
528 }
+
529 if (plantarchitecture_ptr->output_object_data.at("rank")) {
+
530 context_ptr->setObjectData(phytomer->leaf_objIDs, "rank", phytomer->rank);
+
531 }
+
532 if (plantarchitecture_ptr->output_object_data.at("plantID")) {
+
533 context_ptr->setObjectData(phytomer->leaf_objIDs, "plantID", (int) plantID);
+
534 }
+
535
+
536 if (plantarchitecture_ptr->output_object_data.at("leafID")) {
+
537 for (auto &petiole: phytomer->leaf_objIDs) {
+
538 for (uint objID: petiole) {
+
539 context_ptr->setObjectData(objID, "leafID", (int) objID);
+
540 }
+
541 }
+
542 }
+
543
+
544 if( phytomer_parameters.phytomer_creation_function != nullptr ) {
+
545 phytomer_parameters.phytomer_creation_function(phytomer, current_node_number, this->parent_node_index, shoot_parameters.max_nodes.val(), plantarchitecture_ptr->plant_instances.at(plantID).current_age);
+
546 }
+
547
+
548 //calculate fully expanded/elongated carbon costs
+
549 if( plantarchitecture_ptr->carbon_model_enabled ){
+
550 this->carbohydrate_pool_molC -= phytomer->calculatePhytomerConstructionCosts();
+
551 }
+
552
+
553 return (int) phytomers.size() - 1;
+
554}
+
555
-
556 int phytomer_ind = 0;
-
557 for (auto &phytomer: phytomers) {
-
558 for (auto &petiole: phytomer->floral_buds) {
-
559 for (auto &fbud: petiole) {
-
560 if (fbud.state != BUD_DEAD) {
-
561 phytomer->setFloralBudState(BUD_ACTIVE, fbud);
-
562 }
-
563 if (meristem_is_alive && fbud.isterminal) {
-
564 phytomer->setFloralBudState(BUD_ACTIVE, fbud);
-
565 }
-
566 fbud.time_counter = 0;
-
567 }
-
568 }
-
569 for (auto &petiole: phytomer->axillary_vegetative_buds) {
-
570 for (auto &vbud: petiole) {
-
571 if (vbud.state != BUD_DEAD) {
-
572 if ( sampleVegetativeBudBreak(phytomer_ind) ) {
-
573 //randomly sample bud
-
574 phytomer->setVegetativeBudState(BUD_ACTIVE, vbud);
-
575 }else {
-
576 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
-
577 }
-
578 }
-
579 }
-
580 }
-
581
-
582 phytomer->isdormant = false;
-
583 phytomer_ind++;
-
584 }
-
585}
-
586
-
587void Shoot::makeDormant() {
-
588
-
589 isdormant = true;
-
590 dormancy_cycles++;
-
591 nodes_this_season = 0;
+
556void Shoot::breakDormancy() {
+
557
+
558 isdormant = false;
+
559
+
560 int phytomer_ind = 0;
+
561 for (auto &phytomer: phytomers) {
+
562 for (auto &petiole: phytomer->floral_buds) {
+
563 for (auto &fbud: petiole) {
+
564 if (fbud.state != BUD_DEAD) {
+
565 phytomer->setFloralBudState(BUD_ACTIVE, fbud);
+
566 }
+
567 if (meristem_is_alive && fbud.isterminal) {
+
568 phytomer->setFloralBudState(BUD_ACTIVE, fbud);
+
569 }
+
570 fbud.time_counter = 0;
+
571 }
+
572 }
+
573 for (auto &petiole: phytomer->axillary_vegetative_buds) {
+
574 for (auto &vbud: petiole) {
+
575 if (vbud.state != BUD_DEAD) {
+
576 if ( sampleVegetativeBudBreak(phytomer_ind) ) {
+
577 //randomly sample bud
+
578 phytomer->setVegetativeBudState(BUD_ACTIVE, vbud);
+
579 }else {
+
580 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
+
581 }
+
582 }
+
583 }
+
584 }
+
585
+
586 phytomer->isdormant = false;
+
587 phytomer_ind++;
+
588 }
+
589}
+
590
+
591void Shoot::makeDormant() {
592
-
593 for (auto &phytomer: phytomers) {
-
594 for (auto &petiole: phytomer->floral_buds) {
-
595 //all currently active lateral buds die at dormancy
-
596 for (auto &fbud: petiole) {
-
597 if (fbud.state != BUD_DORMANT) {
-
598 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
599 }
-
600 }
-
601 }
-
602 for (auto &petiole: phytomer->axillary_vegetative_buds) {
-
603 for (auto &vbud: petiole) {
-
604 if (vbud.state != BUD_DORMANT) {
-
605 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
-
606 }
-
607 }
-
608 }
-
609 if (!plantarchitecture_ptr->plant_instances.at(plantID).is_evergreen) {
-
610 phytomer->removeLeaf();
-
611 }
-
612 phytomer->isdormant = true;
-
613 }
-
614
-
615 if (meristem_is_alive && shoot_parameters.flowers_require_dormancy && shoot_parameters.max_terminal_floral_buds.val() > 0) {
-
616 addTerminalFloralBud();
+
593 isdormant = true;
+
594 dormancy_cycles++;
+
595 nodes_this_season = 0;
+
596
+
597 for (auto &phytomer: phytomers) {
+
598 for (auto &petiole: phytomer->floral_buds) {
+
599 //all currently active lateral buds die at dormancy
+
600 for (auto &fbud: petiole) {
+
601 if (fbud.state != BUD_DORMANT) {
+
602 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
603 }
+
604 }
+
605 }
+
606 for (auto &petiole: phytomer->axillary_vegetative_buds) {
+
607 for (auto &vbud: petiole) {
+
608 if (vbud.state != BUD_DORMANT) {
+
609 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
+
610 }
+
611 }
+
612 }
+
613 if (!plantarchitecture_ptr->plant_instances.at(plantID).is_evergreen) {
+
614 phytomer->removeLeaf();
+
615 }
+
616 phytomer->isdormant = true;
617 }
-
618}
-
619
-
620void Shoot::terminateApicalBud() {
-
621 this->meristem_is_alive = false;
+
618
+
619 if (meristem_is_alive && shoot_parameters.flowers_require_dormancy && shoot_parameters.max_terminal_floral_buds.val() > 0) {
+
620 addTerminalFloralBud();
+
621 }
622}
623
-
624void Shoot::terminateAxillaryVegetativeBuds() {
-
625 for (auto &phytomer: phytomers) {
-
626 for (auto &petiole: phytomer->axillary_vegetative_buds) {
-
627 for (auto &vbud: petiole) {
-
628 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
-
629 }
-
630 }
-
631 }
-
632}
-
633
-
634void Shoot::addTerminalFloralBud() {
-
635 int Nbuds = shoot_parameters.max_terminal_floral_buds.val();
-
636 for (int bud = 0; bud < Nbuds; bud++) {
-
637 FloralBud bud_new;
-
638 bud_new.isterminal = true;
-
639 bud_new.parent_index = 0;
-
640 bud_new.bud_index = bud;
-
641 bud_new.base_position = shoot_internode_vertices.back().back();
-
642 float pitch_adjustment = 0;
-
643 if (Nbuds > 1) {
-
644 pitch_adjustment = deg2rad(30);
-
645 }
-
646 float yaw_adjustment = bud_new.bud_index * 2.f * M_PI / float(Nbuds);
-
647 //-0.25f * M_PI + bud_new.bud_index * 0.5f * M_PI / float(Nbuds);
-
648 bud_new.base_rotation = make_AxisRotation(pitch_adjustment, yaw_adjustment, 0);
-
649 bud_new.bending_axis = make_vec3(1, 0, 0);
-
650
-
651 phytomers.back()->floral_buds.push_back({bud_new});
-
652 }
-
653
-
654 shoot_parameters.max_terminal_floral_buds.resample();
-
655}
-
656
-
657float Shoot::calculateShootInternodeVolume() const {
-
658 float shoot_volume = 0;
-
659 for (const auto &phytomer: phytomers) {
-
660 if (context_ptr->doesObjectExist(internode_tube_objID)) {
-
661 shoot_volume += context_ptr->getTubeObjectVolume(internode_tube_objID);
-
662 }
-
663 }
-
664 return shoot_volume;
-
665}
-
666
-
667float Shoot::calculateShootLength() const {
-
668 float shoot_length = 0;
-
669 for (const auto &phytomer: phytomers) {
-
670 shoot_length += phytomer->getInternodeLength();
-
671 }
-
672 return shoot_length;
-
673}
-
674
-
-
675void Shoot::updateShootNodes(bool update_context_geometry) {
-
676 // make shoot origin consistent with parent shoot node position
-
677 if( parent_shoot_ID>=0 ) { //only if not the base shoot
+
624void Shoot::terminateApicalBud() {
+
625 this->meristem_is_alive = false;
+
626}
+
627
+
628void Shoot::terminateAxillaryVegetativeBuds() {
+
629 for (auto &phytomer: phytomers) {
+
630 for (auto &petiole: phytomer->axillary_vegetative_buds) {
+
631 for (auto &vbud: petiole) {
+
632 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
+
633 }
+
634 }
+
635 }
+
636}
+
637
+
638void Shoot::addTerminalFloralBud() {
+
639 int Nbuds = shoot_parameters.max_terminal_floral_buds.val();
+
640 for (int bud = 0; bud < Nbuds; bud++) {
+
641 FloralBud bud_new;
+
642 bud_new.isterminal = true;
+
643 bud_new.parent_index = 0;
+
644 bud_new.bud_index = bud;
+
645 bud_new.base_position = shoot_internode_vertices.back().back();
+
646 float pitch_adjustment = 0;
+
647 if (Nbuds > 1) {
+
648 pitch_adjustment = deg2rad(30);
+
649 }
+
650 float yaw_adjustment = bud_new.bud_index * 2.f * M_PI / float(Nbuds);
+
651 //-0.25f * M_PI + bud_new.bud_index * 0.5f * M_PI / float(Nbuds);
+
652 bud_new.base_rotation = make_AxisRotation(pitch_adjustment, yaw_adjustment, 0);
+
653 bud_new.bending_axis = make_vec3(1, 0, 0);
+
654
+
655 phytomers.back()->floral_buds.push_back({bud_new});
+
656 }
+
657
+
658 shoot_parameters.max_terminal_floral_buds.resample();
+
659}
+
660
+
661float Shoot::calculateShootInternodeVolume() const {
+
662 float shoot_volume = 0;
+
663 for (const auto &phytomer: phytomers) {
+
664 if (context_ptr->doesObjectExist(internode_tube_objID)) {
+
665 shoot_volume += context_ptr->getTubeObjectVolume(internode_tube_objID);
+
666 }
+
667 }
+
668 return shoot_volume;
+
669}
+
670
+
671float Shoot::calculateShootLength() const {
+
672 float shoot_length = 0;
+
673 for (const auto &phytomer: phytomers) {
+
674 shoot_length += phytomer->getInternodeLength();
+
675 }
+
676 return shoot_length;
+
677}
678
-
679 auto parent_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID);
-
680
-
681 const vec3 &current_origin = shoot_internode_vertices.front().front();
-
682 const vec3 &updated_origin = parent_shoot->shoot_internode_vertices.at(this->parent_node_index).back();
-
683 vec3 shift = updated_origin - current_origin;
+
+
679void Shoot::updateShootNodes(bool update_context_geometry) {
+
680 // make shoot origin consistent with parent shoot node position
+
681 if( parent_shoot_ID>=0 ) { //only if not the base shoot
+
682
+
683 auto parent_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID);
684
-
685 //shift shoot based outward by the radius of the parent internode
-
686 // shift += radial_outward_axis * parent_shoot->shoot_internode_radii.at(this->parent_node_index).back();
-
687
-
688 if (shift != nullorigin) {
-
689 for (auto &phytomer: shoot_internode_vertices) {
-
690 for (vec3 &node: phytomer) {
-
691 node += shift;
-
692 }
-
693 }
-
694 }
-
695 }
-
696
-
697 if (update_context_geometry && plantarchitecture_ptr->build_context_geometry_internode && context_ptr->doesObjectExist(internode_tube_objID) ){
-
698 context_ptr->setTubeRadii( internode_tube_objID, flatten(shoot_internode_radii) );
-
699 context_ptr->setTubeNodes(internode_tube_objID, flatten(shoot_internode_vertices));
-
700 }
-
701
-
702 //update petiole/leaf positions
-
703 for (int p = 0; p < phytomers.size(); p++) {
-
704 vec3 petiole_base = shoot_internode_vertices.at(p).back();
-
705 if( parent_shoot_ID>=0 ) { //shift petiole base outward by the parent internode radius
-
706 auto parent_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID);
-
707 // petiole_base += radial_outward_axis * parent_shoot->shoot_internode_radii.at(this->parent_node_index).back();
-
708 }
-
709 phytomers.at(p)->setPetioleBase(petiole_base);
-
710 }
-
711
-
712 // update child shoot origins
-
713 for( auto node : childIDs ){
-
714 for( int child_shoot_ID : node.second ) {
-
715 plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(child_shoot_ID)->updateShootNodes(update_context_geometry);
-
716 }
-
717 }
-
718}
-
-
719
-
720helios::vec3 Shoot::getShootAxisVector(float shoot_fraction) const {
-
721 uint phytomer_count = this->phytomers.size();
-
722
-
723 uint phytomer_index = 0;
-
724 if (shoot_fraction > 0) {
-
725 phytomer_index = std::ceil(shoot_fraction * float(phytomer_count)) - 1;
-
726 }
-
727
-
728 assert(phytomer_index>=0 && phytomer_index<phytomer_count);
-
729
-
730 return this->phytomers.at(phytomer_index)->getInternodeAxisVector(0.5);
-
731}
-
732
-
733void Shoot::propagateDownstreamLeafArea(Shoot* shoot, uint node_index, float leaf_area) {
-
734
-
735 for (int i = node_index; i >= 0; i--) {
-
736 shoot->phytomers.at(i)->downstream_leaf_area += leaf_area;
-
737 shoot->phytomers.at(i)->downstream_leaf_area = std::max(0.f, shoot->phytomers.at(i)->downstream_leaf_area);
-
738 }
-
739
-
740 if ( shoot->parent_shoot_ID >= 0 ) {
-
741 Shoot *parent_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(shoot->parent_shoot_ID).get();
-
742 propagateDownstreamLeafArea( parent_shoot, shoot->parent_node_index, leaf_area);
-
743 }
-
744
-
745}
-
746
-
747float Shoot::sumShootLeafArea(uint start_node_index) const {
-
748 if (start_node_index >= phytomers.size()) {
-
749 helios_runtime_error("ERROR (Shoot::sumShootLeafArea): Start node index out of range.");
-
750 }
-
751
-
752 float area = 0;
-
753
-
754 for (uint p = start_node_index; p < phytomers.size(); p++) {
-
755 //sum up leaves directly connected to this shoot
-
756 auto phytomer = phytomers.at(p);
-
757 for (auto &petiole: phytomer->leaf_objIDs) {
-
758 for (uint objID: petiole) {
-
759 if (context_ptr->doesObjectExist(objID)) {
-
760 area += context_ptr->getObjectArea(objID);
-
761 }
-
762 }
-
763 }
-
764
-
765 //call recursively for child shoots
-
766 if( childIDs.find(p)!=childIDs.end() ){
-
767 for( int child_shoot_ID : childIDs.at(p) ) {
-
768 area += plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(child_shoot_ID)->sumShootLeafArea(0);
-
769 }
-
770 }
-
771 }
-
772
-
773 return area;
-
774}
-
775
-
776Phytomer::Phytomer(const PhytomerParameters &params, Shoot *parent_shoot, uint phytomer_index, const helios::vec3 &parent_internode_axis, const helios::vec3 &parent_petiole_axis, helios::vec3 internode_base_origin,
-
777 const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, uint rank, PlantArchitecture *plantarchitecture_ptr,
-
778 helios::Context *context_ptr)
-
779 : context_ptr(context_ptr), plantarchitecture_ptr(plantarchitecture_ptr), rank(rank) {
+
685 const vec3 &current_origin = shoot_internode_vertices.front().front();
+
686 const vec3 &updated_origin = parent_shoot->shoot_internode_vertices.at(this->parent_node_index).back();
+
687 vec3 shift = updated_origin - current_origin;
+
688
+
689 //shift shoot based outward by the radius of the parent internode
+
690 // shift += radial_outward_axis * parent_shoot->shoot_internode_radii.at(this->parent_node_index).back();
+
691
+
692 if (shift != nullorigin) {
+
693 for (auto &phytomer: shoot_internode_vertices) {
+
694 for (vec3 &node: phytomer) {
+
695 node += shift;
+
696 }
+
697 }
+
698 }
+
699 }
+
700
+
701 if (update_context_geometry && plantarchitecture_ptr->build_context_geometry_internode && context_ptr->doesObjectExist(internode_tube_objID) ){
+
702 context_ptr->setTubeRadii( internode_tube_objID, flatten(shoot_internode_radii) );
+
703 context_ptr->setTubeNodes(internode_tube_objID, flatten(shoot_internode_vertices));
+
704 }
+
705
+
706 //update petiole/leaf positions
+
707 for (int p = 0; p < phytomers.size(); p++) {
+
708 vec3 petiole_base = shoot_internode_vertices.at(p).back();
+
709 if( parent_shoot_ID>=0 ) { //shift petiole base outward by the parent internode radius
+
710 auto parent_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID);
+
711 // petiole_base += radial_outward_axis * parent_shoot->shoot_internode_radii.at(this->parent_node_index).back();
+
712 }
+
713 phytomers.at(p)->setPetioleBase(petiole_base);
+
714 }
+
715
+
716 // update child shoot origins
+
717 for( auto node : childIDs ){
+
718 for( int child_shoot_ID : node.second ) {
+
719 plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(child_shoot_ID)->updateShootNodes(update_context_geometry);
+
720 }
+
721 }
+
722}
+
+
723
+
724helios::vec3 Shoot::getShootAxisVector(float shoot_fraction) const {
+
725 uint phytomer_count = this->phytomers.size();
+
726
+
727 uint phytomer_index = 0;
+
728 if (shoot_fraction > 0) {
+
729 phytomer_index = std::ceil(shoot_fraction * float(phytomer_count)) - 1;
+
730 }
+
731
+
732 assert(phytomer_index>=0 && phytomer_index<phytomer_count);
+
733
+
734 return this->phytomers.at(phytomer_index)->getInternodeAxisVector(0.5);
+
735}
+
736
+
737void Shoot::propagateDownstreamLeafArea(Shoot* shoot, uint node_index, float leaf_area) {
+
738
+
739 for (int i = node_index; i >= 0; i--) {
+
740 shoot->phytomers.at(i)->downstream_leaf_area += leaf_area;
+
741 shoot->phytomers.at(i)->downstream_leaf_area = std::max(0.f, shoot->phytomers.at(i)->downstream_leaf_area);
+
742 }
+
743
+
744 if ( shoot->parent_shoot_ID >= 0 ) {
+
745 Shoot *parent_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(shoot->parent_shoot_ID).get();
+
746 propagateDownstreamLeafArea( parent_shoot, shoot->parent_node_index, leaf_area);
+
747 }
+
748
+
749}
+
750
+
751float Shoot::sumShootLeafArea(uint start_node_index) const {
+
752 if (start_node_index >= phytomers.size()) {
+
753 helios_runtime_error("ERROR (Shoot::sumShootLeafArea): Start node index out of range.");
+
754 }
+
755
+
756 float area = 0;
+
757
+
758 for (uint p = start_node_index; p < phytomers.size(); p++) {
+
759 //sum up leaves directly connected to this shoot
+
760 auto phytomer = phytomers.at(p);
+
761 for (auto &petiole: phytomer->leaf_objIDs) {
+
762 for (uint objID: petiole) {
+
763 if (context_ptr->doesObjectExist(objID)) {
+
764 area += context_ptr->getObjectArea(objID);
+
765 }
+
766 }
+
767 }
+
768
+
769 //call recursively for child shoots
+
770 if( childIDs.find(p)!=childIDs.end() ){
+
771 for( int child_shoot_ID : childIDs.at(p) ) {
+
772 area += plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(child_shoot_ID)->sumShootLeafArea(0);
+
773 }
+
774 }
+
775 }
+
776
+
777 return area;
+
778}
+
779
780
-
781 this->phytomer_parameters = params; //note this needs to be an assignment operation not a copy in order to re-randomize all the parameters
+
781float Shoot::sumChildVolume( uint start_node_index ) const{
782
-
783 ShootParameters parent_shoot_parameters = parent_shoot->shoot_parameters;
-
784
-
785 this->internode_radius_initial = internode_radius;
-
786 this->internode_length_max = internode_length_max;
-
787 this->shoot_index = make_int3(phytomer_index, parent_shoot->current_node_number, parent_shoot_parameters.max_nodes.val());
-
788 //.x is the index of the phytomer along the shoot, .y is the current number of phytomers on the parent shoot, .z is the maximum number of phytomers on the parent shoot.
-
789 this->rank = parent_shoot->rank;
-
790 this->plantID = parent_shoot->plantID;
-
791 this->parent_shoot_ID = parent_shoot->ID;
-
792 this->parent_shoot_ptr = parent_shoot;
-
793
-
794 bool build_context_geometry_internode = plantarchitecture_ptr->build_context_geometry_internode;
-
795 bool build_context_geometry_petiole = plantarchitecture_ptr->build_context_geometry_petiole;
-
796 bool build_context_geometry_peduncle = plantarchitecture_ptr->build_context_geometry_peduncle;
-
797
-
798 // if( internode_radius==0.f || internode_length_max==0.f || parent_shoot_parameters.internode_radius_max.val()==0.f ){
-
799 // build_context_geometry_internode = false;
-
800 // }
-
801
-
802 //Number of longitudinal segments for internode and petiole
-
803 //if Ndiv=0, use Ndiv=1 (but don't add any primitives to Context)
-
804 uint Ndiv_internode_length = std::max(uint(1), phytomer_parameters.internode.length_segments);
-
805 uint Ndiv_internode_radius = std::max(uint(3), phytomer_parameters.internode.radial_subdivisions);
-
806 uint Ndiv_petiole_length = std::max(uint(1), phytomer_parameters.petiole.length_segments);
-
807 uint Ndiv_petiole_radius = std::max(uint(3), phytomer_parameters.petiole.radial_subdivisions);
-
808
-
809 //Flags to determine whether internode geometry should be built in the Context. Not building all geometry can save memory and computation time.
-
810 if (phytomer_parameters.internode.length_segments == 0 || phytomer_parameters.internode.radial_subdivisions < 3) {
-
811 build_context_geometry_internode = false;
-
812 }
-
813 if (phytomer_parameters.petiole.length_segments == 0 || phytomer_parameters.petiole.radial_subdivisions < 3) {
-
814 build_context_geometry_petiole = false;
-
815 }
-
816
-
817 if (phytomer_parameters.petiole.petioles_per_internode < 1) {
-
818 build_context_geometry_petiole = false;
-
819 phytomer_parameters.petiole.petioles_per_internode = 1;
-
820 phytomer_parameters.leaf.leaves_per_petiole = 0;
-
821 }
-
822
-
823 if( phytomer_parameters.petiole.petioles_per_internode==0 ){
-
824 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Number of petioles per internode must be greater than zero.");
-
825 }
-
826
-
827 current_internode_scale_factor = internode_length_scale_factor_fraction;
-
828 current_leaf_scale_factor = leaf_scale_factor_fraction;
-
829
-
830 if (internode_radius == 0.f) {
-
831 internode_radius = 1e-5;
-
832 }
-
833
-
834 //Initialize internode variables
-
835 float internode_length = internode_length_scale_factor_fraction * internode_length_max;
-
836 float dr_internode = internode_length / float(phytomer_parameters.internode.length_segments);
-
837 float dr_internode_max = internode_length_max / float(phytomer_parameters.internode.length_segments);
-
838 std::vector<vec3> phytomer_internode_vertices;
-
839 std::vector<float> phytomer_internode_radii;
-
840 phytomer_internode_vertices.resize(Ndiv_internode_length + 1);
-
841 phytomer_internode_vertices.at(0) = internode_base_origin;
-
842 phytomer_internode_radii.resize(Ndiv_internode_length + 1);
-
843 phytomer_internode_radii.at(0) = internode_radius;
-
844 internode_pitch = deg2rad(phytomer_parameters.internode.pitch.val());
-
845 phytomer_parameters.internode.pitch.resample();
-
846 internode_phyllotactic_angle = deg2rad(phytomer_parameters.internode.phyllotactic_angle.val());
-
847 phytomer_parameters.internode.phyllotactic_angle.resample();
-
848
-
849 //initialize petiole variables
-
850 petiole_length.resize(phytomer_parameters.petiole.petioles_per_internode);
-
851 petiole_vertices.resize(phytomer_parameters.petiole.petioles_per_internode);
-
852 petiole_radii.resize(phytomer_parameters.petiole.petioles_per_internode);
-
853 std::vector<float> dr_petiole(phytomer_parameters.petiole.petioles_per_internode);
-
854 std::vector<float> dr_petiole_max(phytomer_parameters.petiole.petioles_per_internode);
-
855 for (int p = 0; p < phytomer_parameters.petiole.petioles_per_internode; p++) {
-
856 petiole_vertices.at(p).resize(Ndiv_petiole_length + 1);
-
857 petiole_radii.at(p).resize(Ndiv_petiole_length + 1);
-
858
-
859 petiole_length.at(p) = leaf_scale_factor_fraction * phytomer_parameters.petiole.length.val();
-
860 dr_petiole.at(p) = petiole_length.at(p) / float(phytomer_parameters.petiole.length_segments);
-
861 dr_petiole_max.at(p) = phytomer_parameters.petiole.length.val() / float(phytomer_parameters.petiole.length_segments);
-
862
-
863 petiole_radii.at(p).at(0) = leaf_scale_factor_fraction * phytomer_parameters.petiole.radius.val();
-
864 }
-
865 phytomer_parameters.petiole.length.resample();
-
866 if (build_context_geometry_petiole) {
-
867 petiole_objIDs.resize(phytomer_parameters.petiole.petioles_per_internode);
-
868 }
-
869
-
870 //initialize leaf variables
-
871 leaf_bases.resize(phytomer_parameters.petiole.petioles_per_internode);
-
872 leaf_objIDs.resize(phytomer_parameters.petiole.petioles_per_internode);
-
873 leaf_size_max.resize(phytomer_parameters.petiole.petioles_per_internode);
-
874 leaf_rotation.resize(phytomer_parameters.petiole.petioles_per_internode);
-
875 int leaves_per_petiole = phytomer_parameters.leaf.leaves_per_petiole.val();
-
876 phytomer_parameters.leaf.leaves_per_petiole.resample();
-
877 for (uint petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
-
878 leaf_size_max.at(petiole).resize(leaves_per_petiole);
-
879 leaf_rotation.at(petiole).resize(leaves_per_petiole);
-
880 }
-
881
-
882 internode_colors.resize(Ndiv_internode_length + 1);
-
883 internode_colors.at(0) = phytomer_parameters.internode.color;
-
884 petiole_colors.resize(Ndiv_petiole_length + 1);
-
885 petiole_colors.at(0) = phytomer_parameters.petiole.color;
-
886
-
887 vec3 internode_axis = parent_internode_axis;
-
888
-
889 vec3 petiole_rotation_axis = cross(parent_internode_axis, parent_petiole_axis);
-
890 if (petiole_rotation_axis == make_vec3(0, 0, 0)) {
-
891 petiole_rotation_axis = make_vec3(1, 0, 0);
-
892 }
-
893
-
894 if( phytomer_index==0 ){ //if this is the first phytomer along a shoot, apply the origin rotation about the parent axis
-
895
-
896 //internode pitch rotation for phytomer base
-
897 if( internode_pitch!=0.f ) {
-
898 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, petiole_rotation_axis, 0.5f*internode_pitch );
-
899 }
-
900
-
901 //internode roll rotation for shoot base rotation
-
902 float roll_nudge = 0.f;
-
903 //\todo Not clear if this is still needed. It causes problems when you want to plant base roll to be exactly 0.
-
904// if( shoot_base_rotation.roll/180.f == floor(shoot_base_rotation.roll/180.f) ) {
-
905// roll_nudge = 0.2;
-
906// }
-
907 if( shoot_base_rotation.roll!=0.f || roll_nudge!=0.f ){
-
908 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, parent_internode_axis,shoot_base_rotation.roll + roll_nudge ); //small additional rotation is to make sure the petiole is not exactly vertical
-
909 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, parent_internode_axis,shoot_base_rotation.roll + roll_nudge );
-
910 }
-
911
-
912 vec3 base_pitch_axis = -1 * cross(parent_internode_axis, parent_petiole_axis);
+
783 if( start_node_index>=phytomers.size() ){
+
784 helios_runtime_error("ERROR (Shoot::sumChildVolume): Start node index out of range.");
+
785 }
+
786
+
787 float volume = 0;
+
788
+
789 for( uint p=start_node_index; p<phytomers.size(); p++ ){
+
790 //call recursively for child shoots
+
791 if( childIDs.find(p)!=childIDs.end() ){
+
792 for( int child_shoot_ID : childIDs.at(p) ) {
+
793 volume += plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(child_shoot_ID)->calculateShootInternodeVolume();
+
794 }
+
795 }
+
796
+
797 }
+
798
+
799 return volume;
+
800
+
801}
+
802
+
803Phytomer::Phytomer(const PhytomerParameters &params, Shoot *parent_shoot, uint phytomer_index, const helios::vec3 &parent_internode_axis, const helios::vec3 &parent_petiole_axis, helios::vec3 internode_base_origin,
+
804 const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, uint rank, PlantArchitecture *plantarchitecture_ptr,
+
805 helios::Context *context_ptr)
+
806 : context_ptr(context_ptr), plantarchitecture_ptr(plantarchitecture_ptr), rank(rank) {
+
807
+
808 this->phytomer_parameters = params; //note this needs to be an assignment operation not a copy in order to re-randomize all the parameters
+
809
+
810 ShootParameters parent_shoot_parameters = parent_shoot->shoot_parameters;
+
811
+
812 this->internode_radius_initial = internode_radius;
+
813 this->internode_length_max = internode_length_max;
+
814 this->shoot_index = make_int3(phytomer_index, parent_shoot->current_node_number, parent_shoot_parameters.max_nodes.val());
+
815 //.x is the index of the phytomer along the shoot, .y is the current number of phytomers on the parent shoot, .z is the maximum number of phytomers on the parent shoot.
+
816 this->rank = parent_shoot->rank;
+
817 this->plantID = parent_shoot->plantID;
+
818 this->parent_shoot_ID = parent_shoot->ID;
+
819 this->parent_shoot_ptr = parent_shoot;
+
820
+
821 bool build_context_geometry_internode = plantarchitecture_ptr->build_context_geometry_internode;
+
822 bool build_context_geometry_petiole = plantarchitecture_ptr->build_context_geometry_petiole;
+
823 bool build_context_geometry_peduncle = plantarchitecture_ptr->build_context_geometry_peduncle;
+
824
+
825 // if( internode_radius==0.f || internode_length_max==0.f || parent_shoot_parameters.internode_radius_max.val()==0.f ){
+
826 // build_context_geometry_internode = false;
+
827 // }
+
828
+
829 //Number of longitudinal segments for internode and petiole
+
830 //if Ndiv=0, use Ndiv=1 (but don't add any primitives to Context)
+
831 uint Ndiv_internode_length = std::max(uint(1), phytomer_parameters.internode.length_segments);
+
832 uint Ndiv_internode_radius = std::max(uint(3), phytomer_parameters.internode.radial_subdivisions);
+
833 uint Ndiv_petiole_length = std::max(uint(1), phytomer_parameters.petiole.length_segments);
+
834 uint Ndiv_petiole_radius = std::max(uint(3), phytomer_parameters.petiole.radial_subdivisions);
+
835
+
836 //Flags to determine whether internode geometry should be built in the Context. Not building all geometry can save memory and computation time.
+
837 if (phytomer_parameters.internode.length_segments == 0 || phytomer_parameters.internode.radial_subdivisions < 3) {
+
838 build_context_geometry_internode = false;
+
839 }
+
840 if (phytomer_parameters.petiole.length_segments == 0 || phytomer_parameters.petiole.radial_subdivisions < 3) {
+
841 build_context_geometry_petiole = false;
+
842 }
+
843
+
844 if (phytomer_parameters.petiole.petioles_per_internode < 1) {
+
845 build_context_geometry_petiole = false;
+
846 phytomer_parameters.petiole.petioles_per_internode = 1;
+
847 phytomer_parameters.leaf.leaves_per_petiole = 0;
+
848 }
+
849
+
850 if( phytomer_parameters.petiole.petioles_per_internode==0 ){
+
851 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Number of petioles per internode must be greater than zero.");
+
852 }
+
853
+
854 current_internode_scale_factor = internode_length_scale_factor_fraction;
+
855 current_leaf_scale_factor = leaf_scale_factor_fraction;
+
856
+
857 if (internode_radius == 0.f) {
+
858 internode_radius = 1e-5;
+
859 }
+
860
+
861 //Initialize internode variables
+
862 float internode_length = internode_length_scale_factor_fraction * internode_length_max;
+
863 float dr_internode = internode_length / float(phytomer_parameters.internode.length_segments);
+
864 float dr_internode_max = internode_length_max / float(phytomer_parameters.internode.length_segments);
+
865 std::vector<vec3> phytomer_internode_vertices;
+
866 std::vector<float> phytomer_internode_radii;
+
867 phytomer_internode_vertices.resize(Ndiv_internode_length + 1);
+
868 phytomer_internode_vertices.at(0) = internode_base_origin;
+
869 phytomer_internode_radii.resize(Ndiv_internode_length + 1);
+
870 phytomer_internode_radii.at(0) = internode_radius;
+
871 internode_pitch = deg2rad(phytomer_parameters.internode.pitch.val());
+
872 phytomer_parameters.internode.pitch.resample();
+
873 internode_phyllotactic_angle = deg2rad(phytomer_parameters.internode.phyllotactic_angle.val());
+
874 phytomer_parameters.internode.phyllotactic_angle.resample();
+
875
+
876 //initialize petiole variables
+
877 petiole_length.resize(phytomer_parameters.petiole.petioles_per_internode);
+
878 petiole_vertices.resize(phytomer_parameters.petiole.petioles_per_internode);
+
879 petiole_radii.resize(phytomer_parameters.petiole.petioles_per_internode);
+
880 std::vector<float> dr_petiole(phytomer_parameters.petiole.petioles_per_internode);
+
881 std::vector<float> dr_petiole_max(phytomer_parameters.petiole.petioles_per_internode);
+
882 for (int p = 0; p < phytomer_parameters.petiole.petioles_per_internode; p++) {
+
883 petiole_vertices.at(p).resize(Ndiv_petiole_length + 1);
+
884 petiole_radii.at(p).resize(Ndiv_petiole_length + 1);
+
885
+
886 petiole_length.at(p) = leaf_scale_factor_fraction * phytomer_parameters.petiole.length.val();
+
887 dr_petiole.at(p) = petiole_length.at(p) / float(phytomer_parameters.petiole.length_segments);
+
888 dr_petiole_max.at(p) = phytomer_parameters.petiole.length.val() / float(phytomer_parameters.petiole.length_segments);
+
889
+
890 petiole_radii.at(p).at(0) = leaf_scale_factor_fraction * phytomer_parameters.petiole.radius.val();
+
891 }
+
892 phytomer_parameters.petiole.length.resample();
+
893 if (build_context_geometry_petiole) {
+
894 petiole_objIDs.resize(phytomer_parameters.petiole.petioles_per_internode);
+
895 }
+
896
+
897 //initialize leaf variables
+
898 leaf_bases.resize(phytomer_parameters.petiole.petioles_per_internode);
+
899 leaf_objIDs.resize(phytomer_parameters.petiole.petioles_per_internode);
+
900 leaf_size_max.resize(phytomer_parameters.petiole.petioles_per_internode);
+
901 leaf_rotation.resize(phytomer_parameters.petiole.petioles_per_internode);
+
902 int leaves_per_petiole = phytomer_parameters.leaf.leaves_per_petiole.val();
+
903 phytomer_parameters.leaf.leaves_per_petiole.resample();
+
904 for (uint petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
+
905 leaf_size_max.at(petiole).resize(leaves_per_petiole);
+
906 leaf_rotation.at(petiole).resize(leaves_per_petiole);
+
907 }
+
908
+
909 internode_colors.resize(Ndiv_internode_length + 1);
+
910 internode_colors.at(0) = phytomer_parameters.internode.color;
+
911 petiole_colors.resize(Ndiv_petiole_length + 1);
+
912 petiole_colors.at(0) = phytomer_parameters.petiole.color;
913
-
914 //internode pitch rotation for shoot base rotation
-
915 if( shoot_base_rotation.pitch!=0.f ) {
-
916 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, base_pitch_axis, -shoot_base_rotation.pitch);
-
917 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, base_pitch_axis, -shoot_base_rotation.pitch);
-
918 }
-
919
-
920 //internode yaw rotation for shoot base rotation
-
921 if( shoot_base_rotation.yaw!=0 ){
-
922 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, parent_internode_axis, shoot_base_rotation.yaw);
-
923 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, parent_internode_axis, shoot_base_rotation.yaw );
-
924 }
-
925
-
926 parent_shoot->radial_outward_axis = rotatePointAboutLine(internode_axis, nullorigin, petiole_rotation_axis, 0.5f*M_PI );
+
914 vec3 internode_axis = parent_internode_axis;
+
915
+
916 vec3 petiole_rotation_axis = cross(parent_internode_axis, parent_petiole_axis);
+
917 if (petiole_rotation_axis == make_vec3(0, 0, 0)) {
+
918 petiole_rotation_axis = make_vec3(1, 0, 0);
+
919 }
+
920
+
921 if( phytomer_index==0 ){ //if this is the first phytomer along a shoot, apply the origin rotation about the parent axis
+
922
+
923 //internode pitch rotation for phytomer base
+
924 if( internode_pitch!=0.f ) {
+
925 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, petiole_rotation_axis, 0.5f*internode_pitch );
+
926 }
927
-
928 // if( parent_shoot->parent_shoot_ID>=0 ) { //if this is not the first shoot on the plant (i.e. it has a parent shoot
-
929 // auto parent_of_parent_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot->parent_shoot_ID);
-
930 // phytomer_internode_vertices.at(0) += parent_shoot->radial_outward_axis * parent_of_parent_shoot->shoot_internode_radii.at(parent_shoot->parent_node_index).back();
-
931 // }
-
932 } else {
-
933 //internode pitch rotation for phytomer base
-
934 if ( internode_pitch != 0) {
-
935 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, petiole_rotation_axis,-1.25f*internode_pitch );
-
936 }
-
937 }
+
928 //internode roll rotation for shoot base rotation
+
929 float roll_nudge = 0.f;
+
930 //\todo Not clear if this is still needed. It causes problems when you want to plant base roll to be exactly 0.
+
931// if( shoot_base_rotation.roll/180.f == floor(shoot_base_rotation.roll/180.f) ) {
+
932// roll_nudge = 0.2;
+
933// }
+
934 if( shoot_base_rotation.roll!=0.f || roll_nudge!=0.f ){
+
935 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, parent_internode_axis,shoot_base_rotation.roll + roll_nudge ); //small additional rotation is to make sure the petiole is not exactly vertical
+
936 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, parent_internode_axis,shoot_base_rotation.roll + roll_nudge );
+
937 }
938
-
939 vec3 shoot_bending_axis = cross(internode_axis, make_vec3(0, 0, 1));
+
939 vec3 base_pitch_axis = -1 * cross(parent_internode_axis, parent_petiole_axis);
940
-
941 internode_axis.normalize();
-
942 if (internode_axis == make_vec3(0, 0, 1)) {
-
943 shoot_bending_axis = make_vec3(0, 1, 0);
-
944 }
-
945
-
946 // create internode tube
-
947 for (int inode_segment = 1; inode_segment <= Ndiv_internode_length; inode_segment++) {
-
948 //apply curvature and tortuosity
-
949 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
-
950
-
951 float current_curvature_fact = 0.5f - internode_axis.z / 2.f;
-
952 if (internode_axis.z < 0) {
-
953 current_curvature_fact *= 2.f;
-
954 }
-
955
-
956 float dt = dr_internode_max / float(Ndiv_internode_length);
-
957
-
958 parent_shoot->curvature_perturbation += - 0.5f*parent_shoot->curvature_perturbation*dt + parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
-
959 float curvature_angle = deg2rad((parent_shoot->gravitropic_curvature*current_curvature_fact * dr_internode_max + parent_shoot->curvature_perturbation));
-
960 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, shoot_bending_axis, curvature_angle);
-
961
-
962 parent_shoot->yaw_perturbation += - 0.5f*parent_shoot->yaw_perturbation*dt + parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
-
963 float yaw_angle = deg2rad((parent_shoot->yaw_perturbation));
-
964 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, make_vec3(0, 0, 1), yaw_angle);
-
965 }
-
966
-
967 phytomer_internode_vertices.at(inode_segment) = phytomer_internode_vertices.at(inode_segment - 1) + dr_internode * internode_axis;
-
968
-
969 phytomer_internode_radii.at(inode_segment) = internode_radius;
-
970 internode_colors.at(inode_segment) = phytomer_parameters.internode.color;
+
941 //internode pitch rotation for shoot base rotation
+
942 if( shoot_base_rotation.pitch!=0.f ) {
+
943 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, base_pitch_axis, -shoot_base_rotation.pitch);
+
944 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, base_pitch_axis, -shoot_base_rotation.pitch);
+
945 }
+
946
+
947 //internode yaw rotation for shoot base rotation
+
948 if( shoot_base_rotation.yaw!=0 ){
+
949 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, parent_internode_axis, shoot_base_rotation.yaw);
+
950 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, parent_internode_axis, shoot_base_rotation.yaw );
+
951 }
+
952
+
953 parent_shoot->radial_outward_axis = rotatePointAboutLine(internode_axis, nullorigin, petiole_rotation_axis, 0.5f*M_PI );
+
954
+
955 // if( parent_shoot->parent_shoot_ID>=0 ) { //if this is not the first shoot on the plant (i.e. it has a parent shoot
+
956 // auto parent_of_parent_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot->parent_shoot_ID);
+
957 // phytomer_internode_vertices.at(0) += parent_shoot->radial_outward_axis * parent_of_parent_shoot->shoot_internode_radii.at(parent_shoot->parent_node_index).back();
+
958 // }
+
959 } else {
+
960 //internode pitch rotation for phytomer base
+
961 if ( internode_pitch != 0) {
+
962 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, petiole_rotation_axis,-1.25f*internode_pitch );
+
963 }
+
964 }
+
965
+
966 vec3 shoot_bending_axis = cross(internode_axis, make_vec3(0, 0, 1));
+
967
+
968 internode_axis.normalize();
+
969 if (internode_axis == make_vec3(0, 0, 1)) {
+
970 shoot_bending_axis = make_vec3(0, 1, 0);
971 }
972
-
973 if( shoot_index.x==0 ) { //first phytomer on shoot
-
974 parent_shoot_ptr->shoot_internode_vertices.push_back(phytomer_internode_vertices);
-
975 parent_shoot_ptr->shoot_internode_radii.push_back(phytomer_internode_radii);
-
976 }else{ //if not the first phytomer on shoot, don't insert the first node because it's already defined on the previous phytomer
-
977 parent_shoot_ptr->shoot_internode_vertices.emplace_back(phytomer_internode_vertices.begin()+1,phytomer_internode_vertices.end());
-
978 parent_shoot_ptr->shoot_internode_radii.emplace_back(phytomer_internode_radii.begin()+1,phytomer_internode_radii.end());
-
979 }
-
980
-
981 //build internode context geometry
-
982 if (build_context_geometry_internode) {
-
983 //calculate texture coordinates
-
984 float texture_repeat_length = 0.25f; //meters
-
985 float length = 0; //shoot length prior to this phytomer
-
986 for (auto &phytomer: parent_shoot_ptr->phytomers) {
-
987 length += phytomer->internode_length_max;
-
988 }
-
989 std::vector<float> uv_y(phytomer_internode_vertices.size());
-
990 float dy = internode_length_max/float(uv_y.size()-1);
-
991 for( int j=0; j<uv_y.size(); j++ ){
-
992 uv_y.at(j) = (length+j*dy)/texture_repeat_length - std::floor((length+j*dy)/texture_repeat_length);
-
993 }
-
994
-
995 if( !context_ptr->doesObjectExist(parent_shoot->internode_tube_objID) ){ //first internode on shoot
-
996 if( !phytomer_parameters.internode.image_texture.empty() ){
-
997 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);
-
998 }else {
-
999 parent_shoot->internode_tube_objID = context_ptr->addTubeObject(Ndiv_internode_radius, phytomer_internode_vertices, phytomer_internode_radii, internode_colors);
-
1000 }
-
1001 }else{ //appending internode to shoot
-
1002 for (int inode_segment = 1; inode_segment <= Ndiv_internode_length; inode_segment++) {
-
1003 if( !phytomer_parameters.internode.image_texture.empty() ) {
-
1004 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)});
-
1005 }else {
-
1006 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));
-
1007 }
-
1008 }
-
1009 }
-
1010 }
-
1011
-
1012 //--- create petiole ---//
-
1013
-
1014 vec3 petiole_axis = internode_axis;
-
1015
-
1016 //petiole pitch rotation
-
1017 petiole_pitch = deg2rad(phytomer_parameters.petiole.pitch.val());
-
1018 phytomer_parameters.petiole.pitch.resample();
-
1019 if (fabs(petiole_pitch) < deg2rad(5.f)) {
-
1020 petiole_pitch = deg2rad(5.f);
-
1021 }
-
1022 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, petiole_rotation_axis, std::abs(petiole_pitch));
-
1023
-
1024 //petiole yaw rotation
-
1025 if( phytomer_index!=0 && internode_phyllotactic_angle!=0 ){ //not first phytomer along shoot
-
1026 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, internode_axis, internode_phyllotactic_angle );
-
1027 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, internode_axis, internode_phyllotactic_angle );
-
1028 }
-
1029
-
1030 //petiole curvature
-
1031 petiole_curvature = phytomer_parameters.petiole.curvature.val();
-
1032 phytomer_parameters.petiole.curvature.resample();
-
1033
-
1034 for(int petiole=0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++ ) { //looping over petioles
-
1035
-
1036 vec3 petiole_rotation_axis_actual = petiole_rotation_axis;
-
1037 vec3 petiole_axis_actual = petiole_axis;
+
973 // create internode tube
+
974 for (int inode_segment = 1; inode_segment <= Ndiv_internode_length; inode_segment++) {
+
975 //apply curvature and tortuosity
+
976 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
+
977
+
978 float current_curvature_fact = 0.5f - internode_axis.z / 2.f;
+
979 if (internode_axis.z < 0) {
+
980 current_curvature_fact *= 2.f;
+
981 }
+
982
+
983 float dt = dr_internode_max / float(Ndiv_internode_length);
+
984
+
985 parent_shoot->curvature_perturbation += - 0.5f*parent_shoot->curvature_perturbation*dt + parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
+
986 float curvature_angle = deg2rad((parent_shoot->gravitropic_curvature*current_curvature_fact * dr_internode_max + parent_shoot->curvature_perturbation));
+
987 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, shoot_bending_axis, curvature_angle);
+
988
+
989 parent_shoot->yaw_perturbation += - 0.5f*parent_shoot->yaw_perturbation*dt + parent_shoot_parameters.tortuosity.val()*context_ptr->randn()*sqrt(dt);
+
990 float yaw_angle = deg2rad((parent_shoot->yaw_perturbation));
+
991 internode_axis = rotatePointAboutLine(internode_axis, nullorigin, make_vec3(0, 0, 1), yaw_angle);
+
992 }
+
993
+
994 phytomer_internode_vertices.at(inode_segment) = phytomer_internode_vertices.at(inode_segment - 1) + dr_internode * internode_axis;
+
995
+
996 phytomer_internode_radii.at(inode_segment) = internode_radius;
+
997 internode_colors.at(inode_segment) = phytomer_parameters.internode.color;
+
998 }
+
999
+
1000 if( shoot_index.x==0 ) { //first phytomer on shoot
+
1001 parent_shoot_ptr->shoot_internode_vertices.push_back(phytomer_internode_vertices);
+
1002 parent_shoot_ptr->shoot_internode_radii.push_back(phytomer_internode_radii);
+
1003 }else{ //if not the first phytomer on shoot, don't insert the first node because it's already defined on the previous phytomer
+
1004 parent_shoot_ptr->shoot_internode_vertices.emplace_back(phytomer_internode_vertices.begin()+1,phytomer_internode_vertices.end());
+
1005 parent_shoot_ptr->shoot_internode_radii.emplace_back(phytomer_internode_radii.begin()+1,phytomer_internode_radii.end());
+
1006 }
+
1007
+
1008 //build internode context geometry
+
1009 if (build_context_geometry_internode) {
+
1010 //calculate texture coordinates
+
1011 float texture_repeat_length = 0.25f; //meters
+
1012 float length = 0; //shoot length prior to this phytomer
+
1013 for (auto &phytomer: parent_shoot_ptr->phytomers) {
+
1014 length += phytomer->internode_length_max;
+
1015 }
+
1016 std::vector<float> uv_y(phytomer_internode_vertices.size());
+
1017 float dy = internode_length_max/float(uv_y.size()-1);
+
1018 for( int j=0; j<uv_y.size(); j++ ){
+
1019 uv_y.at(j) = (length+j*dy)/texture_repeat_length - std::floor((length+j*dy)/texture_repeat_length);
+
1020 }
+
1021
+
1022 if( !context_ptr->doesObjectExist(parent_shoot->internode_tube_objID) ){ //first internode on shoot
+
1023 if( !phytomer_parameters.internode.image_texture.empty() ){
+
1024 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);
+
1025 }else {
+
1026 parent_shoot->internode_tube_objID = context_ptr->addTubeObject(Ndiv_internode_radius, phytomer_internode_vertices, phytomer_internode_radii, internode_colors);
+
1027 }
+
1028 }else{ //appending internode to shoot
+
1029 for (int inode_segment = 1; inode_segment <= Ndiv_internode_length; inode_segment++) {
+
1030 if( !phytomer_parameters.internode.image_texture.empty() ) {
+
1031 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)});
+
1032 }else {
+
1033 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));
+
1034 }
+
1035 }
+
1036 }
+
1037 }
1038
-
1039 if (petiole > 0) {
-
1040 float budrot = float(petiole) * 2.f * M_PI / float(phytomer_parameters.petiole.petioles_per_internode);
-
1041 petiole_axis_actual = rotatePointAboutLine(petiole_axis_actual, nullorigin, internode_axis, budrot );
-
1042 petiole_rotation_axis_actual = rotatePointAboutLine(petiole_rotation_axis_actual, nullorigin, internode_axis, budrot );
-
1043 }
-
1044
-
1045 petiole_vertices.at(petiole).at(0) = phytomer_internode_vertices.back();
-
1046
-
1047 for (int j = 1; j <= Ndiv_petiole_length; j++) {
-
1048
-
1049 if( fabs(petiole_curvature)>0 ) {
-
1050 petiole_axis_actual = rotatePointAboutLine(petiole_axis_actual, nullorigin, petiole_rotation_axis_actual, -deg2rad(petiole_curvature * dr_petiole_max.at(petiole)));
-
1051 }
-
1052
-
1053 petiole_vertices.at(petiole).at(j) = petiole_vertices.at(petiole).at(j - 1) + dr_petiole.at(petiole) * petiole_axis_actual;
-
1054
-
1055 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) );
-
1056 petiole_colors.at(j) = phytomer_parameters.petiole.color;
-
1057 }
-
1058
-
1059 if( build_context_geometry_petiole && petiole_radii.at(petiole).front() > 0.f ) {
-
1060 petiole_objIDs.at(petiole) = makeTubeFromCones(Ndiv_petiole_radius, petiole_vertices.at(petiole), petiole_radii.at(petiole), petiole_colors, context_ptr);
-
1061 }
+
1039 //--- create petiole ---//
+
1040
+
1041 vec3 petiole_axis = internode_axis;
+
1042
+
1043 //petiole pitch rotation
+
1044 petiole_pitch = deg2rad(phytomer_parameters.petiole.pitch.val());
+
1045 phytomer_parameters.petiole.pitch.resample();
+
1046 if (fabs(petiole_pitch) < deg2rad(5.f)) {
+
1047 petiole_pitch = deg2rad(5.f);
+
1048 }
+
1049 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, petiole_rotation_axis, std::abs(petiole_pitch));
+
1050
+
1051 //petiole yaw rotation
+
1052 if( phytomer_index!=0 && internode_phyllotactic_angle!=0 ){ //not first phytomer along shoot
+
1053 petiole_axis = rotatePointAboutLine(petiole_axis, nullorigin, internode_axis, internode_phyllotactic_angle );
+
1054 petiole_rotation_axis = rotatePointAboutLine(petiole_rotation_axis, nullorigin, internode_axis, internode_phyllotactic_angle );
+
1055 }
+
1056
+
1057 //petiole curvature
+
1058 petiole_curvature = phytomer_parameters.petiole.curvature.val();
+
1059 phytomer_parameters.petiole.curvature.resample();
+
1060
+
1061 for(int petiole=0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++ ) { //looping over petioles
1062
-
1063 //--- create buds ---//
-
1064
-
1065 std::vector<VegetativeBud> vegetative_buds_new;
-
1066 vegetative_buds_new.resize(phytomer_parameters.internode.max_vegetative_buds_per_petiole.val());
-
1067 phytomer_parameters.internode.max_vegetative_buds_per_petiole.resample();
-
1068
-
1069 axillary_vegetative_buds.push_back(vegetative_buds_new);
-
1070
-
1071 std::vector<FloralBud> floral_buds_new;
-
1072 floral_buds_new.resize(phytomer_parameters.internode.max_floral_buds_per_petiole.val());
-
1073 phytomer_parameters.internode.max_floral_buds_per_petiole.resample();
-
1074
-
1075 uint index = 0;
-
1076 for (auto &fbud: floral_buds_new) {
-
1077 fbud.bud_index = index;
-
1078 fbud.parent_index = petiole;
-
1079 float pitch_adjustment = fbud.bud_index * 0.1f * M_PI / float(axillary_vegetative_buds.size());
-
1080 float yaw_adjustment = -0.25f * M_PI + fbud.bud_index * 0.5f * M_PI / float(axillary_vegetative_buds.size());
-
1081 fbud.base_rotation = make_AxisRotation(pitch_adjustment, yaw_adjustment, 0);
-
1082 fbud.base_position = phytomer_internode_vertices.back();
-
1083 fbud.bending_axis = shoot_bending_axis;
-
1084 index++;
-
1085 }
-
1086
-
1087 floral_buds.push_back(floral_buds_new);
-
1088
-
1089 //--- create leaves ---//
-
1090
-
1091 if(phytomer_parameters.leaf.prototype.prototype_function == nullptr ){
-
1092 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Leaf prototype function was not defined for shoot type " + parent_shoot->shoot_type_label + ".");
-
1093 }
-
1094
-
1095 vec3 petiole_tip_axis = getPetioleAxisVector(1.f, petiole);
-
1096
-
1097 vec3 leaf_rotation_axis = cross(internode_axis, petiole_tip_axis);
-
1098
-
1099 // Create unique leaf prototypes for each shoot type so we can simply copy them for each leaf
-
1100 // if( phytomer_parameters.leaf.prototype.unique_prototypes>0 && plantarchitecture_ptr->unique_leaf_prototype_objIDs.find(phytomer_parameters.leaf.prototype.prototype_function) == plantarchitecture_ptr->unique_leaf_prototype_objIDs.end() ) {
-
1101 // plantarchitecture_ptr->unique_leaf_prototype_objIDs[phytomer_parameters.leaf.prototype.prototype_function].resize(phytomer_parameters.leaf.prototype.unique_prototypes);
-
1102 // for( int prototype = 0; prototype < phytomer_parameters.leaf.prototype.unique_prototypes; prototype++ ) {
-
1103 // for (int leaf = 0; leaf < leaves_per_petiole; leaf++) {
-
1104 // float ind_from_tip = float(leaf) - float(leaves_per_petiole - 1) / 2.f;
-
1105 // uint objID_leaf = phytomer_parameters.leaf.prototype.prototype_function(context_ptr, &phytomer_parameters.leaf.prototype, ind_from_tip);
-
1106 // plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.prototype_function).at(prototype).push_back(objID_leaf);
-
1107 // std::vector<uint> petiolule_UUIDs = context_ptr->filterPrimitivesByData( context_ptr->getObjectPrimitiveUUIDs(objID_leaf), "object_label", "petiolule" );
-
1108 // context_ptr->setPrimitiveColor( petiolule_UUIDs, phytomer_parameters.petiole.color );
-
1109 // context_ptr->hideObject({objID_leaf});
-
1110 // }
-
1111 // }
-
1112 // }
-
1113 assert( phytomer_parameters.leaf.prototype.unique_prototype_identifier!=0 );
-
1114 if( phytomer_parameters.leaf.prototype.unique_prototypes>0 && plantarchitecture_ptr->unique_leaf_prototype_objIDs.find(phytomer_parameters.leaf.prototype.unique_prototype_identifier) == plantarchitecture_ptr->unique_leaf_prototype_objIDs.end() ) {
-
1115 plantarchitecture_ptr->unique_leaf_prototype_objIDs[phytomer_parameters.leaf.prototype.unique_prototype_identifier].resize(phytomer_parameters.leaf.prototype.unique_prototypes);
-
1116 for( int prototype = 0; prototype < phytomer_parameters.leaf.prototype.unique_prototypes; prototype++ ) {
-
1117 for (int leaf = 0; leaf < leaves_per_petiole; leaf++) {
-
1118 float ind_from_tip = float(leaf) - float(leaves_per_petiole - 1) / 2.f;
-
1119 uint objID_leaf = phytomer_parameters.leaf.prototype.prototype_function(context_ptr, &phytomer_parameters.leaf.prototype, ind_from_tip);
-
1120 plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.unique_prototype_identifier).at(prototype).push_back(objID_leaf);
-
1121 std::vector<uint> petiolule_UUIDs = context_ptr->filterPrimitivesByData( context_ptr->getObjectPrimitiveUUIDs(objID_leaf), "object_label", "petiolule" );
-
1122 context_ptr->setPrimitiveColor( petiolule_UUIDs, phytomer_parameters.petiole.color );
-
1123 context_ptr->hideObject({objID_leaf});
-
1124 }
-
1125 }
-
1126 }
-
1127
-
1128 for (int leaf = 0; leaf < leaves_per_petiole; leaf++) {
-
1129 float ind_from_tip = float(leaf) - float(leaves_per_petiole - 1) / 2.f;
-
1130
-
1131 uint objID_leaf;
-
1132 // if( phytomer_parameters.leaf.prototype.unique_prototypes>0 ) { //copy the existing prototype
-
1133 // int prototype = context_ptr->randu(0, phytomer_parameters.leaf.prototype.unique_prototypes - 1);
-
1134 // objID_leaf = context_ptr->copyObject(plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.prototype_function).at(prototype).at(leaf));
-
1135 // }else{ //load a new prototype
-
1136 // objID_leaf = phytomer_parameters.leaf.prototype.prototype_function(context_ptr, &phytomer_parameters.leaf.prototype, ind_from_tip);
-
1137 // }
-
1138 if( phytomer_parameters.leaf.prototype.unique_prototypes>0 ) { //copy the existing prototype
-
1139 int prototype = context_ptr->randu(0, phytomer_parameters.leaf.prototype.unique_prototypes - 1);
-
1140 assert( plantarchitecture_ptr->unique_leaf_prototype_objIDs.find(phytomer_parameters.leaf.prototype.unique_prototype_identifier) != plantarchitecture_ptr->unique_leaf_prototype_objIDs.end() );
-
1141 assert( plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.unique_prototype_identifier).size()>prototype);
-
1142 assert( plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.unique_prototype_identifier).at(prototype).size()>leaf);
-
1143 objID_leaf = context_ptr->copyObject(plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.unique_prototype_identifier).at(prototype).at(leaf));
-
1144 }else{ //load a new prototype
-
1145 objID_leaf = phytomer_parameters.leaf.prototype.prototype_function(context_ptr, &phytomer_parameters.leaf.prototype, ind_from_tip);
-
1146 }
-
1147
-
1148 // -- leaf scaling -- //
-
1149
-
1150 if( leaves_per_petiole>0 && phytomer_parameters.leaf.leaflet_scale.val()!=1.f && ind_from_tip!=0 ){
-
1151 leaf_size_max.at(petiole).at(leaf) = powf(phytomer_parameters.leaf.leaflet_scale.val(),fabs(ind_from_tip))*phytomer_parameters.leaf.prototype_scale.val();
-
1152 }else{
-
1153 leaf_size_max.at(petiole).at(leaf) = phytomer_parameters.leaf.prototype_scale.val();
-
1154 }
-
1155 vec3 leaf_scale = leaf_scale_factor_fraction * leaf_size_max.at(petiole).at(leaf) * make_vec3(1, 1, 1);
-
1156
-
1157 context_ptr->scaleObject(objID_leaf, leaf_scale);
-
1158
-
1159 float compound_rotation = 0;
-
1160 if (leaves_per_petiole > 1) {
-
1161 if (phytomer_parameters.leaf.leaflet_offset.val() == 0) {
-
1162 float dphi = M_PI / (floor(0.5 * float(leaves_per_petiole - 1)) + 1);
-
1163 compound_rotation = -float(M_PI) + dphi * (leaf + 0.5f);
-
1164 } else {
-
1165 if( leaf == float(leaves_per_petiole-1)/2.f ){ //tip leaf
-
1166 compound_rotation = 0;
-
1167 } else if (leaf < float(leaves_per_petiole - 1) / 2.f) {
-
1168 compound_rotation = -0.5 * M_PI;
-
1169 } else {
-
1170 compound_rotation = 0.5 * M_PI;
-
1171 }
-
1172 }
+
1063 vec3 petiole_rotation_axis_actual = petiole_rotation_axis;
+
1064 vec3 petiole_axis_actual = petiole_axis;
+
1065
+
1066 if (petiole > 0) {
+
1067 float budrot = float(petiole) * 2.f * M_PI / float(phytomer_parameters.petiole.petioles_per_internode);
+
1068 petiole_axis_actual = rotatePointAboutLine(petiole_axis_actual, nullorigin, internode_axis, budrot );
+
1069 petiole_rotation_axis_actual = rotatePointAboutLine(petiole_rotation_axis_actual, nullorigin, internode_axis, budrot );
+
1070 }
+
1071
+
1072 petiole_vertices.at(petiole).at(0) = phytomer_internode_vertices.back();
+
1073
+
1074 for (int j = 1; j <= Ndiv_petiole_length; j++) {
+
1075
+
1076 if( fabs(petiole_curvature)>0 ) {
+
1077 petiole_axis_actual = rotatePointAboutLine(petiole_axis_actual, nullorigin, petiole_rotation_axis_actual, -deg2rad(petiole_curvature * dr_petiole_max.at(petiole)));
+
1078 }
+
1079
+
1080 petiole_vertices.at(petiole).at(j) = petiole_vertices.at(petiole).at(j - 1) + dr_petiole.at(petiole) * petiole_axis_actual;
+
1081
+
1082 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) );
+
1083 petiole_colors.at(j) = phytomer_parameters.petiole.color;
+
1084 }
+
1085
+
1086 if( build_context_geometry_petiole && petiole_radii.at(petiole).front() > 0.f ) {
+
1087 petiole_objIDs.at(petiole) = makeTubeFromCones(Ndiv_petiole_radius, petiole_vertices.at(petiole), petiole_radii.at(petiole), petiole_colors, context_ptr);
+
1088 }
+
1089
+
1090 //--- create buds ---//
+
1091
+
1092 std::vector<VegetativeBud> vegetative_buds_new;
+
1093 vegetative_buds_new.resize(phytomer_parameters.internode.max_vegetative_buds_per_petiole.val());
+
1094 phytomer_parameters.internode.max_vegetative_buds_per_petiole.resample();
+
1095
+
1096 axillary_vegetative_buds.push_back(vegetative_buds_new);
+
1097
+
1098 std::vector<FloralBud> floral_buds_new;
+
1099 floral_buds_new.resize(phytomer_parameters.internode.max_floral_buds_per_petiole.val());
+
1100 phytomer_parameters.internode.max_floral_buds_per_petiole.resample();
+
1101
+
1102 uint index = 0;
+
1103 for (auto &fbud: floral_buds_new) {
+
1104 fbud.bud_index = index;
+
1105 fbud.parent_index = petiole;
+
1106 float pitch_adjustment = fbud.bud_index * 0.1f * M_PI / float(axillary_vegetative_buds.size());
+
1107 float yaw_adjustment = -0.25f * M_PI + fbud.bud_index * 0.5f * M_PI / float(axillary_vegetative_buds.size());
+
1108 fbud.base_rotation = make_AxisRotation(pitch_adjustment, yaw_adjustment, 0);
+
1109 fbud.base_position = phytomer_internode_vertices.back();
+
1110 fbud.bending_axis = shoot_bending_axis;
+
1111 index++;
+
1112 }
+
1113
+
1114 floral_buds.push_back(floral_buds_new);
+
1115
+
1116 //--- create leaves ---//
+
1117
+
1118 if(phytomer_parameters.leaf.prototype.prototype_function == nullptr ){
+
1119 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Leaf prototype function was not defined for shoot type " + parent_shoot->shoot_type_label + ".");
+
1120 }
+
1121
+
1122 vec3 petiole_tip_axis = getPetioleAxisVector(1.f, petiole);
+
1123
+
1124 vec3 leaf_rotation_axis = cross(internode_axis, petiole_tip_axis);
+
1125
+
1126 // Create unique leaf prototypes for each shoot type so we can simply copy them for each leaf
+
1127 // if( phytomer_parameters.leaf.prototype.unique_prototypes>0 && plantarchitecture_ptr->unique_leaf_prototype_objIDs.find(phytomer_parameters.leaf.prototype.prototype_function) == plantarchitecture_ptr->unique_leaf_prototype_objIDs.end() ) {
+
1128 // plantarchitecture_ptr->unique_leaf_prototype_objIDs[phytomer_parameters.leaf.prototype.prototype_function].resize(phytomer_parameters.leaf.prototype.unique_prototypes);
+
1129 // for( int prototype = 0; prototype < phytomer_parameters.leaf.prototype.unique_prototypes; prototype++ ) {
+
1130 // for (int leaf = 0; leaf < leaves_per_petiole; leaf++) {
+
1131 // float ind_from_tip = float(leaf) - float(leaves_per_petiole - 1) / 2.f;
+
1132 // uint objID_leaf = phytomer_parameters.leaf.prototype.prototype_function(context_ptr, &phytomer_parameters.leaf.prototype, ind_from_tip);
+
1133 // plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.prototype_function).at(prototype).push_back(objID_leaf);
+
1134 // std::vector<uint> petiolule_UUIDs = context_ptr->filterPrimitivesByData( context_ptr->getObjectPrimitiveUUIDs(objID_leaf), "object_label", "petiolule" );
+
1135 // context_ptr->setPrimitiveColor( petiolule_UUIDs, phytomer_parameters.petiole.color );
+
1136 // context_ptr->hideObject({objID_leaf});
+
1137 // }
+
1138 // }
+
1139 // }
+
1140 assert( phytomer_parameters.leaf.prototype.unique_prototype_identifier!=0 );
+
1141 if( phytomer_parameters.leaf.prototype.unique_prototypes>0 && plantarchitecture_ptr->unique_leaf_prototype_objIDs.find(phytomer_parameters.leaf.prototype.unique_prototype_identifier) == plantarchitecture_ptr->unique_leaf_prototype_objIDs.end() ) {
+
1142 plantarchitecture_ptr->unique_leaf_prototype_objIDs[phytomer_parameters.leaf.prototype.unique_prototype_identifier].resize(phytomer_parameters.leaf.prototype.unique_prototypes);
+
1143 for( int prototype = 0; prototype < phytomer_parameters.leaf.prototype.unique_prototypes; prototype++ ) {
+
1144 for (int leaf = 0; leaf < leaves_per_petiole; leaf++) {
+
1145 float ind_from_tip = float(leaf) - float(leaves_per_petiole - 1) / 2.f;
+
1146 uint objID_leaf = phytomer_parameters.leaf.prototype.prototype_function(context_ptr, &phytomer_parameters.leaf.prototype, ind_from_tip);
+
1147 plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.unique_prototype_identifier).at(prototype).push_back(objID_leaf);
+
1148 std::vector<uint> petiolule_UUIDs = context_ptr->filterPrimitivesByData( context_ptr->getObjectPrimitiveUUIDs(objID_leaf), "object_label", "petiolule" );
+
1149 context_ptr->setPrimitiveColor( petiolule_UUIDs, phytomer_parameters.petiole.color );
+
1150 context_ptr->hideObject({objID_leaf});
+
1151 }
+
1152 }
+
1153 }
+
1154
+
1155 for (int leaf = 0; leaf < leaves_per_petiole; leaf++) {
+
1156 float ind_from_tip = float(leaf) - float(leaves_per_petiole - 1) / 2.f;
+
1157
+
1158 uint objID_leaf;
+
1159 // if( phytomer_parameters.leaf.prototype.unique_prototypes>0 ) { //copy the existing prototype
+
1160 // int prototype = context_ptr->randu(0, phytomer_parameters.leaf.prototype.unique_prototypes - 1);
+
1161 // objID_leaf = context_ptr->copyObject(plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.prototype_function).at(prototype).at(leaf));
+
1162 // }else{ //load a new prototype
+
1163 // objID_leaf = phytomer_parameters.leaf.prototype.prototype_function(context_ptr, &phytomer_parameters.leaf.prototype, ind_from_tip);
+
1164 // }
+
1165 if( phytomer_parameters.leaf.prototype.unique_prototypes>0 ) { //copy the existing prototype
+
1166 int prototype = context_ptr->randu(0, phytomer_parameters.leaf.prototype.unique_prototypes - 1);
+
1167 assert( plantarchitecture_ptr->unique_leaf_prototype_objIDs.find(phytomer_parameters.leaf.prototype.unique_prototype_identifier) != plantarchitecture_ptr->unique_leaf_prototype_objIDs.end() );
+
1168 assert( plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.unique_prototype_identifier).size()>prototype);
+
1169 assert( plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.unique_prototype_identifier).at(prototype).size()>leaf);
+
1170 objID_leaf = context_ptr->copyObject(plantarchitecture_ptr->unique_leaf_prototype_objIDs.at(phytomer_parameters.leaf.prototype.unique_prototype_identifier).at(prototype).at(leaf));
+
1171 }else{ //load a new prototype
+
1172 objID_leaf = phytomer_parameters.leaf.prototype.prototype_function(context_ptr, &phytomer_parameters.leaf.prototype, ind_from_tip);
1173 }
1174
-
1175 // -- leaf rotations -- //
+
1175 // -- leaf scaling -- //
1176
-
1177 //leaf roll rotation
-
1178 float roll_rot = 0;
-
1179 if( leaves_per_petiole==1 ){
-
1180 int sign = (shoot_index.x%2==0) ? 1 : -1;
-
1181 roll_rot = (acos_safe(internode_axis.z)-deg2rad(phytomer_parameters.leaf.roll.val()))*sign;
-
1182 } else if( ind_from_tip!= 0){
-
1183 roll_rot = (asin_safe(petiole_tip_axis.z)+deg2rad(phytomer_parameters.leaf.roll.val()))*compound_rotation/std::fabs(compound_rotation);
-
1184 }
-
1185 leaf_rotation.at(petiole).at(leaf).roll = deg2rad(phytomer_parameters.leaf.roll.val());
-
1186 phytomer_parameters.leaf.roll.resample();
-
1187 context_ptr->rotateObject(objID_leaf, roll_rot, "x");
-
1188
-
1189 //leaf pitch rotation
-
1190 leaf_rotation.at(petiole).at(leaf).pitch = deg2rad(phytomer_parameters.leaf.pitch.val());
-
1191 float pitch_rot = leaf_rotation.at(petiole).at(leaf).pitch;
-
1192 phytomer_parameters.leaf.pitch.resample();
-
1193 if (ind_from_tip == 0) {
-
1194 pitch_rot += asin_safe(petiole_tip_axis.z);
-
1195 }
-
1196 context_ptr->rotateObject(objID_leaf, -pitch_rot, "y");
-
1197
-
1198 //leaf yaw rotation
-
1199 if (ind_from_tip != 0) {
-
1200 float sign = -compound_rotation / fabs(compound_rotation);
-
1201 leaf_rotation.at(petiole).at(leaf).yaw = sign * deg2rad(phytomer_parameters.leaf.yaw.val());
-
1202 float yaw_rot = leaf_rotation.at(petiole).at(leaf).yaw;
-
1203 phytomer_parameters.leaf.yaw.resample();
-
1204 context_ptr->rotateObject(objID_leaf, yaw_rot, "z");
-
1205 } else {
-
1206 leaf_rotation.at(petiole).at(leaf).yaw = 0;
-
1207 }
-
1208
-
1209 //rotate leaf to azimuth of petiole
-
1210 context_ptr->rotateObject( objID_leaf, -std::atan2(petiole_tip_axis.y, petiole_tip_axis.x)+compound_rotation, "z" );
-
1211
-
1212
-
1213 // -- leaf translation -- //
-
1214
-
1215 vec3 leaf_base = petiole_vertices.at(petiole).back();
-
1216 if( leaves_per_petiole>1 && phytomer_parameters.leaf.leaflet_offset.val()>0 ){
-
1217 if( ind_from_tip != 0 ) {
-
1218 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
-
1219 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val() );
-
1220 }
-
1221 }
-
1222
-
1223 context_ptr->translateObject(objID_leaf, leaf_base);
+
1177 if( leaves_per_petiole>0 && phytomer_parameters.leaf.leaflet_scale.val()!=1.f && ind_from_tip!=0 ){
+
1178 leaf_size_max.at(petiole).at(leaf) = powf(phytomer_parameters.leaf.leaflet_scale.val(),fabs(ind_from_tip))*phytomer_parameters.leaf.prototype_scale.val();
+
1179 }else{
+
1180 leaf_size_max.at(petiole).at(leaf) = phytomer_parameters.leaf.prototype_scale.val();
+
1181 }
+
1182 vec3 leaf_scale = leaf_scale_factor_fraction * leaf_size_max.at(petiole).at(leaf) * make_vec3(1, 1, 1);
+
1183
+
1184 context_ptr->scaleObject(objID_leaf, leaf_scale);
+
1185
+
1186 float compound_rotation = 0;
+
1187 if (leaves_per_petiole > 1) {
+
1188 if (phytomer_parameters.leaf.leaflet_offset.val() == 0) {
+
1189 float dphi = M_PI / (floor(0.5 * float(leaves_per_petiole - 1)) + 1);
+
1190 compound_rotation = -float(M_PI) + dphi * (leaf + 0.5f);
+
1191 } else {
+
1192 if( leaf == float(leaves_per_petiole-1)/2.f ){ //tip leaf
+
1193 compound_rotation = 0;
+
1194 } else if (leaf < float(leaves_per_petiole - 1) / 2.f) {
+
1195 compound_rotation = -0.5 * M_PI;
+
1196 } else {
+
1197 compound_rotation = 0.5 * M_PI;
+
1198 }
+
1199 }
+
1200 }
+
1201
+
1202 // -- leaf rotations -- //
+
1203
+
1204 //leaf roll rotation
+
1205 float roll_rot = 0;
+
1206 if( leaves_per_petiole==1 ){
+
1207 int sign = (shoot_index.x%2==0) ? 1 : -1;
+
1208 roll_rot = (acos_safe(internode_axis.z)-deg2rad(phytomer_parameters.leaf.roll.val()))*sign;
+
1209 } else if( ind_from_tip!= 0){
+
1210 roll_rot = (asin_safe(petiole_tip_axis.z)+deg2rad(phytomer_parameters.leaf.roll.val()))*compound_rotation/std::fabs(compound_rotation);
+
1211 }
+
1212 leaf_rotation.at(petiole).at(leaf).roll = deg2rad(phytomer_parameters.leaf.roll.val());
+
1213 phytomer_parameters.leaf.roll.resample();
+
1214 context_ptr->rotateObject(objID_leaf, roll_rot, "x");
+
1215
+
1216 //leaf pitch rotation
+
1217 leaf_rotation.at(petiole).at(leaf).pitch = deg2rad(phytomer_parameters.leaf.pitch.val());
+
1218 float pitch_rot = leaf_rotation.at(petiole).at(leaf).pitch;
+
1219 phytomer_parameters.leaf.pitch.resample();
+
1220 if (ind_from_tip == 0) {
+
1221 pitch_rot += asin_safe(petiole_tip_axis.z);
+
1222 }
+
1223 context_ptr->rotateObject(objID_leaf, -pitch_rot, "y");
1224
-
1225 leaf_objIDs.at(petiole).push_back(objID_leaf);
-
1226 leaf_bases.at(petiole).push_back(leaf_base);
-
1227 }
-
1228 phytomer_parameters.leaf.prototype_scale.resample();
-
1229
-
1230 if (petiole_axis_actual == make_vec3(0, 0, 1)) {
-
1231 inflorescence_bending_axis = make_vec3(1, 0, 0);
-
1232 } else {
-
1233 inflorescence_bending_axis = cross(make_vec3(0, 0, 1), petiole_axis_actual);
-
1234 }
-
1235 }
-
1236}
-
1237
-
1238void Phytomer::updateInflorescence(FloralBud &fbud) {
-
1239 bool build_context_geometry_peduncle = plantarchitecture_ptr->build_context_geometry_peduncle;
-
1240
-
1241 uint Ndiv_peduncle_length = std::max(uint(1), phytomer_parameters.peduncle.length_segments);
-
1242 uint Ndiv_peduncle_radius = std::max(uint(3), phytomer_parameters.peduncle.radial_subdivisions);
-
1243 if (phytomer_parameters.peduncle.length_segments == 0 || phytomer_parameters.peduncle.radial_subdivisions < 3) {
-
1244 build_context_geometry_peduncle = false;
-
1245 }
-
1246
-
1247 float dr_peduncle = phytomer_parameters.peduncle.length.val() / float(Ndiv_peduncle_length);
-
1248 phytomer_parameters.peduncle.length.resample();
+
1225 //leaf yaw rotation
+
1226 if (ind_from_tip != 0) {
+
1227 float sign = -compound_rotation / fabs(compound_rotation);
+
1228 leaf_rotation.at(petiole).at(leaf).yaw = sign * deg2rad(phytomer_parameters.leaf.yaw.val());
+
1229 float yaw_rot = leaf_rotation.at(petiole).at(leaf).yaw;
+
1230 phytomer_parameters.leaf.yaw.resample();
+
1231 context_ptr->rotateObject(objID_leaf, yaw_rot, "z");
+
1232 } else {
+
1233 leaf_rotation.at(petiole).at(leaf).yaw = 0;
+
1234 }
+
1235
+
1236 //rotate leaf to azimuth of petiole
+
1237 context_ptr->rotateObject( objID_leaf, -std::atan2(petiole_tip_axis.y, petiole_tip_axis.x)+compound_rotation, "z" );
+
1238
+
1239
+
1240 // -- leaf translation -- //
+
1241
+
1242 vec3 leaf_base = petiole_vertices.at(petiole).back();
+
1243 if( leaves_per_petiole>1 && phytomer_parameters.leaf.leaflet_offset.val()>0 ){
+
1244 if( ind_from_tip != 0 ) {
+
1245 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
+
1246 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val() );
+
1247 }
+
1248 }
1249
-
1250 std::vector<vec3> peduncle_vertices(phytomer_parameters.peduncle.length_segments + 1);
-
1251 peduncle_vertices.at(0) = fbud.base_position;
-
1252 std::vector<float> peduncle_radii(phytomer_parameters.peduncle.length_segments + 1);
-
1253 peduncle_radii.at(0) = phytomer_parameters.peduncle.radius.val();
-
1254 std::vector<RGBcolor> peduncle_colors(phytomer_parameters.peduncle.length_segments + 1);
-
1255 peduncle_colors.at(0) = phytomer_parameters.peduncle.color;
+
1250 context_ptr->translateObject(objID_leaf, leaf_base);
+
1251
+
1252 leaf_objIDs.at(petiole).push_back(objID_leaf);
+
1253 leaf_bases.at(petiole).push_back(leaf_base);
+
1254 }
+
1255 phytomer_parameters.leaf.prototype_scale.resample();
1256
-
1257 vec3 peduncle_axis = getAxisVector(1.f, getInternodeNodePositions());
-
1258
-
1259 //peduncle pitch rotation
-
1260 if( phytomer_parameters.peduncle.pitch.val()!=0.f || fbud.base_rotation.pitch!=0.f ) {
-
1261 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, deg2rad(phytomer_parameters.peduncle.pitch.val())+fbud.base_rotation.pitch );
-
1262 phytomer_parameters.peduncle.pitch.resample();
-
1263 }
+
1257 if (petiole_axis_actual == make_vec3(0, 0, 1)) {
+
1258 inflorescence_bending_axis = make_vec3(1, 0, 0);
+
1259 } else {
+
1260 inflorescence_bending_axis = cross(make_vec3(0, 0, 1), petiole_axis_actual);
+
1261 }
+
1262 }
+
1263}
1264
-
1265 //rotate peduncle to azimuth of petiole and apply peduncle base yaw rotation
-
1266 vec3 internode_axis = getAxisVector(1.f, getInternodeNodePositions());
-
1267 vec3 parent_petiole_base_axis = getPetioleAxisVector(0.f, fbud.parent_index);
-
1268 float parent_petiole_azimuth = -std::atan2(parent_petiole_base_axis.y, parent_petiole_base_axis.x);
-
1269 float current_peduncle_azimuth = -std::atan2(peduncle_axis.y, peduncle_axis.x);
-
1270 peduncle_axis = rotatePointAboutLine( peduncle_axis, nullorigin, internode_axis, (current_peduncle_azimuth-parent_petiole_azimuth) );
-
1271
-
1272
-
1273 float theta_base = fabs(cart2sphere(peduncle_axis).zenith);
-
1274
-
1275 for (int i = 1; i <= phytomer_parameters.peduncle.length_segments; i++) {
-
1276 if (phytomer_parameters.peduncle.curvature.val() != 0.f) {
-
1277 float theta_curvature = -deg2rad(phytomer_parameters.peduncle.curvature.val() * dr_peduncle);
-
1278 phytomer_parameters.peduncle.curvature.resample();
-
1279 if (fabs(theta_curvature) * float(i) < M_PI - theta_base) {
-
1280 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, theta_curvature);
-
1281 } else {
-
1282 peduncle_axis = make_vec3(0, 0, -1);
-
1283 }
-
1284 }
+
1265void Phytomer::updateInflorescence(FloralBud &fbud) {
+
1266 bool build_context_geometry_peduncle = plantarchitecture_ptr->build_context_geometry_peduncle;
+
1267
+
1268 uint Ndiv_peduncle_length = std::max(uint(1), phytomer_parameters.peduncle.length_segments);
+
1269 uint Ndiv_peduncle_radius = std::max(uint(3), phytomer_parameters.peduncle.radial_subdivisions);
+
1270 if (phytomer_parameters.peduncle.length_segments == 0 || phytomer_parameters.peduncle.radial_subdivisions < 3) {
+
1271 build_context_geometry_peduncle = false;
+
1272 }
+
1273
+
1274 float dr_peduncle = phytomer_parameters.peduncle.length.val() / float(Ndiv_peduncle_length);
+
1275 phytomer_parameters.peduncle.length.resample();
+
1276
+
1277 std::vector<vec3> peduncle_vertices(phytomer_parameters.peduncle.length_segments + 1);
+
1278 peduncle_vertices.at(0) = fbud.base_position;
+
1279 std::vector<float> peduncle_radii(phytomer_parameters.peduncle.length_segments + 1);
+
1280 peduncle_radii.at(0) = phytomer_parameters.peduncle.radius.val();
+
1281 std::vector<RGBcolor> peduncle_colors(phytomer_parameters.peduncle.length_segments + 1);
+
1282 peduncle_colors.at(0) = phytomer_parameters.peduncle.color;
+
1283
+
1284 vec3 peduncle_axis = getAxisVector(1.f, getInternodeNodePositions());
1285
-
1286 peduncle_vertices.at(i) = peduncle_vertices.at(i - 1) + dr_peduncle * peduncle_axis;
-
1287
-
1288 peduncle_radii.at(i) = phytomer_parameters.peduncle.radius.val();
-
1289 peduncle_colors.at(i) = phytomer_parameters.peduncle.color;
+
1286 //peduncle pitch rotation
+
1287 if( phytomer_parameters.peduncle.pitch.val()!=0.f || fbud.base_rotation.pitch!=0.f ) {
+
1288 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, deg2rad(phytomer_parameters.peduncle.pitch.val())+fbud.base_rotation.pitch );
+
1289 phytomer_parameters.peduncle.pitch.resample();
1290 }
-
1291 phytomer_parameters.peduncle.radius.resample();
-
1292
-
1293 if( build_context_geometry_peduncle) {
-
1294 fbud.peduncle_objIDs.push_back(context_ptr->addTubeObject(Ndiv_peduncle_radius, peduncle_vertices, peduncle_radii, peduncle_colors));
-
1295 }
-
1296
-
1297 // Create unique inflorescence prototypes for each shoot type so we can simply copy them for each leaf
-
1298 std::string parent_shoot_type_label = plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(parent_shoot_ID)->shoot_type_label;
-
1299 if( phytomer_parameters.inflorescence.unique_prototypes>0 ){
-
1300 //closed flowers
-
1301 if( phytomer_parameters.inflorescence.flower_prototype_function!= nullptr && plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.find(phytomer_parameters.inflorescence.flower_prototype_function) == plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.end() ) {
-
1302 plantarchitecture_ptr->unique_closed_flower_prototype_objIDs[phytomer_parameters.inflorescence.flower_prototype_function].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_closed_flower_prototype_objIDs.at(phytomer_parameters.inflorescence.flower_prototype_function).at(prototype) = objID_flower;
-
1306 context_ptr->hideObject({objID_flower});
-
1307 }
-
1308 }
-
1309 //open flowers
-
1310 if( phytomer_parameters.inflorescence.flower_prototype_function!= nullptr && plantarchitecture_ptr->unique_open_flower_prototype_objIDs.find(phytomer_parameters.inflorescence.flower_prototype_function) == plantarchitecture_ptr->unique_open_flower_prototype_objIDs.end() ) {
-
1311 plantarchitecture_ptr->unique_open_flower_prototype_objIDs[phytomer_parameters.inflorescence.flower_prototype_function].resize(phytomer_parameters.inflorescence.unique_prototypes);
-
1312 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
-
1313 uint objID_flower = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, true);
-
1314 plantarchitecture_ptr->unique_open_flower_prototype_objIDs.at(phytomer_parameters.inflorescence.flower_prototype_function).at(prototype) = objID_flower;
-
1315 context_ptr->hideObject({objID_flower});
-
1316 }
-
1317 }
-
1318 //fruit
-
1319 if( phytomer_parameters.inflorescence.fruit_prototype_function!= nullptr && plantarchitecture_ptr->unique_fruit_prototype_objIDs.find(phytomer_parameters.inflorescence.fruit_prototype_function) == plantarchitecture_ptr->unique_fruit_prototype_objIDs.end() ) {
-
1320 plantarchitecture_ptr->unique_fruit_prototype_objIDs[phytomer_parameters.inflorescence.fruit_prototype_function].resize(phytomer_parameters.inflorescence.unique_prototypes);
-
1321 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
-
1322 uint objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr, 1);
-
1323 plantarchitecture_ptr->unique_fruit_prototype_objIDs.at(phytomer_parameters.inflorescence.fruit_prototype_function).at(prototype) = objID_fruit;
-
1324 context_ptr->hideObject({objID_fruit});
-
1325 }
-
1326 }
-
1327 }
-
1328
-
1329 for (int fruit = 0; fruit < phytomer_parameters.inflorescence.flowers_per_peduncle.val(); fruit++) {
-
1330 uint objID_fruit;
-
1331 helios::vec3 fruit_scale;
-
1332
-
1333 if(fbud.state == BUD_FRUITING ){
-
1334 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
-
1335 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
-
1336 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_fruit_prototype_objIDs.at(phytomer_parameters.inflorescence.fruit_prototype_function).at(prototype));
-
1337 }else{ //load new prototype
-
1338 objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr, 1);
-
1339 }
-
1340 fruit_scale = phytomer_parameters.inflorescence.fruit_prototype_scale.val() * make_vec3(1, 1, 1);
-
1341 phytomer_parameters.inflorescence.fruit_prototype_scale.resample();
-
1342 } else {
-
1343 bool flower_is_open;
-
1344 if (fbud.state == BUD_FLOWER_CLOSED) {
-
1345 flower_is_open = false;
-
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_closed_flower_prototype_objIDs.at(phytomer_parameters.inflorescence.flower_prototype_function).at(prototype));
-
1349 }else{ //load new prototype
-
1350 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, flower_is_open);
-
1351 }
-
1352 } else {
-
1353 flower_is_open = true;
-
1354 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
-
1355 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
-
1356 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_open_flower_prototype_objIDs.at(phytomer_parameters.inflorescence.flower_prototype_function).at(prototype));
-
1357 }else{ //load new prototype
-
1358 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, flower_is_open);
-
1359 }
-
1360 }
-
1361 fruit_scale = phytomer_parameters.inflorescence.flower_prototype_scale.val() * make_vec3(1, 1, 1);
-
1362 phytomer_parameters.inflorescence.flower_prototype_scale.resample();
-
1363 }
-
1364
-
1365 float ind_from_tip = fabs(fruit - float(phytomer_parameters.inflorescence.flowers_per_peduncle.val() - 1) / float(phytomer_parameters.petiole.petioles_per_internode));
-
1366
-
1367 context_ptr->scaleObject(objID_fruit, fruit_scale);
-
1368
-
1369 //if we have more than one flower/fruit, we need to adjust the base position of the fruit
-
1370 vec3 fruit_base = peduncle_vertices.back();
-
1371 float frac = 1;
-
1372 if(phytomer_parameters.inflorescence.flowers_per_peduncle.val() > 1 && phytomer_parameters.inflorescence.flower_offset.val() > 0 ){
-
1373 if( ind_from_tip != 0 ) {
-
1374 float offset = offset = (ind_from_tip - 0.5f) * phytomer_parameters.inflorescence.flower_offset.val() * phytomer_parameters.peduncle.length.val();
-
1375 if( phytomer_parameters.peduncle.length.val()>0 ){
-
1376 frac = 1.f - offset / phytomer_parameters.peduncle.length.val();
-
1377 }
-
1378 fruit_base = interpolateTube(peduncle_vertices, frac);
-
1379 }
-
1380 }
-
1381
-
1382 //if we have more than one flower/fruit, we need to adjust the rotation about the peduncle
-
1383 float compound_rotation = 0;
-
1384 if(phytomer_parameters.inflorescence.flowers_per_peduncle.val() > 1 ) {
-
1385 if (phytomer_parameters.inflorescence.flower_offset.val() == 0) { //flowers/fruit are all at the tip, so just equally distribute them about the azimuth
-
1386 float dphi = M_PI / (floor(0.5 * float(phytomer_parameters.inflorescence.flowers_per_peduncle.val() - 1)) + 1);
-
1387 compound_rotation = -float(M_PI) + dphi * (fruit + 0.5f);
-
1388 } else {
-
1389 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);
-
1390 phytomer_parameters.internode.phyllotactic_angle.resample();
-
1391 }
-
1392 }
+
1291
+
1292 //rotate peduncle to azimuth of petiole and apply peduncle base yaw rotation
+
1293 vec3 internode_axis = getAxisVector(1.f, getInternodeNodePositions());
+
1294 vec3 parent_petiole_base_axis = getPetioleAxisVector(0.f, fbud.parent_index);
+
1295 float parent_petiole_azimuth = -std::atan2(parent_petiole_base_axis.y, parent_petiole_base_axis.x);
+
1296 float current_peduncle_azimuth = -std::atan2(peduncle_axis.y, peduncle_axis.x);
+
1297 peduncle_axis = rotatePointAboutLine( peduncle_axis, nullorigin, internode_axis, (current_peduncle_azimuth-parent_petiole_azimuth) );
+
1298
+
1299
+
1300 float theta_base = fabs(cart2sphere(peduncle_axis).zenith);
+
1301
+
1302 for (int i = 1; i <= phytomer_parameters.peduncle.length_segments; i++) {
+
1303 if (phytomer_parameters.peduncle.curvature.val() != 0.f) {
+
1304 float theta_curvature = -deg2rad(phytomer_parameters.peduncle.curvature.val() * dr_peduncle);
+
1305 phytomer_parameters.peduncle.curvature.resample();
+
1306 if (fabs(theta_curvature) * float(i) < M_PI - theta_base) {
+
1307 peduncle_axis = rotatePointAboutLine(peduncle_axis, nullorigin, inflorescence_bending_axis, theta_curvature);
+
1308 } else {
+
1309 peduncle_axis = make_vec3(0, 0, -1);
+
1310 }
+
1311 }
+
1312
+
1313 peduncle_vertices.at(i) = peduncle_vertices.at(i - 1) + dr_peduncle * peduncle_axis;
+
1314
+
1315 peduncle_radii.at(i) = phytomer_parameters.peduncle.radius.val();
+
1316 peduncle_colors.at(i) = phytomer_parameters.peduncle.color;
+
1317 }
+
1318 phytomer_parameters.peduncle.radius.resample();
+
1319
+
1320 if( build_context_geometry_peduncle) {
+
1321 fbud.peduncle_objIDs.push_back(context_ptr->addTubeObject(Ndiv_peduncle_radius, peduncle_vertices, peduncle_radii, peduncle_colors));
+
1322 }
+
1323
+
1324 // Create unique inflorescence prototypes for each shoot type so we can simply copy them for each leaf
+
1325 std::string parent_shoot_type_label = plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(parent_shoot_ID)->shoot_type_label;
+
1326 if( phytomer_parameters.inflorescence.unique_prototypes>0 ){
+
1327 //closed flowers
+
1328 if( phytomer_parameters.inflorescence.flower_prototype_function!= nullptr && plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.find(phytomer_parameters.inflorescence.flower_prototype_function) == plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.end() ) {
+
1329 plantarchitecture_ptr->unique_closed_flower_prototype_objIDs[phytomer_parameters.inflorescence.flower_prototype_function].resize(phytomer_parameters.inflorescence.unique_prototypes);
+
1330 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
+
1331 uint objID_flower = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, false);
+
1332 plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.at(phytomer_parameters.inflorescence.flower_prototype_function).at(prototype) = objID_flower;
+
1333 context_ptr->hideObject({objID_flower});
+
1334 }
+
1335 }
+
1336 //open flowers
+
1337 if( phytomer_parameters.inflorescence.flower_prototype_function!= nullptr && plantarchitecture_ptr->unique_open_flower_prototype_objIDs.find(phytomer_parameters.inflorescence.flower_prototype_function) == plantarchitecture_ptr->unique_open_flower_prototype_objIDs.end() ) {
+
1338 plantarchitecture_ptr->unique_open_flower_prototype_objIDs[phytomer_parameters.inflorescence.flower_prototype_function].resize(phytomer_parameters.inflorescence.unique_prototypes);
+
1339 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
+
1340 uint objID_flower = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, true);
+
1341 plantarchitecture_ptr->unique_open_flower_prototype_objIDs.at(phytomer_parameters.inflorescence.flower_prototype_function).at(prototype) = objID_flower;
+
1342 context_ptr->hideObject({objID_flower});
+
1343 }
+
1344 }
+
1345 //fruit
+
1346 if( phytomer_parameters.inflorescence.fruit_prototype_function!= nullptr && plantarchitecture_ptr->unique_fruit_prototype_objIDs.find(phytomer_parameters.inflorescence.fruit_prototype_function) == plantarchitecture_ptr->unique_fruit_prototype_objIDs.end() ) {
+
1347 plantarchitecture_ptr->unique_fruit_prototype_objIDs[phytomer_parameters.inflorescence.fruit_prototype_function].resize(phytomer_parameters.inflorescence.unique_prototypes);
+
1348 for( int prototype = 0; prototype < phytomer_parameters.inflorescence.unique_prototypes; prototype++ ) {
+
1349 uint objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr, 1);
+
1350 plantarchitecture_ptr->unique_fruit_prototype_objIDs.at(phytomer_parameters.inflorescence.fruit_prototype_function).at(prototype) = objID_fruit;
+
1351 context_ptr->hideObject({objID_fruit});
+
1352 }
+
1353 }
+
1354 }
+
1355
+
1356 for (int fruit = 0; fruit < phytomer_parameters.inflorescence.flowers_per_peduncle.val(); fruit++) {
+
1357 uint objID_fruit;
+
1358 helios::vec3 fruit_scale;
+
1359
+
1360 if(fbud.state == BUD_FRUITING ){
+
1361 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
+
1362 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
+
1363 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_fruit_prototype_objIDs.at(phytomer_parameters.inflorescence.fruit_prototype_function).at(prototype));
+
1364 }else{ //load new prototype
+
1365 objID_fruit = phytomer_parameters.inflorescence.fruit_prototype_function(context_ptr, 1);
+
1366 }
+
1367 fruit_scale = phytomer_parameters.inflorescence.fruit_prototype_scale.val() * make_vec3(1, 1, 1);
+
1368 phytomer_parameters.inflorescence.fruit_prototype_scale.resample();
+
1369 } else {
+
1370 bool flower_is_open;
+
1371 if (fbud.state == BUD_FLOWER_CLOSED) {
+
1372 flower_is_open = false;
+
1373 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
+
1374 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
+
1375 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_closed_flower_prototype_objIDs.at(phytomer_parameters.inflorescence.flower_prototype_function).at(prototype));
+
1376 }else{ //load new prototype
+
1377 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, flower_is_open);
+
1378 }
+
1379 } else {
+
1380 flower_is_open = true;
+
1381 if( phytomer_parameters.inflorescence.unique_prototypes>0 ) { //copy existing prototype
+
1382 int prototype = context_ptr->randu(0, int(phytomer_parameters.inflorescence.unique_prototypes - 1));
+
1383 objID_fruit = context_ptr->copyObject(plantarchitecture_ptr->unique_open_flower_prototype_objIDs.at(phytomer_parameters.inflorescence.flower_prototype_function).at(prototype));
+
1384 }else{ //load new prototype
+
1385 objID_fruit = phytomer_parameters.inflorescence.flower_prototype_function(context_ptr, 1, flower_is_open);
+
1386 }
+
1387 }
+
1388 fruit_scale = phytomer_parameters.inflorescence.flower_prototype_scale.val() * make_vec3(1, 1, 1);
+
1389 phytomer_parameters.inflorescence.flower_prototype_scale.resample();
+
1390 }
+
1391
+
1392 float ind_from_tip = fabs(fruit - float(phytomer_parameters.inflorescence.flowers_per_peduncle.val() - 1) / float(phytomer_parameters.petiole.petioles_per_internode));
1393
-
1394 peduncle_axis = getAxisVector(frac, peduncle_vertices);
+
1394 context_ptr->scaleObject(objID_fruit, fruit_scale);
1395
-
1396 vec3 fruit_axis = peduncle_axis;
-
1397
-
1398 //roll rotation
-
1399 if (phytomer_parameters.inflorescence.roll.val() != 0.f) {
-
1400 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.inflorescence.roll.val()), "x");
-
1401 phytomer_parameters.inflorescence.roll.resample();
-
1402 }
-
1403
-
1404 //pitch rotation
-
1405 float pitch_inflorescence = -asin_safe(peduncle_axis.z) + deg2rad(phytomer_parameters.inflorescence.pitch.val());
-
1406 phytomer_parameters.inflorescence.pitch.resample();
-
1407 if(fbud.state == BUD_FRUITING ) { //gravity effect for fruit
-
1408 pitch_inflorescence = pitch_inflorescence + phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val() * (0.5f * M_PI - pitch_inflorescence);
-
1409 }
-
1410 context_ptr->rotateObject(objID_fruit, pitch_inflorescence, "y");
-
1411 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, make_vec3(1, 0, 0), pitch_inflorescence);
-
1412
-
1413 //rotate flower/fruit to azimuth of peduncle
-
1414 context_ptr->rotateObject(objID_fruit, -std::atan2(peduncle_axis.y, peduncle_axis.x), "z" );
-
1415 fruit_axis = rotatePointAboutLine( fruit_axis, nullorigin, make_vec3(0,0,1), -std::atan2(peduncle_axis.y, peduncle_axis.x) );
-
1416
-
1417 context_ptr->translateObject(objID_fruit, fruit_base);
-
1418
-
1419 //rotate flower/fruit about peduncle (roll)
-
1420 if( phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val()!=0 && fbud.state == BUD_FRUITING ) {
-
1421 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, make_vec3(0, 0, 1));
-
1422 }else{
-
1423 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, peduncle_axis);
-
1424 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, peduncle_axis, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation);
-
1425 }
-
1426 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.resample();
-
1427
-
1428 fbud.inflorescence_bases.push_back(fruit_base);
-
1429
-
1430 fbud.inflorescence_objIDs.push_back(objID_fruit);
-
1431 }
-
1432 phytomer_parameters.inflorescence.flowers_per_peduncle.resample();
-
1433 phytomer_parameters.peduncle.roll.resample();
-
1434
-
1435 if (plantarchitecture_ptr->output_object_data.at("rank")) {
-
1436 context_ptr->setObjectData(fbud.peduncle_objIDs, "rank", rank);
-
1437 context_ptr->setObjectData(fbud.inflorescence_objIDs, "rank", rank);
-
1438 }
+
1396 //if we have more than one flower/fruit, we need to adjust the base position of the fruit
+
1397 vec3 fruit_base = peduncle_vertices.back();
+
1398 float frac = 1;
+
1399 if(phytomer_parameters.inflorescence.flowers_per_peduncle.val() > 1 && phytomer_parameters.inflorescence.flower_offset.val() > 0 ){
+
1400 if( ind_from_tip != 0 ) {
+
1401 float offset = offset = (ind_from_tip - 0.5f) * phytomer_parameters.inflorescence.flower_offset.val() * phytomer_parameters.peduncle.length.val();
+
1402 if( phytomer_parameters.peduncle.length.val()>0 ){
+
1403 frac = 1.f - offset / phytomer_parameters.peduncle.length.val();
+
1404 }
+
1405 fruit_base = interpolateTube(peduncle_vertices, frac);
+
1406 }
+
1407 }
+
1408
+
1409 //if we have more than one flower/fruit, we need to adjust the rotation about the peduncle
+
1410 float compound_rotation = 0;
+
1411 if(phytomer_parameters.inflorescence.flowers_per_peduncle.val() > 1 ) {
+
1412 if (phytomer_parameters.inflorescence.flower_offset.val() == 0) { //flowers/fruit are all at the tip, so just equally distribute them about the azimuth
+
1413 float dphi = M_PI / (floor(0.5 * float(phytomer_parameters.inflorescence.flowers_per_peduncle.val() - 1)) + 1);
+
1414 compound_rotation = -float(M_PI) + dphi * (fruit + 0.5f);
+
1415 } else {
+
1416 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);
+
1417 phytomer_parameters.internode.phyllotactic_angle.resample();
+
1418 }
+
1419 }
+
1420
+
1421 peduncle_axis = getAxisVector(frac, peduncle_vertices);
+
1422
+
1423 vec3 fruit_axis = peduncle_axis;
+
1424
+
1425 //roll rotation
+
1426 if (phytomer_parameters.inflorescence.roll.val() != 0.f) {
+
1427 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.inflorescence.roll.val()), "x");
+
1428 phytomer_parameters.inflorescence.roll.resample();
+
1429 }
+
1430
+
1431 //pitch rotation
+
1432 float pitch_inflorescence = -asin_safe(peduncle_axis.z) + deg2rad(phytomer_parameters.inflorescence.pitch.val());
+
1433 phytomer_parameters.inflorescence.pitch.resample();
+
1434 if(fbud.state == BUD_FRUITING ) { //gravity effect for fruit
+
1435 pitch_inflorescence = pitch_inflorescence + phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val() * (0.5f * M_PI - pitch_inflorescence);
+
1436 }
+
1437 context_ptr->rotateObject(objID_fruit, pitch_inflorescence, "y");
+
1438 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, make_vec3(1, 0, 0), pitch_inflorescence);
1439
-
1440 if (plantarchitecture_ptr->output_object_data.at("peduncleID")) {
-
1441 for (uint objID: fbud.peduncle_objIDs) {
-
1442 context_ptr->setObjectData(objID, "peduncleID", (int) objID);
-
1443 }
-
1444 }
-
1445 for (uint objID: fbud.inflorescence_objIDs) {
-
1446 if (fbud.state == BUD_FLOWER_CLOSED && plantarchitecture_ptr->output_object_data.at("closedflowerID")) {
-
1447 context_ptr->setObjectData(objID, "closedflowerID", (int) objID);
-
1448 } else if (fbud.state == BUD_FLOWER_OPEN && plantarchitecture_ptr->output_object_data.at("openflowerID")) {
-
1449 context_ptr->clearObjectData(objID, "closedflowerID");
-
1450 context_ptr->setObjectData(objID, "openflowerID", (int) objID);
-
1451 } else if (plantarchitecture_ptr->output_object_data.at("fruitID")) {
-
1452 context_ptr->setObjectData(objID, "fruitID", (int) objID);
-
1453 }
-
1454 }
-
1455}
+
1440 //rotate flower/fruit to azimuth of peduncle
+
1441 context_ptr->rotateObject(objID_fruit, -std::atan2(peduncle_axis.y, peduncle_axis.x), "z" );
+
1442 fruit_axis = rotatePointAboutLine( fruit_axis, nullorigin, make_vec3(0,0,1), -std::atan2(peduncle_axis.y, peduncle_axis.x) );
+
1443
+
1444 context_ptr->translateObject(objID_fruit, fruit_base);
+
1445
+
1446 //rotate flower/fruit about peduncle (roll)
+
1447 if( phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.val()!=0 && fbud.state == BUD_FRUITING ) {
+
1448 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, make_vec3(0, 0, 1));
+
1449 }else{
+
1450 context_ptr->rotateObject(objID_fruit, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation, fruit_base, peduncle_axis);
+
1451 fruit_axis = rotatePointAboutLine(fruit_axis, nullorigin, peduncle_axis, deg2rad(phytomer_parameters.peduncle.roll.val()) + compound_rotation);
+
1452 }
+
1453 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.resample();
+
1454
+
1455 fbud.inflorescence_bases.push_back(fruit_base);
1456
-
1457void Phytomer::setPetioleBase(const helios::vec3 &base_position) {
-
1458 vec3 old_base = petiole_vertices.front().front();
-
1459 vec3 shift = base_position - old_base;
-
1460
-
1461 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
-
1462 for (auto &vertex: petiole_vertices.at(petiole)) {
-
1463 vertex += shift;
-
1464 }
+
1457 fbud.inflorescence_objIDs.push_back(objID_fruit);
+
1458 }
+
1459 phytomer_parameters.inflorescence.flowers_per_peduncle.resample();
+
1460 phytomer_parameters.peduncle.roll.resample();
+
1461
+
1462 if (plantarchitecture_ptr->output_object_data.at("rank")) {
+
1463 context_ptr->setObjectData(fbud.peduncle_objIDs, "rank", rank);
+
1464 context_ptr->setObjectData(fbud.inflorescence_objIDs, "rank", rank);
1465 }
1466
-
1467 if (build_context_geometry_petiole) {
-
1468 context_ptr->translateObject(flatten(petiole_objIDs), shift);
-
1469 }
-
1470 context_ptr->translateObject(flatten(leaf_objIDs), shift);
-
1471
-
1472 for (int petiole = 0; petiole < leaf_bases.size(); petiole++) {
-
1473 for (auto &leaf_base: leaf_bases.at(petiole)) {
-
1474 leaf_base += shift;
-
1475 }
-
1476 }
-
1477 for (int petiole = 0; petiole < floral_buds.size(); petiole++) {
-
1478 for (auto &fbud: floral_buds.at(petiole)) {
-
1479 fbud.base_position = petiole_vertices.front().front();
-
1480 context_ptr->translateObject(fbud.inflorescence_objIDs, shift);
-
1481 for (auto &base: fbud.inflorescence_bases) {
-
1482 base += shift;
-
1483 }
-
1484 if (build_context_geometry_peduncle) {
-
1485 context_ptr->translateObject(fbud.peduncle_objIDs, shift);
-
1486 }
-
1487 }
-
1488 }
-
1489}
-
1490
-
1491void Phytomer::rotateLeaf(uint petiole_index, uint leaf_index, const AxisRotation &rotation) {
-
1492 if (petiole_index >= leaf_objIDs.size()) {
-
1493 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Invalid petiole index.");
-
1494 } else if (leaf_index >= leaf_objIDs.at(petiole_index).size()) {
-
1495 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Invalid leaf index.");
+
1467 if (plantarchitecture_ptr->output_object_data.at("peduncleID")) {
+
1468 for (uint objID: fbud.peduncle_objIDs) {
+
1469 context_ptr->setObjectData(objID, "peduncleID", (int) objID);
+
1470 }
+
1471 }
+
1472 for (uint objID: fbud.inflorescence_objIDs) {
+
1473 if (fbud.state == BUD_FLOWER_CLOSED && plantarchitecture_ptr->output_object_data.at("closedflowerID")) {
+
1474 context_ptr->setObjectData(objID, "closedflowerID", (int) objID);
+
1475 } else if (fbud.state == BUD_FLOWER_OPEN && plantarchitecture_ptr->output_object_data.at("openflowerID")) {
+
1476 context_ptr->clearObjectData(objID, "closedflowerID");
+
1477 context_ptr->setObjectData(objID, "openflowerID", (int) objID);
+
1478 } else if (plantarchitecture_ptr->output_object_data.at("fruitID")) {
+
1479 context_ptr->setObjectData(objID, "fruitID", (int) objID);
+
1480 }
+
1481 }
+
1482}
+
1483
+
1484void Phytomer::setPetioleBase(const helios::vec3 &base_position) {
+
1485 vec3 old_base = petiole_vertices.front().front();
+
1486 vec3 shift = base_position - old_base;
+
1487
+
1488 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
+
1489 for (auto &vertex: petiole_vertices.at(petiole)) {
+
1490 vertex += shift;
+
1491 }
+
1492 }
+
1493
+
1494 if (build_context_geometry_petiole) {
+
1495 context_ptr->translateObject(flatten(petiole_objIDs), shift);
1496 }
-
1497
-
1498 vec3 petiole_axis = getPetioleAxisVector(1.f, petiole_index);
-
1499 //note: this is not exactly correct because it should get the axis at the leaf position and not the tip
-
1500
-
1501 vec3 internode_axis = getInternodeAxisVector(1.f);
-
1502
-
1503 vec3 pitch_axis = -1 * cross(internode_axis, petiole_axis);
-
1504
-
1505 int leaves_per_petiole = leaf_rotation.at(petiole_index).size();
-
1506 float yaw;
-
1507 float roll;
-
1508 float compound_rotation = 0;
-
1509 if( leaf_index == float(leaves_per_petiole-1)/2.f ){ //tip leaf
-
1510 roll = 0;
-
1511 yaw = 0;
-
1512 compound_rotation = 0;
-
1513 } else if (leaf_index < float(leaves_per_petiole - 1) / 2.f) {
-
1514 yaw = -rotation.yaw;
-
1515 roll = -rotation.roll;
-
1516 compound_rotation = -0.5 * M_PI;
-
1517 } else {
-
1518 yaw = -rotation.yaw;
-
1519 roll = rotation.roll;
-
1520 compound_rotation = 0.5 * M_PI;
-
1521 }
-
1522
-
1523 //roll
-
1524 if( roll!=0.f ) {
-
1525 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);
-
1526 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), roll, leaf_bases.at(petiole_index).at(leaf_index), roll_axis);
-
1527 leaf_rotation.at(petiole_index).at(leaf_index).roll += roll;
-
1528 }
+
1497 context_ptr->translateObject(flatten(leaf_objIDs), shift);
+
1498
+
1499 for (int petiole = 0; petiole < leaf_bases.size(); petiole++) {
+
1500 for (auto &leaf_base: leaf_bases.at(petiole)) {
+
1501 leaf_base += shift;
+
1502 }
+
1503 }
+
1504 for (int petiole = 0; petiole < floral_buds.size(); petiole++) {
+
1505 for (auto &fbud: floral_buds.at(petiole)) {
+
1506 fbud.base_position = petiole_vertices.front().front();
+
1507 context_ptr->translateObject(fbud.inflorescence_objIDs, shift);
+
1508 for (auto &base: fbud.inflorescence_bases) {
+
1509 base += shift;
+
1510 }
+
1511 if (build_context_geometry_peduncle) {
+
1512 context_ptr->translateObject(fbud.peduncle_objIDs, shift);
+
1513 }
+
1514 }
+
1515 }
+
1516}
+
1517
+
1518void Phytomer::rotateLeaf(uint petiole_index, uint leaf_index, const AxisRotation &rotation) {
+
1519 if (petiole_index >= leaf_objIDs.size()) {
+
1520 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Invalid petiole index.");
+
1521 } else if (leaf_index >= leaf_objIDs.at(petiole_index).size()) {
+
1522 helios_runtime_error("ERROR (PlantArchitecture::Phytomer): Invalid leaf index.");
+
1523 }
+
1524
+
1525 vec3 petiole_axis = getPetioleAxisVector(1.f, petiole_index);
+
1526 //note: this is not exactly correct because it should get the axis at the leaf position and not the tip
+
1527
+
1528 vec3 internode_axis = getInternodeAxisVector(1.f);
1529
-
1530 //pitch
-
1531 if (rotation.pitch != 0) {
-
1532 pitch_axis = rotatePointAboutLine(pitch_axis, nullorigin, {0, 0, 1}, -compound_rotation);
-
1533 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), rotation.pitch, leaf_bases.at(petiole_index).at(leaf_index), pitch_axis);
-
1534 leaf_rotation.at(petiole_index).at(leaf_index).pitch += rotation.pitch;
-
1535 }
-
1536
-
1537 //yaw
-
1538 if( yaw!=0.f ) {
-
1539 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), yaw, leaf_bases.at(petiole_index).at(leaf_index), {0, 0, 1});
-
1540 leaf_rotation.at(petiole_index).at(leaf_index).yaw += yaw;
-
1541 }
-
1542}
-
1543
-
1544void Phytomer::setInternodeLengthScaleFraction(float internode_scale_factor_fraction, bool update_context_geometry) {
-
1545 assert(internode_scale_factor_fraction >= 0 && internode_scale_factor_fraction <= 1);
-
1546
-
1547 if (internode_scale_factor_fraction == current_internode_scale_factor) {
-
1548 return;
-
1549 }
-
1550
-
1551 float delta_scale = internode_scale_factor_fraction / current_internode_scale_factor;
-
1552
-
1553 float current_internode_length = getInternodeLength();
-
1554 float internode_length = current_internode_length * delta_scale;
-
1555 current_internode_scale_factor = internode_scale_factor_fraction;
+
1530 vec3 pitch_axis = -1 * cross(internode_axis, petiole_axis);
+
1531
+
1532 int leaves_per_petiole = leaf_rotation.at(petiole_index).size();
+
1533 float yaw;
+
1534 float roll;
+
1535 float compound_rotation = 0;
+
1536 if( leaf_index == float(leaves_per_petiole-1)/2.f ){ //tip leaf
+
1537 roll = 0;
+
1538 yaw = 0;
+
1539 compound_rotation = 0;
+
1540 } else if (leaf_index < float(leaves_per_petiole - 1) / 2.f) {
+
1541 yaw = -rotation.yaw;
+
1542 roll = -rotation.roll;
+
1543 compound_rotation = -0.5 * M_PI;
+
1544 } else {
+
1545 yaw = -rotation.yaw;
+
1546 roll = rotation.roll;
+
1547 compound_rotation = 0.5 * M_PI;
+
1548 }
+
1549
+
1550 //roll
+
1551 if( roll!=0.f ) {
+
1552 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);
+
1553 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), roll, leaf_bases.at(petiole_index).at(leaf_index), roll_axis);
+
1554 leaf_rotation.at(petiole_index).at(leaf_index).roll += roll;
+
1555 }
1556
-
1557 int p = shoot_index.x;
-
1558 int s_start = (p == 0) ? 1 : 0; //skip the first node at the base of the shoot
-
1559
-
1560 for (int s = s_start; s < parent_shoot_ptr->shoot_internode_vertices.at(p).size(); s++) { //looping over all segments within this phytomer internode
-
1561
-
1562 int p_minus = p;
-
1563 int s_minus = s - 1;
-
1564 if (s_minus < 0) {
-
1565 p_minus--;
-
1566 s_minus = int(parent_shoot_ptr->shoot_internode_vertices.at(p_minus).size() - 1);
-
1567 }
-
1568
-
1569 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));
-
1570 float current_length = central_axis.magnitude();
-
1571 central_axis = central_axis / current_length;
-
1572 vec3 dL = central_axis * current_length * (delta_scale - 1);
+
1557 //pitch
+
1558 if (rotation.pitch != 0) {
+
1559 pitch_axis = rotatePointAboutLine(pitch_axis, nullorigin, {0, 0, 1}, -compound_rotation);
+
1560 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), rotation.pitch, leaf_bases.at(petiole_index).at(leaf_index), pitch_axis);
+
1561 leaf_rotation.at(petiole_index).at(leaf_index).pitch += rotation.pitch;
+
1562 }
+
1563
+
1564 //yaw
+
1565 if( yaw!=0.f ) {
+
1566 context_ptr->rotateObject(leaf_objIDs.at(petiole_index).at(leaf_index), yaw, leaf_bases.at(petiole_index).at(leaf_index), {0, 0, 1});
+
1567 leaf_rotation.at(petiole_index).at(leaf_index).yaw += yaw;
+
1568 }
+
1569}
+
1570
+
1571void Phytomer::setInternodeLengthScaleFraction(float internode_scale_factor_fraction, bool update_context_geometry) {
+
1572 assert(internode_scale_factor_fraction >= 0 && internode_scale_factor_fraction <= 1);
1573
-
1574 //apply shift to all downstream nodes
-
1575 for (int p_downstream = p; p_downstream < parent_shoot_ptr->shoot_internode_vertices.size(); p_downstream++) {
-
1576 int sd_start = ( p_downstream==p ) ? s : 0;
-
1577 for (int s_downstream = sd_start; s_downstream < parent_shoot_ptr->shoot_internode_vertices.at(p_downstream).size(); s_downstream++) {
-
1578 parent_shoot_ptr->shoot_internode_vertices.at(p_downstream).at(s_downstream) += dL;
-
1579 }
-
1580 }
-
1581 }
-
1582
-
1583 parent_shoot_ptr->updateShootNodes(update_context_geometry);
-
1584}
-
1585
-
-
1586void Phytomer::scaleInternodeMaxLength(float scale_factor) {
-
1587 this->internode_length_max *= scale_factor;
+
1574 if (internode_scale_factor_fraction == current_internode_scale_factor) {
+
1575 return;
+
1576 }
+
1577
+
1578 float delta_scale = internode_scale_factor_fraction / current_internode_scale_factor;
+
1579
+
1580 float current_internode_length = getInternodeLength();
+
1581 float internode_length = current_internode_length * delta_scale;
+
1582 current_internode_scale_factor = internode_scale_factor_fraction;
+
1583
+
1584 int p = shoot_index.x;
+
1585 int s_start = (p == 0) ? 1 : 0; //skip the first node at the base of the shoot
+
1586
+
1587 for (int s = s_start; s < parent_shoot_ptr->shoot_internode_vertices.at(p).size(); s++) { //looping over all segments within this phytomer internode
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}
-
-
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}
-
-
1601
-
-
1602void Phytomer::setInternodeMaxRadius(float internode_radius_max_new) {
-
1603 this->internode_radius_max = internode_radius_max_new;
-
1604}
-
-
1605
-
-
1606void Phytomer::setLeafScaleFraction(float leaf_scale_factor_fraction) {
-
1607 assert(leaf_scale_factor_fraction >= 0 && leaf_scale_factor_fraction <= 1);
-
1608
-
1609 if (leaf_scale_factor_fraction == current_leaf_scale_factor || (leaf_objIDs.empty() && petiole_objIDs.empty())) {
-
1610 return;
-
1611 }
+
1589 int p_minus = p;
+
1590 int s_minus = s - 1;
+
1591 if (s_minus < 0) {
+
1592 p_minus--;
+
1593 s_minus = int(parent_shoot_ptr->shoot_internode_vertices.at(p_minus).size() - 1);
+
1594 }
+
1595
+
1596 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));
+
1597 float current_length = central_axis.magnitude();
+
1598 central_axis = central_axis / current_length;
+
1599 vec3 dL = central_axis * current_length * (delta_scale - 1);
+
1600
+
1601 //apply shift to all downstream nodes
+
1602 for (int p_downstream = p; p_downstream < parent_shoot_ptr->shoot_internode_vertices.size(); p_downstream++) {
+
1603 int sd_start = ( p_downstream==p ) ? s : 0;
+
1604 for (int s_downstream = sd_start; s_downstream < parent_shoot_ptr->shoot_internode_vertices.at(p_downstream).size(); s_downstream++) {
+
1605 parent_shoot_ptr->shoot_internode_vertices.at(p_downstream).at(s_downstream) += dL;
+
1606 }
+
1607 }
+
1608 }
+
1609
+
1610 parent_shoot_ptr->updateShootNodes(update_context_geometry);
+
1611}
1612
-
1613 float delta_scale = leaf_scale_factor_fraction / current_leaf_scale_factor;
-
1614
-
1615 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
-
1616 petiole_length.at(petiole) *= delta_scale;
-
1617 }
-
1618 current_leaf_scale_factor = leaf_scale_factor_fraction;
-
1619
-
1620 assert(leaf_objIDs.size() == leaf_bases.size());
-
1621
-
1622 //scale the petiole
-
1623 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
-
1624 if (!petiole_objIDs.empty()) {
-
1625 int node = 0;
-
1626 vec3 old_tip = petiole_vertices.at(petiole).back();
-
1627 vec3 last_base = petiole_vertices.at(petiole).front();//looping over petioles
-
1628 for (uint objID: petiole_objIDs.at(petiole)) { //looping over cones/segments within petiole
-
1629 context_ptr->getConeObjectPointer(objID)->scaleLength(delta_scale);
-
1630 context_ptr->getConeObjectPointer(objID)->scaleGirth(delta_scale);
-
1631 petiole_radii.at(petiole).at(node) *= delta_scale;
-
1632 if (node > 0) {
-
1633 vec3 new_base = context_ptr->getConeObjectNode(objID, 0);
-
1634 context_ptr->translateObject(objID, last_base - new_base);
-
1635 } else {
-
1636 petiole_vertices.at(petiole).at(0) = context_ptr->getConeObjectNode(objID, 0);
-
1637 }
-
1638 last_base = context_ptr->getConeObjectNode(objID, 1);
-
1639 petiole_vertices.at(petiole).at(node + 1) = last_base;
-
1640 node++;
-
1641 }
-
1642 } else {
-
1643 for (int i = 1; i < petiole_vertices.at(petiole).size(); i++) {
-
1644 vec3 axis_vector = petiole_vertices.at(petiole).at(i) - petiole_vertices.at(petiole).at(i - 1);
-
1645 petiole_vertices.at(petiole).at(i) = petiole_vertices.at(petiole).at(i - 1) + delta_scale * axis_vector;
-
1646 petiole_radii.at(petiole).at(i) *= delta_scale;
-
1647 }
-
1648 }
-
1649
-
1650 //scale and translate leaves
-
1651 assert(leaf_objIDs.at(petiole).size() == leaf_bases.at(petiole).size());
-
1652 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
-
1653 float ind_from_tip = float(leaf) - float(leaf_objIDs.at(petiole).size() - 1) / 2.f;
-
1654
-
1655 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), -1 * leaf_bases.at(petiole).at(leaf));
-
1656 context_ptr->scaleObject(leaf_objIDs.at(petiole).at(leaf), delta_scale * make_vec3(1, 1, 1));
-
1657 if (ind_from_tip == 0) {
-
1658 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), petiole_vertices.at(petiole).back());
-
1659 leaf_bases.at(petiole).at(leaf) = petiole_vertices.at(petiole).back();
-
1660 } else {
-
1661 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
-
1662 vec3 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val());
-
1663 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), leaf_base);
-
1664 leaf_bases.at(petiole).at(leaf) = leaf_base;
-
1665 }
-
1666 }
-
1667 }
-
1668}
-
-
1669
-
-
1670void Phytomer::setLeafPrototypeScale(float leaf_prototype_scale) {
-
1671 float tip_ind = ceil(float(leaf_size_max.front().size() - 1) / 2.f);
-
1672 float scale_factor = leaf_prototype_scale / leaf_size_max.front().at(tip_ind);
-
1673 current_leaf_scale_factor = current_leaf_scale_factor * scale_factor;
-
1674
-
1675 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
-
1676 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
-
1677 leaf_size_max.at(petiole).at(leaf) *= scale_factor;
-
1678 }
-
1679 }
-
1680
-
1681 //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.
-
1682 this->petiole_curvature /= scale_factor;
-
1683
-
1684 if (current_leaf_scale_factor >= 1.f) {
- -
1686 current_leaf_scale_factor = 1.f;
-
1687 }
-
1688}
-
-
1689
-
1690void Phytomer::scaleLeafPrototypeScale(float scale_factor) {
-
1691 if (scale_factor < 0.f) {
-
1692 scale_factor = 0;
-
1693 }
-
1694
-
1695 current_leaf_scale_factor = current_leaf_scale_factor / scale_factor;
+
+
1613void Phytomer::scaleInternodeMaxLength(float scale_factor) {
+
1614 this->internode_length_max *= scale_factor;
+
1615
+
1616 current_internode_scale_factor = current_internode_scale_factor / scale_factor;
+
1617
+
1618 if (current_internode_scale_factor >= 1.f) {
+
1619 setInternodeLengthScaleFraction(1.f, true);
+
1620 current_internode_scale_factor = 1.f;
+
1621 }
+
1622}
+
+
1623
+
+
1624void Phytomer::setInternodeMaxLength(float internode_length_max_new) {
+
1625 float scale_factor = internode_length_max_new / this->internode_length_max;
+
1626 scaleInternodeMaxLength(scale_factor);
+
1627}
+
+
1628
+
+
1629void Phytomer::setInternodeMaxRadius(float internode_radius_max_new) {
+
1630 this->internode_radius_max = internode_radius_max_new;
+
1631}
+
+
1632
+
+
1633void Phytomer::setLeafScaleFraction(float leaf_scale_factor_fraction) {
+
1634 assert(leaf_scale_factor_fraction >= 0 && leaf_scale_factor_fraction <= 1);
+
1635
+
1636 if (leaf_scale_factor_fraction == current_leaf_scale_factor || (leaf_objIDs.empty() && petiole_objIDs.empty())) {
+
1637 return;
+
1638 }
+
1639
+
1640 float delta_scale = leaf_scale_factor_fraction / current_leaf_scale_factor;
+
1641
+
1642 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
+
1643 petiole_length.at(petiole) *= delta_scale;
+
1644 }
+
1645 current_leaf_scale_factor = leaf_scale_factor_fraction;
+
1646
+
1647 assert(leaf_objIDs.size() == leaf_bases.size());
+
1648
+
1649 //scale the petiole
+
1650 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
+
1651 if (!petiole_objIDs.empty()) {
+
1652 int node = 0;
+
1653 vec3 old_tip = petiole_vertices.at(petiole).back();
+
1654 vec3 last_base = petiole_vertices.at(petiole).front();//looping over petioles
+
1655 for (uint objID: petiole_objIDs.at(petiole)) { //looping over cones/segments within petiole
+
1656 context_ptr->getConeObjectPointer(objID)->scaleLength(delta_scale);
+
1657 context_ptr->getConeObjectPointer(objID)->scaleGirth(delta_scale);
+
1658 petiole_radii.at(petiole).at(node) *= delta_scale;
+
1659 if (node > 0) {
+
1660 vec3 new_base = context_ptr->getConeObjectNode(objID, 0);
+
1661 context_ptr->translateObject(objID, last_base - new_base);
+
1662 } else {
+
1663 petiole_vertices.at(petiole).at(0) = context_ptr->getConeObjectNode(objID, 0);
+
1664 }
+
1665 last_base = context_ptr->getConeObjectNode(objID, 1);
+
1666 petiole_vertices.at(petiole).at(node + 1) = last_base;
+
1667 node++;
+
1668 }
+
1669 } else {
+
1670 for (int i = 1; i < petiole_vertices.at(petiole).size(); i++) {
+
1671 vec3 axis_vector = petiole_vertices.at(petiole).at(i) - petiole_vertices.at(petiole).at(i - 1);
+
1672 petiole_vertices.at(petiole).at(i) = petiole_vertices.at(petiole).at(i - 1) + delta_scale * axis_vector;
+
1673 petiole_radii.at(petiole).at(i) *= delta_scale;
+
1674 }
+
1675 }
+
1676
+
1677 //scale and translate leaves
+
1678 assert(leaf_objIDs.at(petiole).size() == leaf_bases.at(petiole).size());
+
1679 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
+
1680 float ind_from_tip = float(leaf) - float(leaf_objIDs.at(petiole).size() - 1) / 2.f;
+
1681
+
1682 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), -1 * leaf_bases.at(petiole).at(leaf));
+
1683 context_ptr->scaleObject(leaf_objIDs.at(petiole).at(leaf), delta_scale * make_vec3(1, 1, 1));
+
1684 if (ind_from_tip == 0) {
+
1685 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), petiole_vertices.at(petiole).back());
+
1686 leaf_bases.at(petiole).at(leaf) = petiole_vertices.at(petiole).back();
+
1687 } else {
+
1688 float offset = (fabs(ind_from_tip) - 0.5f) * phytomer_parameters.leaf.leaflet_offset.val() * phytomer_parameters.petiole.length.val();
+
1689 vec3 leaf_base = interpolateTube(petiole_vertices.at(petiole), 1.f - offset / phytomer_parameters.petiole.length.val());
+
1690 context_ptr->translateObject(leaf_objIDs.at(petiole).at(leaf), leaf_base);
+
1691 leaf_bases.at(petiole).at(leaf) = leaf_base;
+
1692 }
+
1693 }
+
1694 }
+
1695}
+
1696
-
1697 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
-
1698 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
-
1699 leaf_size_max.at(petiole).at(leaf) *= scale_factor;
-
1700 }
-
1701 }
-
1702
-
1703 //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.
-
1704 this->petiole_curvature /= scale_factor;
-
1705
-
1706 if (current_leaf_scale_factor >= 1.f) {
- -
1708 current_leaf_scale_factor = 1.f;
-
1709 }
-
1710}
-
1711
-
1712
-
1713void Phytomer::setInflorescenceScaleFraction(FloralBud &fbud, float inflorescence_scale_factor_fraction) {
-
1714 assert(inflorescence_scale_factor_fraction >= 0 && inflorescence_scale_factor_fraction <= 1);
-
1715
-
1716 if (inflorescence_scale_factor_fraction == fbud.current_fruit_scale_factor) {
-
1717 return;
-
1718 }
-
1719
-
1720 float delta_scale = inflorescence_scale_factor_fraction / fbud.current_fruit_scale_factor;
+
+
1697void Phytomer::setLeafPrototypeScale(float leaf_prototype_scale) {
+
1698 float tip_ind = ceil(float(leaf_size_max.front().size() - 1) / 2.f);
+
1699 float scale_factor = leaf_prototype_scale / leaf_size_max.front().at(tip_ind);
+
1700 current_leaf_scale_factor = current_leaf_scale_factor * scale_factor;
+
1701
+
1702 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
+
1703 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
+
1704 leaf_size_max.at(petiole).at(leaf) *= scale_factor;
+
1705 }
+
1706 }
+
1707
+
1708 //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.
+
1709 this->petiole_curvature /= scale_factor;
+
1710
+
1711 if (current_leaf_scale_factor >= 1.f) {
+ +
1713 current_leaf_scale_factor = 1.f;
+
1714 }
+
1715}
+
+
1716
+
1717void Phytomer::scaleLeafPrototypeScale(float scale_factor) {
+
1718 if (scale_factor < 0.f) {
+
1719 scale_factor = 0;
+
1720 }
1721
-
1722 fbud.current_fruit_scale_factor = inflorescence_scale_factor_fraction;
+
1722 current_leaf_scale_factor = current_leaf_scale_factor / scale_factor;
1723
-
1724 //scale and translate flowers/fruit
-
1725 for( int inflorescence=0; inflorescence<fbud.inflorescence_objIDs.size(); inflorescence++ ) {
-
1726 context_ptr->scaleObjectAboutPoint(fbud.inflorescence_objIDs.at(inflorescence), delta_scale*make_vec3(1,1,1), fbud.inflorescence_bases.at(inflorescence));
-
1727 }
-
1728}
+
1724 for (int petiole = 0; petiole < phytomer_parameters.petiole.petioles_per_internode; petiole++) {
+
1725 for (int leaf = 0; leaf < leaf_objIDs.at(petiole).size(); leaf++) {
+
1726 leaf_size_max.at(petiole).at(leaf) *= scale_factor;
+
1727 }
+
1728 }
1729
-
1730void Phytomer::removeLeaf() {
-
1731
-
1732 // parent_shoot_ptr->propagateDownstreamLeafArea( parent_shoot_ptr, this->shoot_index.x, -1.f*getLeafArea());
-
1733
-
1734 this->petiole_radii.resize(0);
-
1735 // this->petiole_vertices.resize(0);
-
1736 this->petiole_colors.resize(0);
-
1737 this->petiole_length.resize(0);
-
1738 this->leaf_size_max.resize(0);
-
1739 this->leaf_rotation.resize(0);
-
1740 this->leaf_bases.resize(0);
-
1741
-
1742 context_ptr->deleteObject(flatten(leaf_objIDs));
-
1743 leaf_objIDs.resize(0);
-
1744 leaf_bases.resize(0);
-
1745
-
1746 if (build_context_geometry_petiole) {
-
1747 context_ptr->deleteObject(flatten(petiole_objIDs));
-
1748 petiole_objIDs.resize(0);
-
1749 }
-
1750}
-
1751
-
1752bool Phytomer::hasLeaf() const {
-
1753 return (!leaf_bases.empty() && !leaf_bases.front().empty());
-
1754}
-
1755
-
1756float Phytomer::calculateDownstreamLeafArea() const {
-
1757 return parent_shoot_ptr->sumShootLeafArea(shoot_index.x);
-
1758}
-
1759
-
1760Shoot::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,
-
1761 float internode_length_shoot_initial, ShootParameters &shoot_params, std::string shoot_type_label, PlantArchitecture *plant_architecture_ptr) :
-
1762 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) {
-
1763 carbohydrate_pool_molC = 0;
-
1764 phyllochron_counter = 0;
-
1765 isdormant = true;
-
1766 gravitropic_curvature = shoot_params.gravitropic_curvature.val();
-
1767 context_ptr = plant_architecture_ptr->context_ptr;
+
1730 //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.
+
1731 this->petiole_curvature /= scale_factor;
+
1732
+
1733 if (current_leaf_scale_factor >= 1.f) {
+ +
1735 current_leaf_scale_factor = 1.f;
+
1736 }
+
1737}
+
1738
+
1739
+
1740void Phytomer::setInflorescenceScaleFraction(FloralBud &fbud, float inflorescence_scale_factor_fraction) {
+
1741 assert(inflorescence_scale_factor_fraction >= 0 && inflorescence_scale_factor_fraction <= 1);
+
1742
+
1743 if (inflorescence_scale_factor_fraction == fbud.current_fruit_scale_factor) {
+
1744 return;
+
1745 }
+
1746
+
1747 float delta_scale = inflorescence_scale_factor_fraction / fbud.current_fruit_scale_factor;
+
1748
+
1749 fbud.current_fruit_scale_factor = inflorescence_scale_factor_fraction;
+
1750
+
1751 //scale and translate flowers/fruit
+
1752 for( int inflorescence=0; inflorescence<fbud.inflorescence_objIDs.size(); inflorescence++ ) {
+
1753 context_ptr->scaleObjectAboutPoint(fbud.inflorescence_objIDs.at(inflorescence), delta_scale*make_vec3(1,1,1), fbud.inflorescence_bases.at(inflorescence));
+
1754 }
+
1755}
+
1756
+
1757void Phytomer::removeLeaf() {
+
1758
+
1759 // parent_shoot_ptr->propagateDownstreamLeafArea( parent_shoot_ptr, this->shoot_index.x, -1.f*getLeafArea());
+
1760
+
1761 this->petiole_radii.resize(0);
+
1762 // this->petiole_vertices.resize(0);
+
1763 this->petiole_colors.resize(0);
+
1764 this->petiole_length.resize(0);
+
1765 this->leaf_size_max.resize(0);
+
1766 this->leaf_rotation.resize(0);
+
1767 this->leaf_bases.resize(0);
1768
-
1769 if( parent_shoot_ID>=0 ) {
-
1770 plant_architecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->childIDs[(int) parent_node_index].push_back(shoot_ID);
-
1771 }
-
1772}
-
1773
-
1774void Shoot::buildShootPhytomers(float internode_radius, float internode_length, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper) {
-
1775
-
1776 for( int i=0; i<current_node_number; i++ ) { //loop over phytomers to build up the shoot
-
1777
-
1778 //Determine position of internode base
-
1779 vec3 internode_base_position;
-
1780 if( i==0 ){ //first phytomer on shoot
-
1781 internode_base_position = base_position;
-
1782 }else{ // not the first phytomer on the shoot
-
1783 internode_base_position = shoot_internode_vertices.back().back();
-
1784 }
-
1785
-
1786 float taper = 1.f;
-
1787 if (current_node_number > 1) {
-
1788 taper = 1.f - radius_taper * float(i) / float(current_node_number - 1);
-
1789 }
-
1790
-
1791 //Adding the phytomer(s) to the shoot
-
1792 int pID = appendPhytomer(internode_radius * taper, internode_length, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, shoot_parameters.phytomer_parameters);
-
1793
-
1794 }
-
1795}
-
1796
-
-
1797std::string Shoot::sampleChildShootType() const {
-
1798 auto shoot_ptr = this;
-
1799
-
1800 assert( shoot_ptr->shoot_parameters.child_shoot_type_labels.size() == shoot_ptr->shoot_parameters.child_shoot_type_probabilities.size() );
-
1801
-
1802 std::string child_shoot_type_label = "";
-
1803
-
1804 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
-
1805 child_shoot_type_label = shoot_ptr->shoot_type_label;
-
1806 }else if( shoot_ptr->shoot_parameters.child_shoot_type_labels.size()==1 ){ //if only one child shoot types was specified, use it
-
1807 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(0);
-
1808 } else {
-
1809 float randf = context_ptr->randu();
-
1810 int shoot_type_index = -1;
-
1811 float cumulative_probability = 0;
-
1812 for (int s = 0; s < shoot_ptr->shoot_parameters.child_shoot_type_labels.size(); s++) {
-
1813 cumulative_probability += shoot_ptr->shoot_parameters.child_shoot_type_probabilities.at(s);
-
1814 if (randf < cumulative_probability) {
-
1815 shoot_type_index = s;
-
1816 break;
-
1817 }
-
1818 }
-
1819 if (shoot_type_index < 0) {
-
1820 shoot_type_index = shoot_ptr->shoot_parameters.child_shoot_type_labels.size() - 1;
-
1821 }
-
1822 child_shoot_type_label = shoot_ptr->shoot_type_label;
-
1823 if (shoot_type_index >= 0) {
-
1824 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(shoot_type_index);
-
1825 }
-
1826 }
-
1827
-
1828 return child_shoot_type_label;
-
1829
-
1830}
-
-
1831
-
-
1832bool Shoot::sampleVegetativeBudBreak( uint node_index ) const {
-
1833
-
1834 if ( node_index>=phytomers.size() ) {
-
1835 helios_runtime_error("ERROR (PlantArchitecture::sampleVegetativeBudBreak): Invalid node index. Node index must be less than the number of phytomers on the shoot.");
-
1836 }
-
1837
-
1838 float probability_min = plantarchitecture_ptr->shoot_types.at(this->shoot_type_label).vegetative_bud_break_probability_min.val();
-
1839 float probability_decay = plantarchitecture_ptr->shoot_types.at(this->shoot_type_label).vegetative_bud_break_probability_decay_rate.val();
-
1840
-
1841 float bud_break_probability;
-
1842 if ( !shoot_parameters.growth_requires_dormancy && probability_decay<0 ) {
-
1843 bud_break_probability = probability_min;
-
1844 } else if ( probability_decay>0 ) { //probability maximum at apex
-
1845 bud_break_probability = std::fmax( probability_min, 1.f - probability_decay * float(this->current_node_number - node_index - 1) );
-
1846 } else if ( probability_decay<0 ) { //probability maximum at base
-
1847 bud_break_probability = std::fmax( probability_min, 1.f - fabs(probability_decay) * float(node_index) );
-
1848 } else {
-
1849 bud_break_probability = 1.f;
-
1850 }
-
1851
-
1852 bool bud_break = true;
-
1853 if (context_ptr->randu() > bud_break_probability ) {
-
1854 bud_break = false;
-
1855 }
-
1856
-
1857 return bud_break;
-
1858
-
1859}
-
-
1860
-
-
1861uint Shoot::sampleEpicormicShoot( float dt, std::vector<float> &epicormic_positions_fraction ){
+
1769 context_ptr->deleteObject(flatten(leaf_objIDs));
+
1770 leaf_objIDs.resize(0);
+
1771 leaf_bases.resize(0);
+
1772
+
1773 if (build_context_geometry_petiole) {
+
1774 context_ptr->deleteObject(flatten(petiole_objIDs));
+
1775 petiole_objIDs.resize(0);
+
1776 }
+
1777}
+
1778
+
1779void Phytomer::deletePhytomer(){
+
1780
+
1781 // internode
+
1782 if( context_ptr->doesObjectExist(parent_shoot_ptr->internode_tube_objID) ) {
+
1783 context_ptr->pruneTubeNodes(parent_shoot_ptr->internode_tube_objID, this->shoot_index.x);
+
1784 parent_shoot_ptr->terminateApicalBud();
+
1785 }
+
1786
+
1787 // leaves
+
1788 this->removeLeaf();
+
1789
+
1790 //inflorescence
+
1791 for (auto &petiole: this->floral_buds) {
+
1792 for (auto &fbud: petiole) {
+
1793 for (int p = fbud.inflorescence_objIDs.size() - 1; p >= 0; p--) {
+
1794 uint objID = fbud.inflorescence_objIDs.at(p);
+
1795 context_ptr->deleteObject(objID);
+
1796 fbud.inflorescence_objIDs.erase(fbud.inflorescence_objIDs.begin() + p);
+
1797 fbud.inflorescence_bases.erase(fbud.inflorescence_bases.begin() + p);
+
1798 }
+
1799 for (int p = fbud.peduncle_objIDs.size() - 1; p >= 0; p--) {
+
1800 uint objID = fbud.peduncle_objIDs.at(p);
+
1801 context_ptr->deleteObject(fbud.peduncle_objIDs);
+
1802 context_ptr->deleteObject(fbud.inflorescence_objIDs);
+
1803 fbud.peduncle_objIDs.clear();
+
1804 fbud.inflorescence_objIDs.clear();
+
1805 fbud.inflorescence_bases.clear();
+
1806 break;
+
1807 }
+
1808 }
+
1809 }
+
1810
+
1811 // delete next phytomer on shoot
+
1812 if (shoot_index.x < parent_shoot_ptr->phytomers.size() - 1) {
+
1813 auto next_phytomer = parent_shoot_ptr->phytomers.at(shoot_index.x + 1);
+
1814 next_phytomer->deletePhytomer();
+
1815 }
+
1816
+
1817 // delete any child shoots
+
1818 if( parent_shoot_ptr->childIDs.find(shoot_index.x) != parent_shoot_ptr->childIDs.end() ){
+
1819 for( auto childID: parent_shoot_ptr->childIDs.at(shoot_index.x) ){
+
1820 auto child_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(childID);
+
1821 child_shoot->phytomers.front()->deletePhytomer();
+
1822 }
+
1823 }
+
1824
+
1825}
+
1826
+
1827bool Phytomer::hasLeaf() const {
+
1828 return (!leaf_bases.empty() && !leaf_bases.front().empty());
+
1829}
+
1830
+
1831float Phytomer::calculateDownstreamLeafArea() const {
+
1832 return parent_shoot_ptr->sumShootLeafArea(shoot_index.x);
+
1833}
+
1834
+
1835Shoot::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,
+
1836 float internode_length_shoot_initial, ShootParameters &shoot_params, std::string shoot_type_label, PlantArchitecture *plant_architecture_ptr) :
+
1837 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) {
+
1838 carbohydrate_pool_molC = 0;
+
1839 phyllochron_counter = 0;
+
1840 isdormant = true;
+
1841 gravitropic_curvature = shoot_params.gravitropic_curvature.val();
+
1842 context_ptr = plant_architecture_ptr->context_ptr;
+
1843 phyllochron_instantaneous = shoot_parameters.phyllochron_min.val();
+
1844 elongation_rate_instantaneous = shoot_parameters.elongation_rate_max.val();
+
1845
+
1846 if( parent_shoot_ID>=0 ) {
+
1847 plant_architecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->childIDs[(int) parent_node_index].push_back(shoot_ID);
+
1848 }
+
1849}
+
1850
+
1851void Shoot::buildShootPhytomers(float internode_radius, float internode_length, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper) {
+
1852
+
1853 for( int i=0; i<current_node_number; i++ ) { //loop over phytomers to build up the shoot
+
1854
+
1855 //Determine position of internode base
+
1856 vec3 internode_base_position;
+
1857 if( i==0 ){ //first phytomer on shoot
+
1858 internode_base_position = base_position;
+
1859 }else{ // not the first phytomer on the shoot
+
1860 internode_base_position = shoot_internode_vertices.back().back();
+
1861 }
1862
-
1863 std::string epicormic_shoot_label = plantarchitecture_ptr->plant_instances.at(this->plantID).epicormic_shoot_probability_perlength_per_day.first;
-
1864
-
1865 if (epicormic_shoot_label.empty()) {
-
1866 return 0;
-
1867 }
-
1868
-
1869 float epicormic_probability = plantarchitecture_ptr->plant_instances.at(this->plantID).epicormic_shoot_probability_perlength_per_day.second;
+
1863 float taper = 1.f;
+
1864 if (current_node_number > 1) {
+
1865 taper = 1.f - radius_taper * float(i) / float(current_node_number - 1);
+
1866 }
+
1867
+
1868 //Adding the phytomer(s) to the shoot
+
1869 int pID = appendPhytomer(internode_radius * taper, internode_length, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, shoot_parameters.phytomer_parameters);
1870
-
1871 if (epicormic_probability == 0) {
-
1872 return 0;
-
1873 }
-
1874
-
1875 uint Nshoots = 0;
+
1871 }
+
1872}
+
1873
+
+
1874std::string Shoot::sampleChildShootType() const {
+
1875 auto shoot_ptr = this;
1876
-
1877 epicormic_positions_fraction.clear();
+
1877 assert( shoot_ptr->shoot_parameters.child_shoot_type_labels.size() == shoot_ptr->shoot_parameters.child_shoot_type_probabilities.size() );
1878
-
1879 float shoot_length = this->calculateShootLength();
+
1879 std::string child_shoot_type_label = "";
1880
-
1881 float time = dt;
-
1882 while (time > 0) {
-
1883 float dta = std::min(time, 1.f);
-
1884
-
1885 float shoot_fraction = context_ptr->randu();
-
1886
-
1887 float elevation = fabs(getShootAxisVector(shoot_fraction).z);
-
1888
-
1889 bool new_shoot = uint((epicormic_probability * shoot_length * dta * elevation > context_ptr->randu()));
-
1890
-
1891 Nshoots += uint(new_shoot);
-
1892
-
1893 if (new_shoot) {
-
1894 epicormic_positions_fraction.push_back(shoot_fraction);
+
1881 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
+
1882 child_shoot_type_label = shoot_ptr->shoot_type_label;
+
1883 }else if( shoot_ptr->shoot_parameters.child_shoot_type_labels.size()==1 ){ //if only one child shoot types was specified, use it
+
1884 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(0);
+
1885 } else {
+
1886 float randf = context_ptr->randu();
+
1887 int shoot_type_index = -1;
+
1888 float cumulative_probability = 0;
+
1889 for (int s = 0; s < shoot_ptr->shoot_parameters.child_shoot_type_labels.size(); s++) {
+
1890 cumulative_probability += shoot_ptr->shoot_parameters.child_shoot_type_probabilities.at(s);
+
1891 if (randf < cumulative_probability) {
+
1892 shoot_type_index = s;
+
1893 break;
+
1894 }
1895 }
-
1896
-
1897 time -= dta;
-
1898 }
-
1899
-
1900 assert(epicormic_positions_fraction.size() == Nshoots);
-
1901
-
1902 return Nshoots;
-
1903}
-
+
1896 if (shoot_type_index < 0) {
+
1897 shoot_type_index = shoot_ptr->shoot_parameters.child_shoot_type_labels.size() - 1;
+
1898 }
+
1899 child_shoot_type_label = shoot_ptr->shoot_type_label;
+
1900 if (shoot_type_index >= 0) {
+
1901 child_shoot_type_label = shoot_ptr->shoot_parameters.child_shoot_type_labels.at(shoot_type_index);
+
1902 }
+
1903 }
1904
-
-
1905uint 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,
-
1906 float radius_taper, const std::string &shoot_type_label) {
-
1907
-
1908 if( plant_instances.find(plantID) == plant_instances.end() ){
-
1909 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
1910 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
-
1911 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
-
1912 }
-
1913
-
1914 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
-
1915
-
1916 auto shoot_parameters = shoot_types.at(shoot_type_label);
-
1917 validateShootTypes(shoot_parameters);
-
1918
-
1919 if(current_node_number > shoot_parameters.max_nodes.val() ){
-
1920 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()) + ".");
-
1921 }
-
1922
-
1923 uint shootID = shoot_tree_ptr->size();
-
1924 vec3 base_position = plant_instances.at(plantID).base_position;
-
1925
-
1926 // Create the new shoot
-
1927 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));
-
1928 shoot_tree_ptr->emplace_back(shoot_new);
-
1929
-
1930 // Build phytomer geometry
-
1931 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
-
1932
-
1933 return shootID;
-
1934}
-
+
1905 return child_shoot_type_label;
+
1906
+
1907}
+
+
1908
+
+
1909bool Shoot::sampleVegetativeBudBreak( uint node_index ) const {
+
1910
+
1911 if ( node_index>=phytomers.size() ) {
+
1912 helios_runtime_error("ERROR (PlantArchitecture::sampleVegetativeBudBreak): Invalid node index. Node index must be less than the number of phytomers on the shoot.");
+
1913 }
+
1914
+
1915 float probability_min = plantarchitecture_ptr->shoot_types.at(this->shoot_type_label).vegetative_bud_break_probability_min.val();
+
1916 float probability_decay = plantarchitecture_ptr->shoot_types.at(this->shoot_type_label).vegetative_bud_break_probability_decay_rate.val();
+
1917
+
1918 float bud_break_probability;
+
1919 if ( !shoot_parameters.growth_requires_dormancy && probability_decay<0 ) {
+
1920 bud_break_probability = probability_min;
+
1921 } else if ( probability_decay>0 ) { //probability maximum at apex
+
1922 bud_break_probability = std::fmax( probability_min, 1.f - probability_decay * float(this->current_node_number - node_index - 1) );
+
1923 } else if ( probability_decay<0 ) { //probability maximum at base
+
1924 bud_break_probability = std::fmax( probability_min, 1.f - fabs(probability_decay) * float(node_index) );
+
1925 } else {
+
1926 bud_break_probability = 1.f;
+
1927 }
+
1928
+
1929 bool bud_break = true;
+
1930 if (context_ptr->randu() > bud_break_probability ) {
+
1931 bud_break = false;
+
1932 }
+
1933
+
1934 return bud_break;
1935
-
-
1936uint 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,
-
1937 float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label) {
-
1938
-
1939 if( plant_instances.find(plantID) == plant_instances.end() ) {
-
1940 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
1941 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
-
1942 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
-
1943 }
-
1944
-
1945 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
-
1946
-
1947 auto shoot_parameters = shoot_types.at(shoot_type_label);
-
1948 validateShootTypes(shoot_parameters);
-
1949
-
1950 if( shoot_tree_ptr->empty() ){
-
1951 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Cannot append shoot to empty shoot. You must call addBaseStemShoot() first for each plant.");
-
1952 }else if( parent_shoot_ID >= int(shoot_tree_ptr->size()) ){
-
1953 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
-
1954 }else if(current_node_number > shoot_parameters.max_nodes.val() ){
-
1955 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()) + ".");
-
1956 }else if( shoot_tree_ptr->at(parent_shoot_ID)->phytomers.empty() ){
-
1957 std::cerr << "WARNING (PlantArchitecture::appendShoot): Shoot does not have any phytomers to append." << std::endl;
-
1958 }
-
1959
-
1960 //stop parent shoot from producing new phytomers at the apex
-
1961 shoot_tree_ptr->at(parent_shoot_ID)->shoot_parameters.max_nodes = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
-
1962 shoot_tree_ptr->at(parent_shoot_ID)->terminateApicalBud(); //meristem should not keep growing after appending shoot
+
1936}
+
+
1937
+
+
1938uint Shoot::sampleEpicormicShoot( float dt, std::vector<float> &epicormic_positions_fraction ){
+
1939
+
1940 std::string epicormic_shoot_label = plantarchitecture_ptr->plant_instances.at(this->plantID).epicormic_shoot_probability_perlength_per_day.first;
+
1941
+
1942 if (epicormic_shoot_label.empty()) {
+
1943 return 0;
+
1944 }
+
1945
+
1946 float epicormic_probability = plantarchitecture_ptr->plant_instances.at(this->plantID).epicormic_shoot_probability_perlength_per_day.second;
+
1947
+
1948 if (epicormic_probability == 0) {
+
1949 return 0;
+
1950 }
+
1951
+
1952 uint Nshoots = 0;
+
1953
+
1954 epicormic_positions_fraction.clear();
+
1955
+
1956 float shoot_length = this->calculateShootLength();
+
1957
+
1958 float time = dt;
+
1959 while (time > 0) {
+
1960 float dta = std::min(time, 1.f);
+
1961
+
1962 float shoot_fraction = context_ptr->randu();
1963
-
1964 //accumulate all the values that will be passed to Shoot constructor
-
1965 int appended_shootID = int(shoot_tree_ptr->size());
-
1966 uint parent_node = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number - 1;
-
1967 uint rank = shoot_tree_ptr->at(parent_shoot_ID)->rank;
-
1968 vec3 base_position = interpolateTube(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.back()->getInternodeNodePositions(), 0.9f );
+
1964 float elevation = fabs(getShootAxisVector(shoot_fraction).z);
+
1965
+
1966 bool new_shoot = uint((epicormic_probability * shoot_length * dta * elevation > context_ptr->randu()));
+
1967
+
1968 Nshoots += uint(new_shoot);
1969
-
1970 // Create the new shoot
-
1971 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));
-
1972 shoot_tree_ptr->emplace_back(shoot_new);
+
1970 if (new_shoot) {
+
1971 epicormic_positions_fraction.push_back(shoot_fraction);
+
1972 }
1973
-
1974 // Build phytomer geometry
-
1975 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
+
1974 time -= dta;
+
1975 }
1976
-
1977 return appended_shootID;
-
1978}
-
-
1979
-
-
1980uint 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,
-
1981 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label, uint petiole_index) {
-
1982
-
1983 if( plant_instances.find(plantID) == plant_instances.end() ){
-
1984 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
1985 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
-
1986 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
-
1987 }
-
1988
-
1989 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1977 assert(epicormic_positions_fraction.size() == Nshoots);
+
1978
+
1979 return Nshoots;
+
1980}
+
+
1981
+
+
1982uint 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,
+
1983 float radius_taper, const std::string &shoot_type_label) {
+
1984
+
1985 if( plant_instances.find(plantID) == plant_instances.end() ){
+
1986 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
1987 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
1988 helios_runtime_error("ERROR (PlantArchitecture::addBaseStemShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
1989 }
1990
-
1991 if(parent_shoot_ID <= -1 || parent_shoot_ID >= shoot_tree_ptr->size() ){
-
1992 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
-
1993 }else if(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.size() <= parent_node_index ) {
-
1994 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent shoot does not have a node " + std::to_string(parent_node_index) + ".");
-
1995 }
-
1996
-
1997 // accumulate all the values that will be passed to Shoot constructor
-
1998 auto shoot_parameters = shoot_types.at(shoot_type_label);
-
1999 validateShootTypes(shoot_parameters);
-
2000 uint parent_rank = (int) shoot_tree_ptr->at(parent_shoot_ID)->rank;
-
2001 int parent_node_count = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
-
2002 int childID = int(shoot_tree_ptr->size());
-
2003
-
2004 // Calculate the position of the shoot base
-
2005 auto parent_shoot_ptr = shoot_tree_ptr->at(parent_shoot_ID);
+
1991 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
1992
+
1993 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
1994 validateShootTypes(shoot_parameters);
+
1995
+
1996 if(current_node_number > shoot_parameters.max_nodes.val() ){
+
1997 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()) + ".");
+
1998 }
+
1999
+
2000 uint shootID = shoot_tree_ptr->size();
+
2001 vec3 base_position = plant_instances.at(plantID).base_position;
+
2002
+
2003 // Create the new shoot
+
2004 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));
+
2005 shoot_tree_ptr->emplace_back(shoot_new);
2006
-
2007 vec3 shoot_base_position = parent_shoot_ptr->shoot_internode_vertices.at(parent_node_index).back();
-
2008
-
2009 // Shift the shoot base position outward by the parent internode radius
-
2010 vec3 petiole_axis = parent_shoot_ptr->phytomers.at(parent_node_index)->getPetioleAxisVector(0,petiole_index);
-
2011 shoot_base_position += 0.9f * petiole_axis * parent_shoot_ptr->phytomers.at(parent_node_index)->getInternodeRadius(1.f);
+
2007 // Build phytomer geometry
+
2008 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
+
2009
+
2010 return shootID;
+
2011}
+
2012
-
2013 // Create the new shoot
-
2014 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));
-
2015 shoot_tree_ptr->emplace_back(shoot_new);
-
2016
-
2017 // Build phytomer geometry
-
2018 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
-
2019
-
2020 return childID;
-
2021}
-
-
2022
-
-
2023uint 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,
-
2024 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label) {
-
2025
-
2026 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2027 helios_runtime_error("ERROR (PlantArchitecture::addEpicormicShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2028 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
-
2029 helios_runtime_error("ERROR (PlantArchitecture::addEpicormicShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
-
2030 }
-
2031
-
2032 auto &parent_shoot = plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID);
-
2033
-
2034 uint parent_node_index = 0;
-
2035 if (parent_position_fraction > 0) {
-
2036 parent_node_index = std::ceil(parent_position_fraction * float(parent_shoot->phytomers.size())) - 1;
-
2037 }
-
2038
-
2039 vec3 petiole_axis = plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->phytomers.at(parent_node_index)->getPetioleAxisVector(0,0);
+
+
2013uint 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,
+
2014 float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label) {
+
2015
+
2016 if( plant_instances.find(plantID) == plant_instances.end() ) {
+
2017 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2018 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
2019 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
2020 }
+
2021
+
2022 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
2023
+
2024 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
2025 validateShootTypes(shoot_parameters);
+
2026
+
2027 if( shoot_tree_ptr->empty() ){
+
2028 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Cannot append shoot to empty shoot. You must call addBaseStemShoot() first for each plant.");
+
2029 }else if( parent_shoot_ID >= int(shoot_tree_ptr->size()) ){
+
2030 helios_runtime_error("ERROR (PlantArchitecture::appendShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
+
2031 }else if(current_node_number > shoot_parameters.max_nodes.val() ){
+
2032 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()) + ".");
+
2033 }else if( shoot_tree_ptr->at(parent_shoot_ID)->phytomers.empty() ){
+
2034 std::cerr << "WARNING (PlantArchitecture::appendShoot): Shoot does not have any phytomers to append." << std::endl;
+
2035 }
+
2036
+
2037 //stop parent shoot from producing new phytomers at the apex
+
2038 shoot_tree_ptr->at(parent_shoot_ID)->shoot_parameters.max_nodes = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
+
2039 shoot_tree_ptr->at(parent_shoot_ID)->terminateApicalBud(); //meristem should not keep growing after appending shoot
2040
-
2041 //\todo Figuring out how to set this correctly to make the shoot vertical, which avoids having to write a child shoot function.
-
2042 AxisRotation base_rotation = make_AxisRotation(0, acos_safe(petiole_axis.z), 0);
-
2043
-
2044 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);
-
2045
-
2046}
-
-
2047
-
2048void PlantArchitecture::validateShootTypes(ShootParameters &shoot_parameters) const {
-
2049 assert(shoot_parameters.child_shoot_type_probabilities.size() == shoot_parameters.child_shoot_type_labels.size());
+
2041 //accumulate all the values that will be passed to Shoot constructor
+
2042 int appended_shootID = int(shoot_tree_ptr->size());
+
2043 uint parent_node = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number - 1;
+
2044 uint rank = shoot_tree_ptr->at(parent_shoot_ID)->rank;
+
2045 vec3 base_position = interpolateTube(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.back()->getInternodeNodePositions(), 0.9f );
+
2046
+
2047 // Create the new shoot
+
2048 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));
+
2049 shoot_tree_ptr->emplace_back(shoot_new);
2050
-
2051 for( int ind = shoot_parameters.child_shoot_type_labels.size()-1; ind>=0; ind-- ){
-
2052 if( shoot_types.find(shoot_parameters.child_shoot_type_labels.at(ind)) == shoot_types.end() ){
-
2053 shoot_parameters.child_shoot_type_labels.erase(shoot_parameters.child_shoot_type_labels.begin()+ind);
-
2054 shoot_parameters.child_shoot_type_probabilities.erase(shoot_parameters.child_shoot_type_probabilities.begin()+ind);
-
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, phytomer_parameters);
-
2074
-
2075 current_shoot_ptr->current_node_number++;
-
2076 current_shoot_ptr->nodes_this_season++;
-
2077
-
2078 for (auto &phytomers: current_shoot_ptr->phytomers) {
-
2079 phytomers->shoot_index.y = current_shoot_ptr->current_node_number;
-
2080 }
-
2081
-
2082 //If this shoot reached max nodes, add a terminal floral bud if max_terminal_floral_buds > 0
-
2083 if( current_shoot_ptr->current_node_number == current_shoot_ptr->shoot_parameters.max_nodes.val() ){
-
2084 if ( !current_shoot_ptr->shoot_parameters.flowers_require_dormancy && current_shoot_ptr->shoot_parameters.max_terminal_floral_buds.val() > 0) {
-
2085 current_shoot_ptr->addTerminalFloralBud();
-
2086 BudState state;
-
2087 if( current_shoot_ptr->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function!=nullptr ){
-
2088 state = BUD_FLOWER_CLOSED;
-
2089 }else if( current_shoot_ptr->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function!=nullptr ) {
-
2090 state = BUD_FRUITING;
-
2091 } else {
-
2092 return pID;
-
2093 }
-
2094 for (auto &fbuds: current_shoot_ptr->phytomers.back()->floral_buds) {
-
2095 for (auto &fbud: fbuds) {
-
2096 if (fbud.isterminal) {
-
2097 fbud.state = state;
-
2098 current_shoot_ptr->phytomers.back()->updateInflorescence(fbud);
-
2099 }
-
2100 }
-
2101 }
-
2102 }
-
2103 }
-
2104
-
2105 //If this shoot reached the max nodes for the season, add a dormant floral bud and make terminal vegetative bud dormant
-
2106 else if( current_shoot_ptr->nodes_this_season >= current_shoot_ptr->shoot_parameters.max_nodes_per_season.val() ){
-
2107 if ( !current_shoot_ptr->shoot_parameters.flowers_require_dormancy && current_shoot_ptr->shoot_parameters.max_terminal_floral_buds.val() > 0) {
-
2108 current_shoot_ptr->addTerminalFloralBud();
-
2109 for (auto &fbuds: current_shoot_ptr->phytomers.back()->floral_buds) {
-
2110 for (auto &fbud: fbuds) {
-
2111 if (fbud.isterminal) {
-
2112 fbud.state = BUD_DORMANT;
-
2113 current_shoot_ptr->phytomers.back()->updateInflorescence(fbud);
-
2114 }
-
2115 }
-
2116 }
-
2117 }
-
2118 current_shoot_ptr->phytomers.at(pID)->isdormant = true;
-
2119 }
+
2051 // Build phytomer geometry
+
2052 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
+
2053
+
2054 return appended_shootID;
+
2055}
+
+
2056
+
+
2057uint 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,
+
2058 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label, uint petiole_index) {
+
2059
+
2060 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2061 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2062 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
2063 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
2064 }
+
2065
+
2066 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
2067
+
2068 if(parent_shoot_ID <= -1 || parent_shoot_ID >= shoot_tree_ptr->size() ){
+
2069 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent with ID of " + std::to_string(parent_shoot_ID) + " does not exist.");
+
2070 }else if(shoot_tree_ptr->at(parent_shoot_ID)->phytomers.size() <= parent_node_index ) {
+
2071 helios_runtime_error("ERROR (PlantArchitecture::addChildShoot): Parent shoot does not have a node " + std::to_string(parent_node_index) + ".");
+
2072 }
+
2073
+
2074 // accumulate all the values that will be passed to Shoot constructor
+
2075 auto shoot_parameters = shoot_types.at(shoot_type_label);
+
2076 validateShootTypes(shoot_parameters);
+
2077 uint parent_rank = (int) shoot_tree_ptr->at(parent_shoot_ID)->rank;
+
2078 int parent_node_count = shoot_tree_ptr->at(parent_shoot_ID)->current_node_number;
+
2079 int childID = int(shoot_tree_ptr->size());
+
2080
+
2081 // Calculate the position of the shoot base
+
2082 auto parent_shoot_ptr = shoot_tree_ptr->at(parent_shoot_ID);
+
2083
+
2084 vec3 shoot_base_position = parent_shoot_ptr->shoot_internode_vertices.at(parent_node_index).back();
+
2085
+
2086 // Shift the shoot base position outward by the parent internode radius
+
2087 vec3 petiole_axis = parent_shoot_ptr->phytomers.at(parent_node_index)->getPetioleAxisVector(0,petiole_index);
+
2088 shoot_base_position += 0.9f * petiole_axis * parent_shoot_ptr->phytomers.at(parent_node_index)->getInternodeRadius(1.f);
+
2089
+
2090 // Create the new shoot
+
2091 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));
+
2092 shoot_tree_ptr->emplace_back(shoot_new);
+
2093
+
2094 // Build phytomer geometry
+
2095 shoot_new->buildShootPhytomers(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, radius_taper);
+
2096
+
2097 return childID;
+
2098}
+
+
2099
+
+
2100uint 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,
+
2101 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label) {
+
2102
+
2103 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2104 helios_runtime_error("ERROR (PlantArchitecture::addEpicormicShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2105 }else if( shoot_types.find(shoot_type_label) == shoot_types.end() ) {
+
2106 helios_runtime_error("ERROR (PlantArchitecture::addEpicormicShoot): Shoot type with label of " + shoot_type_label + " does not exist.");
+
2107 }
+
2108
+
2109 auto &parent_shoot = plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID);
+
2110
+
2111 uint parent_node_index = 0;
+
2112 if (parent_position_fraction > 0) {
+
2113 parent_node_index = std::ceil(parent_position_fraction * float(parent_shoot->phytomers.size())) - 1;
+
2114 }
+
2115
+
2116 vec3 petiole_axis = plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->phytomers.at(parent_node_index)->getPetioleAxisVector(0,0);
+
2117
+
2118 //\todo Figuring out how to set this correctly to make the shoot vertical, which avoids having to write a child shoot function.
+
2119 AxisRotation base_rotation = make_AxisRotation(0, acos_safe(petiole_axis.z), 0);
2120
-
2121 return pID;
-
2122}
-
-
2123
-
-
2124void PlantArchitecture::enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday) {
-
2125
-
2126 if(shoot_types.find(epicormic_shoot_type_label) == shoot_types.end() ){
-
2127 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Shoot type with label of " + epicormic_shoot_type_label + " does not exist.");
-
2128 }else if( epicormic_probability_perlength_perday<0 ){
-
2129 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Epicormic probability must be greater than or equal to zero.");
-
2130 }else if( plant_instances.find(plantID) == plant_instances.end() ){
-
2131 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2132 }
-
2133
-
2134 plant_instances.at(plantID).epicormic_shoot_probability_perlength_per_day = std::make_pair(epicormic_shoot_type_label, epicormic_probability_perlength_perday);
+
2121 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);
+
2122
+
2123}
+
+
2124
+
2125void PlantArchitecture::validateShootTypes(ShootParameters &shoot_parameters) const {
+
2126 assert(shoot_parameters.child_shoot_type_probabilities.size() == shoot_parameters.child_shoot_type_labels.size());
+
2127
+
2128 for( int ind = shoot_parameters.child_shoot_type_labels.size()-1; ind>=0; ind-- ){
+
2129 if( shoot_types.find(shoot_parameters.child_shoot_type_labels.at(ind)) == shoot_types.end() ){
+
2130 shoot_parameters.child_shoot_type_labels.erase(shoot_parameters.child_shoot_type_labels.begin()+ind);
+
2131 shoot_parameters.child_shoot_type_probabilities.erase(shoot_parameters.child_shoot_type_probabilities.begin()+ind);
+
2132 }
+
2133 }
+
2134}
2135
-
2136}
-
+
+
2136int 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) {
2137
-
- -
2139 build_context_geometry_internode = false;
-
2140}
-
+
2138 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2139 helios_runtime_error("ERROR (PlantArchitecture::appendPhytomerToShoot): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2140 }
2141
-
- -
2143 build_context_geometry_petiole = false;
-
2144}
-
-
2145
-
- -
2147 build_context_geometry_peduncle = false;
-
2148}
-
+
2142 auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree;
+
2143
+
2144 if(shootID >= shoot_tree_ptr->size() ){
+
2145 helios_runtime_error("ERROR (PlantArchitecture::appendPhytomerToShoot): Parent with ID of " + std::to_string(shootID) + " does not exist.");
+
2146 }
+
2147
+
2148 auto current_shoot_ptr = plant_instances.at(plantID).shoot_tree.at(shootID);
2149
-
- -
2151 ground_clipping_height = ground_height;
-
2152}
-
-
2153
-
2154void PlantArchitecture::incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, bool update_context_geometry) {
-
2155
-
2156 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2157 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2158 }
-
2159
-
2160 auto shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
-
2161
-
2162 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
-
2163 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
-
2164 }else if( node_number>=shoot->current_node_number ){
-
2165 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.");
-
2166 }
-
2167
-
2168 auto phytomer = shoot->phytomers.at(node_number);
-
2169
-
2170 // float leaf_area = phytomer->calculateDownstreamLeafArea();
-
2171 float leaf_area = phytomer->downstream_leaf_area;
-
2172 // std::cout << "leaf area: " << leaf_area_old << " " << leaf_area << std::endl;
-
2173 if ( context_ptr->doesObjectExist(shoot->internode_tube_objID) ) {
-
2174 context_ptr->setObjectData( shoot->internode_tube_objID, "leaf_area", leaf_area );
-
2175 }
-
2176
-
2177 float internode_area = phytomer->parent_shoot_ptr->shoot_parameters.girth_area_factor.val() * leaf_area * 1e-4;
-
2178 phytomer->parent_shoot_ptr->shoot_parameters.girth_area_factor.resample();
-
2179
-
2180 float phytomer_radius = sqrtf(internode_area / M_PI);
+
2150 int pID = current_shoot_ptr->appendPhytomer(internode_radius, internode_length_max, internode_length_scale_factor_fraction, leaf_scale_factor_fraction, phytomer_parameters);
+
2151
+
2152 current_shoot_ptr->current_node_number++;
+
2153 current_shoot_ptr->nodes_this_season++;
+
2154
+
2155 for (auto &phytomers: current_shoot_ptr->phytomers) {
+
2156 phytomers->shoot_index.y = current_shoot_ptr->current_node_number;
+
2157 }
+
2158
+
2159 //If this shoot reached max nodes, add a terminal floral bud if max_terminal_floral_buds > 0
+
2160 if( current_shoot_ptr->current_node_number == current_shoot_ptr->shoot_parameters.max_nodes.val() ){
+
2161 if ( !current_shoot_ptr->shoot_parameters.flowers_require_dormancy && current_shoot_ptr->shoot_parameters.max_terminal_floral_buds.val() > 0) {
+
2162 current_shoot_ptr->addTerminalFloralBud();
+
2163 BudState state;
+
2164 if( current_shoot_ptr->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function!=nullptr ){
+
2165 state = BUD_FLOWER_CLOSED;
+
2166 }else if( current_shoot_ptr->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function!=nullptr ) {
+
2167 state = BUD_FRUITING;
+
2168 } else {
+
2169 return pID;
+
2170 }
+
2171 for (auto &fbuds: current_shoot_ptr->phytomers.back()->floral_buds) {
+
2172 for (auto &fbud: fbuds) {
+
2173 if (fbud.isterminal) {
+
2174 fbud.state = state;
+
2175 current_shoot_ptr->phytomers.back()->updateInflorescence(fbud);
+
2176 }
+
2177 }
+
2178 }
+
2179 }
+
2180 }
2181
-
2182 auto &segment = shoot->shoot_internode_radii.at(node_number);
-
2183 for( float &radius : segment ) {
-
2184 if( phytomer_radius > radius ) { //radius should only increase
-
2185 radius = phytomer_radius;
-
2186 }
-
2187 }
-
2188
-
2189 if (update_context_geometry && context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
-
2190 context_ptr->setTubeRadii(shoot->internode_tube_objID, flatten(shoot->shoot_internode_radii));
-
2191 }
-
2192}
-
2193
-
2194void PlantArchitecture::setPhytomerLeafScale(uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction) {
-
2195
-
2196 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2197 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2198 }
-
2199
-
2200 auto parent_shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
-
2201
-
2202 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
-
2203 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
-
2204 }else if( node_number>=parent_shoot->current_node_number ){
-
2205 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.");
-
2206 }
-
2207 if(leaf_scale_factor_fraction < 0 || leaf_scale_factor_fraction > 1 ){
-
2208 std::cerr << "WARNING (PlantArchitecture::setPhytomerLeafScale): Leaf scaling factor was outside the range of 0 to 1. No scaling was applied." << std::endl;
-
2209 return;
-
2210 }
-
2211
-
2212 parent_shoot->phytomers.at(node_number)->setLeafScaleFraction(leaf_scale_factor_fraction);
+
2182 //If this shoot reached the max nodes for the season, add a dormant floral bud and make terminal vegetative bud dormant
+
2183 else if( current_shoot_ptr->nodes_this_season >= current_shoot_ptr->shoot_parameters.max_nodes_per_season.val() ){
+
2184 if ( !current_shoot_ptr->shoot_parameters.flowers_require_dormancy && current_shoot_ptr->shoot_parameters.max_terminal_floral_buds.val() > 0) {
+
2185 current_shoot_ptr->addTerminalFloralBud();
+
2186 for (auto &fbuds: current_shoot_ptr->phytomers.back()->floral_buds) {
+
2187 for (auto &fbud: fbuds) {
+
2188 if (fbud.isterminal) {
+
2189 fbud.state = BUD_DORMANT;
+
2190 current_shoot_ptr->phytomers.back()->updateInflorescence(fbud);
+
2191 }
+
2192 }
+
2193 }
+
2194 }
+
2195 current_shoot_ptr->phytomers.at(pID)->isdormant = true;
+
2196 }
+
2197
+
2198 return pID;
+
2199}
+
+
2200
+
+
2201void PlantArchitecture::enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday) {
+
2202
+
2203 if(shoot_types.find(epicormic_shoot_type_label) == shoot_types.end() ){
+
2204 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Shoot type with label of " + epicormic_shoot_type_label + " does not exist.");
+
2205 }else if( epicormic_probability_perlength_perday<0 ){
+
2206 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Epicormic probability must be greater than or equal to zero.");
+
2207 }else if( plant_instances.find(plantID) == plant_instances.end() ){
+
2208 helios_runtime_error("ERROR (PlantArchitecture::enableEpicormicChildShoots): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2209 }
+
2210
+
2211 plant_instances.at(plantID).epicormic_shoot_probability_perlength_per_day = std::make_pair(epicormic_shoot_type_label, epicormic_probability_perlength_perday);
+
2212
2213}
+
2214
-
2215void PlantArchitecture::setPlantBasePosition(uint plantID, const helios::vec3 &base_position) {
-
2216
-
2217 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2218 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2219 }
-
2220
-
2221 plant_instances.at(plantID).base_position = base_position;
-
2222
-
2223 //\todo Does not work after shoots have been added to the plant.
-
2224 if( !plant_instances.at(plantID).shoot_tree.empty() ){
-
2225 std::cerr << "WARNING (PlantArchitecture::setPlantBasePosition): This function does not work after shoots have been added to the plant." << std::endl;
-
2226 }
-
2227}
-
2228
-
2229helios::vec3 PlantArchitecture::getPlantBasePosition(uint plantID) const{
-
2230 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2231 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2232 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
-
2233 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
-
2234 }
-
2235 return plant_instances.at(plantID).base_position;
-
2236}
-
2237
-
-
2238float PlantArchitecture::sumPlantLeafArea(uint plantID) const{
-
2239
-
2240 if( plantID>=plant_instances.size() ){
-
2241 helios_runtime_error("ERROR (PlantArchitecture::sumPlantLeafArea): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2242 }
-
2243
-
2244 std::vector<uint> leaf_objIDs = getPlantLeafObjectIDs(plantID);
-
2245
-
2246 float area = 0;
-
2247 for (uint objID: leaf_objIDs) {
-
2248 area += context_ptr->getObjectArea(objID);
-
2249 }
-
2250
-
2251 return area;
-
2252}
+
+ +
2216 build_context_geometry_internode = false;
+
2217}
+
2218
+
+ +
2220 build_context_geometry_petiole = false;
+
2221}
+
+
2222
+
+ +
2224 build_context_geometry_peduncle = false;
+
2225}
+
+
2226
+
+ +
2228 ground_clipping_height = ground_height;
+
2229}
+
+
2230
+
2231void PlantArchitecture::incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, bool update_context_geometry) {
+
2232
+
2233 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2234 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2235 }
+
2236
+
2237 auto shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2238
+
2239 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
2240 helios_runtime_error("ERROR (PlantArchitecture::incrementPhytomerInternodeGirth): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
2241 }else if( node_number>=shoot->current_node_number ){
+
2242 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.");
+
2243 }
+
2244
+
2245 auto phytomer = shoot->phytomers.at(node_number);
+
2246
+
2247 // float leaf_area = phytomer->calculateDownstreamLeafArea();
+
2248 float leaf_area = phytomer->downstream_leaf_area;
+
2249 // std::cout << "leaf area: " << leaf_area_old << " " << leaf_area << std::endl;
+
2250 if ( context_ptr->doesObjectExist(shoot->internode_tube_objID) ) {
+
2251 context_ptr->setObjectData( shoot->internode_tube_objID, "leaf_area", leaf_area );
+
2252 }
2253
-
2254void PlantArchitecture::setPlantAge(uint plantID, float a_current_age) {
-
2255 //\todo
-
2256 // this->current_age = current_age;
-
2257}
+
2254 float internode_area = phytomer->parent_shoot_ptr->shoot_parameters.girth_area_factor.val() * leaf_area * 1e-4;
+
2255 phytomer->parent_shoot_ptr->shoot_parameters.girth_area_factor.resample();
+
2256
+
2257 float phytomer_radius = sqrtf(internode_area / M_PI);
2258
-
2259float PlantArchitecture::getPlantAge(uint plantID) const{
-
2260 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2261 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2262 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
-
2263 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
+
2259 auto &segment = shoot->shoot_internode_radii.at(node_number);
+
2260 for( float &radius : segment ) {
+
2261 if( phytomer_radius > radius ) { //radius should only increase
+
2262 radius = phytomer_radius;
+
2263 }
2264 }
-
2265 return plant_instances.at(plantID).current_age;
-
2266}
-
2267
-
2268void PlantArchitecture::harvestPlant(uint plantID){
-
2269
-
2270 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2271 helios_runtime_error("ERROR (PlantArchitecture::harvestPlant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2272 }
-
2273
-
2274 for (auto &shoot: plant_instances.at(plantID).shoot_tree) {
-
2275 for (auto &phytomer: shoot->phytomers) {
-
2276 for (auto &petiole: phytomer->floral_buds) {
-
2277 for (auto &fbud: petiole) {
-
2278 if (fbud.state != BUD_DORMANT) {
-
2279 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
2280 }
-
2281 }
-
2282 }
-
2283 }
-
2284 }
-
2285}
-
2286
-
2287void PlantArchitecture::removeShootLeaves(uint plantID, uint shootID){
-
2288 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2289 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2290 }
+
2265
+
2266 if (update_context_geometry && context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
+
2267 context_ptr->setTubeRadii(shoot->internode_tube_objID, flatten(shoot->shoot_internode_radii));
+
2268 }
+
2269}
+
2270
+
2271void PlantArchitecture::setPhytomerLeafScale(uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction) {
+
2272
+
2273 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2274 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2275 }
+
2276
+
2277 auto parent_shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2278
+
2279 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
2280 helios_runtime_error("ERROR (PlantArchitecture::setPhytomerLeafScale): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
2281 }else if( node_number>=parent_shoot->current_node_number ){
+
2282 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.");
+
2283 }
+
2284 if(leaf_scale_factor_fraction < 0 || leaf_scale_factor_fraction > 1 ){
+
2285 std::cerr << "WARNING (PlantArchitecture::setPhytomerLeafScale): Leaf scaling factor was outside the range of 0 to 1. No scaling was applied." << std::endl;
+
2286 return;
+
2287 }
+
2288
+
2289 parent_shoot->phytomers.at(node_number)->setLeafScaleFraction(leaf_scale_factor_fraction);
+
2290}
2291
-
2292 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
-
2293 helios_runtime_error("ERROR (PlantArchitecture::removeShootLeaves): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
-
2294 }
-
2295
-
2296 auto &shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2292void PlantArchitecture::setPlantBasePosition(uint plantID, const helios::vec3 &base_position) {
+
2293
+
2294 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2295 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2296 }
2297
-
2298 for (auto &phytomer: shoot->phytomers) {
-
2299 phytomer->removeLeaf();
-
2300 }
-
2301}
-
2302
-
2303void PlantArchitecture::removePlantLeaves(uint plantID ){
-
2304 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2305 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2306 }
-
2307
-
2308 for (auto &shoot: plant_instances.at(plantID).shoot_tree) {
-
2309 for (auto &phytomer: shoot->phytomers) {
-
2310 phytomer->removeLeaf();
-
2311 }
-
2312 }
+
2298 plant_instances.at(plantID).base_position = base_position;
+
2299
+
2300 //\todo Does not work after shoots have been added to the plant.
+
2301 if( !plant_instances.at(plantID).shoot_tree.empty() ){
+
2302 std::cerr << "WARNING (PlantArchitecture::setPlantBasePosition): This function does not work after shoots have been added to the plant." << std::endl;
+
2303 }
+
2304}
+
2305
+
2306helios::vec3 PlantArchitecture::getPlantBasePosition(uint plantID) const{
+
2307 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2308 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2309 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
+
2310 helios_runtime_error("ERROR (PlantArchitecture::setPlantBasePosition): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
+
2311 }
+
2312 return plant_instances.at(plantID).base_position;
2313}
2314
-
2315void PlantArchitecture::makePlantDormant( uint plantID ){
-
2316 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2317 helios_runtime_error("ERROR (PlantArchitecture::makePlantDormant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2318 }
-
2319
-
2320 for (auto &shoot: plant_instances.at(plantID).shoot_tree) {
-
2321 shoot->makeDormant();
-
2322 }
-
2323 plant_instances.at(plantID).time_since_dormancy = 0;
-
2324
-
2325}
-
2326
-
2327void PlantArchitecture::breakPlantDormancy( uint plantID ){
-
2328 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2329 helios_runtime_error("ERROR (PlantArchitecture::breakPlantDormancy): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2330 }
-
2331
-
2332 for (auto &shoot: plant_instances.at(plantID).shoot_tree) {
-
2333 shoot->breakDormancy();
-
2334 }
-
2335}
+
+
2315float PlantArchitecture::sumPlantLeafArea(uint plantID) const{
+
2316
+
2317 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2318 helios_runtime_error("ERROR (PlantArchitecture::sumPlantLeafArea): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2319 }
+
2320
+
2321 std::vector<uint> leaf_objIDs = getPlantLeafObjectIDs(plantID);
+
2322
+
2323 float area = 0;
+
2324 for (uint objID: leaf_objIDs) {
+
2325 area += context_ptr->getObjectArea(objID);
+
2326 }
+
2327
+
2328 return area;
+
2329}
+
+
2330
+
+
2331float PlantArchitecture::getPlantStemHeight(uint plantID) const {
+
2332
+
2333 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2334 helios_runtime_error("ERROR (PlantArchitecture::getPlantStemHeight): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2335 }
2336
-
2337
-
2338uint PlantArchitecture::getShootNodeCount( uint plantID, uint shootID ) const{
-
2339 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2340 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2341 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
-
2342 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Shoot ID is out of range.");
+
2337 auto base_shoot_ptr = plant_instances.at(plantID).shoot_tree.front();
+
2338
+
2339 std::vector<uint> stem_objID{base_shoot_ptr->internode_tube_objID};
+
2340
+
2341 if( !context_ptr->doesObjectExist(stem_objID.front()) ){
+
2342 helios_runtime_error("ERROR (PlantArchitecture::getPlantStemHeight): The plant does not contain any geometry.");
2343 }
-
2344 return plant_instances.at(plantID).shoot_tree.at(shootID)->current_node_number;
-
2345}
-
2346
-
2347float PlantArchitecture::getShootTaper( uint plantID, uint shootID ) const{
-
2348
-
2349 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2350 helios_runtime_error("ERROR (PlantArchitecture::getShootTaper): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2351 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
-
2352 helios_runtime_error("ERROR (PlantArchitecture::getShootTaper): Shoot ID is out of range.");
-
2353 }
-
2354
-
2355 float r0 = plant_instances.at(plantID).shoot_tree.at(shootID)->shoot_internode_radii.front().front();
-
2356 float r1 = plant_instances.at(plantID).shoot_tree.at(shootID)->shoot_internode_radii.back().back();
-
2357
-
2358 float taper = (r0 - r1) / r0;
-
2359 if (taper < 0) {
-
2360 taper = 0;
-
2361 } else if (taper > 1) {
-
2362 taper = 1;
-
2363 }
+
2344
+
2345 //check if there was an appended shoot on this same shoot
+
2346 if ( base_shoot_ptr->childIDs.find(base_shoot_ptr->current_node_number-1) != base_shoot_ptr->childIDs.end() ) {
+
2347 auto terminal_children = base_shoot_ptr->childIDs.at(base_shoot_ptr->current_node_number-1);
+
2348 for ( uint childID : terminal_children ) {
+
2349 auto child_shoot_ptr = plant_instances.at(plantID).shoot_tree.at(childID);
+
2350 if ( child_shoot_ptr->rank == base_shoot_ptr->rank ) {
+
2351 if ( context_ptr->doesObjectExist(child_shoot_ptr->internode_tube_objID)) {
+
2352 stem_objID.push_back(child_shoot_ptr->internode_tube_objID);
+
2353 }
+
2354 }
+
2355 }
+
2356
+
2357 }
+
2358
+
2359 vec3 min_box;
+
2360 vec3 max_box;
+
2361 context_ptr->getObjectBoundingBox( stem_objID, min_box, max_box);
+
2362
+
2363 return max_box.z - min_box.z;
2364
-
2365 return taper;
-
2366}
+
2365}
+
+
2366
2367
-
2368std::vector<uint> PlantArchitecture::getAllPlantObjectIDs(uint plantID) const{
+
2368float PlantArchitecture::getPlantHeight(uint plantID) const{
2369
-
2370 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2371 helios_runtime_error("ERROR (PlantArchitecture::getAllPlantObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2370 if( plant_instances.find(plantID) == plant_instances.end() ) {
+
2371 helios_runtime_error("ERROR (PlantArchitecture::getPlantHeight): Plant with ID of " + std::to_string(plantID) + " does not exist.");
2372 }
2373
-
2374 std::vector<uint> objIDs;
-
2375
-
2376 for (const auto &shoot: plant_instances.at(plantID).shoot_tree) {
-
2377 if (context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
-
2378 objIDs.push_back(shoot->internode_tube_objID);
-
2379 }
-
2380 for (const auto &phytomer: shoot->phytomers) {
-
2381 std::vector<uint> petiole_objIDs_flat = flatten(phytomer->petiole_objIDs);
-
2382 objIDs.insert(objIDs.end(), petiole_objIDs_flat.begin(), petiole_objIDs_flat.end());
-
2383 std::vector<uint> leaf_objIDs_flat = flatten(phytomer->leaf_objIDs);
-
2384 objIDs.insert(objIDs.end(), leaf_objIDs_flat.begin(), leaf_objIDs_flat.end());
-
2385 for (auto &petiole: phytomer->floral_buds) {
-
2386 for (auto &fbud: petiole) {
-
2387 std::vector<uint> inflorescence_objIDs_flat = fbud.inflorescence_objIDs;
-
2388 objIDs.insert(objIDs.end(), inflorescence_objIDs_flat.begin(), inflorescence_objIDs_flat.end());
-
2389 std::vector<uint> peduncle_objIDs_flat = fbud.peduncle_objIDs;
-
2390 objIDs.insert(objIDs.end(), peduncle_objIDs_flat.begin(), peduncle_objIDs_flat.end());
-
2391 }
-
2392 }
-
2393 }
-
2394 }
-
2395
-
2396 return objIDs;
-
2397}
-
-
2398
-
-
2399std::vector<uint> PlantArchitecture::getAllPlantUUIDs(uint plantID) const {
-
2400 return context_ptr->getObjectPrimitiveUUIDs(getAllPlantObjectIDs(plantID));
-
2401}
-
-
2402
-
-
2403std::vector<uint> PlantArchitecture::getPlantInternodeObjectIDs(uint plantID) const{
-
2404
-
2405 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2406 helios_runtime_error("ERROR (PlantArchitecture::getPlantInternodeObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2374 vec3 min_box;
+
2375 vec3 max_box;
+
2376 context_ptr->getObjectBoundingBox(getAllPlantObjectIDs(plantID), min_box, max_box);
+
2377
+
2378 return max_box.z - min_box.z;
+
2379
+
2380}
+
+
2381
+
+
2382std::vector<float> PlantArchitecture::getPlantLeafInclinationAngleDistribution(uint plantID, uint Nbins) const {
+
2383
+
2384 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2385 helios_runtime_error("ERROR (PlantArchitecture::getPlantLeafInclinationAngleDistribution): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2386 }
+
2387
+
2388 std::vector<uint> leaf_objIDs = getPlantLeafObjectIDs(plantID);
+
2389 std::vector<uint> leaf_UUIDs = context_ptr->getObjectPrimitiveUUIDs(leaf_objIDs);
+
2390
+
2391 std::vector<float> leaf_inclination_angles(Nbins);
+
2392 float dtheta = 0.5f * PI_F / float(Nbins);
+
2393 for( uint UUID : leaf_UUIDs ){
+
2394 vec3 normal = context_ptr->getPrimitiveNormal(UUID);
+
2395 float theta = acos_safe(fabs(normal.z));
+
2396 float area = context_ptr->getPrimitiveArea(UUID);
+
2397 uint bin = uint( std::floor(theta / dtheta) );
+
2398 if (bin >= Nbins) {
+
2399 bin = Nbins - 1; // Ensure bin index is within range
+
2400 }
+
2401 leaf_inclination_angles.at(bin)+=area;
+
2402 }
+
2403
+
2404 float sum = helios::sum(leaf_inclination_angles);
+
2405 for( float &angle : leaf_inclination_angles ){
+
2406 angle /= sum;
2407 }
2408
-
2409 std::vector<uint> objIDs;
+
2409 return leaf_inclination_angles;
2410
-
2411 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2412
-
2413 for (auto &shoot: shoot_tree) {
-
2414 if (context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
-
2415 objIDs.push_back(shoot->internode_tube_objID);
-
2416 }
-
2417 }
-
2418
-
2419 return objIDs;
-
2420}
+
2411}
+
2412
+
2413
+
+ +
2415
+
2416 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2417 helios_runtime_error("ERROR (PlantArchitecture::getPlantLeafCount): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2418 }
+
2419
+
2420 return getPlantLeafObjectIDs(plantID).size();
2421
-
-
2422std::vector<uint> PlantArchitecture::getPlantPetioleObjectIDs(uint plantID) const{
-
2423 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2424 helios_runtime_error("ERROR (PlantArchitecture::getPlantPetioleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2425 }
-
2426
-
2427 std::vector<uint> objIDs;
-
2428
-
2429 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2430
-
2431 for (auto &shoot: shoot_tree) {
-
2432 for (auto &phytomer: shoot->phytomers) {
-
2433 for (auto &petiole: phytomer->petiole_objIDs) {
-
2434 objIDs.insert(objIDs.end(), petiole.begin(), petiole.end());
-
2435 }
-
2436 }
+
2422}
+
+
2423
+
+
2424void PlantArchitecture::writePlantMeshVertices(uint plantID, const std::string &filename) const{
+
2425
+
2426 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2427 helios_runtime_error("ERROR (PlantArchitecture::writePlantMeshVertices): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2428 }
+
2429
+
2430 std::vector<uint> plant_UUIDs = getAllPlantUUIDs(plantID);
+
2431
+
2432 std::ofstream file;
+
2433 file.open(filename);
+
2434
+
2435 if( !file.is_open() ){
+
2436 helios_runtime_error("ERROR (PlantArchitecture::writePlantMeshVertices): Could not open file " + filename + " for writing.");
2437 }
2438
-
2439 return objIDs;
-
2440}
-
-
2441
-
-
2442std::vector<uint> PlantArchitecture::getPlantLeafObjectIDs(uint plantID) const{
-
2443 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2444 helios_runtime_error("ERROR (PlantArchitecture::getPlantLeafObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2445 }
-
2446
-
2447 std::vector<uint> objIDs;
-
2448
-
2449 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2450
-
2451 for( auto &shoot : shoot_tree ){
-
2452 for( auto &phytomer : shoot->phytomers ){
-
2453 for( int petiole=0; petiole<phytomer->leaf_objIDs.size(); petiole++ ) {
-
2454 objIDs.insert(objIDs.end(), phytomer->leaf_objIDs.at(petiole).begin(), phytomer->leaf_objIDs.at(petiole).end());
-
2455 }
-
2456 }
-
2457 }
-
2458
-
2459 return objIDs;
+
2439 for( uint UUID : plant_UUIDs ){
+
2440 std::vector<vec3> vertex = context_ptr->getPrimitiveVertices(UUID);
+
2441 for( vec3 &v : vertex ){
+
2442 file << v.x << " " << v.y << " " << v.z << std::endl;
+
2443 }
+
2444 }
+
2445
+
2446 file.close();
+
2447
+
2448}
+
+
2449
+
2450void PlantArchitecture::setPlantAge(uint plantID, float a_current_age) {
+
2451 //\todo
+
2452 // this->current_age = current_age;
+
2453}
+
2454
+
2455std::string PlantArchitecture::getPlantName(uint plantID) const{
+
2456 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2457 helios_runtime_error("ERROR (PlantArchitecture::getPlantName): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2458 }
+
2459 return plant_instances.at(plantID).plant_name;
2460}
-
2461
-
-
2462std::vector<uint> PlantArchitecture::getPlantPeduncleObjectIDs(uint plantID) const{
-
2463
-
2464 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2465 helios_runtime_error("ERROR (PlantArchitecture::getPlantPeduncleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2466 }
-
2467
-
2468 std::vector<uint> objIDs;
-
2469
-
2470 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2471
-
2472 for (auto &shoot: shoot_tree) {
-
2473 for (auto &phytomer: shoot->phytomers) {
-
2474 for (auto &petiole: phytomer->floral_buds) {
-
2475 for (auto &fbud: petiole) {
-
2476 objIDs.insert(objIDs.end(), fbud.peduncle_objIDs.begin(), fbud.peduncle_objIDs.end());
-
2477 }
-
2478 }
-
2479 }
-
2480 }
-
2481
-
2482 return objIDs;
-
2483}
-
-
2484
-
-
2485std::vector<uint> PlantArchitecture::getPlantFlowerObjectIDs(uint plantID) const{
-
2486
-
2487 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2488 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2489 }
-
2490
-
2491 std::vector<uint> objIDs;
-
2492
-
2493 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2462float PlantArchitecture::getPlantAge(uint plantID) const{
+
2463 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2464 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2465 }else if( plant_instances.at(plantID).shoot_tree.empty() ){
+
2466 helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " has no shoots, so could not get a base position.");
+
2467 }
+
2468 return plant_instances.at(plantID).current_age;
+
2469}
+
2470
+
2471void PlantArchitecture::harvestPlant(uint plantID){
+
2472
+
2473 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2474 helios_runtime_error("ERROR (PlantArchitecture::harvestPlant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2475 }
+
2476
+
2477 for (auto &shoot: plant_instances.at(plantID).shoot_tree) {
+
2478 for (auto &phytomer: shoot->phytomers) {
+
2479 for (auto &petiole: phytomer->floral_buds) {
+
2480 for (auto &fbud: petiole) {
+
2481 if (fbud.state != BUD_DORMANT) {
+
2482 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
2483 }
+
2484 }
+
2485 }
+
2486 }
+
2487 }
+
2488}
+
2489
+
2490void PlantArchitecture::removeShootLeaves(uint plantID, uint shootID){
+
2491 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2492 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2493 }
2494
-
2495 for( auto &shoot : shoot_tree ){
-
2496 for( auto &phytomer : shoot->phytomers ){
-
2497 for(int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
-
2498 for(int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
-
2499 if(phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_OPEN || phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_CLOSED ) {
-
2500 objIDs.insert(objIDs.end(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.begin(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.end());
-
2501 }
-
2502 }
-
2503 }
-
2504 }
-
2505 }
-
2506
-
2507 return objIDs;
-
2508}
-
-
2509
-
-
2510std::vector<uint> PlantArchitecture::getPlantFruitObjectIDs(uint plantID) const{
-
2511
-
2512 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2513 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2514 }
-
2515
-
2516 std::vector<uint> objIDs;
+
2495 if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
2496 helios_runtime_error("ERROR (PlantArchitecture::removeShootLeaves): Shoot with ID of " + std::to_string(shootID) + " does not exist.");
+
2497 }
+
2498
+
2499 auto &shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2500
+
2501 for (auto &phytomer: shoot->phytomers) {
+
2502 phytomer->removeLeaf();
+
2503 }
+
2504}
+
2505
+
2506void PlantArchitecture::removePlantLeaves(uint plantID ){
+
2507 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2508 helios_runtime_error("ERROR (PlantArchitecture::removePlantLeaves): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2509 }
+
2510
+
2511 for (auto &shoot: plant_instances.at(plantID).shoot_tree) {
+
2512 for (auto &phytomer: shoot->phytomers) {
+
2513 phytomer->removeLeaf();
+
2514 }
+
2515 }
+
2516}
2517
-
2518 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
-
2519
-
2520 for( auto &shoot : shoot_tree ){
-
2521 for( auto &phytomer : shoot->phytomers ){
-
2522 for(int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
-
2523 for(int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
-
2524 if(phytomer->floral_buds.at(petiole).at(bud).state == BUD_FRUITING ) {
-
2525 objIDs.insert(objIDs.end(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.begin(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.end());
-
2526 }
-
2527 }
-
2528 }
-
2529 }
-
2530 }
-
2531
-
2532 return objIDs;
-
2533}
-
+
2518void PlantArchitecture::makePlantDormant( uint plantID ){
+
2519 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2520 helios_runtime_error("ERROR (PlantArchitecture::makePlantDormant): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2521 }
+
2522
+
2523 for (auto &shoot: plant_instances.at(plantID).shoot_tree) {
+
2524 shoot->makeDormant();
+
2525 }
+
2526 plant_instances.at(plantID).time_since_dormancy = 0;
+
2527
+
2528}
+
2529
+
2530void PlantArchitecture::breakPlantDormancy( uint plantID ){
+
2531 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2532 helios_runtime_error("ERROR (PlantArchitecture::breakPlantDormancy): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2533 }
2534
-
-
2535std::vector<uint> PlantArchitecture::getAllUUIDs() const {
-
2536 std::vector<uint> UUIDs_all;
-
2537 for (const auto &instance: plant_instances) {
-
2538 std::vector<uint> UUIDs = getAllPlantUUIDs(instance.first);
-
2539 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
-
2540 }
-
2541 return UUIDs_all;
-
2542}
-
-
2543
-
-
2544std::vector<uint> PlantArchitecture::getAllLeafUUIDs() const {
-
2545 std::vector<uint> UUIDs_all;
-
2546 for (const auto &instance: plant_instances) {
-
2547 std::vector<uint> objIDs = getPlantLeafObjectIDs(instance.first);
-
2548 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
-
2549 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
-
2550 }
-
2551 return UUIDs_all;
-
2552}
-
+
2535 for (auto &shoot: plant_instances.at(plantID).shoot_tree) {
+
2536 shoot->breakDormancy();
+
2537 }
+
2538}
+
2539
+
2540void PlantArchitecture::pruneBranch(uint plantID, uint shootID, uint node_index){
+
2541
+
2542 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2543 helios_runtime_error("ERROR (PlantArchitecture::pruneBranch): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2544 }else if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){
+
2545 helios_runtime_error("ERROR (PlantArchitecture::pruneBranch): Shoot with ID of " + std::to_string(shootID) + " does not exist on plant " + std::to_string(plantID) + ".");
+
2546 }else if( node_index>=plant_instances.at(plantID).shoot_tree.at(shootID)->current_node_number ){
+
2547 helios_runtime_error("ERROR (PlantArchitecture::pruneBranch): Node index " + std::to_string(node_index) + " is out of range for shoot " + std::to_string(shootID) + ".");
+
2548 }
+
2549
+
2550 auto &shoot = plant_instances.at(plantID).shoot_tree.at(shootID);
+
2551
+
2552 shoot->phytomers.at(node_index)->deletePhytomer();
2553
-
- -
2555 std::vector<uint> UUIDs_all;
-
2556 for (const auto &instance: plant_instances) {
-
2557 std::vector<uint> objIDs = getPlantInternodeObjectIDs(instance.first);
-
2558 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
-
2559 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
-
2560 }
-
2561 return UUIDs_all;
-
2562}
-
-
2563
-
-
2564std::vector<uint> PlantArchitecture::getAllPetioleUUIDs() const {
-
2565 std::vector<uint> UUIDs_all;
-
2566 for (const auto &instance: plant_instances) {
-
2567 std::vector<uint> objIDs = getPlantPetioleObjectIDs(instance.first);
-
2568 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
-
2569 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
-
2570 }
-
2571 return UUIDs_all;
-
2572}
-
-
2573
-
- -
2575 std::vector<uint> UUIDs_all;
-
2576 for (const auto &instance: plant_instances) {
-
2577 std::vector<uint> objIDs = getPlantPeduncleObjectIDs(instance.first);
-
2578 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
-
2579 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
-
2580 }
-
2581 return UUIDs_all;
-
2582}
-
-
2583
-
-
2584std::vector<uint> PlantArchitecture::getAllFlowerUUIDs() const {
-
2585 std::vector<uint> UUIDs_all;
-
2586 for (const auto &instance: plant_instances) {
-
2587 std::vector<uint> objIDs = getPlantFlowerObjectIDs(instance.first);
-
2588 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
-
2589 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
-
2590 }
-
2591 return UUIDs_all;
-
2592}
-
-
2593
-
-
2594std::vector<uint> PlantArchitecture::getAllFruitUUIDs() const {
-
2595 std::vector<uint> UUIDs_all;
-
2596 for (const auto &instance: plant_instances) {
-
2597 std::vector<uint> objIDs = getPlantFruitObjectIDs(instance.first);
-
2598 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
-
2599 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
-
2600 }
-
2601 return UUIDs_all;
-
2602}
-
+
2554}
+
2555
+
2556uint PlantArchitecture::getShootNodeCount( uint plantID, uint shootID ) const{
+
2557 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2558 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2559 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
+
2560 helios_runtime_error("ERROR (PlantArchitecture::getShootNodeCount): Shoot ID is out of range.");
+
2561 }
+
2562 return plant_instances.at(plantID).shoot_tree.at(shootID)->current_node_number;
+
2563}
+
2564
+
2565float PlantArchitecture::getShootTaper( uint plantID, uint shootID ) const{
+
2566
+
2567 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2568 helios_runtime_error("ERROR (PlantArchitecture::getShootTaper): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2569 }else if( plant_instances.at(plantID).shoot_tree.size()<=shootID ){
+
2570 helios_runtime_error("ERROR (PlantArchitecture::getShootTaper): Shoot ID is out of range.");
+
2571 }
+
2572
+
2573 float r0 = plant_instances.at(plantID).shoot_tree.at(shootID)->shoot_internode_radii.front().front();
+
2574 float r1 = plant_instances.at(plantID).shoot_tree.at(shootID)->shoot_internode_radii.back().back();
+
2575
+
2576 float taper = (r0 - r1) / r0;
+
2577 if (taper < 0) {
+
2578 taper = 0;
+
2579 } else if (taper > 1) {
+
2580 taper = 1;
+
2581 }
+
2582
+
2583 return taper;
+
2584}
+
2585
+
+
2586std::vector<uint> PlantArchitecture::getAllPlantIDs() const{
+
2587
+
2588 std::vector<uint> objIDs;
+
2589 objIDs.reserve(plant_instances.size());
+
2590
+
2591 for( const auto &plant : plant_instances ){
+
2592 objIDs.push_back(plant.first);
+
2593 }
+
2594
+
2595 return objIDs;
+
2596}
+
+
2597
+
+
2598std::vector<uint> PlantArchitecture::getAllPlantObjectIDs(uint plantID) const{
+
2599
+
2600 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2601 helios_runtime_error("ERROR (PlantArchitecture::getAllPlantObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2602 }
2603
-
-
2604std::vector<uint> PlantArchitecture::getAllObjectIDs() const {
-
2605 std::vector<uint> objIDs_all;
-
2606 for (const auto &instance: plant_instances) {
-
2607 std::vector<uint> objIDs = getAllPlantObjectIDs(instance.first);
-
2608 objIDs_all.insert(objIDs_all.end(), objIDs.begin(), objIDs.end());
-
2609 }
-
2610 return objIDs_all;
-
2611}
-
-
2612
-
-
2613uint PlantArchitecture::addPlantInstance(const helios::vec3 &base_position, float current_age) {
-
2614
-
2615 if( current_age<0 ){
-
2616 helios_runtime_error("ERROR (PlantArchitecture::addPlantInstance): Current age must be greater than or equal to zero.");
-
2617 }
-
2618
-
2619 PlantInstance instance(base_position, current_age, context_ptr);
-
2620
-
2621 plant_instances.emplace(plant_count, instance);
-
2622
-
2623 plant_count++;
-
2624
-
2625 return plant_count - 1;
-
2626}
-
-
2627
-
-
2628uint PlantArchitecture::duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age) {
-
2629
-
2630 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2631 helios_runtime_error("ERROR (PlantArchitecture::duplicatePlantInstance): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2632 }
-
2633
-
2634 auto plant_shoot_tree = &plant_instances.at(plantID).shoot_tree;
-
2635
-
2636 uint plantID_new = addPlantInstance(base_position, current_age);
-
2637
-
2638 if( plant_shoot_tree->empty() ){ //no shoots to add
-
2639 return plantID_new;
-
2640 }
-
2641 if( plant_shoot_tree->front()->phytomers.empty() ){ //no phytomers to add
-
2642 return plantID_new;
-
2643 }
-
2644
-
2645 for (auto shoot: *plant_shoot_tree) {
-
2646 uint shootID_new; //ID of the new shoot; will be set once the shoot is created on the first loop iteration
-
2647 for (int node = 0; node < shoot->current_node_number; node++) {
-
2648 auto phytomer = shoot->phytomers.at(node);
-
2649 float internode_radius = phytomer->internode_radius_initial;
-
2650 float internode_length_max = phytomer->internode_length_max;
-
2651 float internode_scale_factor_fraction = phytomer->current_internode_scale_factor;
-
2652 float leaf_scale_factor_fraction = phytomer->current_leaf_scale_factor;
-
2653
-
2654 if (node == 0) {//first phytomer on shoot
-
2655 AxisRotation original_base_rotation = shoot->base_rotation;
-
2656 if(shoot->parent_shoot_ID == -1 ) { //first shoot on plant
-
2657 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);
-
2658 }else{ //child shoot
-
2659 uint parent_node = plant_shoot_tree->at(shoot->parent_shoot_ID)->parent_node_index;
-
2660 uint parent_petiole_index = 0;
-
2661 for( auto &petiole : phytomer->axillary_vegetative_buds ) {
-
2662 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);
-
2663 parent_petiole_index++;
-
2664 }
-
2665 }
-
2666 } else {
-
2667 //each phytomer needs to be added one-by-one to account for possible internodes/leaves that are not fully elongated
-
2668 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);
-
2669 }
-
2670 }
-
2671 }
-
2672
-
2673 return plantID_new;
-
2674}
-
-
2675
-
- -
2677 if (plant_instances.find(plantID) == plant_instances.end()) {
-
2678 return;
-
2679 }
+
2604 std::vector<uint> objIDs;
+
2605
+
2606 for (const auto &shoot: plant_instances.at(plantID).shoot_tree) {
+
2607 if (context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
+
2608 objIDs.push_back(shoot->internode_tube_objID);
+
2609 }
+
2610 for (const auto &phytomer: shoot->phytomers) {
+
2611 std::vector<uint> petiole_objIDs_flat = flatten(phytomer->petiole_objIDs);
+
2612 objIDs.insert(objIDs.end(), petiole_objIDs_flat.begin(), petiole_objIDs_flat.end());
+
2613 std::vector<uint> leaf_objIDs_flat = flatten(phytomer->leaf_objIDs);
+
2614 objIDs.insert(objIDs.end(), leaf_objIDs_flat.begin(), leaf_objIDs_flat.end());
+
2615 for (auto &petiole: phytomer->floral_buds) {
+
2616 for (auto &fbud: petiole) {
+
2617 std::vector<uint> inflorescence_objIDs_flat = fbud.inflorescence_objIDs;
+
2618 objIDs.insert(objIDs.end(), inflorescence_objIDs_flat.begin(), inflorescence_objIDs_flat.end());
+
2619 std::vector<uint> peduncle_objIDs_flat = fbud.peduncle_objIDs;
+
2620 objIDs.insert(objIDs.end(), peduncle_objIDs_flat.begin(), peduncle_objIDs_flat.end());
+
2621 }
+
2622 }
+
2623 }
+
2624 }
+
2625
+
2626 return objIDs;
+
2627}
+
+
2628
+
+
2629std::vector<uint> PlantArchitecture::getAllPlantUUIDs(uint plantID) const {
+
2630 return context_ptr->getObjectPrimitiveUUIDs(getAllPlantObjectIDs(plantID));
+
2631}
+
+
2632
+
+
2633std::vector<uint> PlantArchitecture::getPlantInternodeObjectIDs(uint plantID) const{
+
2634
+
2635 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2636 helios_runtime_error("ERROR (PlantArchitecture::getPlantInternodeObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2637 }
+
2638
+
2639 std::vector<uint> objIDs;
+
2640
+
2641 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2642
+
2643 for (auto &shoot: shoot_tree) {
+
2644 if (context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
+
2645 objIDs.push_back(shoot->internode_tube_objID);
+
2646 }
+
2647 }
+
2648
+
2649 return objIDs;
+
2650}
+
+
2651
+
+
2652std::vector<uint> PlantArchitecture::getPlantPetioleObjectIDs(uint plantID) const{
+
2653 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2654 helios_runtime_error("ERROR (PlantArchitecture::getPlantPetioleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2655 }
+
2656
+
2657 std::vector<uint> objIDs;
+
2658
+
2659 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2660
+
2661 for (auto &shoot: shoot_tree) {
+
2662 for (auto &phytomer: shoot->phytomers) {
+
2663 for (auto &petiole: phytomer->petiole_objIDs) {
+
2664 objIDs.insert(objIDs.end(), petiole.begin(), petiole.end());
+
2665 }
+
2666 }
+
2667 }
+
2668
+
2669 return objIDs;
+
2670}
+
+
2671
+
+
2672std::vector<uint> PlantArchitecture::getPlantLeafObjectIDs(uint plantID) const{
+
2673 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2674 helios_runtime_error("ERROR (PlantArchitecture::getPlantLeafObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2675 }
+
2676
+
2677 std::vector<uint> objIDs;
+
2678
+
2679 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
2680
-
2681 context_ptr->deleteObject(getAllPlantObjectIDs(plantID));
-
2682
-
2683 plant_instances.erase(plantID);
-
2684}
-
-
2685
-
-
2686void PlantArchitecture::deletePlantInstance(const std::vector<uint> &plantIDs) {
-
2687 for (uint ID: plantIDs) {
- -
2689 }
+
2681 for( auto &shoot : shoot_tree ){
+
2682 for( auto &phytomer : shoot->phytomers ){
+
2683 for( int petiole=0; petiole<phytomer->leaf_objIDs.size(); petiole++ ) {
+
2684 objIDs.insert(objIDs.end(), phytomer->leaf_objIDs.at(petiole).begin(), phytomer->leaf_objIDs.at(petiole).end());
+
2685 }
+
2686 }
+
2687 }
+
2688
+
2689 return objIDs;
2690}
2691
-
2692void 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_dormancy,float max_leaf_lifespan, bool is_evergreen) {
+
2692std::vector<uint> PlantArchitecture::getPlantPeduncleObjectIDs(uint plantID) const{
2693
2694 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2695 helios_runtime_error("ERROR (PlantArchitecture::setPlantPhenologicalThresholds): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2695 helios_runtime_error("ERROR (PlantArchitecture::getPlantPeduncleObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
2696 }
2697
-
2698 plant_instances.at(plantID).dd_to_dormancy_break = time_to_dormancy_break;
-
2699 plant_instances.at(plantID).dd_to_flower_initiation = time_to_flower_initiation;
-
2700 plant_instances.at(plantID).dd_to_flower_opening = time_to_flower_opening;
-
2701 plant_instances.at(plantID).dd_to_fruit_set = time_to_fruit_set;
-
2702 plant_instances.at(plantID).dd_to_fruit_maturity = time_to_fruit_maturity;
-
2703 plant_instances.at(plantID).dd_to_dormancy = time_to_dormancy;
-
2704 if (max_leaf_lifespan == 0) {
-
2705 plant_instances.at(plantID).max_leaf_lifespan = 1e6;
-
2706 } else {
-
2707 plant_instances.at(plantID).max_leaf_lifespan = max_leaf_lifespan;
-
2708 }
-
2709 plant_instances.at(plantID).is_evergreen = is_evergreen;
-
2710}
-
+
2698 std::vector<uint> objIDs;
+
2699
+
2700 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2701
+
2702 for (auto &shoot: shoot_tree) {
+
2703 for (auto &phytomer: shoot->phytomers) {
+
2704 for (auto &petiole: phytomer->floral_buds) {
+
2705 for (auto &fbud: petiole) {
+
2706 objIDs.insert(objIDs.end(), fbud.peduncle_objIDs.begin(), fbud.peduncle_objIDs.end());
+
2707 }
+
2708 }
+
2709 }
+
2710 }
2711
-
2712void PlantArchitecture::disablePlantPhenology(uint plantID) {
-
2713 plant_instances.at(plantID).dd_to_dormancy_break = 0;
-
2714 plant_instances.at(plantID).dd_to_flower_initiation = -1;
-
2715 plant_instances.at(plantID).dd_to_flower_opening = -1;
-
2716 plant_instances.at(plantID).dd_to_fruit_set = -1;
-
2717 plant_instances.at(plantID).dd_to_fruit_maturity = -1;
-
2718 plant_instances.at(plantID).dd_to_dormancy = 1e6;
-
2719}
+
2712 return objIDs;
+
2713}
+
+
2714
+
+
2715std::vector<uint> PlantArchitecture::getPlantFlowerObjectIDs(uint plantID) const{
+
2716
+
2717 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2718 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2719 }
2720
-
-
2721void PlantArchitecture::advanceTime(float time_step_days) {
-
2722 for (auto &plant: plant_instances) {
-
2723 uint plantID = plant.first;
+
2721 std::vector<uint> objIDs;
+
2722
+
2723 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
2724
-
2725 advanceTime(plantID, time_step_days);
-
2726 }
-
2727}
-
-
2728
-
-
2729void PlantArchitecture::advanceTime( int time_step_years, float time_step_days ) {
-
2730 for (auto &plant: plant_instances) {
-
2731 uint plantID = plant.first;
-
2732
-
2733 advanceTime(plantID, float(time_step_years)*365.f+time_step_days);
-
2734 }
-
2735}
-
+
2725 for( auto &shoot : shoot_tree ){
+
2726 for( auto &phytomer : shoot->phytomers ){
+
2727 for(int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
+
2728 for(int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
+
2729 if(phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_OPEN || phytomer->floral_buds.at(petiole).at(bud).state == BUD_FLOWER_CLOSED ) {
+
2730 objIDs.insert(objIDs.end(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.begin(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.end());
+
2731 }
+
2732 }
+
2733 }
+
2734 }
+
2735 }
2736
-
-
2737void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) {
-
2738
-
2739 if( plant_instances.find(plantID) == plant_instances.end() ){
-
2740 helios_runtime_error("ERROR (PlantArchitecture::advanceTime): Plant with ID of " + std::to_string(plantID) + " does not exist.");
-
2741 }
-
2742
-
2743 PlantInstance &plant_instance = plant_instances.at(plantID);
-
2744
-
2745 auto shoot_tree = &plant_instance.shoot_tree;
-
2746
-
2747 if (shoot_tree->empty()) {
-
2748 return;
-
2749 }
-
2750
-
2751 //accounting for case of time_step_days>phyllochron_min
-
2752 float phyllochron_min = shoot_tree->front()->shoot_parameters.phyllochron_min.val();
-
2753 for (int i = 1; i < shoot_tree->size(); i++) {
-
2754 if (shoot_tree->at(i)->shoot_parameters.phyllochron_min.val() < phyllochron_min) {
-
2755 phyllochron_min = shoot_tree->at(i)->shoot_parameters.phyllochron_min.val();
-
2756 }
-
2757 }
-
2758
-
2759 int Nsteps = std::floor(time_step_days / phyllochron_min);
-
2760 float remainder_time = time_step_days - phyllochron_min * float(Nsteps);
-
2761 if (remainder_time > 0.f) {
-
2762 Nsteps++;
-
2763 }
+
2737 return objIDs;
+
2738}
+
+
2739
+
+
2740std::vector<uint> PlantArchitecture::getPlantFruitObjectIDs(uint plantID) const{
+
2741
+
2742 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2743 helios_runtime_error("ERROR (PlantArchitecture::getPlantInflorescenceObjectIDs): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2744 }
+
2745
+
2746 std::vector<uint> objIDs;
+
2747
+
2748 auto &shoot_tree = plant_instances.at(plantID).shoot_tree;
+
2749
+
2750 for( auto &shoot : shoot_tree ){
+
2751 for( auto &phytomer : shoot->phytomers ){
+
2752 for(int petiole=0; petiole<phytomer->floral_buds.size(); petiole++ ){
+
2753 for(int bud=0; bud<phytomer->floral_buds.at(petiole).size(); bud++ ){
+
2754 if(phytomer->floral_buds.at(petiole).at(bud).state == BUD_FRUITING ) {
+
2755 objIDs.insert(objIDs.end(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.begin(), phytomer->floral_buds.at(petiole).at(bud).inflorescence_objIDs.end());
+
2756 }
+
2757 }
+
2758 }
+
2759 }
+
2760 }
+
2761
+
2762 return objIDs;
+
2763}
+
2764
-
2765 for (int timestep = 0; timestep < Nsteps; timestep++) {
-
2766 float dt_max = phyllochron_min;
-
2767 if (timestep == Nsteps - 1 && remainder_time != 0.f) {
-
2768 dt_max = remainder_time;
-
2769 }
-
2770
-
2771 if (plant_instance.current_age <= plant_instance.max_age && plant_instance.current_age + dt_max > plant_instance.max_age) {
-
2772 std::cout << "PlantArchitecture::advanceTime: Plant has reached its maximum supported age. No further growth will occur." << std::endl;
-
2773 } else if (plant_instance.current_age >= plant_instance.max_age) {
-
2774 //update Context geometry
-
2775 shoot_tree->front()->updateShootNodes(true);
-
2776 return;
-
2777 }
-
2778
-
2779 plant_instance.current_age += dt_max;
-
2780 plant_instance.time_since_dormancy += dt_max;
-
2781
-
2782 if (plant_instance.time_since_dormancy > plant_instance.dd_to_dormancy_break+plant_instance.dd_to_dormancy) {
-
2783 // std::cout << "Going dormant " << plant_instance.current_age << " " << plant_instance.time_since_dormancy << std::endl;
-
2784 plant_instance.time_since_dormancy = 0;
-
2785 for (const auto &shoot: *shoot_tree) {
-
2786 shoot->makeDormant();
-
2787 shoot->carbohydrate_pool_molC = 100;
-
2788 }
-
2789 harvestPlant(plantID);
-
2790 continue;
-
2791 }
-
2792
-
2793 size_t shoot_count = shoot_tree->size();
-
2794 for (int i = 0; i < shoot_count; i++) {
-
2795 auto shoot = shoot_tree->at(i);
-
2796
-
2797 for (auto &phytomer: shoot->phytomers) {
-
2798 phytomer->age += dt_max;
-
2799
-
2800 if (phytomer->phytomer_parameters.phytomer_callback_function != nullptr) {
-
2801 phytomer->phytomer_parameters.phytomer_callback_function(phytomer);
-
2802 }
-
2803 }
-
2804
-
2805 // ****** PHENOLOGICAL TRANSITIONS ****** //
-
2806
-
2807 // breaking dormancy
-
2808 if (shoot->isdormant && plant_instance.time_since_dormancy >= plant_instance.dd_to_dormancy_break) {
-
2809 shoot->breakDormancy();
-
2810 shoot->carbohydrate_pool_molC = 1e6;
-
2811 }
-
2812
-
2813 if (shoot->isdormant) {
-
2814 //dormant, don't do anything
-
2815 continue;
-
2816 }
-
2817
-
2818 for (auto &phytomer: shoot->phytomers) {
-
2819 if (phytomer->age > plant_instance.max_leaf_lifespan) {
-
2820 //delete old leaves that exceed maximum lifespan
-
2821 phytomer->removeLeaf();
-
2822 }
+
+
2765std::vector<uint> PlantArchitecture::getAllUUIDs() const {
+
2766 std::vector<uint> UUIDs_all;
+
2767 for (const auto &instance: plant_instances) {
+
2768 std::vector<uint> UUIDs = getAllPlantUUIDs(instance.first);
+
2769 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
+
2770 }
+
2771 return UUIDs_all;
+
2772}
+
+
2773
+
+
2774std::vector<uint> PlantArchitecture::getAllLeafUUIDs() const {
+
2775 std::vector<uint> UUIDs_all;
+
2776 for (const auto &instance: plant_instances) {
+
2777 std::vector<uint> objIDs = getPlantLeafObjectIDs(instance.first);
+
2778 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
+
2779 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
+
2780 }
+
2781 return UUIDs_all;
+
2782}
+
+
2783
+
+ +
2785 std::vector<uint> UUIDs_all;
+
2786 for (const auto &instance: plant_instances) {
+
2787 std::vector<uint> objIDs = getPlantInternodeObjectIDs(instance.first);
+
2788 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
+
2789 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
+
2790 }
+
2791 return UUIDs_all;
+
2792}
+
+
2793
+
+
2794std::vector<uint> PlantArchitecture::getAllPetioleUUIDs() const {
+
2795 std::vector<uint> UUIDs_all;
+
2796 for (const auto &instance: plant_instances) {
+
2797 std::vector<uint> objIDs = getPlantPetioleObjectIDs(instance.first);
+
2798 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
+
2799 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
+
2800 }
+
2801 return UUIDs_all;
+
2802}
+
+
2803
+
+ +
2805 std::vector<uint> UUIDs_all;
+
2806 for (const auto &instance: plant_instances) {
+
2807 std::vector<uint> objIDs = getPlantPeduncleObjectIDs(instance.first);
+
2808 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
+
2809 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
+
2810 }
+
2811 return UUIDs_all;
+
2812}
+
+
2813
+
+
2814std::vector<uint> PlantArchitecture::getAllFlowerUUIDs() const {
+
2815 std::vector<uint> UUIDs_all;
+
2816 for (const auto &instance: plant_instances) {
+
2817 std::vector<uint> objIDs = getPlantFlowerObjectIDs(instance.first);
+
2818 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
+
2819 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
+
2820 }
+
2821 return UUIDs_all;
+
2822}
+
2823
-
2824 if (phytomer->floral_buds.empty()) {
-
2825 //no floral buds - skip this phytomer
-
2826 continue;
-
2827 }
-
2828
-
2829 for (auto &petiole: phytomer->floral_buds) {
-
2830 for (auto &fbud: petiole) {
-
2831 if (fbud.state != BUD_DORMANT && fbud.state != BUD_DEAD) {
-
2832 fbud.time_counter += dt_max;
-
2833 }
-
2834
-
2835 // -- Flowering -- //
-
2836 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function != nullptr) { //user defined a flower prototype function
-
2837 // -- Flower initiation (closed flowers) -- //
-
2838 if (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation >= 0.f) { //bud is active and flower initiation is enabled
-
2839 if ((!shoot->shoot_parameters.flowers_require_dormancy && plant_instance.current_age >= plant_instance.dd_to_flower_initiation) ||
-
2840 (shoot->shoot_parameters.flowers_require_dormancy && phytomer->age >= plant_instance.dd_to_flower_initiation)) {
-
2841 fbud.time_counter = 0;
-
2842 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
-
2843 phytomer->setFloralBudState(BUD_FLOWER_CLOSED, fbud);
-
2844 } else {
-
2845 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
2846 }
-
2847 if (shoot->shoot_parameters.determinate_shoot_growth) {
-
2848 shoot->terminateApicalBud();
-
2849 shoot->terminateAxillaryVegetativeBuds();
-
2850 }
-
2851 }
+
+
2824std::vector<uint> PlantArchitecture::getAllFruitUUIDs() const {
+
2825 std::vector<uint> UUIDs_all;
+
2826 for (const auto &instance: plant_instances) {
+
2827 std::vector<uint> objIDs = getPlantFruitObjectIDs(instance.first);
+
2828 std::vector<uint> UUIDs = context_ptr->getObjectPrimitiveUUIDs(objIDs);
+
2829 UUIDs_all.insert(UUIDs_all.end(), UUIDs.begin(), UUIDs.end());
+
2830 }
+
2831 return UUIDs_all;
+
2832}
+
+
2833
+
+
2834std::vector<uint> PlantArchitecture::getAllObjectIDs() const {
+
2835 std::vector<uint> objIDs_all;
+
2836 for (const auto &instance: plant_instances) {
+
2837 std::vector<uint> objIDs = getAllPlantObjectIDs(instance.first);
+
2838 objIDs_all.insert(objIDs_all.end(), objIDs.begin(), objIDs.end());
+
2839 }
+
2840 return objIDs_all;
+
2841}
+
+
2842
+
2843void PlantArchitecture::enableCarbohydrateModel() {
+
2844 carbon_model_enabled = true;
+
2845}
+
2846
+
2847void PlantArchitecture::disableCarbohydrateModel() {
+
2848 carbon_model_enabled = false;
+
2849}
+
2850
+
+
2851uint PlantArchitecture::addPlantInstance(const helios::vec3 &base_position, float current_age) {
2852
-
2853 // -- Flower opening -- //
-
2854 } else if ((fbud.state == BUD_FLOWER_CLOSED && plant_instance.dd_to_flower_opening >= 0.f) ||
-
2855 (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation < 0.f && plant_instance.dd_to_flower_opening >= 0.f)) {
-
2856 if (fbud.time_counter >= plant_instance.dd_to_flower_opening) {
-
2857 fbud.time_counter = 0;
-
2858 if (fbud.state == BUD_FLOWER_CLOSED) {
-
2859 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
-
2860 }else{
-
2861 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
-
2862 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
-
2863 } else {
-
2864 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
2865 }
-
2866 }
-
2867 if (shoot->shoot_parameters.determinate_shoot_growth) {
-
2868 shoot->terminateApicalBud();
-
2869 shoot->terminateAxillaryVegetativeBuds();
-
2870 }
-
2871 }
-
2872 }
-
2873 }
-
2874
-
2875 // -- Fruit Set -- //
-
2876 // If the flower bud is in a 'flowering' state, the fruit set occurs after a certain amount of time
-
2877 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function != nullptr) {
-
2878 if ((fbud.state == BUD_FLOWER_OPEN && plant_instance.dd_to_fruit_set >= 0.f) || //flower opened and fruit set is enabled
-
2879 (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
-
2880 (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
-
2881 if (fbud.time_counter >= plant_instance.dd_to_fruit_set) {
-
2882 fbud.time_counter = 0;
-
2883 if (context_ptr->randu() < shoot->shoot_parameters.fruit_set_probability.val()) {
-
2884 phytomer->setFloralBudState(BUD_FRUITING, fbud);
-
2885 } else {
-
2886 phytomer->setFloralBudState(BUD_DEAD, fbud);
-
2887 }
-
2888 if (shoot->shoot_parameters.determinate_shoot_growth) {
-
2889 shoot->terminateApicalBud();
-
2890 shoot->terminateAxillaryVegetativeBuds();
-
2891 }
-
2892 }
-
2893 }
-
2894 }
-
2895 }
-
2896 }
-
2897 }
-
2898
-
2899 // ****** GROWTH/SCALING OF CURRENT PHYTOMERS/FRUIT ****** //
-
2900
-
2901 int node_index = 0;
-
2902 for (auto &phytomer: shoot->phytomers) {
-
2903 //scale internode length
-
2904 if (phytomer->current_internode_scale_factor < 1) {
-
2905 float dL_internode = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->internode_length_max;
-
2906 float length_scale = fmin(1.f, (phytomer->getInternodeLength() + dL_internode) / phytomer->internode_length_max);
-
2907 phytomer->setInternodeLengthScaleFraction(length_scale, false);
-
2908 }
-
2909
-
2910 //scale internode girth
-
2911 float inode_radius = phytomer->getInternodeRadius();
-
2912 if (shoot->shoot_parameters.girth_area_factor.val() > 0.f) {
-
2913 incrementPhytomerInternodeGirth(plantID, shoot->ID, node_index, false);
-
2914 }
-
2915
-
2916 node_index++;
-
2917 }
+
2853 if( current_age<0 ){
+
2854 helios_runtime_error("ERROR (PlantArchitecture::addPlantInstance): Current age must be greater than or equal to zero.");
+
2855 }
+
2856
+
2857 PlantInstance instance(base_position, current_age, "custom", context_ptr);
+
2858
+
2859 plant_instances.emplace(plant_count, instance);
+
2860
+
2861 plant_count++;
+
2862
+
2863 return plant_count - 1;
+
2864}
+
+
2865
+
+
2866uint PlantArchitecture::duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age) {
+
2867
+
2868 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2869 helios_runtime_error("ERROR (PlantArchitecture::duplicatePlantInstance): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2870 }
+
2871
+
2872 auto plant_shoot_tree = &plant_instances.at(plantID).shoot_tree;
+
2873
+
2874 uint plantID_new = addPlantInstance(base_position, current_age);
+
2875
+
2876 if( plant_shoot_tree->empty() ){ //no shoots to add
+
2877 return plantID_new;
+
2878 }
+
2879 if( plant_shoot_tree->front()->phytomers.empty() ){ //no phytomers to add
+
2880 return plantID_new;
+
2881 }
+
2882
+
2883 for (auto shoot: *plant_shoot_tree) {
+
2884 uint shootID_new; //ID of the new shoot; will be set once the shoot is created on the first loop iteration
+
2885 for (int node = 0; node < shoot->current_node_number; node++) {
+
2886 auto phytomer = shoot->phytomers.at(node);
+
2887 float internode_radius = phytomer->internode_radius_initial;
+
2888 float internode_length_max = phytomer->internode_length_max;
+
2889 float internode_scale_factor_fraction = phytomer->current_internode_scale_factor;
+
2890 float leaf_scale_factor_fraction = phytomer->current_leaf_scale_factor;
+
2891
+
2892 if (node == 0) {//first phytomer on shoot
+
2893 AxisRotation original_base_rotation = shoot->base_rotation;
+
2894 if(shoot->parent_shoot_ID == -1 ) { //first shoot on plant
+
2895 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);
+
2896 }else{ //child shoot
+
2897 uint parent_node = plant_shoot_tree->at(shoot->parent_shoot_ID)->parent_node_index;
+
2898 uint parent_petiole_index = 0;
+
2899 for( auto &petiole : phytomer->axillary_vegetative_buds ) {
+
2900 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);
+
2901 parent_petiole_index++;
+
2902 }
+
2903 }
+
2904 } else {
+
2905 //each phytomer needs to be added one-by-one to account for possible internodes/leaves that are not fully elongated
+
2906 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);
+
2907 }
+
2908 }
+
2909 }
+
2910
+
2911 return plantID_new;
+
2912}
+
+
2913
+
+ +
2915 if (plant_instances.find(plantID) == plant_instances.end()) {
+
2916 return;
+
2917 }
2918
-
2919 node_index = 0;
-
2920 for (auto &phytomer: shoot->phytomers) {
-
2921 //scale petiole/leaves
-
2922 if (phytomer->hasLeaf() && phytomer->current_leaf_scale_factor <= 1) {
-
2923 float tip_ind = ceil(float(phytomer->leaf_size_max.front().size()-1)/2.f);
-
2924 float leaf_length = phytomer->current_leaf_scale_factor * phytomer->leaf_size_max.front().at(tip_ind);
-
2925 float dL_leaf = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->leaf_size_max.front().at(tip_ind);
-
2926 float scale = fmin(1.f, (leaf_length + dL_leaf) / phytomer->phytomer_parameters.leaf.prototype_scale.val() );
-
2927 phytomer->phytomer_parameters.leaf.prototype_scale.resample();
-
2928 phytomer->setLeafScaleFraction(scale);
-
2929 }
-
2930
-
2931 //Fruit Growth
-
2932 for (auto &petiole: phytomer->floral_buds) {
-
2933 for (auto &fbud: petiole) {
-
2934 // If the floral bud it in a 'fruiting' state, the fruit grows with time
-
2935 if (fbud.state == BUD_FRUITING && fbud.time_counter > 0) {
-
2936 float scale = fmin(1, 0.25f + 0.75f * fbud.time_counter / plant_instance.dd_to_fruit_maturity);
-
2937 phytomer->setInflorescenceScaleFraction(fbud, scale);
-
2938 }
-
2939 }
-
2940 }
-
2941
-
2942 // ****** NEW CHILD SHOOTS FROM VEGETATIVE BUDS ****** //
-
2943 uint parent_petiole_index = 0;
-
2944 for (auto &petiole: phytomer->axillary_vegetative_buds) {
-
2945 for (auto &vbud: petiole) {
-
2946
-
2947 if (vbud.state == BUD_ACTIVE && phytomer->age + dt_max > shoot->shoot_parameters.vegetative_bud_break_time.val()) {
-
2948
-
2949 ShootParameters *new_shoot_parameters = &shoot_types.at(vbud.shoot_type_label);
-
2950 int parent_node_count = shoot->current_node_number;
-
2951
-
2952// 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);
-
2953// AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
-
2954// new_shoot_parameters->base_yaw.resample();
-
2955// if( new_shoot_parameters->insertion_angle_decay_rate.val()==0 ){
-
2956// new_shoot_parameters->insertion_angle_tip.resample();
-
2957// }
-
2958 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);
-
2959 AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
-
2960 new_shoot_parameters->base_yaw.resample();
-
2961 if (shoot->shoot_parameters.insertion_angle_decay_rate.val() == 0) {
-
2962 shoot->shoot_parameters.insertion_angle_tip.resample();
-
2963 }
-
2964
-
2965 //scale the shoot internode length based on proximity from the tip
-
2966 float internode_length_max;
-
2967 if (new_shoot_parameters->growth_requires_dormancy) {
-
2968 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),
-
2969 new_shoot_parameters->internode_length_min.val());
-
2970 } else {
-
2971 internode_length_max = new_shoot_parameters->internode_length_max.val();
-
2972 }
-
2973
-
2974 float internode_radius = phytomer->internode_radius_initial;
-
2975
-
2976 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);
-
2977
-
2978 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
-
2979 vbud.shoot_ID = childID;
-
2980 shoot_tree->at(childID)->isdormant = false;
-
2981 }
-
2982 }
-
2983 parent_petiole_index++;
-
2984 }
-
2985
-
2986 // check for ground collisions
-
2987 if (ground_clipping_height != -99999) {
-
2988 // internode
-
2989 if ( (phytomer->shoot_index.x==0 && phytomer->rank>0 ) && context_ptr->doesObjectExist(shoot->internode_tube_objID) && detectGroundCollision( shoot->internode_tube_objID ) ) {
-
2990 context_ptr->deleteObject(shoot->internode_tube_objID);
-
2991 shoot->terminateApicalBud();
-
2992 }
-
2993
-
2994 // leaves
-
2995 for (uint petiole = 0; petiole < phytomer->leaf_objIDs.size(); petiole++) {
-
2996 if (detectGroundCollision(phytomer->leaf_objIDs.at(petiole))) {
-
2997 context_ptr->deleteObject(phytomer->leaf_objIDs.at(petiole));
-
2998 phytomer->leaf_objIDs.at(petiole).clear();
-
2999 phytomer->leaf_bases.at(petiole).clear();
-
3000 context_ptr->deleteObject(phytomer->petiole_objIDs.at(petiole));
-
3001 phytomer->petiole_objIDs.at(petiole).clear();
-
3002 }
-
3003 }
-
3004
-
3005 //inflorescence
-
3006 for (auto &petiole: phytomer->floral_buds) {
-
3007 for (auto &fbud: petiole) {
-
3008 for (int p = fbud.inflorescence_objIDs.size() - 1; p >= 0; p--) {
-
3009 uint objID = fbud.inflorescence_objIDs.at(p);
-
3010 if (detectGroundCollision(objID)) {
-
3011 context_ptr->deleteObject(objID);
-
3012 fbud.inflorescence_objIDs.erase(fbud.inflorescence_objIDs.begin() + p);
-
3013 fbud.inflorescence_bases.erase(fbud.inflorescence_bases.begin() + p);
-
3014 }
-
3015 }
-
3016 for (int p = fbud.peduncle_objIDs.size() - 1; p >= 0; p--) {
-
3017 uint objID = fbud.peduncle_objIDs.at(p);
-
3018 if (detectGroundCollision(objID)) {
-
3019 context_ptr->deleteObject(fbud.peduncle_objIDs);
-
3020 context_ptr->deleteObject(fbud.inflorescence_objIDs);
-
3021 fbud.peduncle_objIDs.clear();
-
3022 fbud.inflorescence_objIDs.clear();
-
3023 fbud.inflorescence_bases.clear();
-
3024 break;
-
3025 }
-
3026 }
-
3027 }
-
3028 }
-
3029 }
-
3030
-
3031 if (output_object_data.at("age")) {
-
3032 if (shoot->build_context_geometry_internode) {
-
3033 //\todo This is redundant and only needs to be done once per shoot
-
3034 if (context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
-
3035 context_ptr->setObjectData(shoot->internode_tube_objID, "age", phytomer->age);
-
3036 }
-
3037 }
-
3038 if (phytomer->build_context_geometry_petiole) {
-
3039 context_ptr->setObjectData(phytomer->petiole_objIDs, "age", phytomer->age);
-
3040 }
-
3041 context_ptr->setObjectData(phytomer->leaf_objIDs, "age", phytomer->age);
-
3042 }
-
3043
-
3044 node_index++;
+
2919 context_ptr->deleteObject(getAllPlantObjectIDs(plantID));
+
2920
+
2921 plant_instances.erase(plantID);
+
2922}
+
+
2923
+
+
2924void PlantArchitecture::deletePlantInstance(const std::vector<uint> &plantIDs) {
+
2925 for (uint ID: plantIDs) {
+ +
2927 }
+
2928}
+
+
2929
+
+
2930void 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_dormancy,float max_leaf_lifespan, bool is_evergreen) {
+
2931
+
2932 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2933 helios_runtime_error("ERROR (PlantArchitecture::setPlantPhenologicalThresholds): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2934 }
+
2935
+
2936 plant_instances.at(plantID).dd_to_dormancy_break = time_to_dormancy_break;
+
2937 plant_instances.at(plantID).dd_to_flower_initiation = time_to_flower_initiation;
+
2938 plant_instances.at(plantID).dd_to_flower_opening = time_to_flower_opening;
+
2939 plant_instances.at(plantID).dd_to_fruit_set = time_to_fruit_set;
+
2940 plant_instances.at(plantID).dd_to_fruit_maturity = time_to_fruit_maturity;
+
2941 plant_instances.at(plantID).dd_to_dormancy = time_to_dormancy;
+
2942 if (max_leaf_lifespan == 0) {
+
2943 plant_instances.at(plantID).max_leaf_lifespan = 1e6;
+
2944 } else {
+
2945 plant_instances.at(plantID).max_leaf_lifespan = max_leaf_lifespan;
+
2946 }
+
2947 plant_instances.at(plantID).is_evergreen = is_evergreen;
+
2948}
+
+
2949
+
2950void PlantArchitecture::disablePlantPhenology(uint plantID) {
+
2951 plant_instances.at(plantID).dd_to_dormancy_break = 0;
+
2952 plant_instances.at(plantID).dd_to_flower_initiation = -1;
+
2953 plant_instances.at(plantID).dd_to_flower_opening = -1;
+
2954 plant_instances.at(plantID).dd_to_fruit_set = -1;
+
2955 plant_instances.at(plantID).dd_to_fruit_maturity = -1;
+
2956 plant_instances.at(plantID).dd_to_dormancy = 1e6;
+
2957}
+
2958
+
+
2959void PlantArchitecture::advanceTime(float time_step_days) {
+
2960 for (auto &plant: plant_instances) {
+
2961 uint plantID = plant.first;
+
2962
+
2963 advanceTime(plantID, time_step_days);
+
2964 }
+
2965}
+
+
2966
+
+
2967void PlantArchitecture::advanceTime(int time_step_years, float time_step_days) {
+
2968 for (auto &plant: plant_instances) {
+
2969 uint plantID = plant.first;
+
2970
+
2971 advanceTime(plantID, float(time_step_years)*365.f+time_step_days);
+
2972 }
+
2973}
+
+
2974
+
+
2975void PlantArchitecture::advanceTime(uint plantID, float time_step_days) {
+
2976
+
2977 if( plant_instances.find(plantID) == plant_instances.end() ){
+
2978 helios_runtime_error("ERROR (PlantArchitecture::advanceTime): Plant with ID of " + std::to_string(plantID) + " does not exist.");
+
2979 }
+
2980
+
2981 PlantInstance &plant_instance = plant_instances.at(plantID);
+
2982
+
2983 auto shoot_tree = &plant_instance.shoot_tree;
+
2984
+
2985 if (shoot_tree->empty()) {
+
2986 return;
+
2987 }
+
2988
+
2989 //accounting for case of time_step_days>phyllochron_min
+
2990 float phyllochron_min = shoot_tree->front()->shoot_parameters.phyllochron_min.val();
+
2991 for (int i = 1; i < shoot_tree->size(); i++) {
+
2992 if (shoot_tree->at(i)->shoot_parameters.phyllochron_min.val() < phyllochron_min) {
+
2993 phyllochron_min = shoot_tree->at(i)->shoot_parameters.phyllochron_min.val();
+
2994 }
+
2995 }
+
2996
+
2997 int Nsteps = std::floor(time_step_days / phyllochron_min);
+
2998 float remainder_time = time_step_days - phyllochron_min * float(Nsteps);
+
2999 if (remainder_time > 0.f) {
+
3000 Nsteps++;
+
3001 }
+
3002
+
3003 for (int timestep = 0; timestep < Nsteps; timestep++) {
+
3004 float dt_max = phyllochron_min;
+
3005 if (timestep == Nsteps - 1 && remainder_time != 0.f) {
+
3006 dt_max = remainder_time;
+
3007 }
+
3008
+
3009 // **** accumulate photosynthate **** //
+
3010 if( carbon_model_enabled ){
+
3011 accumulateShootPhotosynthesis();
+
3012 }
+
3013
+
3014 if (plant_instance.current_age <= plant_instance.max_age && plant_instance.current_age + dt_max > plant_instance.max_age) {
+
3015 std::cout << "PlantArchitecture::advanceTime: Plant has reached its maximum supported age. No further growth will occur." << std::endl;
+
3016 } else if (plant_instance.current_age >= plant_instance.max_age) {
+
3017 //update Context geometry
+
3018 shoot_tree->front()->updateShootNodes(true);
+
3019 return;
+
3020 }
+
3021
+
3022 plant_instance.current_age += dt_max;
+
3023 plant_instance.time_since_dormancy += dt_max;
+
3024
+
3025 if (plant_instance.time_since_dormancy > plant_instance.dd_to_dormancy_break+plant_instance.dd_to_dormancy) {
+
3026 // std::cout << "Going dormant " << plant_instance.current_age << " " << plant_instance.time_since_dormancy << std::endl;
+
3027 plant_instance.time_since_dormancy = 0;
+
3028 for (const auto &shoot: *shoot_tree) {
+
3029 shoot->makeDormant();
+
3030 }
+
3031 harvestPlant(plantID);
+
3032 continue;
+
3033 }
+
3034
+
3035 size_t shoot_count = shoot_tree->size();
+
3036 for (int i = 0; i < shoot_count; i++) {
+
3037 auto shoot = shoot_tree->at(i);
+
3038
+
3039 for (auto &phytomer: shoot->phytomers) {
+
3040 phytomer->age += dt_max;
+
3041
+
3042 if (phytomer->phytomer_parameters.phytomer_callback_function != nullptr) {
+
3043 phytomer->phytomer_parameters.phytomer_callback_function(phytomer);
+
3044 }
3045 }
3046
-
3047 // if shoot has reached max_nodes, stop apical growth
-
3048 if (shoot->current_node_number >= shoot->shoot_parameters.max_nodes.val()) {
-
3049 shoot->terminateApicalBud();
-
3050 }
-
3051
-
3052 // If the apical bud is dead, don't do anything more with the shoot
-
3053 if (!shoot->meristem_is_alive) {
-
3054 continue;
-
3055 }
-
3056
-
3057 // ****** PHYLLOCHRON - NEW PHYTOMERS ****** //
-
3058 shoot->phyllochron_counter += dt_max;
-
3059 if (shoot->phyllochron_counter >= shoot->shoot_parameters.phyllochron_min.val() && !shoot->phytomers.back()->isdormant ) {
-
3060 float internode_radius = shoot->shoot_parameters.phytomer_parameters.internode.radius_initial.val();
-
3061 shoot->shoot_parameters.phytomer_parameters.internode.radius_initial.resample();
-
3062 float internode_length_max = shoot->internode_length_max_shoot_initial;
-
3063 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
-
3064 shoot->shoot_parameters.phyllochron_min.resample();
-
3065 shoot->phyllochron_counter = shoot->phyllochron_counter - shoot->shoot_parameters.phyllochron_min.val();
-
3066 }
-
3067
-
3068 // ****** EPICORMIC SHOOTS ****** //
-
3069 std::string epicormic_shoot_label = plant_instance.epicormic_shoot_probability_perlength_per_day.first;
-
3070 if (!epicormic_shoot_label.empty()) {
-
3071 std::vector<float> epicormic_fraction;
-
3072 uint Nepicormic = shoot->sampleEpicormicShoot(time_step_days, epicormic_fraction);
-
3073 for (int s = 0; s < Nepicormic; s++) {
-
3074 float internode_radius = shoot_types.at(epicormic_shoot_label).phytomer_parameters.internode.radius_initial.val();
-
3075 shoot_types.at(epicormic_shoot_label).phytomer_parameters.internode.radius_initial.resample();
-
3076 float internode_length_max = shoot_types.at(epicormic_shoot_label).internode_length_max.val();
-
3077 shoot_types.at(epicormic_shoot_label).internode_length_max.resample();
-
3078 std::cout << "Adding epicormic shoot" << std::endl;
-
3079 addEpicormicShoot(plantID, shoot->ID, epicormic_fraction.at(s), 1, 0, internode_radius, internode_length_max, 0.01, 0.01, 0, epicormic_shoot_label);
-
3080 }
-
3081 }
-
3082
-
3083 // **** subtract maintenance carbon costs **** //
-
3084 // subtractShootMaintenanceCarbon(dt_max);
-
3085
-
3086 if (output_object_data.find("carbohydrate_concentration") != output_object_data.end() && context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
-
3087 float shoot_volume = shoot->calculateShootInternodeVolume();
-
3088 context_ptr->setObjectData(shoot->internode_tube_objID, "carbohydrate_concentration",shoot->carbohydrate_pool_molC / shoot_volume);
-
3089 }
-
3090 }
-
3091 }
-
3092
-
3093 //update Context geometry
-
3094 shoot_tree->front()->updateShootNodes(true);
-
3095
-
3096}
-
-
3097
-
3098std::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) {
-
3099
-
3100 uint Nverts = vertices.size();
-
3101
-
3102 if (radii.size() != Nverts || colors.size() != Nverts) {
-
3103 helios_runtime_error("ERROR (makeTubeFromCones): Length of vertex vectors is not consistent.");
-
3104 }
-
3105
-
3106 std::vector<uint> objIDs(Nverts - 1);
-
3107
-
3108 for( uint v=0; v<Nverts-1; v++ ){
-
3109
-
3110 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) );
-
3111
-
3112 }
-
3113
-
3114 return objIDs;
-
3115}
-
3116
-
3117bool PlantArchitecture::detectGroundCollision(uint objID) {
-
3118 std::vector<uint> objIDs = {objID};
-
3119 return detectGroundCollision(objIDs);
-
3120}
-
3121
-
3122bool PlantArchitecture::detectGroundCollision(const std::vector<uint> &objID) {
-
3123 for (uint ID: objID) {
-
3124 if (context_ptr->doesObjectExist(ID)) {
-
3125 const std::vector<uint> &UUIDs = context_ptr->getObjectPrimitiveUUIDs(ID);
-
3126 for (uint UUID: UUIDs) {
-
3127 const std::vector<vec3> &vertices = context_ptr->getPrimitiveVertices(UUID);
-
3128 for (const vec3 &v: vertices) {
-
3129 if (v.z < ground_clipping_height) {
-
3130 return true;
-
3131 }
-
3132 }
-
3133 }
-
3134 }
-
3135 }
-
3136 return false;
-
3137}
-
3138
-
-
3139void PlantArchitecture::optionalOutputObjectData( const std::string &object_data_label ){
-
3140 if( output_object_data.find(object_data_label)==output_object_data.end() ){
-
3141 std::cerr << "WARNING (PlantArchitecture::optionalOutputObjectData): Output object data of '" << object_data_label << "' is not a valid option." << std::endl;
-
3142 return;
-
3143 }
-
3144 output_object_data.at(object_data_label) = true;
-
3145}
-
-
3146
-
-
3147void PlantArchitecture::optionalOutputObjectData( const std::vector<std::string> &object_data_labels ){
-
3148 for( auto &label : object_data_labels){
-
3149 if( output_object_data.find(label)==output_object_data.end() ){
-
3150 std::cerr << "WARNING (PlantArchitecture::optionalOutputObjectData): Output object data of '" << label << "' is not a valid option." << std::endl;
-
3151 continue;
-
3152 }
-
3153 output_object_data.at(label) = true;
-
3154 }
-
3155}
+
3047 // ****** PHENOLOGICAL TRANSITIONS ****** //
+
3048
+
3049 // breaking dormancy
+
3050 if (shoot->isdormant && plant_instance.time_since_dormancy >= plant_instance.dd_to_dormancy_break) {
+
3051 shoot->breakDormancy();
+
3052 }
+
3053
+
3054 if (shoot->isdormant) {
+
3055 //dormant, don't do anything
+
3056 continue;
+
3057 }
+
3058
+
3059 for (auto &phytomer: shoot->phytomers) {
+
3060 if (phytomer->age > plant_instance.max_leaf_lifespan) {
+
3061 //delete old leaves that exceed maximum lifespan
+
3062 phytomer->removeLeaf();
+
3063 }
+
3064
+
3065 if (phytomer->floral_buds.empty()) {
+
3066 //no floral buds - skip this phytomer
+
3067 continue;
+
3068 }
+
3069
+
3070 for (auto &petiole: phytomer->floral_buds) {
+
3071 for (auto &fbud: petiole) {
+
3072 if (fbud.state != BUD_DORMANT && fbud.state != BUD_DEAD) {
+
3073 fbud.time_counter += dt_max;
+
3074 }
+
3075
+
3076 // -- Flowering -- //
+
3077 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.flower_prototype_function != nullptr) { //user defined a flower prototype function
+
3078 // -- Flower initiation (closed flowers) -- //
+
3079 if (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation >= 0.f) { //bud is active and flower initiation is enabled
+
3080 if ((!shoot->shoot_parameters.flowers_require_dormancy && plant_instance.current_age >= plant_instance.dd_to_flower_initiation) ||
+
3081 (shoot->shoot_parameters.flowers_require_dormancy && phytomer->age >= plant_instance.dd_to_flower_initiation)) {
+
3082 fbud.time_counter = 0;
+
3083 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
+
3084 phytomer->setFloralBudState(BUD_FLOWER_CLOSED, fbud);
+
3085 } else {
+
3086 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
3087 }
+
3088 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
3089 shoot->terminateApicalBud();
+
3090 shoot->terminateAxillaryVegetativeBuds();
+
3091 }
+
3092 }
+
3093
+
3094 // -- Flower opening -- //
+
3095 } else if ((fbud.state == BUD_FLOWER_CLOSED && plant_instance.dd_to_flower_opening >= 0.f) ||
+
3096 (fbud.state == BUD_ACTIVE && plant_instance.dd_to_flower_initiation < 0.f && plant_instance.dd_to_flower_opening >= 0.f)) {
+
3097 if (fbud.time_counter >= plant_instance.dd_to_flower_opening) {
+
3098 fbud.time_counter = 0;
+
3099 if (fbud.state == BUD_FLOWER_CLOSED) {
+
3100 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
+
3101 }else{
+
3102 if (context_ptr->randu() < shoot->shoot_parameters.flower_bud_break_probability.val() ) {
+
3103 phytomer->setFloralBudState(BUD_FLOWER_OPEN, fbud);
+
3104 } else {
+
3105 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
3106 }
+
3107 }
+
3108 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
3109 shoot->terminateApicalBud();
+
3110 shoot->terminateAxillaryVegetativeBuds();
+
3111 }
+
3112 }
+
3113 }
+
3114 }
+
3115
+
3116 // -- Fruit Set -- //
+
3117 // If the flower bud is in a 'flowering' state, the fruit set occurs after a certain amount of time
+
3118 if (shoot->shoot_parameters.phytomer_parameters.inflorescence.fruit_prototype_function != nullptr) {
+
3119 if ((fbud.state == BUD_FLOWER_OPEN && plant_instance.dd_to_fruit_set >= 0.f) || //flower opened and fruit set is enabled
+
3120 (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
+
3121 (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
+
3122 if (fbud.time_counter >= plant_instance.dd_to_fruit_set) {
+
3123 fbud.time_counter = 0;
+
3124 if (context_ptr->randu() < shoot->shoot_parameters.fruit_set_probability.val()) {
+
3125 phytomer->setFloralBudState(BUD_FRUITING, fbud);
+
3126 } else {
+
3127 phytomer->setFloralBudState(BUD_DEAD, fbud);
+
3128 }
+
3129 if (shoot->shoot_parameters.determinate_shoot_growth) {
+
3130 shoot->terminateApicalBud();
+
3131 shoot->terminateAxillaryVegetativeBuds();
+
3132 }
+
3133 }
+
3134 }
+
3135 }
+
3136 }
+
3137 }
+
3138 }
+
3139
+
3140 // ****** GROWTH/SCALING OF CURRENT PHYTOMERS/FRUIT ****** //
+
3141
+
3142 int node_index = 0;
+
3143 for (auto &phytomer: shoot->phytomers) {
+
3144 //scale internode length
+
3145 if (phytomer->current_internode_scale_factor < 1) {
+
3146 float dL_internode = dt_max * shoot->elongation_rate_instantaneous * phytomer->internode_length_max;
+
3147 float length_scale = fmin(1.f, (phytomer->getInternodeLength() + dL_internode) / phytomer->internode_length_max);
+
3148 phytomer->setInternodeLengthScaleFraction(length_scale, false);
+
3149 }
+
3150
+
3151 //scale internode girth
+
3152 float inode_radius = phytomer->getInternodeRadius();
+
3153 if (shoot->shoot_parameters.girth_area_factor.val() > 0.f) {
+
3154 incrementPhytomerInternodeGirth(plantID, shoot->ID, node_index, false);
+
3155 }
+
3156
+
3157 node_index++;
+
3158 }
+
3159
+
3160 node_index = 0;
+
3161 for (auto &phytomer: shoot->phytomers) {
+
3162 //scale petiole/leaves
+
3163 if (phytomer->hasLeaf() && phytomer->current_leaf_scale_factor <= 1) {
+
3164 float tip_ind = ceil(float(phytomer->leaf_size_max.front().size()-1)/2.f);
+
3165 float leaf_length = phytomer->current_leaf_scale_factor * phytomer->leaf_size_max.front().at(tip_ind);
+
3166 float dL_leaf = dt_max * shoot->elongation_rate_instantaneous * phytomer->leaf_size_max.front().at(tip_ind);
+
3167 float scale = fmin(1.f, (leaf_length + dL_leaf) / phytomer->phytomer_parameters.leaf.prototype_scale.val() );
+
3168 phytomer->phytomer_parameters.leaf.prototype_scale.resample();
+
3169 phytomer->setLeafScaleFraction(scale);
+
3170 }
+
3171
+
3172 //Fruit Growth
+
3173 for (auto &petiole: phytomer->floral_buds) {
+
3174 for (auto &fbud: petiole) {
+
3175 // If the floral bud it in a 'fruiting' state, the fruit grows with time
+
3176 if (fbud.state == BUD_FRUITING && fbud.time_counter > 0) {
+
3177 float scale = fmin(1, 0.25f + 0.75f * fbud.time_counter / plant_instance.dd_to_fruit_maturity);
+
3178 phytomer->setInflorescenceScaleFraction(fbud, scale);
+
3179 }
+
3180 }
+
3181 }
+
3182
+
3183 // ****** NEW CHILD SHOOTS FROM VEGETATIVE BUDS ****** //
+
3184 uint parent_petiole_index = 0;
+
3185 for (auto &petiole: phytomer->axillary_vegetative_buds) {
+
3186 for (auto &vbud: petiole) {
+
3187
+
3188 if (vbud.state == BUD_ACTIVE && phytomer->age + dt_max > shoot->shoot_parameters.vegetative_bud_break_time.val()) {
+
3189
+
3190 ShootParameters *new_shoot_parameters = &shoot_types.at(vbud.shoot_type_label);
+
3191 int parent_node_count = shoot->current_node_number;
+
3192
+
3193// 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);
+
3194// AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
+
3195// new_shoot_parameters->base_yaw.resample();
+
3196// if( new_shoot_parameters->insertion_angle_decay_rate.val()==0 ){
+
3197// new_shoot_parameters->insertion_angle_tip.resample();
+
3198// }
+
3199 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);
+
3200 AxisRotation base_rotation = make_AxisRotation(deg2rad(insertion_angle_adjustment), deg2rad(new_shoot_parameters->base_yaw.val()), deg2rad(new_shoot_parameters->base_roll.val()));
+
3201 new_shoot_parameters->base_yaw.resample();
+
3202 if (shoot->shoot_parameters.insertion_angle_decay_rate.val() == 0) {
+
3203 shoot->shoot_parameters.insertion_angle_tip.resample();
+
3204 }
+
3205
+
3206 //scale the shoot internode length based on proximity from the tip
+
3207 float internode_length_max;
+
3208 if (new_shoot_parameters->growth_requires_dormancy) {
+
3209 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),
+
3210 new_shoot_parameters->internode_length_min.val());
+
3211 } else {
+
3212 internode_length_max = new_shoot_parameters->internode_length_max.val();
+
3213 }
+
3214
+
3215 float internode_radius = phytomer->internode_radius_initial;
+
3216
+
3217 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);
+
3218
+
3219 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
+
3220 vbud.shoot_ID = childID;
+
3221 shoot_tree->at(childID)->isdormant = false;
+
3222 }
+
3223 }
+
3224 parent_petiole_index++;
+
3225 }
+
3226
+
3227 // check for ground collisions
+
3228 if (ground_clipping_height != -99999) {
+
3229 // internode
+
3230 if ( (phytomer->shoot_index.x==0 && phytomer->rank>0 ) && context_ptr->doesObjectExist(shoot->internode_tube_objID) && detectGroundCollision( shoot->internode_tube_objID ) ) {
+
3231 context_ptr->deleteObject(shoot->internode_tube_objID);
+
3232 shoot->terminateApicalBud();
+
3233 }
+
3234
+
3235 // leaves
+
3236 for (uint petiole = 0; petiole < phytomer->leaf_objIDs.size(); petiole++) {
+
3237 if (detectGroundCollision(phytomer->leaf_objIDs.at(petiole))) {
+
3238 phytomer->removeLeaf();
+
3239 }
+
3240 }
+
3241
+
3242 //inflorescence
+
3243 for (auto &petiole: phytomer->floral_buds) {
+
3244 for (auto &fbud: petiole) {
+
3245 for (int p = fbud.inflorescence_objIDs.size() - 1; p >= 0; p--) {
+
3246 uint objID = fbud.inflorescence_objIDs.at(p);
+
3247 if (detectGroundCollision(objID)) {
+
3248 context_ptr->deleteObject(objID);
+
3249 fbud.inflorescence_objIDs.erase(fbud.inflorescence_objIDs.begin() + p);
+
3250 fbud.inflorescence_bases.erase(fbud.inflorescence_bases.begin() + p);
+
3251 }
+
3252 }
+
3253 for (int p = fbud.peduncle_objIDs.size() - 1; p >= 0; p--) {
+
3254 uint objID = fbud.peduncle_objIDs.at(p);
+
3255 if (detectGroundCollision(objID)) {
+
3256 context_ptr->deleteObject(fbud.peduncle_objIDs);
+
3257 context_ptr->deleteObject(fbud.inflorescence_objIDs);
+
3258 fbud.peduncle_objIDs.clear();
+
3259 fbud.inflorescence_objIDs.clear();
+
3260 fbud.inflorescence_bases.clear();
+
3261 break;
+
3262 }
+
3263 }
+
3264 }
+
3265 }
+
3266 }
+
3267
+
3268 if (output_object_data.at("age")) {
+
3269 if (shoot->build_context_geometry_internode) {
+
3270 //\todo This is redundant and only needs to be done once per shoot
+
3271 if (context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
+
3272 context_ptr->setObjectData(shoot->internode_tube_objID, "age", phytomer->age);
+
3273 }
+
3274 }
+
3275 if (phytomer->build_context_geometry_petiole) {
+
3276 context_ptr->setObjectData(phytomer->petiole_objIDs, "age", phytomer->age);
+
3277 }
+
3278 context_ptr->setObjectData(phytomer->leaf_objIDs, "age", phytomer->age);
+
3279 }
+
3280
+
3281 node_index++;
+
3282 }
+
3283
+
3284 // if shoot has reached max_nodes, stop apical growth
+
3285 if (shoot->current_node_number >= shoot->shoot_parameters.max_nodes.val()) {
+
3286 shoot->terminateApicalBud();
+
3287 }
+
3288
+
3289 // If the apical bud is dead, don't do anything more with the shoot
+
3290 if (!shoot->meristem_is_alive) {
+
3291 continue;
+
3292 }
+
3293
+
3294 // ****** PHYLLOCHRON - NEW PHYTOMERS ****** //
+
3295 shoot->phyllochron_counter += dt_max;
+
3296 if (shoot->phyllochron_counter >= shoot->shoot_parameters.phyllochron_min.val() && !shoot->phytomers.back()->isdormant ) {
+
3297 float internode_radius = shoot->shoot_parameters.phytomer_parameters.internode.radius_initial.val();
+
3298 shoot->shoot_parameters.phytomer_parameters.internode.radius_initial.resample();
+
3299 float internode_length_max = shoot->internode_length_max_shoot_initial;
+
3300 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
+
3301 shoot->shoot_parameters.phyllochron_min.resample();
+
3302 shoot->phyllochron_counter = shoot->phyllochron_counter - shoot->shoot_parameters.phyllochron_min.val();
+
3303 }
+
3304
+
3305 // ****** EPICORMIC SHOOTS ****** //
+
3306 std::string epicormic_shoot_label = plant_instance.epicormic_shoot_probability_perlength_per_day.first;
+
3307 if (!epicormic_shoot_label.empty()) {
+
3308 std::vector<float> epicormic_fraction;
+
3309 uint Nepicormic = shoot->sampleEpicormicShoot(time_step_days, epicormic_fraction);
+
3310 for (int s = 0; s < Nepicormic; s++) {
+
3311 float internode_radius = shoot_types.at(epicormic_shoot_label).phytomer_parameters.internode.radius_initial.val();
+
3312 shoot_types.at(epicormic_shoot_label).phytomer_parameters.internode.radius_initial.resample();
+
3313 float internode_length_max = shoot_types.at(epicormic_shoot_label).internode_length_max.val();
+
3314 shoot_types.at(epicormic_shoot_label).internode_length_max.resample();
+
3315 std::cout << "Adding epicormic shoot" << std::endl;
+
3316 addEpicormicShoot(plantID, shoot->ID, epicormic_fraction.at(s), 1, 0, internode_radius, internode_length_max, 0.01, 0.01, 0, epicormic_shoot_label);
+
3317 }
+
3318 }
+
3319 if( carbon_model_enabled ){
+
3320 if (output_object_data.find("carbohydrate_concentration") != output_object_data.end() && context_ptr->doesObjectExist(shoot->internode_tube_objID)) {
+
3321 float shoot_volume = shoot->calculateShootInternodeVolume();
+
3322 context_ptr->setObjectData(shoot->internode_tube_objID, "carbohydrate_concentration",shoot->carbohydrate_pool_molC / shoot_volume);
+
3323 }
+
3324 }
+
3325 }
+
3326
+
3327 // **** subtract maintenance carbon costs **** //
+
3328 if( carbon_model_enabled ){
+
3329 subtractShootMaintenanceCarbon(time_step_days);
+
3330 subtractShootGrowthCarbon();
+
3331 checkCarbonPool_adjustPhyllochron();
+
3332 checkCarbonPool_abortBuds();
+
3333 checkCarbonPool_transferCarbon();
+
3334 }
+
3335 }
+
3336
+
3337 //update Context geometry
+
3338 shoot_tree->front()->updateShootNodes(true);
+
3339
+
3340}
+
+
3341
+
3342std::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) {
+
3343
+
3344 uint Nverts = vertices.size();
+
3345
+
3346 if (radii.size() != Nverts || colors.size() != Nverts) {
+
3347 helios_runtime_error("ERROR (makeTubeFromCones): Length of vertex vectors is not consistent.");
+
3348 }
+
3349
+
3350 std::vector<uint> objIDs(Nverts - 1);
+
3351
+
3352 for( uint v=0; v<Nverts-1; v++ ){
+
3353
+
3354 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) );
+
3355
+
3356 }
+
3357
+
3358 return objIDs;
+
3359}
+
3360
+
3361bool PlantArchitecture::detectGroundCollision(uint objID) {
+
3362 std::vector<uint> objIDs = {objID};
+
3363 return detectGroundCollision(objIDs);
+
3364}
+
3365
+
3366bool PlantArchitecture::detectGroundCollision(const std::vector<uint> &objID) {
+
3367 for (uint ID: objID) {
+
3368 if (context_ptr->doesObjectExist(ID)) {
+
3369 const std::vector<uint> &UUIDs = context_ptr->getObjectPrimitiveUUIDs(ID);
+
3370 for (uint UUID: UUIDs) {
+
3371 const std::vector<vec3> &vertices = context_ptr->getPrimitiveVertices(UUID);
+
3372 for (const vec3 &v: vertices) {
+
3373 if (v.z < ground_clipping_height) {
+
3374 return true;
+
3375 }
+
3376 }
+
3377 }
+
3378 }
+
3379 }
+
3380 return false;
+
3381}
+
3382
+
+
3383void PlantArchitecture::optionalOutputObjectData( const std::string &object_data_label ){
+
3384 if( output_object_data.find(object_data_label)==output_object_data.end() ){
+
3385 std::cerr << "WARNING (PlantArchitecture::optionalOutputObjectData): Output object data of '" << object_data_label << "' is not a valid option." << std::endl;
+
3386 return;
+
3387 }
+
3388 output_object_data.at(object_data_label) = true;
+
3389}
+
+
3390
+
+
3391void PlantArchitecture::optionalOutputObjectData( const std::vector<std::string> &object_data_labels ){
+
3392 for( auto &label : object_data_labels){
+
3393 if( output_object_data.find(label)==output_object_data.end() ){
+
3394 std::cerr << "WARNING (PlantArchitecture::optionalOutputObjectData): Output object data of '" << label << "' is not a valid option." << std::endl;
+
3395 continue;
+
3396 }
+
3397 output_object_data.at(label) = true;
+
3398 }
+
3399}
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.
- -
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_dormancy, float max_leaf_lifespan=1e6, bool is_evergreen=false)
Specify the threshold values for plant phenological stages.
-
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
-
std::vector< uint > getAllFlowerUUIDs() const
Get UUIDs for all existing flower primitives.
-
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.
-
void advanceTime(float time_step_days)
Advance plant growth by a specified time interval for all plants.
-
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.
-
std::vector< uint > getPlantInternodeObjectIDs(uint plantID) const
Get object IDs for all internode (Tube) objects for a given plant.
-
std::vector< uint > getAllLeafUUIDs() const
Get UUIDs for all existing leaf primitives.
-
std::vector< uint > getAllInternodeUUIDs() const
Get UUIDs for all existing internode primitives.
-
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)
-
std::vector< uint > getAllObjectIDs() const
Get object IDs for all existing plant compound objects.
+ +
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_dormancy, float max_leaf_lifespan=1e6, bool is_evergreen=false)
Specify the threshold values for plant phenological stages.
+
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
std::vector< uint > getAllFlowerUUIDs() const
Get UUIDs for all existing flower primitives.
+
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.
+
void writePlantMeshVertices(uint plantID, const std::string &filename) const
Write all vertices in the plant to a file for external processing (e.g., bounding volume,...
+
std::vector< uint > getPlantFlowerObjectIDs(uint plantID) const
Get object IDs for all inflorescence objects for a given plant.
+
void advanceTime(float time_step_days)
Advance plant growth by a specified time interval for all plants.
+
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.
+
float getPlantHeight(uint plantID) const
Calculate the height of the highest element in the plant.
+
std::vector< float > getPlantLeafInclinationAngleDistribution(uint plantID, uint Nbins) const
Calculate the leaf angle distribution of all leaves in the plant.
+
std::vector< uint > getPlantInternodeObjectIDs(uint plantID) const
Get object IDs for all internode (Tube) objects for a given plant.
+
std::vector< uint > getAllLeafUUIDs() const
Get UUIDs for all existing leaf primitives.
+
std::vector< uint > getAllInternodeUUIDs() const
Get UUIDs for all existing internode primitives.
+
void disablePeduncleContextBuild()
Do not build peduncle primitive geometry in the Context.
+
std::vector< uint > getAllPlantIDs() const
Get IDs for all plant instances.
+
uint getPlantLeafCount(uint plantID) const
Get the total number of leaves on the plant.
+
float getPlantStemHeight(uint plantID) const
Calculate the height of the last internode on the base stem/shoot.
+
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)
+
std::vector< uint > getAllObjectIDs() const
Get object IDs for all existing plant compound objects.
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 > buildPlantCanopyFromLibrary(const helios::vec3 &canopy_center_position, const helios::vec2 &plant_spacing_xy, const helios::int2 &plant_count_xy, float age, float germination_rate=1.f)
Build a canopy of regularly spaced plants based on the model currently loaded from the library.
-
std::vector< uint > getAllFruitUUIDs() const
Get UUIDs for all existing fruit primitives.
-
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 > getAllFruitUUIDs() const
Get UUIDs for all existing fruit primitives.
+
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.
-
std::vector< uint > getAllPeduncleUUIDs() const
Get UUIDs for all existing peduncle primitives.
-
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.
-
std::vector< uint > getPlantLeafObjectIDs(uint plantID) const
Get object IDs for all leaf objects for a given plant.
-
std::vector< uint > getAllPetioleUUIDs() const
Get UUIDs for all existing petiole primitives.
-
std::vector< uint > getAllUUIDs() const
Get UUIDs for all existing plant primitives.
-
void scaleLength(float S)
Method to scale the length of the cone.
Definition Context.cpp:4212
-
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition Context.cpp:4261
-
Stores the state associated with simulation.
Definition Context.h:1882
-
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7139
-
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:2897
-
uint copyObject(uint ObjID)
Make a copy of a Compound Objects from the context.
Definition Context.cpp:2642
-
float randn()
Draw a random number from a normal distribution with mean = 0, stddev = 1.
Definition Context.cpp:1204
-
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4123
-
void rotateObject(uint ObjID, float rotation_radians, const char *rotation_axis_xyz)
Rotate a single compound object about the x, y, or z axis.
Definition Context.cpp:2847
-
std::vector< uint > filterPrimitivesByData(const std::vector< uint > &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator)
Filter a set of primitives based on their primitive data and a condition and float value.
-
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
-
helios::vec3 getConeObjectNode(uint ObjID, int number) const
get a node of a Cone object from the context
Definition Context.cpp:8262
-
float getTubeObjectVolume(uint ObjID) const
get the volume of a Tube object from the context
Definition Context.cpp:8172
-
void appendTubeSegment(uint ObjID, const helios::vec3 &node_position, float radius, const RGBcolor &color)
Append a tube segment to an existing tube object.
Definition Context.cpp:8180
-
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
-
void clearObjectData(uint objID, const char *label)
Clear primitive data for a single primitive based on its objID.
-
void translateObject(uint ObjID, const vec3 &shift)
Translate a single compound object.
Definition Context.cpp:2837
-
std::vector< uint > getObjectPrimitiveUUIDs(uint ObjID) const
Get primitive UUIDs associated with compound object (single object ID input)
Definition Context.cpp:2907
-
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition Context.cpp:49
-
void hideObject(const std::vector< uint > &ObjIDs)
Hide compound objects in the Context such that their object IDs are not returned in Context::getAllOb...
Definition Context.cpp:7901
-
bool doesObjectExist(uint ObjID) const
Check whether Compound Object exists in the Context.
Definition Context.cpp:2585
-
void deleteObject(uint ObjID)
Delete a single Compound Object from the context.
Definition Context.cpp:2609
-
float getObjectArea(uint ObjID) const
Method to return the one-sided surface area of an object.
Definition Context.cpp:7920
-
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:7122
-
void setTubeNodes(uint ObjID, const std::vector< helios::vec3 > &node_xyz)
Set tube vertex coordinates at each segment node.
Definition Context.cpp:8215
-
void setTubeRadii(uint ObjID, const std::vector< float > &node_radii)
Set tube radii at each segment node.
Definition Context.cpp:8201
-
void scaleObject(uint ObjID, const helios::vec3 &scalefact)
Method to scale a compound object in the x-, y- and z-directions.
Definition Context.cpp:2877
+
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.
+
std::vector< uint > getAllPeduncleUUIDs() const
Get UUIDs for all existing peduncle primitives.
+
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.
+
std::vector< uint > getPlantLeafObjectIDs(uint plantID) const
Get object IDs for all leaf objects for a given plant.
+
std::vector< uint > getAllPetioleUUIDs() const
Get UUIDs for all existing petiole primitives.
+
std::vector< uint > getAllUUIDs() const
Get UUIDs for all existing plant primitives.
+
Stores the state associated with simulation.
Definition Context.h:1888
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
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
vec3 nullorigin
Default null vec3 that gives the origin (0,0,0)
Definition global.cpp:58
-
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:4728
-
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5426
+
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5453
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:1943
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
float deg2rad(float deg)
Convert degrees to radians.
Definition global.cpp:576
@@ -3459,45 +3701,48 @@
uint(* prototype_function)(helios::Context *, LeafPrototype *prototype_parameters, int compound_leaf_index)
Custom prototype function for creating leaf prototypes.
RandomParameter_float wave_amplitude
Amplitude of leaf waves (sets the height of leaf waves)
RandomParameter_float longitudinal_curvature
Leaf curvature factor along the longitudinal/length (x-direction). (+curves upward,...
-
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.
-
int appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const PhytomerParameters &phytomer_parameters)
Append a phytomer at the shoot apex.
-
bool sampleVegetativeBudBreak(uint node_index) const
Randomly sample whether a vegetative bud should break into a new shoot.
-
std::string sampleChildShootType() const
Randomly sample the type of a child shoot based on the probabilities defined in the shoot parameters.
-
uint sampleEpicormicShoot(float dt, std::vector< float > &epicormic_positions_fraction)
Randomly sample whether the shoot should produce an epicormic shoot (water sprout) over timestep.
+
void updateShootNodes(bool update_context_geometry=true)
Recalculate and apply the shoot's origin position and shift all downstream shoots.
+
int appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const PhytomerParameters &phytomer_parameters)
Append a phytomer at the shoot apex.
+
bool sampleVegetativeBudBreak(uint node_index) const
Randomly sample whether a vegetative bud should break into a new shoot.
+
std::string sampleChildShootType() const
Randomly sample the type of a child shoot based on the probabilities defined in the shoot parameters.
+
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.
RandomParameter_float vegetative_bud_break_probability_decay_rate
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
float magnitude() const
Compute the vector magnitude.
- -
+ + diff --git a/doc/html/_plant_architecture_8h.html b/doc/html/_plant_architecture_8h.html index 3eead998d..6019d6516 100644 --- a/doc/html/_plant_architecture_8h.html +++ b/doc/html/_plant_architecture_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Data Structures | @@ -215,7 +221,7 @@

-inline +inline

+ + diff --git a/doc/html/_plant_architecture_8h.js b/doc/html/_plant_architecture_8h.js new file mode 100644 index 000000000..fc016ca8d --- /dev/null +++ b/doc/html/_plant_architecture_8h.js @@ -0,0 +1,16 @@ +var _plant_architecture_8h = +[ + [ "RandomParameter_float", "struct_random_parameter__float.html", "struct_random_parameter__float" ], + [ "RandomParameter_int", "struct_random_parameter__int.html", null ], + [ "AxisRotation", "struct_axis_rotation.html", null ], + [ "VegetativeBud", "struct_vegetative_bud.html", null ], + [ "FloralBud", "struct_floral_bud.html", null ], + [ "LeafPrototype", "struct_leaf_prototype.html", "struct_leaf_prototype" ], + [ "PhytomerParameters", "struct_phytomer_parameters.html", "struct_phytomer_parameters" ], + [ "ShootParameters", "struct_shoot_parameters.html", "struct_shoot_parameters" ], + [ "Phytomer", "struct_phytomer.html", "struct_phytomer" ], + [ "Shoot", "struct_shoot.html", "struct_shoot" ], + [ "PlantInstance", "struct_plant_instance.html", null ], + [ "PlantArchitecture", "class_plant_architecture.html", "class_plant_architecture" ], + [ "makeTubeFromCones", "_plant_architecture_8h.html#a90314e1f16ad76c838da858b9bf0ae86", null ] +]; \ No newline at end of file diff --git a/doc/html/_plant_architecture_8h_source.html b/doc/html/_plant_architecture_8h_source.html index c07e4da8c..77455d91a 100644 --- a/doc/html/_plant_architecture_8h_source.html +++ b/doc/html/_plant_architecture_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
PlantArchitecture.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef PLANT_ARCHITECTURE
17#define PLANT_ARCHITECTURE
18
@@ -117,10 +124,10 @@
25struct Phytomer;
26
- +
28public:
-
29
-
31
+
29
+
31
35 constval = 0.f;
@@ -129,8 +136,8 @@
38 sampled = false;
39 }
-
40
-
42
+
40
+
42
45 explicit RandomParameter_float( float val ){
46 constval = val;
@@ -139,8 +146,8 @@
49 sampled = false;
50 }
-
51
-
53
+
51
+
53
56 explicit RandomParameter_float( std::minstd_rand0 *rand_generator ){
57 constval = 0.f;
@@ -164,7 +171,7 @@
74 sampled = false;
75 }
76
-
77 RandomParameter_float& operator=(float a){
+
77 RandomParameter_float& operator=(float a){
78 this->distribution = "constant";
79 this->constval = a;
80 this->sampled = false;
@@ -232,10 +239,10 @@
142
- +
143struct RandomParameter_int {
144public:
145
-
146 explicit RandomParameter_int(){
+
146 explicit RandomParameter_int(){
147 constval = 1;
148 distribution = "constant";
149 generator = nullptr;
@@ -256,7 +263,7 @@
164 sampled = false;
165 }
166
-
167 RandomParameter_int& operator=(int a){
+
167 RandomParameter_int& operator=(int a){
168 this->distribution = "constant";
169 this->constval = a;
170 this->sampled = false;
@@ -312,16 +319,16 @@
220
- +
221struct AxisRotation{
222public:
223
-
224 AxisRotation(){
+
224 AxisRotation(){
225 pitch = 0;
226 yaw = 0;
227 roll = 0;
228 }
229
-
230 AxisRotation( float a_pitch, float a_yaw, float a_roll ){
+
230 AxisRotation( float a_pitch, float a_yaw, float a_roll ){
231 pitch = a_pitch;
232 yaw = a_yaw;
233 roll = a_roll;
@@ -331,10 +338,10 @@
237 float yaw;
238 float roll;
239
-
240 AxisRotation operator+(const AxisRotation& a) const;
-
241 AxisRotation operator-(const AxisRotation& a) const;
+
240 AxisRotation operator+(const AxisRotation& a) const;
+
241 AxisRotation operator-(const AxisRotation& a) const;
242
-
243 friend std::ostream &operator<<(std::ostream &os, const AxisRotation &rot) {
+
243 friend std::ostream &operator<<(std::ostream &os, const AxisRotation &rot) {
244 return os << "AxisRotation<" << rot.pitch << ", " << rot.yaw << ", " << rot.roll << ">";
245 }
246
@@ -361,8 +368,8 @@
266 BUD_FRUITING = 4,
267 BUD_DEAD = 5
268};
-
269
-
271
+
269
+
271
279std::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);
280
@@ -409,30 +416,30 @@
319
- +
321public:
-
322
+
322
324 explicit LeafPrototype( std::minstd_rand0 *generator );
-
325
+
325
-
328
-
330 uint (*prototype_function)(helios::Context *, LeafPrototype* prototype_parameters, int compound_leaf_index) = nullptr;
-
331
-
333
+
328
+
330 uint (*prototype_function)(helios::Context *, LeafPrototype* prototype_parameters, int compound_leaf_index) = nullptr;
+
331
+
333
336 std::string OBJ_model_file;
-
337
-
339
+
337
+
339
342 std::map<int,std::string> leaf_texture_file;
343
344 // Ratio of leaf width to leaf length
345 RandomParameter_float leaf_aspect_ratio;
-
346
+
346
349
350 // Parameters for leaf curvature
-
355
+
355
358
359 // Parameters for leaf wave/wrinkles
@@ -442,18 +449,18 @@
365 // Parameters for leaf buckling
-
370
+
370
-
373
+
373
-
376
+
376
-
379
+
379
382
383 uint unique_prototype_identifier = 0;
384
-
385 void duplicate( const LeafPrototype &a){
+
385 void duplicate( const LeafPrototype &a){
386 this->leaf_texture_file = a.leaf_texture_file;
387 this->OBJ_model_file = a.OBJ_model_file;
388 this->leaf_aspect_ratio = a.leaf_aspect_ratio;
@@ -473,9 +480,9 @@
403 this->generator = a.generator;
404 }
-
405
+
405
- +
408 if (this != &a) {
409 this->leaf_texture_file = a.leaf_texture_file;
410 this->OBJ_model_file = a.OBJ_model_file;
@@ -526,7 +533,7 @@
454
- +
456private:
457
458 struct InternodeParameters{
@@ -709,23 +716,23 @@
642 //Custom user-defined function that is called for each phytomer on every time step
646 void (*phytomer_callback_function)(std::shared_ptr<Phytomer> phytomer_ptr) = nullptr;
647
-
648
+
648
-
651
+
651
653 explicit PhytomerParameters( std::minstd_rand0 *generator );
654
-
655 friend class PlantArchitecture;
-
656 friend struct Phytomer;
-
657 friend struct Shoot;
+
655 friend class PlantArchitecture;
+
656 friend struct Phytomer;
+
657 friend struct Shoot;
658
659};
660
- -
662
+ +
662
-
665
+
665
667 explicit ShootParameters( std::minstd_rand0 *generator );
668
669 PhytomerParameters phytomer_parameters;
@@ -759,7 +766,7 @@
697
698 RandomParameter_float phyllochron_min; //days/phytomer
699
-
700 RandomParameter_float elongation_rate; //length/day
+
700 RandomParameter_float elongation_rate_max; //length/day
701
702 // Minimum probability that bud with this shoot type will break and form a new shoot
703 RandomParameter_float vegetative_bud_break_probability_min;
@@ -787,7 +794,7 @@
728
729 void defineChildShootTypes( const std::vector<std::string> &child_shoot_type_labels, const std::vector<float> &child_shoot_type_probabilities );
730
-
731 ShootParameters& operator=(const ShootParameters &a) {
+
731 ShootParameters& operator=(const ShootParameters &a) {
732 this->phytomer_parameters = a.phytomer_parameters;
733 this->max_nodes = a.max_nodes;
734 this->max_nodes.resample();
@@ -795,149 +802,149 @@
736 this->max_nodes_per_season.resample();
737 this->phyllochron_min = a.phyllochron_min;
738 this->phyllochron_min.resample();
-
739 this->elongation_rate = a.elongation_rate;
-
740 this->elongation_rate.resample();
-
741 this->girth_area_factor = a.girth_area_factor;
-
742 this->girth_area_factor.resample();
-
743 this->vegetative_bud_break_probability_min = a.vegetative_bud_break_probability_min;
-
744 this->vegetative_bud_break_probability_min.resample();
-
745 this->flower_bud_break_probability = a.flower_bud_break_probability;
-
746 this->flower_bud_break_probability.resample();
-
747 this->fruit_set_probability = a.fruit_set_probability;
-
748 this->fruit_set_probability.resample();
-
749 this->gravitropic_curvature = a.gravitropic_curvature;
-
750 this->gravitropic_curvature.resample();
-
751 this->tortuosity = a.tortuosity;
-
752 this->tortuosity.resample();
-
753 this->vegetative_bud_break_probability_min = a.vegetative_bud_break_probability_min;
-
754 this->vegetative_bud_break_probability_min.resample();
-
755 this->vegetative_bud_break_probability_decay_rate = a.vegetative_bud_break_probability_decay_rate;
-
756 this->vegetative_bud_break_probability_decay_rate.resample();
-
757 this->max_terminal_floral_buds = a.max_terminal_floral_buds;
-
758 this->max_terminal_floral_buds.resample();
-
759 this->flower_bud_break_probability = a.flower_bud_break_probability;
-
760 this->flower_bud_break_probability.resample();
-
761 this->fruit_set_probability = a.fruit_set_probability;
-
762 this->fruit_set_probability.resample();
-
763 this->vegetative_bud_break_time = a.vegetative_bud_break_time;
-
764 this->vegetative_bud_break_time.resample();
-
765 this->insertion_angle_tip = a.insertion_angle_tip;
-
766 this->insertion_angle_tip.resample();
-
767 this->insertion_angle_decay_rate = a.insertion_angle_decay_rate;
-
768 this->insertion_angle_decay_rate.resample();
-
769 this->internode_length_max = a.internode_length_max;
-
770 this->internode_length_max.resample();
-
771 this->internode_length_min = a.internode_length_min;
-
772 this->internode_length_min.resample();
-
773 this->internode_length_decay_rate = a.internode_length_decay_rate;
-
774 this->internode_length_decay_rate.resample();
-
775 this->base_roll = a.base_roll;
-
776 this->base_roll.resample();
-
777 this->base_yaw = a.base_yaw;
-
778 this->base_yaw.resample();
-
779 this->flowers_require_dormancy = a.flowers_require_dormancy;
-
780 this->growth_requires_dormancy = a.growth_requires_dormancy;
-
781 this->child_shoot_type_labels = a.child_shoot_type_labels;
-
782 this->child_shoot_type_probabilities = a.child_shoot_type_probabilities;
-
783 this->determinate_shoot_growth = a.determinate_shoot_growth;
-
784 this->child_shoot_type_labels = a.child_shoot_type_labels;
-
785 this->child_shoot_type_probabilities = a.child_shoot_type_probabilities;
-
786 return *this;
-
787 }
-
788
-
789 friend class PlantArchitecture;
-
790 friend struct Shoot;
+
739 this->girth_area_factor = a.girth_area_factor;
+
740 this->girth_area_factor.resample();
+
741 this->vegetative_bud_break_probability_min = a.vegetative_bud_break_probability_min;
+
742 this->vegetative_bud_break_probability_min.resample();
+
743 this->flower_bud_break_probability = a.flower_bud_break_probability;
+
744 this->flower_bud_break_probability.resample();
+
745 this->fruit_set_probability = a.fruit_set_probability;
+
746 this->fruit_set_probability.resample();
+
747 this->gravitropic_curvature = a.gravitropic_curvature;
+
748 this->gravitropic_curvature.resample();
+
749 this->tortuosity = a.tortuosity;
+
750 this->tortuosity.resample();
+
751 this->vegetative_bud_break_probability_min = a.vegetative_bud_break_probability_min;
+
752 this->vegetative_bud_break_probability_min.resample();
+
753 this->vegetative_bud_break_probability_decay_rate = a.vegetative_bud_break_probability_decay_rate;
+
754 this->vegetative_bud_break_probability_decay_rate.resample();
+
755 this->max_terminal_floral_buds = a.max_terminal_floral_buds;
+
756 this->max_terminal_floral_buds.resample();
+
757 this->flower_bud_break_probability = a.flower_bud_break_probability;
+
758 this->flower_bud_break_probability.resample();
+
759 this->fruit_set_probability = a.fruit_set_probability;
+
760 this->fruit_set_probability.resample();
+
761 this->vegetative_bud_break_time = a.vegetative_bud_break_time;
+
762 this->vegetative_bud_break_time.resample();
+
763 this->insertion_angle_tip = a.insertion_angle_tip;
+
764 this->insertion_angle_tip.resample();
+
765 this->insertion_angle_decay_rate = a.insertion_angle_decay_rate;
+
766 this->insertion_angle_decay_rate.resample();
+
767 this->internode_length_max = a.internode_length_max;
+
768 this->internode_length_max.resample();
+
769 this->internode_length_min = a.internode_length_min;
+
770 this->internode_length_min.resample();
+
771 this->internode_length_decay_rate = a.internode_length_decay_rate;
+
772 this->internode_length_decay_rate.resample();
+
773 this->base_roll = a.base_roll;
+
774 this->base_roll.resample();
+
775 this->base_yaw = a.base_yaw;
+
776 this->base_yaw.resample();
+
777 this->flowers_require_dormancy = a.flowers_require_dormancy;
+
778 this->growth_requires_dormancy = a.growth_requires_dormancy;
+
779 this->child_shoot_type_labels = a.child_shoot_type_labels;
+
780 this->child_shoot_type_probabilities = a.child_shoot_type_probabilities;
+
781 this->determinate_shoot_growth = a.determinate_shoot_growth;
+
782 this->child_shoot_type_labels = a.child_shoot_type_labels;
+
783 this->child_shoot_type_probabilities = a.child_shoot_type_probabilities;
+
784 return *this;
+
785 }
+
786
+
787 friend class PlantArchitecture;
+
788 friend struct Shoot;
+
789
+
790protected:
791
-
792protected:
-
793
-
794 std::vector<std::string> child_shoot_type_labels;
-
795 std::vector<float> child_shoot_type_probabilities;
-
796
-
797};
+
792 std::vector<std::string> child_shoot_type_labels;
+
793 std::vector<float> child_shoot_type_probabilities;
+
794
+
795};
-
798
-
-
799struct Phytomer {
-
800public:
+
796
+
+
797struct Phytomer {
+
798public:
+
799
+
800 float phytomer_carbohydrate_cost_molC = 0;
801
-
802 float phytomer_carbohydrate_cost_molC = 0;
-
803
-
804 // Constructor
-
805 Phytomer(const PhytomerParameters &params, Shoot *parent_shoot, uint phytomer_index, const helios::vec3 &parent_internode_axis, const helios::vec3 &parent_petiole_axis, helios::vec3 internode_base_origin,
-
806 const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, uint rank, PlantArchitecture *plantarchitecture_ptr,
-
807 helios::Context *context_ptr);
+
802 // Constructor
+
803 Phytomer(const PhytomerParameters &params, Shoot *parent_shoot, uint phytomer_index, const helios::vec3 &parent_internode_axis, const helios::vec3 &parent_petiole_axis, helios::vec3 internode_base_origin,
+
804 const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, uint rank, PlantArchitecture *plantarchitecture_ptr,
+
805 helios::Context *context_ptr);
+
806
+
807 // ---- query info about the phytomer ---- //
808
-
809 // ---- query info about the phytomer ---- //
+
809 std::vector<helios::vec3> getInternodeNodePositions() const;
810
-
811 std::vector<helios::vec3> getInternodeNodePositions() const;
+
811 std::vector<float> getInternodeNodeRadii() const;
812
-
813 std::vector<float> getInternodeNodeRadii() const;
+
813 helios::vec3 getInternodeAxisVector( float stem_fraction ) const;
814
-
815 helios::vec3 getInternodeAxisVector( float stem_fraction ) const;
+
815 helios::vec3 getPetioleAxisVector(float stem_fraction, uint petiole_index) const;
816
-
817 helios::vec3 getPetioleAxisVector(float stem_fraction, uint petiole_index) const;
+
817 static helios::vec3 getAxisVector( float stem_fraction, const std::vector<helios::vec3> &axis_vertices ) ;
818
-
819 static helios::vec3 getAxisVector( float stem_fraction, const std::vector<helios::vec3> &axis_vertices ) ;
+
819 float getInternodeLength() const;
820
-
821 float getInternodeLength() const;
+
821 float getInternodeRadius() const;
822
-
823 float getInternodeRadius() const;
+
823 float getPetioleLength() const;
824
-
825 float getPetioleLength() const;
+
825 float getInternodeRadius( float stem_fraction ) const;
826
-
827 float getInternodeRadius( float stem_fraction ) const;
+
827 float getLeafArea() const;
828
-
829 float getLeafArea() const;
+
829 bool hasLeaf() const;
830
-
831 bool hasLeaf() const;
+
831 float calculateDownstreamLeafArea() const;
832
-
833 float calculateDownstreamLeafArea() const;
+
833 // ---- modify the phytomer ---- //
834
-
835 // ---- modify the phytomer ---- //
-
836
-
837 void setInternodeLengthScaleFraction(float internode_scale_factor_fraction, bool update_context_geometry);
-
838
-
840
-
843 void scaleInternodeMaxLength( float scale_factor );
-
844
-
846
-
849 void setInternodeMaxLength( float internode_length_max_new );
-
850
-
852
-
855 void setInternodeMaxRadius( float internode_radius_max_new );
-
856
-
858
-
861 void setLeafScaleFraction(float leaf_scale_factor_fraction );
-
862
-
864
-
867 void setLeafPrototypeScale( float leaf_prototype_scale );
+
835 void setInternodeLengthScaleFraction(float internode_scale_factor_fraction, bool update_context_geometry);
+
836
+
838
+
841 void scaleInternodeMaxLength( float scale_factor );
+
842
+
844
+
847 void setInternodeMaxLength( float internode_length_max_new );
+
848
+
850
+
853 void setInternodeMaxRadius( float internode_radius_max_new );
+
854
+
856
+
859 void setLeafScaleFraction(float leaf_scale_factor_fraction );
+
860
+
862
+
865 void setLeafPrototypeScale( float leaf_prototype_scale );
+
866
+
867 void scaleLeafPrototypeScale( float scale_factor );
868
-
869 void scaleLeafPrototypeScale( float scale_factor );
+
869 void setInflorescenceScaleFraction(FloralBud &fbud, float inflorescence_scale_factor_fraction);
870
-
871 void setInflorescenceScaleFraction(FloralBud &fbud, float inflorescence_scale_factor_fraction);
+
871 void setPetioleBase( const helios::vec3 &base_position );
872
-
873 void setPetioleBase( const helios::vec3 &base_position );
+
873 void rotateLeaf( uint petiole_index, uint leaf_index, const AxisRotation &rotation );
874
-
875 void rotateLeaf( uint petiole_index, uint leaf_index, const AxisRotation &rotation );
+
875 void setVegetativeBudState( BudState state );
876
-
877 void setVegetativeBudState( BudState state );
+
877 void setVegetativeBudState(BudState state, uint petiole_index, uint bud_index);
878
-
879 void setVegetativeBudState(BudState state, uint petiole_index, uint bud_index);
+
879 void setVegetativeBudState( BudState state, VegetativeBud &vbud );
880
-
881 void setVegetativeBudState( BudState state, VegetativeBud &vbud );
+
881 void setFloralBudState(BudState state );
882
-
883 void setFloralBudState(BudState state );
+
883 void setFloralBudState(BudState state, uint petiole_index, uint bud_index);
884
-
885 void setFloralBudState(BudState state, uint petiole_index, uint bud_index);
+
885 void setFloralBudState(BudState state, FloralBud &fbud);
886
-
887 void setFloralBudState(BudState state, FloralBud &fbud);
+
887 float calculateFruitConstructionCosts(const FloralBud &fbud);
888
-
889 float calculateFruitConstructionCosts(const FloralBud &fbud);
+
889 void removeLeaf();
890
-
891 void removeLeaf();
+
891 void deletePhytomer();
892
893 // ---- phytomer data ---- //
-
894
+
894
896 std::vector<std::vector<helios::vec3>> petiole_vertices; //first index is petiole within internode, second index is tube segment within petiole
897 std::vector<std::vector<helios::vec3>> leaf_bases; //first index is petiole within internode, second index is leaf within petiole
898 float internode_pitch, internode_phyllotactic_angle;
@@ -962,8 +969,8 @@
918
919 uint plantID;
920 uint parent_shoot_ID;
-
921 Shoot *parent_shoot_ptr;
-
922
+
921 Shoot *parent_shoot_ptr;
+
922
924 float age = 0;
925 bool isdormant = false;
926
@@ -988,37 +995,37 @@
945
946 helios::Context *context_ptr;
947
-
948 PlantArchitecture *plantarchitecture_ptr;
+
948 PlantArchitecture *plantarchitecture_ptr;
949
950 void updateInflorescence(FloralBud &fbud);
951
952 float calculatePhytomerConstructionCosts();
953 float calculateFlowerConstructionCosts(const FloralBud &fbud);
954
-
955 friend struct Shoot;
-
956 friend class PlantArchitecture;
+
955 friend struct Shoot;
+
956 friend class PlantArchitecture;
957
958};
959
-
960struct Shoot {
+
960struct Shoot {
961
-
962 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,
+
962 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,
963 float internode_length_shoot_initial, ShootParameters &shoot_params, std::string shoot_type_label, PlantArchitecture *plant_architecture_ptr);
964
965 void buildShootPhytomers(float internode_radius, float internode_length, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper);
-
966
-
968
+
966
+
968
975 int appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const PhytomerParameters &phytomer_parameters);
-
976
-
978
+
976
+
978
981 std::string sampleChildShootType() const;
-
982
-
984
+
982
+
984
988 bool sampleVegetativeBudBreak( uint node_index ) const;
-
989
-
991
+
989
+
991
996 uint sampleEpicormicShoot( float dt, std::vector<float> &epicormic_positions_fraction );
997
998 void terminateApicalBud();
@@ -1030,516 +1037,574 @@
1004 float calculateShootInternodeVolume() const;
1005
1006 float calculateShootLength() const;
-
1007
+
1007
1009 void updateShootNodes(bool update_context_geometry = true );
1010
1011 helios::vec3 getShootAxisVector( float shoot_fraction ) const;
1012
1013 float sumShootLeafArea( uint start_node_index = 0 ) const;
1014
-
1015 void propagateDownstreamLeafArea(Shoot* shoot, uint node_index, float leaf_area);
+
1015 float sumChildVolume( uint start_node_index = 0) const;
1016
-
1017 uint current_node_number = 0;
-
1018 uint nodes_this_season = 0;
-
1019
-
1020 helios::vec3 base_position;
-
1021 AxisRotation base_rotation;
-
1022 helios::vec3 radial_outward_axis;
-
1023
-
1024 const int ID;
-
1025 const int parent_shoot_ID;
-
1026 const uint plantID;
-
1027 const uint parent_node_index;
-
1028 const uint rank;
-
1029 const uint parent_petiole_index;
-
1030
-
1031 float carbohydrate_pool_molC = 0.01; // mol C
-
1032 float old_shoot_volume = 0;
-
1033
-
1034 uint days_with_negative_carbon_balance = 0;
+
1017 void propagateDownstreamLeafArea(Shoot* shoot, uint node_index, float leaf_area);
+
1018
+
1019 uint current_node_number = 0;
+
1020 uint nodes_this_season = 0;
+
1021
+
1022 helios::vec3 base_position;
+
1023 AxisRotation base_rotation;
+
1024 helios::vec3 radial_outward_axis;
+
1025
+
1026 const int ID;
+
1027 const int parent_shoot_ID;
+
1028 const uint plantID;
+
1029 const uint parent_node_index;
+
1030 const uint rank;
+
1031 const uint parent_petiole_index;
+
1032
+
1033 float carbohydrate_pool_molC = 0; // mol C
+
1034 float old_shoot_volume;
1035
-
1036 void breakDormancy();
-
1037 void makeDormant();
+
1036 float phyllochron_increase = 2;
+
1037 float phyllochron_recovery = phyllochron_increase * 1.5;
1038
-
1039 bool isdormant;
-
1040 uint dormancy_cycles = 0;
+
1039 float elongation_decay = 0.5;
+
1040 float elongation_recovery = elongation_decay /1.5 ;
1041
-
1042 bool meristem_is_alive = true;
+
1042 uint days_with_negative_carbon_balance = 0;
1043
-
1044 float phyllochron_counter = 0;
-
1045
-
1046 float curvature_perturbation = 0;
-
1047 float yaw_perturbation = 0;
-
1048
-
1049 float gravitropic_curvature = 0;
-
1050
-
1051 const float internode_length_max_shoot_initial;
-
1052
-
1053 uint internode_tube_objID = 4294967294;
-
1054
-
1055 std::vector<std::vector<helios::vec3>> shoot_internode_vertices; //first index is phytomer within shoot, second index is segment within phytomer internode tube
-
1056 std::vector<std::vector<float>> shoot_internode_radii; //first index is phytomer within shoot, second index is segment within phytomer internode tube
-
1057
-
1058 bool build_context_geometry_internode = true;
-
1059
-
1060 //map of node number (key) to IDs of shoot children (value)
-
1061 std::map<int,std::vector<int> > childIDs;
+
1044 void breakDormancy();
+
1045 void makeDormant();
+
1046
+
1047 bool isdormant;
+
1048 uint dormancy_cycles = 0;
+
1049
+
1050 bool meristem_is_alive = true;
+
1051
+
1052 float phyllochron_counter = 0;
+
1053 float phyllochron_min = 6;
+
1054 float elongation_max = .25;
+
1055
+
1056 float curvature_perturbation = 0;
+
1057 float yaw_perturbation = 0;
+
1058
+
1059 float gravitropic_curvature = 0;
+
1060
+
1061 const float internode_length_max_shoot_initial;
1062
-
1063 ShootParameters shoot_parameters;
+
1063 uint internode_tube_objID = 4294967294;
1064
-
1065 std::string shoot_type_label;
-
1066
-
1067 std::vector<std::shared_ptr<Phytomer> > phytomers;
-
1068
-
1069 PlantArchitecture* plantarchitecture_ptr;
-
1070
-
1071 helios::Context *context_ptr;
+
1065 std::vector<std::vector<helios::vec3>> shoot_internode_vertices; //first index is phytomer within shoot, second index is segment within phytomer internode tube
+
1066 std::vector<std::vector<float>> shoot_internode_radii; //first index is phytomer within shoot, second index is segment within phytomer internode tube
+
1067
+
1068 bool build_context_geometry_internode = true;
+
1069
+
1070 //map of node number (key) to IDs of shoot children (value)
+
1071 std::map<int,std::vector<int> > childIDs;
1072
-
1073};
-
+
1073 ShootParameters shoot_parameters;
1074
-
- +
1075 std::string shoot_type_label;
1076
-
1077 PlantInstance(const helios::vec3 &a_base_position, float a_current_age, helios::Context *a_context_ptr) : base_position(a_base_position), current_age(a_current_age), context_ptr(a_context_ptr) {}
-
1078 std::vector<std::shared_ptr<Shoot> > shoot_tree;
-
1079 helios::vec3 base_position;
-
1080 float current_age;
-
1081 float time_since_dormancy = 0;
-
1082 helios::Context *context_ptr;
-
1083 std::pair<std::string,float> epicormic_shoot_probability_perlength_per_day; //.first is the epicormic shoot label string, .second is the probability
-
1084
-
1085 //Phenological thresholds
-
1086 float dd_to_dormancy_break = 0;
-
1087 float dd_to_flower_initiation = 0;
-
1088 float dd_to_flower_opening = 0;
-
1089 float dd_to_fruit_set = 0;
-
1090 float dd_to_fruit_maturity = 0;
-
1091 float dd_to_dormancy = 0;
-
1092 float max_leaf_lifespan = 1e6;
-
1093 bool is_evergreen = false;
-
1094
-
1095 float max_age = 999;
-
1096
-
1097};
+
1077 float phyllochron_instantaneous;
+
1078 float elongation_rate_instantaneous;
+
1079
+
1080 std::vector<std::shared_ptr<Phytomer> > phytomers;
+
1081
+
1082 PlantArchitecture* plantarchitecture_ptr;
+
1083
+
1084 helios::Context *context_ptr;
+
1085
+
1086};
+
1087
+
+
1088struct PlantInstance{
+
1089
+
1090 PlantInstance(const helios::vec3 &a_base_position, float a_current_age, const std::string &a_plant_name, helios::Context *a_context_ptr) : base_position(a_base_position), current_age(a_current_age), plant_name(a_plant_name), context_ptr(a_context_ptr) {}
+
1091 std::vector<std::shared_ptr<Shoot> > shoot_tree;
+
1092 helios::vec3 base_position;
+
1093 float current_age;
+
1094 float time_since_dormancy = 0;
+
1095 helios::Context *context_ptr;
+
1096 std::string plant_name;
+
1097 std::pair<std::string,float> epicormic_shoot_probability_perlength_per_day; //.first is the epicormic shoot label string, .second is the probability
1098
-
- -
1100public:
-
1101
-
1103
-
1106 explicit PlantArchitecture( helios::Context* context_ptr );
-
1107
-
1109 static int selfTest();
+
1099 //Phenological thresholds
+
1100 float dd_to_dormancy_break = 0;
+
1101 float dd_to_flower_initiation = 0;
+
1102 float dd_to_flower_opening = 0;
+
1103 float dd_to_fruit_set = 0;
+
1104 float dd_to_fruit_maturity = 0;
+
1105 float dd_to_dormancy = 0;
+
1106 float max_leaf_lifespan = 1e6;
+
1107 bool is_evergreen = false;
+
1108
+
1109 float max_age = 999;
1110
+
1111};
+
1112
-
1115 void optionalOutputObjectData( const std::string &object_data_label );
-
1116
-
1118
-
1121 void optionalOutputObjectData( const std::vector<std::string> &object_data_labels );
-
1122
-
1123 // ********* Methods for Building Plants from Existing Library ********* //
-
1124
-
1126
-
1129 void loadPlantModelFromLibrary( const std::string &plant_label );
-
1130
-
1132
-
1137 uint buildPlantInstanceFromLibrary( const helios::vec3 &base_position, float age );
-
1138
-
1140
-
1148 std::vector<uint> buildPlantCanopyFromLibrary(const helios::vec3 &canopy_center_position, const helios::vec2 &plant_spacing_xy, const helios::int2 &plant_count_xy, float age, float germination_rate = 1.f);
-
1149
-
1151
-
1155 ShootParameters getCurrentShootParameters( const std::string &shoot_type_label );
-
1156
-
1158
-
1161 std::map<std::string, ShootParameters> getCurrentShootParameters( );
-
1162
-
1164
-
1167 std::map<std::string, PhytomerParameters> getCurrentPhytomerParameters( );
-
1168
-
1170
-
1175 void updateCurrentShootParameters( const std::string &shoot_type_label, const ShootParameters &params );
-
1176
-
1178
-
1183 void updateCurrentShootParameters( const std::map<std::string, ShootParameters> &params );
-
1184
-
1185 // ********* Methods for Building Custom Plant Geometry from Scratch ********* //
-
1186
-
1188
-
1193 uint addPlantInstance(const helios::vec3 &base_position, float current_age);
-
1194
-
1196
-
1202 uint duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age);
-
1203
-
1205
-
1208 void deletePlantInstance(uint plantID);
-
1209
-
1211
-
1214 void deletePlantInstance( const std::vector<uint> &plantIDs );
-
1215
-
1217
-
1229 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_dormancy, float max_leaf_lifespan = 1e6, bool is_evergreen= false);
-
1230
-
1231 void disablePlantPhenology( uint plantID );
-
1232
-
1234
-
1237 void advanceTime( float time_step_days );
-
1238
-
1240
-
1244 void advanceTime( int time_step_years, float time_step_days );
-
1245
-
1247
-
1251 void advanceTime( uint plantID, float time_step_days );
+
+ +
1114public:
+
1115
+
1117
+
1120 explicit PlantArchitecture( helios::Context* context_ptr );
+
1121
+
1123 static int selfTest();
+
1124
+
1126
+
1129 void optionalOutputObjectData( const std::string &object_data_label );
+
1130
+
1132
+
1135 void optionalOutputObjectData( const std::vector<std::string> &object_data_labels );
+
1136
+
1137 // ********* Methods for Building Plants from Existing Library ********* //
+
1138
+
1140
+
1143 void loadPlantModelFromLibrary( const std::string &plant_label );
+
1144
+
1146
+
1151 uint buildPlantInstanceFromLibrary( const helios::vec3 &base_position, float age );
+
1152
+
1154
+
1162 std::vector<uint> buildPlantCanopyFromLibrary(const helios::vec3 &canopy_center_position, const helios::vec2 &plant_spacing_xy, const helios::int2 &plant_count_xy, float age, float germination_rate = 1.f);
+
1163
+
1165
+
1169 ShootParameters getCurrentShootParameters( const std::string &shoot_type_label );
+
1170
+
1172
+
1175 std::map<std::string, ShootParameters> getCurrentShootParameters( );
+
1176
+
1178
+
1181 std::map<std::string, PhytomerParameters> getCurrentPhytomerParameters( );
+
1182
+
1184
+
1189 void updateCurrentShootParameters( const std::string &shoot_type_label, const ShootParameters &params );
+
1190
+
1192
+
1197 void updateCurrentShootParameters( const std::map<std::string, ShootParameters> &params );
+
1198
+
1199 // ********* Methods for Building Custom Plant Geometry from Scratch ********* //
+
1200
+
1202
+
1207 uint addPlantInstance(const helios::vec3 &base_position, float current_age);
+
1208
+
1210
+
1216 uint duplicatePlantInstance(uint plantID, const helios::vec3 &base_position, const AxisRotation &base_rotation, float current_age);
+
1217
+
1219
+
1222 void deletePlantInstance(uint plantID);
+
1223
+
1225
+
1228 void deletePlantInstance( const std::vector<uint> &plantIDs );
+
1229
+
1231
+
1243 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_dormancy, float max_leaf_lifespan = 1e6, bool is_evergreen= false);
+
1244
+
1245 void disablePlantPhenology( uint plantID );
+
1246
+
1248
+
1251 void advanceTime(float time_step_days);
1252
-
1253 // -- plant building methods -- //
-
1254
-
1256
-
1260 void defineShootType( const std::string &shoot_type_label, const ShootParameters &shoot_params );
-
1261
-
1263
-
1275 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,
-
1276 float radius_taper, const std::string &shoot_type_label);
-
1277
-
1279
-
1292 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,
-
1293 float radius_taper, const std::string &shoot_type_label);
-
1294
-
1296
-
1311 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,
-
1312 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label, uint petiole_index = 0);
-
1313
-
1315
-
1329 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,
-
1330 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label);
-
1331
-
1333
-
1343 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);
-
1344
-
1346
-
1352 void enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday);
-
1353
- -
1356
- -
1359
- -
1362
-
1364
-
1367 void enableGroundClipping( float ground_height = 0.f );
-
1368
-
1369 // -- methods for modifying the current plant state -- //
-
1370
-
1371 void initializePlantCarbohydratePool(uint plantID, float carbohydrate_concentration_molC_m3 );
-
1372
-
1373 void initializeShootCarbohydratePool(uint plantID, uint shootID, float carbohydrate_concentration_molC_m3 );
-
1374
-
1375 void incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, bool update_context_geometry);
-
1376
-
1377 void setPhytomerLeafScale(uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction);
-
1378
-
1379// void setShootOrigin(uint plantID, uint shootID, const helios::vec3 &origin);
-
1380
-
1381 void setPlantBasePosition(uint plantID, const helios::vec3 &base_position);
-
1382
-
1383 void setPlantAge(uint plantID, float current_age);
+
1253 void accumulateHourlyLeafPhotosynthesis();
+
1254
+
1256
+
1260 void advanceTime(int time_step_years, float time_step_days);
+
1261
+
1263
+
1267 void advanceTime(uint plantID, float time_step_days);
+
1268
+
1269 // -- plant building methods -- //
+
1270
+
1272
+
1276 void defineShootType( const std::string &shoot_type_label, const ShootParameters &shoot_params );
+
1277
+
1279
+
1291 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,
+
1292 float radius_taper, const std::string &shoot_type_label);
+
1293
+
1295
+
1308 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,
+
1309 float radius_taper, const std::string &shoot_type_label);
+
1310
+
1312
+
1327 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,
+
1328 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label, uint petiole_index = 0);
+
1329
+
1331
+
1345 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,
+
1346 float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, float radius_taper, const std::string &shoot_type_label);
+
1347
+
1349
+
1359 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);
+
1360
+
1362
+
1368 void enableEpicormicChildShoots(uint plantID, const std::string &epicormic_shoot_type_label, float epicormic_probability_perlength_perday);
+
1369
+ +
1372
+ +
1375
+ +
1378
+
1380
+
1383 void enableGroundClipping( float ground_height = 0.f );
1384
-
1385 void harvestPlant(uint plantID);
+
1385 // -- methods for modifying the current plant state -- //
1386
-
1387 void removeShootLeaves(uint plantID, uint shootID);
+
1387 void initializeCarbohydratePool(float carbohydrate_concentration_molC_m3);
1388
-
1389 void removePlantLeaves(uint plantID );
+
1389 void initializePlantCarbohydratePool(uint plantID, float carbohydrate_concentration_molC_m3 );
1390
-
1391 void makePlantDormant( uint plantID );
+
1391 void initializeShootCarbohydratePool(uint plantID, uint shootID, float carbohydrate_concentration_molC_m3 );
1392
-
1393 void breakPlantDormancy( uint plantID );
+
1393 void incrementPhytomerInternodeGirth(uint plantID, uint shootID, uint node_number, bool update_context_geometry);
1394
-
1395 // -- methods for querying information about the plant -- //
+
1395 void setPhytomerLeafScale(uint plantID, uint shootID, uint node_number, float leaf_scale_factor_fraction);
1396
-
1397 float getPlantAge(uint plantID) const;
+
1397// void setShootOrigin(uint plantID, uint shootID, const helios::vec3 &origin);
1398
-
1399 uint getShootNodeCount( uint plantID, uint shootID ) const;
+
1399 void setPlantBasePosition(uint plantID, const helios::vec3 &base_position);
1400
-
1401 float getShootTaper( uint plantID, uint shootID ) const;
+
1401 void setPlantAge(uint plantID, float current_age);
1402
-
1403 helios::vec3 getPlantBasePosition(uint plantID) const;
+
1403 void harvestPlant(uint plantID);
1404
+
1405 void removeShootLeaves(uint plantID, uint shootID);
1406
-
1410 float sumPlantLeafArea(uint plantID) const;
-
1411
-
1413
-
1417 std::vector<uint> getAllPlantObjectIDs(uint plantID) const;
+
1407 void removePlantLeaves(uint plantID );
+
1408
+
1409 void makePlantDormant( uint plantID );
+
1410
+
1411 void breakPlantDormancy( uint plantID );
+
1412
+
1413 void pruneBranch(uint plantID, uint shootID, uint node_index);
+
1414
+
1415 // -- methods for querying information about the plant -- //
+
1416
+
1417 std::string getPlantName(uint plantID) const;
1418
+
1419 float getPlantAge(uint plantID) const;
1420
-
1424 std::vector<uint> getAllPlantUUIDs(uint plantID) const;
-
1425
-
1427
-
1431 std::vector<uint> getPlantInternodeObjectIDs(uint plantID) const;
-
1432
-
1434
-
1438 std::vector<uint> getPlantPetioleObjectIDs(uint plantID) const;
-
1439
-
1441
-
1445 std::vector<uint> getPlantLeafObjectIDs(uint plantID) const;
-
1446
-
1448
-
1452 std::vector<uint> getPlantPeduncleObjectIDs(uint plantID) const;
-
1453
-
1455
-
1459 std::vector<uint> getPlantFlowerObjectIDs(uint plantID) const;
-
1460
-
1462
-
1466 std::vector<uint> getPlantFruitObjectIDs(uint plantID) const;
-
1467
-
1469
-
1472 std::vector<uint> getAllUUIDs() const;
-
1473
-
1475
-
1478 std::vector<uint> getAllLeafUUIDs() const;
-
1479
-
1481
-
1484 std::vector<uint> getAllInternodeUUIDs() const;
-
1485
-
1487
-
1490 std::vector<uint> getAllPetioleUUIDs() const;
-
1491
-
1493
-
1496 std::vector<uint> getAllPeduncleUUIDs() const;
-
1497
-
1499
-
1502 std::vector<uint> getAllFlowerUUIDs() const;
-
1503
-
1505
-
1508 std::vector<uint> getAllFruitUUIDs() const;
-
1509
-
1511
-
1514 std::vector<uint> getAllObjectIDs() const;
-
1515
-
1516 // -- manual plant generation from input string -- //
-
1517
-
1518 std::string getPlantString(uint plantID) const;
-
1519
-
1520 uint generatePlantFromString(const std::string &generation_string, const PhytomerParameters &phytomer_parameters);
-
1521
-
1522 uint generatePlantFromString(const std::string &generation_string, const std::map<std::string,PhytomerParameters> &phytomer_parameters);
-
1523
-
1524 void writePlantStructureXML(uint plantID, const std::string &filename) const;
-
1525
-
1526 std::vector<uint> readPlantStructureXML( const std::string &filename, bool quiet = false);
-
1527
-
1528 friend struct Phytomer;
-
1529 friend struct Shoot;
-
1530
-
1531protected:
-
1532
-
1533 helios::Context* context_ptr;
-
1534
-
1535 std::minstd_rand0 *generator = nullptr;
-
1536
-
1537 uint plant_count = 0;
-
1538
-
1539 std::string current_plant_model;
-
1540
-
1541 std::map<uint,PlantInstance> plant_instances;
-
1542
-
1543 [[nodiscard]] std::string makeShootString(const std::string &current_string, const std::shared_ptr<Shoot> &shoot, const std::vector<std::shared_ptr<Shoot>> & shoot_tree) const;
-
1544
-
1545 std::map<std::string,ShootParameters> shoot_types;
-
1546
-
1547 // Key is the prototype function pointer; value first index is the unique leaf prototype, second index is the leaflet along a compound leaf (if applicable)
-
1548 // std::map<uint(*)(helios::Context* context_ptr, LeafPrototype* prototype_parameters, int compound_leaf_index),std::vector<std::vector<uint>> > unique_leaf_prototype_objIDs;
-
1549 std::map<uint,std::vector<std::vector<uint>> > unique_leaf_prototype_objIDs;
-
1550
-
1551 // Key is the prototype function pointer; value index is the unique flower prototype
-
1552 std::map<uint(*)(helios::Context* context_ptr, uint subdivisions, bool flower_is_open),std::vector<uint> > unique_open_flower_prototype_objIDs;
-
1553 // Key is the prototype function pointer; value index is the unique flower prototype
-
1554 std::map<uint(*)(helios::Context* context_ptr, uint subdivisions, bool flower_is_open),std::vector<uint> > unique_closed_flower_prototype_objIDs;
-
1555 // Key is the prototype function pointer; value index is the unique fruit prototype
-
1556 std::map<uint(*)(helios::Context* context_ptr, uint subdivisions),std::vector<uint> > unique_fruit_prototype_objIDs;
-
1557
-
1558 bool build_context_geometry_internode = true;
-
1559 bool build_context_geometry_petiole = true;
-
1560 bool build_context_geometry_peduncle = true;
-
1561
-
1562 float ground_clipping_height = -99999;
-
1563
-
1564 void validateShootTypes( ShootParameters &shoot_parameters ) const;
-
1565
-
1566 void parseStringShoot(const std::string &LString_shoot, uint plantID, int parentID, uint parent_node, const std::map<std::string, PhytomerParameters> &phytomer_parameters, ShootParameters &shoot_parameters);
-
1567
-
1568 void parseShootArgument(const std::string &shoot_argument, const std::map<std::string, PhytomerParameters> &phytomer_parameters, ShootParameters &shoot_parameters, AxisRotation &base_rotation, std::string &phytomer_label);
-
1569
-
1570 void parseInternodeArgument(const std::string &internode_argument, float &internode_radius, float &internode_length, PhytomerParameters &phytomer_parameters);
-
1571
-
1572 void parsePetioleArgument(const std::string& petiole_argument, PhytomerParameters &phytomer_parameters );
-
1573
-
1574 void parseLeafArgument(const std::string& leaf_argument, PhytomerParameters &phytomer_parameters );
-
1575
-
1576// void shiftDownstreamShoots(uint plantID, std::vector<std::shared_ptr<Shoot>> &shoot_tree, std::shared_ptr<Shoot> parent_shoot_ptr, const helios::vec3 &base_position );
-
1577
-
1578 void initializeDefaultShoots( const std::string &plant_label );
+
1421 uint getShootNodeCount( uint plantID, uint shootID ) const;
+
1422
+
1423 float getShootTaper( uint plantID, uint shootID ) const;
+
1424
+
1425 helios::vec3 getPlantBasePosition(uint plantID) const;
+
1426
+
1428
+
1432 float sumPlantLeafArea(uint plantID) const;
+
1433
+
1435
+
1439 float getPlantStemHeight(uint plantID) const;
+
1440
+
1442
+
1446 float getPlantHeight(uint plantID) const;
+
1447
+
1449
+
1454 std::vector<float> getPlantLeafInclinationAngleDistribution(uint plantID, uint Nbins) const;
+
1455
+
1457
+
1461 uint getPlantLeafCount(uint plantID) const;
+
1462
+
1464
+
1468 void writePlantMeshVertices(uint plantID, const std::string &filename) const;
+
1469
+
1471
+
1474 std::vector<uint> getAllPlantIDs() const;
+
1475
+
1477
+
1481 std::vector<uint> getAllPlantObjectIDs(uint plantID) const;
+
1482
+
1484
+
1488 std::vector<uint> getAllPlantUUIDs(uint plantID) const;
+
1489
+
1491
+
1495 std::vector<uint> getPlantInternodeObjectIDs(uint plantID) const;
+
1496
+
1498
+
1502 std::vector<uint> getPlantPetioleObjectIDs(uint plantID) const;
+
1503
+
1505
+
1509 std::vector<uint> getPlantLeafObjectIDs(uint plantID) const;
+
1510
+
1512
+
1516 std::vector<uint> getPlantPeduncleObjectIDs(uint plantID) const;
+
1517
+
1519
+
1523 std::vector<uint> getPlantFlowerObjectIDs(uint plantID) const;
+
1524
+
1526
+
1530 std::vector<uint> getPlantFruitObjectIDs(uint plantID) const;
+
1531
+
1533
+
1536 std::vector<uint> getAllUUIDs() const;
+
1537
+
1539
+
1542 std::vector<uint> getAllLeafUUIDs() const;
+
1543
+
1545
+
1548 std::vector<uint> getAllInternodeUUIDs() const;
+
1549
+
1551
+
1554 std::vector<uint> getAllPetioleUUIDs() const;
+
1555
+
1557
+
1560 std::vector<uint> getAllPeduncleUUIDs() const;
+
1561
+
1563
+
1566 std::vector<uint> getAllFlowerUUIDs() const;
+
1567
+
1569
+
1572 std::vector<uint> getAllFruitUUIDs() const;
+
1573
+
1575
+
1578 std::vector<uint> getAllObjectIDs() const;
1579
-
1580 bool detectGroundCollision(uint objID);
+
1580 // -- carbohydrate model -- //
1581
-
1582 bool detectGroundCollision(const std::vector<uint> &objID);
+
1582 void enableCarbohydrateModel();
1583
-
1585 std::map<std::string,bool> output_object_data;
-
1586
-
1587 // --- Carbohydrate Model --- //
-
1588
-
1589 void accumulateShootPhotosynthesis();
-
1590
-
1591 void accumulateHourlyLeafPhotosynthesis();
-
1592
-
1593 void subtractShootMaintenanceCarbon(float dt );
-
1594 void subtractShootGrowthCarbon();
+
1584 void disableCarbohydrateModel();
+
1585
+
1586 // -- manual plant generation from input string -- //
+
1587
+
1588 std::string getPlantString(uint plantID) const;
+
1589
+
1590 uint generatePlantFromString(const std::string &generation_string, const PhytomerParameters &phytomer_parameters);
+
1591
+
1592 uint generatePlantFromString(const std::string &generation_string, const std::map<std::string,PhytomerParameters> &phytomer_parameters);
+
1593
+
1594 void writePlantStructureXML(uint plantID, const std::string &filename) const;
1595
-
1596 void checkCarbonPool_abortbuds();
+
1596 std::vector<uint> readPlantStructureXML( const std::string &filename, bool quiet = false);
1597
-
1598 // --- Plant Library --- //
-
1599
-
1600 void initializeAlmondTreeShoots();
-
1601
-
1602 uint buildAlmondTree( const helios::vec3 &base_position );
-
1603
-
1604 void initializeAppleTreeShoots();
-
1605
-
1606 uint buildAppleTree( const helios::vec3 &base_position );
-
1607
-
1608 void initializeAsparagusShoots();
-
1609
-
1610 uint buildAsparagusPlant( const helios::vec3 &base_position );
-
1611
-
1612 void initializeBindweedShoots();
-
1613
-
1614 uint buildBindweedPlant( const helios::vec3 &base_position );
-
1615
-
1616 void initializeBeanShoots();
-
1617
-
1618 uint buildBeanPlant( const helios::vec3 &base_position );
-
1619
-
1620 void initializeCheeseweedShoots();
-
1621
-
1622 uint buildCheeseweedPlant( const helios::vec3 &base_position );
-
1623
-
1624 void initializeCowpeaShoots();
-
1625
-
1626 uint buildCowpeaPlant( const helios::vec3 &base_position );
+
1598 friend struct Phytomer;
+
1599 friend struct Shoot;
+
1600
+
1601protected:
+
1602
+
1603 helios::Context* context_ptr;
+
1604
+
1605 std::minstd_rand0 *generator = nullptr;
+
1606
+
1607 uint plant_count = 0;
+
1608
+
1609 std::string current_plant_model;
+
1610
+
1611 std::map<uint,PlantInstance> plant_instances;
+
1612
+
1613 [[nodiscard]] std::string makeShootString(const std::string &current_string, const std::shared_ptr<Shoot> &shoot, const std::vector<std::shared_ptr<Shoot>> & shoot_tree) const;
+
1614
+
1615 std::map<std::string,ShootParameters> shoot_types;
+
1616
+
1617 // Key is the prototype function pointer; value first index is the unique leaf prototype, second index is the leaflet along a compound leaf (if applicable)
+
1618 // std::map<uint(*)(helios::Context* context_ptr, LeafPrototype* prototype_parameters, int compound_leaf_index),std::vector<std::vector<uint>> > unique_leaf_prototype_objIDs;
+
1619 std::map<uint,std::vector<std::vector<uint>> > unique_leaf_prototype_objIDs;
+
1620
+
1621 // Key is the prototype function pointer; value index is the unique flower prototype
+
1622 std::map<uint(*)(helios::Context* context_ptr, uint subdivisions, bool flower_is_open),std::vector<uint> > unique_open_flower_prototype_objIDs;
+
1623 // Key is the prototype function pointer; value index is the unique flower prototype
+
1624 std::map<uint(*)(helios::Context* context_ptr, uint subdivisions, bool flower_is_open),std::vector<uint> > unique_closed_flower_prototype_objIDs;
+
1625 // Key is the prototype function pointer; value index is the unique fruit prototype
+
1626 std::map<uint(*)(helios::Context* context_ptr, uint subdivisions),std::vector<uint> > unique_fruit_prototype_objIDs;
1627
-
1628 void initializeGrapevineVSPShoots();
-
1629
-
1630 uint buildGrapevineVSP( const helios::vec3 &base_position );
+
1628 bool build_context_geometry_internode = true;
+
1629 bool build_context_geometry_petiole = true;
+
1630 bool build_context_geometry_peduncle = true;
1631
-
1632 void initializeMaizeShoots();
+
1632 float ground_clipping_height = -99999;
1633
-
1634 uint buildMaizePlant( const helios::vec3 &base_position );
+
1634 void validateShootTypes( ShootParameters &shoot_parameters ) const;
1635
-
1636 void initializeOliveTreeShoots();
+
1636 void parseStringShoot(const std::string &LString_shoot, uint plantID, int parentID, uint parent_node, const std::map<std::string, PhytomerParameters> &phytomer_parameters, ShootParameters &shoot_parameters);
1637
-
1638 uint buildOliveTree( const helios::vec3 &base_position );
+
1638 void parseShootArgument(const std::string &shoot_argument, const std::map<std::string, PhytomerParameters> &phytomer_parameters, ShootParameters &shoot_parameters, AxisRotation &base_rotation, std::string &phytomer_label);
1639
-
1640 void initializePistachioTreeShoots();
+
1640 void parseInternodeArgument(const std::string &internode_argument, float &internode_radius, float &internode_length, PhytomerParameters &phytomer_parameters);
1641
-
1642 uint buildPistachioTree( const helios::vec3 &base_position );
+
1642 void parsePetioleArgument(const std::string& petiole_argument, PhytomerParameters &phytomer_parameters );
1643
-
1644 void initializePuncturevineShoots();
+
1644 void parseLeafArgument(const std::string& leaf_argument, PhytomerParameters &phytomer_parameters );
1645
-
1646 uint buildPuncturevinePlant( const helios::vec3 &base_position );
+
1646// void shiftDownstreamShoots(uint plantID, std::vector<std::shared_ptr<Shoot>> &shoot_tree, std::shared_ptr<Shoot> parent_shoot_ptr, const helios::vec3 &base_position );
1647
-
1648 void initializeEasternRedbudShoots();
+
1648 void initializeDefaultShoots( const std::string &plant_label );
1649
-
1650 uint buildEasternRedbudPlant( const helios::vec3 &base_position );
+
1650 bool detectGroundCollision(uint objID);
1651
-
1652 void initializeRiceShoots();
-
1653
-
1654 uint buildRicePlant( const helios::vec3 &base_position );
-
1655
-
1656 void initializeButterLettuceShoots();
-
1657
-
1658 uint buildButterLettucePlant(const helios::vec3 &base_position );
-
1659
-
1660 void initializeSoybeanShoots();
-
1661
-
1662 uint buildSoybeanPlant( const helios::vec3 &base_position );
+
1652 bool detectGroundCollision(const std::vector<uint> &objID);
+
1653
+
1655 std::map<std::string,bool> output_object_data;
+
1656
+
1657 // --- Carbohydrate Model --- //
+
1658
+
1659 void accumulateShootPhotosynthesis();
+
1660
+
1661 void subtractShootMaintenanceCarbon(float dt );
+
1662 void subtractShootGrowthCarbon();
1663
-
1664 void initializeSorghumShoots();
-
1665
-
1666 uint buildSorghumPlant( const helios::vec3 &base_position );
+
1664 void checkCarbonPool_abortBuds();
+
1665 void checkCarbonPool_adjustPhyllochron();
+
1666 void checkCarbonPool_transferCarbon();
1667
-
1668 void initializeStrawberryShoots();
+
1668 bool carbon_model_enabled = false;
1669
-
1670 uint buildStrawberryPlant( const helios::vec3 &base_position );
+
1670 // --- Plant Library --- //
1671
-
1672 void initializeSugarbeetShoots();
+
1672 void initializeAlmondTreeShoots();
1673
-
1674 uint buildSugarbeetPlant( const helios::vec3 &base_position );
+
1674 uint buildAlmondTree( const helios::vec3 &base_position );
1675
-
1676 void initializeTomatoShoots();
+
1676 void initializeAppleTreeShoots();
1677
-
1678 uint buildTomatoPlant( const helios::vec3 &base_position );
+
1678 uint buildAppleTree( const helios::vec3 &base_position );
1679
-
1680 void initializeWalnutTreeShoots();
+
1680 void initializeAsparagusShoots();
1681
-
1682 uint buildWalnutTree( const helios::vec3 &base_position );
+
1682 uint buildAsparagusPlant( const helios::vec3 &base_position );
1683
-
1684 void initializeWheatShoots();
+
1684 void initializeBindweedShoots();
1685
-
1686 uint buildWheatPlant( const helios::vec3 &base_position );
+
1686 uint buildBindweedPlant( const helios::vec3 &base_position );
1687
-
1688
-
1689};
+
1688 void initializeBeanShoots();
+
1689
+
1690 uint buildBeanPlant( const helios::vec3 &base_position );
+
1691
+
1692 void initializeCheeseweedShoots();
+
1693
+
1694 uint buildCheeseweedPlant( const helios::vec3 &base_position );
+
1695
+
1696 void initializeCowpeaShoots();
+
1697
+
1698 uint buildCowpeaPlant( const helios::vec3 &base_position );
+
1699
+
1700 void initializeGrapevineVSPShoots();
+
1701
+
1702 uint buildGrapevineVSP( const helios::vec3 &base_position );
+
1703
+
1704 void initializeGroundCherryWeedShoots();
+
1705
+
1706 uint buildGroundCherryWeedPlant( const helios::vec3 &base_position );
+
1707
+
1708 void initializeMaizeShoots();
+
1709
+
1710 uint buildMaizePlant( const helios::vec3 &base_position );
+
1711
+
1712 void initializeOliveTreeShoots();
+
1713
+
1714 uint buildOliveTree( const helios::vec3 &base_position );
+
1715
+
1716 void initializePistachioTreeShoots();
+
1717
+
1718 uint buildPistachioTree( const helios::vec3 &base_position );
+
1719
+
1720 void initializePuncturevineShoots();
+
1721
+
1722 uint buildPuncturevinePlant( const helios::vec3 &base_position );
+
1723
+
1724 void initializeEasternRedbudShoots();
+
1725
+
1726 uint buildEasternRedbudPlant( const helios::vec3 &base_position );
+
1727
+
1728 void initializeRiceShoots();
+
1729
+
1730 uint buildRicePlant( const helios::vec3 &base_position );
+
1731
+
1732 void initializeButterLettuceShoots();
+
1733
+
1734 uint buildButterLettucePlant(const helios::vec3 &base_position );
+
1735
+
1736 void initializeSoybeanShoots();
+
1737
+
1738 uint buildSoybeanPlant( const helios::vec3 &base_position );
+
1739
+
1740 void initializeSorghumShoots();
+
1741
+
1742 uint buildSorghumPlant( const helios::vec3 &base_position );
+
1743
+
1744 void initializeStrawberryShoots();
+
1745
+
1746 uint buildStrawberryPlant( const helios::vec3 &base_position );
+
1747
+
1748 void initializeSugarbeetShoots();
+
1749
+
1750 uint buildSugarbeetPlant( const helios::vec3 &base_position );
+
1751
+
1752 void initializeTomatoShoots();
+
1753
+
1754 uint buildTomatoPlant( const helios::vec3 &base_position );
+
1755
+
1756 void initializeWalnutTreeShoots();
+
1757
+
1758 uint buildWalnutTree( const helios::vec3 &base_position );
+
1759
+
1760 void initializeWheatShoots();
+
1761
+
1762 uint buildWheatPlant( const helios::vec3 &base_position );
+
1763
+
1764
+
1765};
-
1690
-
1691#include "Assets.h"
-
1692
-
1693#endif //PLANT_ARCHITECTURE
+
1766
+
1767#include "Assets.h"
+
1768
+
1769#endif //PLANT_ARCHITECTURE
std::vector< uint > makeTubeFromCones(uint radial_subdivisions, const std::vector< helios::vec3 > &vertices, const std::vector< float > &radii, const std::vector< helios::RGBcolor > &colors, helios::Context *context_ptr)
Add geometry to the Context consisting of a series of Cone objects to form a tube-like shape.
- -
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_dormancy, float max_leaf_lifespan=1e6, bool is_evergreen=false)
Specify the threshold values for plant phenological stages.
-
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
-
std::vector< uint > getAllFlowerUUIDs() const
Get UUIDs for all existing flower primitives.
-
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.
-
void advanceTime(float time_step_days)
Advance plant growth by a specified time interval for all plants.
-
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.
-
std::vector< uint > getPlantInternodeObjectIDs(uint plantID) const
Get object IDs for all internode (Tube) objects for a given plant.
-
std::vector< uint > getAllLeafUUIDs() const
Get UUIDs for all existing leaf primitives.
+ +
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_dormancy, float max_leaf_lifespan=1e6, bool is_evergreen=false)
Specify the threshold values for plant phenological stages.
+
uint addPlantInstance(const helios::vec3 &base_position, float current_age)
Create an instance of a plant.
+
std::vector< uint > getAllFlowerUUIDs() const
Get UUIDs for all existing flower primitives.
+
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.
+
void writePlantMeshVertices(uint plantID, const std::string &filename) const
Write all vertices in the plant to a file for external processing (e.g., bounding volume,...
+
std::map< std::string, ShootParameters > getCurrentShootParameters()
Get the shoot parameters structure for all shoot types in the current plant model.
+
std::vector< uint > getPlantFlowerObjectIDs(uint plantID) const
Get object IDs for all inflorescence objects for a given plant.
+
void advanceTime(float time_step_days)
Advance plant growth by a specified time interval for all plants.
+
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.
+
float getPlantHeight(uint plantID) const
Calculate the height of the highest element in the plant.
+
std::vector< float > getPlantLeafInclinationAngleDistribution(uint plantID, uint Nbins) const
Calculate the leaf angle distribution of all leaves in the plant.
+
std::vector< uint > getPlantInternodeObjectIDs(uint plantID) const
Get object IDs for all internode (Tube) objects for a given plant.
+
std::vector< uint > getAllLeafUUIDs() const
Get UUIDs for all existing leaf primitives.
static int selfTest()
Unit test routines.
Definition selfTest.cpp:21
-
std::vector< uint > getAllInternodeUUIDs() const
Get UUIDs for all existing internode primitives.
-
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)
-
std::vector< uint > getAllObjectIDs() const
Get object IDs for all existing plant compound objects.
+
std::vector< uint > getAllInternodeUUIDs() const
Get UUIDs for all existing internode primitives.
+
void disablePeduncleContextBuild()
Do not build peduncle primitive geometry in the Context.
+
std::vector< uint > getAllPlantIDs() const
Get IDs for all plant instances.
+
uint getPlantLeafCount(uint plantID) const
Get the total number of leaves on the plant.
+
float getPlantStemHeight(uint plantID) const
Calculate the height of the last internode on the base stem/shoot.
+
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)
+
std::vector< uint > getAllObjectIDs() const
Get object IDs for all existing plant compound objects.
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 > buildPlantCanopyFromLibrary(const helios::vec3 &canopy_center_position, const helios::vec2 &plant_spacing_xy, const helios::int2 &plant_count_xy, float age, float germination_rate=1.f)
Build a canopy of regularly spaced plants based on the model currently loaded from the library.
-
std::vector< uint > getAllFruitUUIDs() const
Get UUIDs for all existing fruit primitives.
-
std::map< std::string, PhytomerParameters > getCurrentPhytomerParameters()
Get the phytomer parameters structure for all shoot types in the current plant model.
-
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 > getAllFruitUUIDs() const
Get UUIDs for all existing fruit primitives.
+
std::map< std::string, PhytomerParameters > getCurrentPhytomerParameters()
Get the phytomer parameters structure for all shoot types in the current plant model.
+
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.
-
std::vector< uint > getAllPeduncleUUIDs() const
Get UUIDs for all existing peduncle primitives.
+
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.
+
std::vector< uint > getAllPeduncleUUIDs() const
Get UUIDs for all existing peduncle primitives.
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.
-
std::vector< uint > getPlantLeafObjectIDs(uint plantID) const
Get object IDs for all leaf objects for a given plant.
-
std::vector< uint > getAllPetioleUUIDs() const
Get UUIDs for all existing petiole primitives.
-
std::vector< uint > getAllUUIDs() const
Get UUIDs for all existing plant primitives.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
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.
+
std::vector< uint > getPlantLeafObjectIDs(uint plantID) const
Get object IDs for all leaf objects for a given plant.
+
std::vector< uint > getAllPetioleUUIDs() const
Get UUIDs for all existing petiole primitives.
+
std::vector< uint > getAllUUIDs() const
Get UUIDs for all existing plant primitives.
+
Stores the state associated with simulation.
Definition Context.h:1888
float mean(const std::vector< float > &vect)
Mean value of a vector of floats.
Definition global.cpp:1084
@@ -1561,45 +1626,48 @@
RandomParameter_float wave_amplitude
Amplitude of leaf waves (sets the height of leaf waves)
std::string OBJ_model_file
OBJ model file to load for the leaf.
RandomParameter_float longitudinal_curvature
Leaf curvature factor along the longitudinal/length (x-direction). (+curves upward,...
- -
void setInternodeMaxLength(float internode_length_max_new)
Set the fully-elongated (maximum) internode length.
+
LeafPrototype(std::minstd_rand0 *generator)
Constructor - sets random number generator.
+ +
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 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)
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)
-
RandomParameter_float()
Constructor initializing to a constant default value of 0.
RandomParameter_float(std::minstd_rand0 *rand_generator)
Constructor initializing the random number generator.
RandomParameter_float(float val)
Constructor initializing to a constant value.
-
void updateShootNodes(bool update_context_geometry=true)
Recalculate and apply the shoot's origin position and shift all downstream shoots.
-
int appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const PhytomerParameters &phytomer_parameters)
Append a phytomer at the shoot apex.
-
bool sampleVegetativeBudBreak(uint node_index) const
Randomly sample whether a vegetative bud should break into a new shoot.
-
std::string sampleChildShootType() const
Randomly sample the type of a child shoot based on the probabilities defined in the shoot parameters.
-
uint sampleEpicormicShoot(float dt, std::vector< float > &epicormic_positions_fraction)
Randomly sample whether the shoot should produce an epicormic shoot (water sprout) over timestep.
+
void updateShootNodes(bool update_context_geometry=true)
Recalculate and apply the shoot's origin position and shift all downstream shoots.
+
int appendPhytomer(float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, const PhytomerParameters &phytomer_parameters)
Append a phytomer at the shoot apex.
+
bool sampleVegetativeBudBreak(uint node_index) const
Randomly sample whether a vegetative bud should break into a new shoot.
+
std::string sampleChildShootType() const
Randomly sample the type of a child shoot based on the probabilities defined in the shoot parameters.
+
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.
RandomParameter_float vegetative_bud_break_probability_decay_rate
R-G-B color vector.
-
Vector of two elements of type 'int'.
-
Vector of three elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_plant_architecture_doc.html b/doc/html/_plant_architecture_doc.html index 63cd5d3cd..c254ce70f 100644 --- a/doc/html/_plant_architecture_doc.html +++ b/doc/html/_plant_architecture_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Plant Architecture Model Plugin Documentation
@@ -300,7 +306,7 @@

PlantArchitecture plantarchitecture(&context);
plantarchitecture.optionalOutputData("plantID"); //insert appropriate label from the table above
- +

Plug-in Overview

This plug-in provides a generalized framework for creating dynamic procedural plant models for a very wide range of species. The plug-in comes with a library of a number of different plant models, which have a common set of parameters that can be adjusted by the user. Parameters defining the plant can be set to constant values, or randomized based on a number of different distributions. The plant model can be grown over time, and will transition through different phenological stages such as dormancy, flowering, fruit set, and senescence. Users can also create their own plant models by changing model parameters, or build custom plants branch-by-branch.

@@ -369,12 +375,13 @@

plantarchitecture.loadPlantModelFromLibrary( "bean" );
float age = 45;
-
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, age );
+
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, age );
return 0;
}
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
+
vec3 nullorigin
Default null vec3 that gives the origin (0,0,0)
Definition global.cpp:58

This will create a default bean plant that is 45 days old (i.e., 45 days since emergence).

Multiple plants can be created manually by calling the PlantArchitecture::buildPlantInstanceFromLibrary() method multiple times with different base positions. There is also a method available to build a canopy of regularly-spaced plants: PlantArchitecture::buildPlantCanopyFromLibrary().

@@ -388,7 +395,7 @@

plantarchitecture.loadPlantModelFromLibrary( "bean" );
-
vec3 canopy_center = nullorigin;
+
vec3 canopy_center = nullorigin;
vec2 plant_spacing(0.5, 0.15);
int2 plant_count(3,3);
float age = 45;
@@ -396,9 +403,9 @@

return 0;
}
-
Vector of two elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.

Growing the Model over Time

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

@@ -488,7 +495,7 @@

plantarchitecture.loadPlantModelFromLibrary( "bean" );
-
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 45 );
+
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 45 );
return 0;
}
@@ -789,9 +796,9 @@

Growth Parameters — -phyllochron_min RandomParameter_float 1.0 days/leaf Time between the emergence of successive phytomers along the shoot (minimum time or maximum growth rate). +phyllochron_min RandomParameter_float 1.0 days/leaf Minimum time between the emergence of successive phytomers along the shoot (minimum time or maximum growth rate). The actual phyllochron can be increased dynamically if the carbohydrate model is enabled. -elongation_rate RandomParameter_float 0.2 meter/meter/day Relative rate of elongation of the internode of the shoot. Units are meters of elongation per meter of maximum internode length per day. +elongation_rate_max RandomParameter_float 0.2 meter/meter/day Maximum relative rate of elongation of the internode of the shoot. Units are meters of elongation per meter of maximum internode length per day. The actual elongation rate can be reduced dynamically if the carbohydrate model is enabled. girth_area_factor RandomParameter_float 0 cm^2 branch area / m^2 downstream leaf area Cross-sectional area of internode (girth), determined by the amount of downstream leaf area. The girth will only increase and does not decrease if leaves are lost. Set this factor to 0 to prevent girth scaling. @@ -853,8 +860,7 @@

tortuosity

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

-\[
-    d\theta = -\frac{1}{2}\left(\theta\right)dL + T\xi(dL)
+<img class=

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

@@ -882,7 +888,7 @@

shoot_parameters.phytomer_parameters.internode.pitch = 10;
plantarchitecture.updateCurrentShootParameters( "trunk", shoot_parameters );
-
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );
+
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );

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

plantarchitecture.loadPlantModelFromLibrary( "almond" );
@@ -895,14 +901,14 @@

P.phytomer_parameters.internode.pitch = 10;
plantarchitecture.updateCurrentShootParameters( shoot_type, P );
}
-
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );
+
plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );

Modifying Phenological Threshold Parameters

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

PlantArchitecture plantarchitecture(&context);
plantarchitecture.loadPlantModelFromLibrary( "bean" );
-
uint plantID = plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );
+
uint plantID = plantarchitecture.buildPlantInstanceFromLibrary( nullorigin, 0 );
plantarchitecture.setPlantPhenologicalThresholds( plantID, 0, 20, 10, 10, 5, 70 );

@@ -970,10 +976,13 @@

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

- -
+ + diff --git a/doc/html/_plant_library_8cpp.html b/doc/html/_plant_library_8cpp.html index c631ef452..9be73c5a8 100644 --- a/doc/html/_plant_library_8cpp.html +++ b/doc/html/_plant_library_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
PlantLibrary.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file PlantLibrary.cpp.

- - + + diff --git a/doc/html/_plant_library_8cpp_source.html b/doc/html/_plant_library_8cpp_source.html index 3c0c440e2..5346af6fc 100644 --- a/doc/html/_plant_library_8cpp_source.html +++ b/doc/html/_plant_library_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
PlantLibrary.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "PlantArchitecture.h"
17
18using namespace helios;
@@ -142,2928 +149,3049 @@
47 plantID = buildCowpeaPlant(base_position);
48 }else if( current_plant_model == "grapevine_VSP" ) {
49 plantID = buildGrapevineVSP(base_position);
-
50 }else if( current_plant_model == "maize" ) {
-
51 plantID = buildMaizePlant(base_position);
-
52 }else if( current_plant_model == "olive" ) {
-
53 plantID = buildOliveTree(base_position);
-
54 }else if( current_plant_model == "pistachio" ) {
-
55 plantID = buildPistachioTree(base_position);
-
56 }else if( current_plant_model == "puncturevine" ) {
-
57 plantID = buildPuncturevinePlant(base_position);
-
58 }else if( current_plant_model == "easternredbud" ) {
-
59 plantID = buildEasternRedbudPlant(base_position);
-
60 }else if( current_plant_model == "rice" ) {
-
61 plantID = buildRicePlant(base_position);
-
62 }else if( current_plant_model == "butterlettuce" ) {
-
63 plantID = buildButterLettucePlant(base_position);
-
64 }else if( current_plant_model == "sorghum" ) {
-
65 plantID = buildSorghumPlant(base_position);
-
66 }else if( current_plant_model == "soybean" ) {
-
67 plantID = buildSoybeanPlant(base_position);
-
68 }else if( current_plant_model == "strawberry" ) {
-
69 plantID = buildStrawberryPlant(base_position);
-
70 }else if( current_plant_model == "sugarbeet" ) {
-
71 plantID = buildSugarbeetPlant(base_position);
-
72 }else if( current_plant_model == "tomato" ) {
-
73 plantID = buildTomatoPlant(base_position);
-
74 }else if( current_plant_model == "walnut" ) {
-
75 plantID = buildWalnutTree(base_position);
-
76 }else if( current_plant_model == "wheat" ) {
-
77 plantID = buildWheatPlant(base_position);
-
78 }else{
-
79 assert(true); //shouldn't be here
-
80 }
-
81
-
82 if( age>0 ){
-
83 advanceTime( plantID, age);
-
84 }
+
50 }else if( current_plant_model == "groundcherryweed" ) {
+
51 plantID = buildGroundCherryWeedPlant(base_position);
+
52 }else if( current_plant_model == "maize" ) {
+
53 plantID = buildMaizePlant(base_position);
+
54 }else if( current_plant_model == "olive" ) {
+
55 plantID = buildOliveTree(base_position);
+
56 }else if( current_plant_model == "pistachio" ) {
+
57 plantID = buildPistachioTree(base_position);
+
58 }else if( current_plant_model == "puncturevine" ) {
+
59 plantID = buildPuncturevinePlant(base_position);
+
60 }else if( current_plant_model == "easternredbud" ) {
+
61 plantID = buildEasternRedbudPlant(base_position);
+
62 }else if( current_plant_model == "rice" ) {
+
63 plantID = buildRicePlant(base_position);
+
64 }else if( current_plant_model == "butterlettuce" ) {
+
65 plantID = buildButterLettucePlant(base_position);
+
66 }else if( current_plant_model == "sorghum" ) {
+
67 plantID = buildSorghumPlant(base_position);
+
68 }else if( current_plant_model == "soybean" ) {
+
69 plantID = buildSoybeanPlant(base_position);
+
70 }else if( current_plant_model == "strawberry" ) {
+
71 plantID = buildStrawberryPlant(base_position);
+
72 }else if( current_plant_model == "sugarbeet" ) {
+
73 plantID = buildSugarbeetPlant(base_position);
+
74 }else if( current_plant_model == "tomato" ) {
+
75 plantID = buildTomatoPlant(base_position);
+
76 }else if( current_plant_model == "walnut" ) {
+
77 plantID = buildWalnutTree(base_position);
+
78 }else if( current_plant_model == "wheat" ) {
+
79 plantID = buildWheatPlant(base_position);
+
80 }else{
+
81 assert(true); //shouldn't be here
+
82 }
+
83
+
84 plant_instances.at(plantID).plant_name = current_plant_model;
85
-
86 return plantID;
-
87
-
88}
-
+
86 if( age>0 ){
+
87 advanceTime( plantID, age);
+
88 }
89
-
- +
90 return plantID;
91
-
92 if( shoot_types.find(shoot_type_label) == shoot_types.end() ){
-
93 helios_runtime_error("ERROR (PlantArchitecture::getCurrentShootParameters): shoot type label of " + shoot_type_label + " does not exist in the current shoot parameters.");
-
94 }
+
92}
+
+
93
+
+
95
-
96 return shoot_types.at(shoot_type_label);
-
97}
+
96 if( shoot_types.find(shoot_type_label) == shoot_types.end() ){
+
97 helios_runtime_error("ERROR (PlantArchitecture::getCurrentShootParameters): shoot type label of " + shoot_type_label + " does not exist in the current shoot parameters.");
+
98 }
+
99
+
100 return shoot_types.at(shoot_type_label);
+
101}
-
98
-
-
99std::map<std::string, ShootParameters> PlantArchitecture::getCurrentShootParameters(){
-
100 if( shoot_types.empty() ){
-
101 std::cerr << "WARNING (PlantArchitecture::getCurrentShootParameters): No plant models have been loaded. You need to first load a plant model from the library (see loadPlantModelFromLibrary()) or manually add shoot parameters (see updateCurrentShootParameters())." << std::endl;
-
102 }
-
103 return shoot_types;
-
104}
+
102
+
+
103std::map<std::string, ShootParameters> PlantArchitecture::getCurrentShootParameters(){
+
104 if( shoot_types.empty() ){
+
105 std::cerr << "WARNING (PlantArchitecture::getCurrentShootParameters): No plant models have been loaded. You need to first load a plant model from the library (see loadPlantModelFromLibrary()) or manually add shoot parameters (see updateCurrentShootParameters())." << std::endl;
+
106 }
+
107 return shoot_types;
+
108}
-
105
-
-
106std::map<std::string, PhytomerParameters> PlantArchitecture::getCurrentPhytomerParameters( ){
-
107 if( shoot_types.empty() ){
-
108 std::cerr << "WARNING (PlantArchitecture::getCurrentPhytomerParameters): No plant models have been loaded. You need to first load a plant model from the library (see loadPlantModelFromLibrary()) or manually add shoot parameters (see updateCurrentShootParameters())." << std::endl;
-
109 }
-
110 std::map<std::string, PhytomerParameters> phytomer_parameters;
-
111 for( const auto & type : shoot_types ){
-
112 phytomer_parameters[type.first] = type.second.phytomer_parameters;
+
109
+
+
110std::map<std::string, PhytomerParameters> PlantArchitecture::getCurrentPhytomerParameters( ){
+
111 if( shoot_types.empty() ){
+
112 std::cerr << "WARNING (PlantArchitecture::getCurrentPhytomerParameters): No plant models have been loaded. You need to first load a plant model from the library (see loadPlantModelFromLibrary()) or manually add shoot parameters (see updateCurrentShootParameters())." << std::endl;
113 }
-
114 return phytomer_parameters;
-
115}
-
-
116
-
-
117void PlantArchitecture::updateCurrentShootParameters( const std::string &shoot_type_label, const ShootParameters &params ){
-
118 shoot_types[shoot_type_label] = params;
+
114 std::map<std::string, PhytomerParameters> phytomer_parameters;
+
115 for( const auto & type : shoot_types ){
+
116 phytomer_parameters[type.first] = type.second.phytomer_parameters;
+
117 }
+
118 return phytomer_parameters;
119}
120
-
121void PlantArchitecture::updateCurrentShootParameters( const std::map<std::string, ShootParameters> &params ){
-
122 shoot_types = params;
+
121void PlantArchitecture::updateCurrentShootParameters( const std::string &shoot_type_label, const ShootParameters &params ){
+
122 shoot_types[shoot_type_label] = params;
123}
124
-
125void PlantArchitecture::initializeDefaultShoots( const std::string &plant_label ){
-
126
-
127 if( plant_label == "almond" ) {
-
128 initializeAlmondTreeShoots();
-
129 }else if( plant_label == "apple" ) {
-
130 initializeAppleTreeShoots();
-
131 }else if( plant_label == "asparagus" ) {
-
132 initializeAsparagusShoots();
-
133 }else if( plant_label == "bindweed" ) {
-
134 initializeBindweedShoots();
-
135 }else if( plant_label == "bean" ) {
-
136 initializeBeanShoots();
-
137 }else if( plant_label == "cheeseweed" ) {
-
138 initializeCheeseweedShoots();
-
139 }else if( plant_label == "cowpea" ) {
-
140 initializeCowpeaShoots();
-
141 }else if( plant_label == "grapevine_VSP" ) {
-
142 initializeGrapevineVSPShoots();
-
143 }else if( plant_label == "maize" ) {
-
144 initializeMaizeShoots();
-
145 }else if( plant_label == "olive" ) {
-
146 initializeOliveTreeShoots();
-
147 }else if( plant_label == "pistachio" ) {
-
148 initializePistachioTreeShoots();
-
149 }else if( plant_label == "puncturevine" ) {
-
150 initializePuncturevineShoots();
-
151 }else if( plant_label == "easternredbud" ) {
-
152 initializeEasternRedbudShoots();
-
153 }else if( plant_label == "rice" ) {
-
154 initializeRiceShoots();
-
155 }else if( plant_label == "butterlettuce" ) {
-
156 initializeButterLettuceShoots();
-
157 }else if( plant_label == "sorghum" ) {
-
158 initializeSorghumShoots();
-
159 }else if( plant_label == "soybean" ) {
-
160 initializeSoybeanShoots();
-
161 }else if( plant_label == "strawberry" ) {
-
162 initializeStrawberryShoots();
-
163 }else if( plant_label == "sugarbeet" ) {
-
164 initializeSugarbeetShoots();
-
165 }else if( plant_label == "tomato" ) {
-
166 initializeTomatoShoots();
-
167 }else if( plant_label == "walnut" ) {
-
168 initializeWalnutTreeShoots();
-
169 }else if( plant_label == "wheat" ) {
-
170 initializeWheatShoots();
-
171 }else{
-
172 helios_runtime_error("ERROR (PlantArchitecture::loadPlantModelFromLibrary): plant label of " + plant_label + " does not exist in the library.");
-
173 }
-
174
-
175}
-
176
-
177void PlantArchitecture::initializeAlmondTreeShoots(){
-
178
-
179 // ---- Leaf Prototype ---- //
+
+
125void PlantArchitecture::updateCurrentShootParameters( const std::map<std::string, ShootParameters> &params ){
+
126 shoot_types = params;
+
127}
+
+
128
+
129void PlantArchitecture::initializeDefaultShoots( const std::string &plant_label ){
+
130
+
131 if( plant_label == "almond" ) {
+
132 initializeAlmondTreeShoots();
+
133 }else if( plant_label == "apple" ) {
+
134 initializeAppleTreeShoots();
+
135 }else if( plant_label == "asparagus" ) {
+
136 initializeAsparagusShoots();
+
137 }else if( plant_label == "bindweed" ) {
+
138 initializeBindweedShoots();
+
139 }else if( plant_label == "bean" ) {
+
140 initializeBeanShoots();
+
141 }else if( plant_label == "cheeseweed" ) {
+
142 initializeCheeseweedShoots();
+
143 }else if( plant_label == "cowpea" ) {
+
144 initializeCowpeaShoots();
+
145 }else if( plant_label == "grapevine_VSP" ) {
+
146 initializeGrapevineVSPShoots();
+
147 }else if( plant_label == "groundcherryweed" ) {
+
148 initializeGroundCherryWeedShoots();
+
149 }else if( plant_label == "maize" ) {
+
150 initializeMaizeShoots();
+
151 }else if( plant_label == "olive" ) {
+
152 initializeOliveTreeShoots();
+
153 }else if( plant_label == "pistachio" ) {
+
154 initializePistachioTreeShoots();
+
155 }else if( plant_label == "puncturevine" ) {
+
156 initializePuncturevineShoots();
+
157 }else if( plant_label == "easternredbud" ) {
+
158 initializeEasternRedbudShoots();
+
159 }else if( plant_label == "rice" ) {
+
160 initializeRiceShoots();
+
161 }else if( plant_label == "butterlettuce" ) {
+
162 initializeButterLettuceShoots();
+
163 }else if( plant_label == "sorghum" ) {
+
164 initializeSorghumShoots();
+
165 }else if( plant_label == "soybean" ) {
+
166 initializeSoybeanShoots();
+
167 }else if( plant_label == "strawberry" ) {
+
168 initializeStrawberryShoots();
+
169 }else if( plant_label == "sugarbeet" ) {
+
170 initializeSugarbeetShoots();
+
171 }else if( plant_label == "tomato" ) {
+
172 initializeTomatoShoots();
+
173 }else if( plant_label == "walnut" ) {
+
174 initializeWalnutTreeShoots();
+
175 }else if( plant_label == "wheat" ) {
+
176 initializeWheatShoots();
+
177 }else{
+
178 helios_runtime_error("ERROR (PlantArchitecture::loadPlantModelFromLibrary): plant label of " + plant_label + " does not exist in the library.");
+
179 }
180
-
181 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
182 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/AlmondLeaf.png";
-
183 leaf_prototype.leaf_aspect_ratio = 0.4f;
-
184 leaf_prototype.midrib_fold_fraction = 0.1f;
-
185 leaf_prototype.longitudinal_curvature = 0.05;
-
186 leaf_prototype.lateral_curvature = 0.1f;
-
187 leaf_prototype.subdivisions = 1;
-
188 leaf_prototype.unique_prototypes = 1;
-
189
-
190 // ---- Phytomer Parameters ---- //
-
191
-
192 PhytomerParameters phytomer_parameters_almond(context_ptr->getRandomGenerator());
-
193
-
194 phytomer_parameters_almond.internode.pitch = 3;
-
195 phytomer_parameters_almond.internode.phyllotactic_angle.uniformDistribution( 130, 145 );
-
196 phytomer_parameters_almond.internode.radius_initial = 0.004;
-
197 phytomer_parameters_almond.internode.length_segments = 1;
-
198 phytomer_parameters_almond.internode.image_texture = "plugins/plantarchitecture/assets/textures/AlmondBark.jpg";
-
199 phytomer_parameters_almond.internode.max_floral_buds_per_petiole = 3;
-
200
-
201 phytomer_parameters_almond.petiole.petioles_per_internode = 1;
-
202 phytomer_parameters_almond.petiole.pitch.uniformDistribution(-145,-90);
-
203 phytomer_parameters_almond.petiole.taper = 0.1;
-
204 phytomer_parameters_almond.petiole.curvature = 0;
-
205 phytomer_parameters_almond.petiole.length = 0.04;
-
206 phytomer_parameters_almond.petiole.radius = 0.0005;
-
207 phytomer_parameters_almond.petiole.length_segments = 1;
-
208 phytomer_parameters_almond.petiole.radial_subdivisions = 3;
-
209 phytomer_parameters_almond.petiole.color = make_RGBcolor(0.61,0.5,0.24);
-
210
-
211 phytomer_parameters_almond.leaf.leaves_per_petiole = 1;
-
212 phytomer_parameters_almond.leaf.roll.uniformDistribution(-10,10);
-
213 phytomer_parameters_almond.leaf.prototype_scale = 0.08;
-
214 phytomer_parameters_almond.leaf.prototype = leaf_prototype;
-
215
-
216 phytomer_parameters_almond.peduncle.length = 0.005;
-
217 phytomer_parameters_almond.peduncle.radius = 0.0005;
-
218 phytomer_parameters_almond.peduncle.pitch = 90;
-
219 phytomer_parameters_almond.peduncle.roll = 90;
-
220 phytomer_parameters_almond.peduncle.length_segments = 1;
-
221 phytomer_parameters_almond.petiole.radial_subdivisions = 3;
-
222
-
223 phytomer_parameters_almond.inflorescence.flowers_per_peduncle = 1;
-
224 phytomer_parameters_almond.inflorescence.pitch = 0;
-
225 phytomer_parameters_almond.inflorescence.roll = 0;
-
226 phytomer_parameters_almond.inflorescence.flower_prototype_scale = 0.04;
-
227 phytomer_parameters_almond.inflorescence.flower_prototype_function = AlmondFlowerPrototype;
-
228 phytomer_parameters_almond.inflorescence.fruit_prototype_scale = 0.06;
-
229 phytomer_parameters_almond.inflorescence.fruit_prototype_function = AlmondFruitPrototype;
-
230
-
231 // ---- Shoot Parameters ---- //
-
232
-
233 // Trunk
-
234 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
-
235 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_almond;
-
236 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
-
237 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
-
238 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.01;
-
239 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24;
-
240 shoot_parameters_trunk.max_nodes = 20;
-
241 shoot_parameters_trunk.girth_area_factor = 8.f;
-
242 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
-
243 shoot_parameters_trunk.vegetative_bud_break_time = 0;
-
244 shoot_parameters_trunk.tortuosity = 1.5;
-
245 shoot_parameters_trunk.internode_length_max = 0.05;
-
246 shoot_parameters_trunk.internode_length_decay_rate = 0;
-
247 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
-
248
-
249 // Proleptic shoots
-
250 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
-
251 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_almond;
-
252 shoot_parameters_proleptic.phytomer_parameters.internode.color = make_RGBcolor(0.3,0.2,0.2);
-
253 shoot_parameters_proleptic.phytomer_parameters.internode.radial_subdivisions = 5;
-
254 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = AlmondPhytomerCreationFunction;
-
255 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = AlmondPhytomerCallbackFunction;
-
256 shoot_parameters_proleptic.max_nodes = 50;
-
257 shoot_parameters_proleptic.max_nodes_per_season = 25;
-
258 shoot_parameters_proleptic.phyllochron_min = 2;
-
259 shoot_parameters_proleptic.elongation_rate = 0.15;
-
260 shoot_parameters_proleptic.girth_area_factor = 8.f;
-
261 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.15;
-
262 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.4;
-
263 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
-
264 shoot_parameters_proleptic.gravitropic_curvature = 200;
-
265 shoot_parameters_proleptic.tortuosity = 3;
-
266 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 25, 30);
-
267 shoot_parameters_proleptic.insertion_angle_decay_rate = 15;
-
268 shoot_parameters_proleptic.internode_length_max = 0.03;
-
269 shoot_parameters_proleptic.internode_length_min = 0.004;
-
270 shoot_parameters_proleptic.internode_length_decay_rate = 0.004;
-
271 shoot_parameters_proleptic.fruit_set_probability = 0.5;
-
272 shoot_parameters_proleptic.flower_bud_break_probability = 0.3;
-
273 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
-
274 shoot_parameters_proleptic.flowers_require_dormancy = true;
-
275 shoot_parameters_proleptic.growth_requires_dormancy = true;
-
276 shoot_parameters_proleptic.determinate_shoot_growth = false;
-
277 shoot_parameters_proleptic.defineChildShootTypes({"proleptic","sylleptic"},{1.0,0.});
-
278
-
279 // Sylleptic shoots
-
280 ShootParameters shoot_parameters_sylleptic = shoot_parameters_proleptic;
-
281// shoot_parameters_sylleptic.phytomer_parameters.internode.color = RGB::red;
-
282 shoot_parameters_sylleptic.phytomer_parameters.internode.image_texture = "";
-
283 shoot_parameters_sylleptic.phytomer_parameters.leaf.prototype_scale = 0.12;
-
284 shoot_parameters_sylleptic.phytomer_parameters.leaf.pitch.uniformDistribution(-45, -20);
-
285 shoot_parameters_sylleptic.insertion_angle_tip = 0;
-
286 shoot_parameters_sylleptic.insertion_angle_decay_rate = 0;
-
287 shoot_parameters_sylleptic.phyllochron_min = 2;
-
288 shoot_parameters_sylleptic.vegetative_bud_break_probability_min = 0.1;
-
289 shoot_parameters_sylleptic.gravitropic_curvature= 600;
-
290 shoot_parameters_sylleptic.internode_length_max = 0.06;
-
291 shoot_parameters_sylleptic.flowers_require_dormancy = true;
-
292 shoot_parameters_sylleptic.growth_requires_dormancy = true;
-
293 shoot_parameters_sylleptic.defineChildShootTypes({"proleptic"},{1.0});
-
294
-
295 // Main scaffolds
-
296 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
-
297// shoot_parameters_scaffold.phytomer_parameters.internode.color = RGB::blue;
-
298 shoot_parameters_scaffold.phytomer_parameters.internode.radial_subdivisions = 10;
-
299 shoot_parameters_scaffold.max_nodes = 40;
-
300 shoot_parameters_scaffold.gravitropic_curvature = 150;
-
301 shoot_parameters_scaffold.internode_length_max = 0.04;
-
302 shoot_parameters_scaffold.tortuosity = 1.5;
-
303 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
-
304
-
305 defineShootType("trunk", shoot_parameters_trunk);
-
306 defineShootType("scaffold", shoot_parameters_scaffold);
-
307 defineShootType("proleptic", shoot_parameters_proleptic);
-
308 defineShootType("sylleptic", shoot_parameters_sylleptic);
-
309
-
310}
-
311
-
312uint PlantArchitecture::buildAlmondTree(const helios::vec3 &base_position) {
-
313
-
314 if( shoot_types.empty() ){
-
315 //automatically initialize almond tree shoots
-
316 initializeAlmondTreeShoots();
-
317 }
-
318
-
319 uint plantID = addPlantInstance(base_position, 0);
-
320
-
321// enableEpicormicChildShoots(plantID,"sylleptic",0.001);
-
322
-
323 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), 0.f * M_PI), 0.015, 0.04, 1.f, 1.f, 0, "trunk");
-
324 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
-
325
-
326 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
-
327
-
328 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
-
329 for( const auto & phytomer : phytomers ){
-
330 phytomer->removeLeaf();
-
331 phytomer->setVegetativeBudState(BUD_DEAD);
-
332 phytomer->setFloralBudState(BUD_DEAD);
-
333 }
-
334
-
335 uint Nscaffolds = 4;//context_ptr->randu(4,5);
-
336
-
337 for( int i=0; i<Nscaffolds; i++ ) {
-
338 float pitch = context_ptr->randu(deg2rad(35), deg2rad(45));
-
339 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, context_ptr->randu(7, 9), 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);
+
181}
+
182
+
183void PlantArchitecture::initializeAlmondTreeShoots(){
+
184
+
185 // ---- Leaf Prototype ---- //
+
186
+
187 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
188 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/AlmondLeaf.png";
+
189 leaf_prototype.leaf_aspect_ratio = 0.4f;
+
190 leaf_prototype.midrib_fold_fraction = 0.1f;
+
191 leaf_prototype.longitudinal_curvature = 0.05;
+
192 leaf_prototype.lateral_curvature = 0.1f;
+
193 leaf_prototype.subdivisions = 1;
+
194 leaf_prototype.unique_prototypes = 1;
+
195
+
196 // ---- Phytomer Parameters ---- //
+
197
+
198 PhytomerParameters phytomer_parameters_almond(context_ptr->getRandomGenerator());
+
199
+
200 phytomer_parameters_almond.internode.pitch = 3;
+
201 phytomer_parameters_almond.internode.phyllotactic_angle.uniformDistribution( 130, 145 );
+
202 phytomer_parameters_almond.internode.radius_initial = 0.004;
+
203 phytomer_parameters_almond.internode.length_segments = 1;
+
204 phytomer_parameters_almond.internode.image_texture = "plugins/plantarchitecture/assets/textures/AlmondBark.jpg";
+
205 phytomer_parameters_almond.internode.max_floral_buds_per_petiole = 3;
+
206
+
207 phytomer_parameters_almond.petiole.petioles_per_internode = 1;
+
208 phytomer_parameters_almond.petiole.pitch.uniformDistribution(-145,-90);
+
209 phytomer_parameters_almond.petiole.taper = 0.1;
+
210 phytomer_parameters_almond.petiole.curvature = 0;
+
211 phytomer_parameters_almond.petiole.length = 0.04;
+
212 phytomer_parameters_almond.petiole.radius = 0.0005;
+
213 phytomer_parameters_almond.petiole.length_segments = 1;
+
214 phytomer_parameters_almond.petiole.radial_subdivisions = 3;
+
215 phytomer_parameters_almond.petiole.color = make_RGBcolor(0.61,0.5,0.24);
+
216
+
217 phytomer_parameters_almond.leaf.leaves_per_petiole = 1;
+
218 phytomer_parameters_almond.leaf.roll.uniformDistribution(-10,10);
+
219 phytomer_parameters_almond.leaf.prototype_scale = 0.08;
+
220 phytomer_parameters_almond.leaf.prototype = leaf_prototype;
+
221
+
222 phytomer_parameters_almond.peduncle.length = 0.005;
+
223 phytomer_parameters_almond.peduncle.radius = 0.0005;
+
224 phytomer_parameters_almond.peduncle.pitch = 90;
+
225 phytomer_parameters_almond.peduncle.roll = 90;
+
226 phytomer_parameters_almond.peduncle.length_segments = 1;
+
227 phytomer_parameters_almond.petiole.radial_subdivisions = 3;
+
228
+
229 phytomer_parameters_almond.inflorescence.flowers_per_peduncle = 1;
+
230 phytomer_parameters_almond.inflorescence.pitch = 0;
+
231 phytomer_parameters_almond.inflorescence.roll = 0;
+
232 phytomer_parameters_almond.inflorescence.flower_prototype_scale = 0.04;
+
233 phytomer_parameters_almond.inflorescence.flower_prototype_function = AlmondFlowerPrototype;
+
234 phytomer_parameters_almond.inflorescence.fruit_prototype_scale = 0.06;
+
235 phytomer_parameters_almond.inflorescence.fruit_prototype_function = AlmondFruitPrototype;
+
236
+
237 // ---- Shoot Parameters ---- //
+
238
+
239 // Trunk
+
240 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
+
241 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_almond;
+
242 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
+
243 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
+
244 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.01;
+
245 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24;
+
246 shoot_parameters_trunk.max_nodes = 20;
+
247 shoot_parameters_trunk.girth_area_factor = 8.f;
+
248 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
+
249 shoot_parameters_trunk.vegetative_bud_break_time = 0;
+
250 shoot_parameters_trunk.tortuosity = 1;
+
251 shoot_parameters_trunk.internode_length_max = 0.05;
+
252 shoot_parameters_trunk.internode_length_decay_rate = 0;
+
253 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
+
254
+
255 // Proleptic shoots
+
256 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
+
257 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_almond;
+
258 shoot_parameters_proleptic.phytomer_parameters.internode.color = make_RGBcolor(0.3,0.2,0.2);
+
259 shoot_parameters_proleptic.phytomer_parameters.internode.radial_subdivisions = 5;
+
260 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = AlmondPhytomerCreationFunction;
+
261 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = AlmondPhytomerCallbackFunction;
+
262 shoot_parameters_proleptic.max_nodes = 50;
+
263 shoot_parameters_proleptic.max_nodes_per_season = 25;
+
264 shoot_parameters_proleptic.phyllochron_min = 2;
+
265 shoot_parameters_proleptic.elongation_rate_max = 0.15;
+
266 shoot_parameters_proleptic.girth_area_factor = 8.f;
+
267 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.15;
+
268 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.4;
+
269 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
+
270 shoot_parameters_proleptic.gravitropic_curvature = 200;
+
271 shoot_parameters_proleptic.tortuosity = 3;
+
272 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 25, 30);
+
273 shoot_parameters_proleptic.insertion_angle_decay_rate = 15;
+
274 shoot_parameters_proleptic.internode_length_max = 0.03;
+
275 shoot_parameters_proleptic.internode_length_min = 0.004;
+
276 shoot_parameters_proleptic.internode_length_decay_rate = 0.004;
+
277 shoot_parameters_proleptic.fruit_set_probability = 0.5;
+
278 shoot_parameters_proleptic.flower_bud_break_probability = 0.3;
+
279 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
+
280 shoot_parameters_proleptic.flowers_require_dormancy = true;
+
281 shoot_parameters_proleptic.growth_requires_dormancy = true;
+
282 shoot_parameters_proleptic.determinate_shoot_growth = false;
+
283 shoot_parameters_proleptic.defineChildShootTypes({"proleptic","sylleptic"},{1.0,0.});
+
284
+
285 // Sylleptic shoots
+
286 ShootParameters shoot_parameters_sylleptic = shoot_parameters_proleptic;
+
287// shoot_parameters_sylleptic.phytomer_parameters.internode.color = RGB::red;
+
288 shoot_parameters_sylleptic.phytomer_parameters.internode.image_texture = "";
+
289 shoot_parameters_sylleptic.phytomer_parameters.leaf.prototype_scale = 0.12;
+
290 shoot_parameters_sylleptic.phytomer_parameters.leaf.pitch.uniformDistribution(-45, -20);
+
291 shoot_parameters_sylleptic.insertion_angle_tip = 0;
+
292 shoot_parameters_sylleptic.insertion_angle_decay_rate = 0;
+
293 shoot_parameters_sylleptic.phyllochron_min = 2;
+
294 shoot_parameters_sylleptic.vegetative_bud_break_probability_min = 0.1;
+
295 shoot_parameters_sylleptic.gravitropic_curvature= 600;
+
296 shoot_parameters_sylleptic.internode_length_max = 0.06;
+
297 shoot_parameters_sylleptic.flowers_require_dormancy = true;
+
298 shoot_parameters_sylleptic.growth_requires_dormancy = true;
+
299 shoot_parameters_sylleptic.defineChildShootTypes({"proleptic"},{1.0});
+
300
+
301 // Main scaffolds
+
302 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
+
303// shoot_parameters_scaffold.phytomer_parameters.internode.color = RGB::blue;
+
304 shoot_parameters_scaffold.phytomer_parameters.internode.radial_subdivisions = 10;
+
305 shoot_parameters_scaffold.max_nodes = 40;
+
306 shoot_parameters_scaffold.gravitropic_curvature = 150;
+
307 shoot_parameters_scaffold.internode_length_max = 0.04;
+
308 shoot_parameters_scaffold.tortuosity = 1.;
+
309 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
+
310
+
311 defineShootType("trunk", shoot_parameters_trunk);
+
312 defineShootType("scaffold", shoot_parameters_scaffold);
+
313 defineShootType("proleptic", shoot_parameters_proleptic);
+
314 defineShootType("sylleptic", shoot_parameters_sylleptic);
+
315
+
316}
+
317
+
318uint PlantArchitecture::buildAlmondTree(const helios::vec3 &base_position) {
+
319
+
320 if( shoot_types.empty() ){
+
321 //automatically initialize almond tree shoots
+
322 initializeAlmondTreeShoots();
+
323 }
+
324
+
325 uint plantID = addPlantInstance(base_position, 0);
+
326
+
327// enableEpicormicChildShoots(plantID,"sylleptic",0.001);
+
328
+
329 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), 0.f * M_PI), 0.015, 0.04, 1.f, 1.f, 0, "trunk");
+
330 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
+
331
+
332 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
+
333
+
334 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
+
335 for( const auto & phytomer : phytomers ){
+
336 phytomer->removeLeaf();
+
337 phytomer->setVegetativeBudState(BUD_DEAD);
+
338 phytomer->setFloralBudState(BUD_DEAD);
+
339 }
340
-
341 }
+
341 uint Nscaffolds = 4;//context_ptr->randu(4,5);
342
-
343 makePlantDormant(plantID);
-
344
-
345 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 20, 200, false);
-
346 plant_instances.at(plantID).max_age = 1825;
-
347
-
348 return plantID;
-
349
-
350}
-
351
-
352void PlantArchitecture::initializeAppleTreeShoots(){
+
343 for( int i=0; i<Nscaffolds; i++ ) {
+
344 float pitch = context_ptr->randu(deg2rad(35), deg2rad(45));
+
345 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, context_ptr->randu(7, 9), 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);
+
346
+
347 }
+
348
+
349 makePlantDormant(plantID);
+
350
+
351 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 20, 200, false);
+
352 plant_instances.at(plantID).max_age = 1825;
353
-
354 // ---- Leaf Prototype ---- //
+
354 return plantID;
355
-
356 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
357 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/AppleLeaf.png";
-
358 leaf_prototype.leaf_aspect_ratio = 0.6f;
-
359 leaf_prototype.midrib_fold_fraction = 0.4f;
-
360 leaf_prototype.longitudinal_curvature = -0.3f;
-
361 leaf_prototype.lateral_curvature = 0.1f;
-
362 leaf_prototype.subdivisions = 3;
-
363 leaf_prototype.unique_prototypes = 1;
-
364
-
365 // ---- Phytomer Parameters ---- //
-
366
-
367 PhytomerParameters phytomer_parameters_apple(context_ptr->getRandomGenerator());
-
368
-
369 phytomer_parameters_apple.internode.pitch = 0;
-
370 phytomer_parameters_apple.internode.phyllotactic_angle.uniformDistribution( 130, 145 );
-
371 phytomer_parameters_apple.internode.radius_initial = 0.004;
-
372 phytomer_parameters_apple.internode.length_segments = 1;
-
373 phytomer_parameters_apple.internode.image_texture = "plugins/plantarchitecture/assets/textures/AppleBark.jpg";
-
374 phytomer_parameters_apple.internode.max_floral_buds_per_petiole = 1;
-
375
-
376 phytomer_parameters_apple.petiole.petioles_per_internode = 1;
-
377 phytomer_parameters_apple.petiole.pitch.uniformDistribution(-40,-25);
-
378 phytomer_parameters_apple.petiole.taper = 0.1;
-
379 phytomer_parameters_apple.petiole.curvature = 0;
-
380 phytomer_parameters_apple.petiole.length = 0.04;
-
381 phytomer_parameters_apple.petiole.radius = 0.00075;
-
382 phytomer_parameters_apple.petiole.length_segments = 1;
-
383 phytomer_parameters_apple.petiole.radial_subdivisions = 3;
-
384 phytomer_parameters_apple.petiole.color = make_RGBcolor(0.61,0.5,0.24);
-
385
-
386 phytomer_parameters_apple.leaf.leaves_per_petiole = 1;
-
387 phytomer_parameters_apple.leaf.prototype_scale = 0.12;
-
388 phytomer_parameters_apple.leaf.prototype = leaf_prototype;
-
389
-
390 phytomer_parameters_apple.peduncle.length = 0.04;
-
391 phytomer_parameters_apple.peduncle.radius = 0.001;
-
392 phytomer_parameters_apple.peduncle.pitch = 90;
-
393 phytomer_parameters_apple.peduncle.roll = 90;
-
394 phytomer_parameters_apple.peduncle.length_segments = 1;
+
356}
+
357
+
358void PlantArchitecture::initializeAppleTreeShoots(){
+
359
+
360 // ---- Leaf Prototype ---- //
+
361
+
362 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
363 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/AppleLeaf.png";
+
364 leaf_prototype.leaf_aspect_ratio = 0.6f;
+
365 leaf_prototype.midrib_fold_fraction = 0.4f;
+
366 leaf_prototype.longitudinal_curvature = -0.3f;
+
367 leaf_prototype.lateral_curvature = 0.1f;
+
368 leaf_prototype.subdivisions = 3;
+
369 leaf_prototype.unique_prototypes = 1;
+
370
+
371 // ---- Phytomer Parameters ---- //
+
372
+
373 PhytomerParameters phytomer_parameters_apple(context_ptr->getRandomGenerator());
+
374
+
375 phytomer_parameters_apple.internode.pitch = 0;
+
376 phytomer_parameters_apple.internode.phyllotactic_angle.uniformDistribution( 130, 145 );
+
377 phytomer_parameters_apple.internode.radius_initial = 0.004;
+
378 phytomer_parameters_apple.internode.length_segments = 1;
+
379 phytomer_parameters_apple.internode.image_texture = "plugins/plantarchitecture/assets/textures/AppleBark.jpg";
+
380 phytomer_parameters_apple.internode.max_floral_buds_per_petiole = 1;
+
381
+
382 phytomer_parameters_apple.petiole.petioles_per_internode = 1;
+
383 phytomer_parameters_apple.petiole.pitch.uniformDistribution(-40,-25);
+
384 phytomer_parameters_apple.petiole.taper = 0.1;
+
385 phytomer_parameters_apple.petiole.curvature = 0;
+
386 phytomer_parameters_apple.petiole.length = 0.04;
+
387 phytomer_parameters_apple.petiole.radius = 0.00075;
+
388 phytomer_parameters_apple.petiole.length_segments = 1;
+
389 phytomer_parameters_apple.petiole.radial_subdivisions = 3;
+
390 phytomer_parameters_apple.petiole.color = make_RGBcolor(0.61,0.5,0.24);
+
391
+
392 phytomer_parameters_apple.leaf.leaves_per_petiole = 1;
+
393 phytomer_parameters_apple.leaf.prototype_scale = 0.12;
+
394 phytomer_parameters_apple.leaf.prototype = leaf_prototype;
395
-
396 phytomer_parameters_apple.inflorescence.flowers_per_peduncle = 1;
-
397 phytomer_parameters_apple.inflorescence.pitch = 0;
-
398 phytomer_parameters_apple.inflorescence.roll = 0;
-
399 phytomer_parameters_apple.inflorescence.flower_prototype_scale = 0.03;
-
400 phytomer_parameters_apple.inflorescence.flower_prototype_function = AppleFlowerPrototype;
-
401 phytomer_parameters_apple.inflorescence.fruit_prototype_scale = 0.1;
-
402 phytomer_parameters_apple.inflorescence.fruit_prototype_function = AppleFruitPrototype;
-
403 phytomer_parameters_apple.inflorescence.fruit_gravity_factor_fraction = 0.5;
-
404
-
405 // ---- Shoot Parameters ---- //
-
406
-
407 // Trunk
-
408 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
-
409 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_apple;
-
410 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
-
411 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.01;
-
412 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24;
-
413 shoot_parameters_trunk.max_nodes = 20;
-
414 shoot_parameters_trunk.girth_area_factor = 5.f;
-
415 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
-
416 shoot_parameters_trunk.vegetative_bud_break_time = 0;
-
417 shoot_parameters_trunk.tortuosity = 1;
-
418 shoot_parameters_trunk.internode_length_max = 0.05;
-
419 shoot_parameters_trunk.internode_length_decay_rate = 0;
-
420 shoot_parameters_trunk.defineChildShootTypes({"proleptic"},{1});
-
421
-
422 // Proleptic shoots
-
423 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
-
424 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_apple;
-
425 shoot_parameters_proleptic.phytomer_parameters.internode.color = make_RGBcolor(0.3,0.2,0.2);
-
426 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = ApplePhytomerCreationFunction;
-
427 shoot_parameters_proleptic.max_nodes = 40;
-
428 shoot_parameters_proleptic.max_nodes_per_season = 20;
-
429 shoot_parameters_proleptic.phyllochron_min = 2.0;
-
430 shoot_parameters_proleptic.elongation_rate = 0.15;
-
431 shoot_parameters_proleptic.girth_area_factor = 5.f;
-
432 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.1;
-
433 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.4;
-
434 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
-
435 shoot_parameters_proleptic.gravitropic_curvature.uniformDistribution(450,500);
-
436 shoot_parameters_proleptic.tortuosity = 3;
-
437 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 30, 40);
-
438 shoot_parameters_proleptic.insertion_angle_decay_rate = 20;
-
439 shoot_parameters_proleptic.internode_length_max = 0.04;
-
440 shoot_parameters_proleptic.internode_length_min = 0.01;
-
441 shoot_parameters_proleptic.internode_length_decay_rate = 0.004;
-
442 shoot_parameters_proleptic.fruit_set_probability = 0.4;
-
443 shoot_parameters_proleptic.flower_bud_break_probability = 0.3;
-
444 shoot_parameters_proleptic.max_terminal_floral_buds = 1;
-
445 shoot_parameters_proleptic.flowers_require_dormancy = true;
-
446 shoot_parameters_proleptic.growth_requires_dormancy = true;
-
447 shoot_parameters_proleptic.determinate_shoot_growth = false;
-
448 shoot_parameters_proleptic.defineChildShootTypes({"proleptic"},{1.0});
-
449
-
450 defineShootType("trunk", shoot_parameters_trunk);
-
451 defineShootType("proleptic", shoot_parameters_proleptic);
-
452
-
453}
-
454
-
455uint PlantArchitecture::buildAppleTree(const helios::vec3 &base_position) {
-
456
-
457 if( shoot_types.empty() ){
-
458 //automatically initialize apple tree shoots
-
459 initializeAppleTreeShoots();
-
460 }
-
461
-
462 uint plantID = addPlantInstance(base_position, 0);
-
463
-
464 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), 0.f * M_PI), 0.015, 0.04, 1.f, 1.f, 0, "trunk");
-
465 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
-
466
-
467 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
-
468
-
469 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
-
470 for( const auto & phytomer : phytomers ){
-
471 phytomer->removeLeaf();
-
472 phytomer->setVegetativeBudState(BUD_DEAD);
-
473 phytomer->setFloralBudState(BUD_DEAD);
-
474 }
-
475
-
476 uint Nscaffolds = 4;//context_ptr->randu(4,5);
-
477
-
478 for( int i=0; i<Nscaffolds; i++ ) {
-
479 float pitch = context_ptr->randu(deg2rad(55), deg2rad(65));
-
480 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, context_ptr->randu(7, 9), make_AxisRotation(pitch, (float(i) + context_ptr->randu(-0.2f, 0.2f)) / float(Nscaffolds) * 2 * M_PI, 0), 0.005, 0.04, 1.f, 1.f, 0.5, "proleptic", 0);
+
396 phytomer_parameters_apple.peduncle.length = 0.04;
+
397 phytomer_parameters_apple.peduncle.radius = 0.001;
+
398 phytomer_parameters_apple.peduncle.pitch = 90;
+
399 phytomer_parameters_apple.peduncle.roll = 90;
+
400 phytomer_parameters_apple.peduncle.length_segments = 1;
+
401
+
402 phytomer_parameters_apple.inflorescence.flowers_per_peduncle = 1;
+
403 phytomer_parameters_apple.inflorescence.pitch = 0;
+
404 phytomer_parameters_apple.inflorescence.roll = 0;
+
405 phytomer_parameters_apple.inflorescence.flower_prototype_scale = 0.03;
+
406 phytomer_parameters_apple.inflorescence.flower_prototype_function = AppleFlowerPrototype;
+
407 phytomer_parameters_apple.inflorescence.fruit_prototype_scale = 0.1;
+
408 phytomer_parameters_apple.inflorescence.fruit_prototype_function = AppleFruitPrototype;
+
409 phytomer_parameters_apple.inflorescence.fruit_gravity_factor_fraction = 0.5;
+
410
+
411 // ---- Shoot Parameters ---- //
+
412
+
413 // Trunk
+
414 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
+
415 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_apple;
+
416 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
+
417 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.01;
+
418 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24;
+
419 shoot_parameters_trunk.max_nodes = 20;
+
420 shoot_parameters_trunk.girth_area_factor = 5.f;
+
421 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
+
422 shoot_parameters_trunk.vegetative_bud_break_time = 0;
+
423 shoot_parameters_trunk.tortuosity = 1;
+
424 shoot_parameters_trunk.internode_length_max = 0.05;
+
425 shoot_parameters_trunk.internode_length_decay_rate = 0;
+
426 shoot_parameters_trunk.defineChildShootTypes({"proleptic"},{1});
+
427
+
428 // Proleptic shoots
+
429 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
+
430 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_apple;
+
431 shoot_parameters_proleptic.phytomer_parameters.internode.color = make_RGBcolor(0.3,0.2,0.2);
+
432 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = ApplePhytomerCreationFunction;
+
433 shoot_parameters_proleptic.max_nodes = 40;
+
434 shoot_parameters_proleptic.max_nodes_per_season = 20;
+
435 shoot_parameters_proleptic.phyllochron_min = 2.0;
+
436 shoot_parameters_proleptic.elongation_rate_max = 0.2;
+
437 shoot_parameters_proleptic.girth_area_factor = 5.f;
+
438 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.1;
+
439 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.4;
+
440 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
+
441 shoot_parameters_proleptic.gravitropic_curvature.uniformDistribution(450,500);
+
442 shoot_parameters_proleptic.tortuosity = 3;
+
443 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 30, 40);
+
444 shoot_parameters_proleptic.insertion_angle_decay_rate = 20;
+
445 shoot_parameters_proleptic.internode_length_max = 0.04;
+
446 shoot_parameters_proleptic.internode_length_min = 0.01;
+
447 shoot_parameters_proleptic.internode_length_decay_rate = 0.004;
+
448 shoot_parameters_proleptic.fruit_set_probability = 0.4;
+
449 shoot_parameters_proleptic.flower_bud_break_probability = 0.3;
+
450 shoot_parameters_proleptic.max_terminal_floral_buds = 1;
+
451 shoot_parameters_proleptic.flowers_require_dormancy = true;
+
452 shoot_parameters_proleptic.growth_requires_dormancy = true;
+
453 shoot_parameters_proleptic.determinate_shoot_growth = false;
+
454 shoot_parameters_proleptic.defineChildShootTypes({"proleptic"},{1.0});
+
455
+
456 defineShootType("trunk", shoot_parameters_trunk);
+
457 defineShootType("proleptic", shoot_parameters_proleptic);
+
458
+
459}
+
460
+
461uint PlantArchitecture::buildAppleTree(const helios::vec3 &base_position) {
+
462
+
463 if( shoot_types.empty() ){
+
464 //automatically initialize apple tree shoots
+
465 initializeAppleTreeShoots();
+
466 }
+
467
+
468 uint plantID = addPlantInstance(base_position, 0);
+
469
+
470 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), 0.f * M_PI), 0.015, 0.04, 1.f, 1.f, 0, "trunk");
+
471 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
+
472
+
473 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
+
474
+
475 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
+
476 for( const auto & phytomer : phytomers ){
+
477 phytomer->removeLeaf();
+
478 phytomer->setVegetativeBudState(BUD_DEAD);
+
479 phytomer->setFloralBudState(BUD_DEAD);
+
480 }
481
-
482 }
+
482 uint Nscaffolds = 4;//context_ptr->randu(4,5);
483
-
484 makePlantDormant(plantID);
-
485
-
486 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 30, 200, false);
-
487 plant_instances.at(plantID).max_age = 1460;
-
488
-
489 return plantID;
-
490
-
491}
-
492
-
493void PlantArchitecture::initializeAsparagusShoots() {
+
484 for( int i=0; i<Nscaffolds; i++ ) {
+
485 float pitch = context_ptr->randu(deg2rad(55), deg2rad(65));
+
486 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, context_ptr->randu(7, 9), make_AxisRotation(pitch, (float(i) + context_ptr->randu(-0.2f, 0.2f)) / float(Nscaffolds) * 2 * M_PI, 0), 0.005, 0.04, 1.f, 1.f, 0.5, "proleptic", 0);
+
487
+
488 }
+
489
+
490 makePlantDormant(plantID);
+
491
+
492 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 30, 200, false);
+
493 plant_instances.at(plantID).max_age = 1460;
494
-
495 // ---- Phytomer Parameters ---- //
+
495 return plantID;
496
-
497 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
497}
498
-
499 phytomer_parameters.internode.pitch = 1;
-
500 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(127.5, 147.5);
-
501 phytomer_parameters.internode.radius_initial = 0.00025;
-
502 phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
-
503 phytomer_parameters.internode.max_vegetative_buds_per_petiole = 1;
-
504 phytomer_parameters.internode.color = RGB::forestgreen;
-
505 phytomer_parameters.internode.length_segments = 2;
-
506
-
507 phytomer_parameters.petiole.petioles_per_internode = 1;
-
508 phytomer_parameters.petiole.pitch = 90;
-
509 phytomer_parameters.petiole.radius = 0.0001;
-
510 phytomer_parameters.petiole.length = 0.0005;
-
511 phytomer_parameters.petiole.taper = 0.5;
-
512 phytomer_parameters.petiole.curvature = 0;
-
513 phytomer_parameters.petiole.color = phytomer_parameters.internode.color;
-
514 phytomer_parameters.petiole.length_segments = 1;
-
515 phytomer_parameters.petiole.radial_subdivisions = 5;
-
516
-
517 phytomer_parameters.leaf.leaves_per_petiole = 5;
-
518 phytomer_parameters.leaf.pitch.normalDistribution(-5, 30);
-
519 phytomer_parameters.leaf.yaw = 30;
-
520 phytomer_parameters.leaf.roll = 0;
-
521 phytomer_parameters.leaf.leaflet_offset = 0;
-
522 phytomer_parameters.leaf.leaflet_scale = 0.9;
-
523 phytomer_parameters.leaf.prototype.prototype_function = AsparagusLeafPrototype;
-
524 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.018, 0.02);
-
525// phytomer_parameters.leaf.subdivisions = 6;
-
526
-
527 phytomer_parameters.peduncle.length = 0.17;
-
528 phytomer_parameters.peduncle.radius = 0.0015;
-
529 phytomer_parameters.peduncle.pitch.uniformDistribution(0, 30);
-
530 phytomer_parameters.peduncle.roll = 90;
-
531 phytomer_parameters.peduncle.curvature.uniformDistribution(50, 250);
-
532 phytomer_parameters.peduncle.length_segments = 6;
-
533 phytomer_parameters.peduncle.radial_subdivisions = 6;
-
534
-
535 phytomer_parameters.inflorescence.flowers_per_peduncle.uniformDistribution(1, 3);
-
536 phytomer_parameters.inflorescence.flower_offset = 0.;
-
537 phytomer_parameters.inflorescence.pitch.uniformDistribution(50, 70);
-
538 phytomer_parameters.inflorescence.roll.uniformDistribution(-20, 20);
-
539 phytomer_parameters.inflorescence.flower_prototype_scale = 0.015;
-
540 phytomer_parameters.inflorescence.fruit_prototype_scale.uniformDistribution(0.02, 0.025);
-
541 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0., 0.5);
-
542
-
543 // ---- Shoot Parameters ---- //
-
544
-
545 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
-
546 shoot_parameters.phytomer_parameters = phytomer_parameters;
-
547 shoot_parameters.phytomer_parameters.phytomer_creation_function = AsparagusPhytomerCreationFunction;
+
499void PlantArchitecture::initializeAsparagusShoots() {
+
500
+
501 // ---- Phytomer Parameters ---- //
+
502
+
503 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
504
+
505 phytomer_parameters.internode.pitch = 1;
+
506 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(127.5, 147.5);
+
507 phytomer_parameters.internode.radius_initial = 0.00025;
+
508 phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
+
509 phytomer_parameters.internode.max_vegetative_buds_per_petiole = 1;
+
510 phytomer_parameters.internode.color = RGB::forestgreen;
+
511 phytomer_parameters.internode.length_segments = 2;
+
512
+
513 phytomer_parameters.petiole.petioles_per_internode = 1;
+
514 phytomer_parameters.petiole.pitch = 90;
+
515 phytomer_parameters.petiole.radius = 0.0001;
+
516 phytomer_parameters.petiole.length = 0.0005;
+
517 phytomer_parameters.petiole.taper = 0.5;
+
518 phytomer_parameters.petiole.curvature = 0;
+
519 phytomer_parameters.petiole.color = phytomer_parameters.internode.color;
+
520 phytomer_parameters.petiole.length_segments = 1;
+
521 phytomer_parameters.petiole.radial_subdivisions = 5;
+
522
+
523 phytomer_parameters.leaf.leaves_per_petiole = 5;
+
524 phytomer_parameters.leaf.pitch.normalDistribution(-5, 30);
+
525 phytomer_parameters.leaf.yaw = 30;
+
526 phytomer_parameters.leaf.roll = 0;
+
527 phytomer_parameters.leaf.leaflet_offset = 0;
+
528 phytomer_parameters.leaf.leaflet_scale = 0.9;
+
529 phytomer_parameters.leaf.prototype.prototype_function = AsparagusLeafPrototype;
+
530 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.018, 0.02);
+
531// phytomer_parameters.leaf.subdivisions = 6;
+
532
+
533 phytomer_parameters.peduncle.length = 0.17;
+
534 phytomer_parameters.peduncle.radius = 0.0015;
+
535 phytomer_parameters.peduncle.pitch.uniformDistribution(0, 30);
+
536 phytomer_parameters.peduncle.roll = 90;
+
537 phytomer_parameters.peduncle.curvature.uniformDistribution(50, 250);
+
538 phytomer_parameters.peduncle.length_segments = 6;
+
539 phytomer_parameters.peduncle.radial_subdivisions = 6;
+
540
+
541 phytomer_parameters.inflorescence.flowers_per_peduncle.uniformDistribution(1, 3);
+
542 phytomer_parameters.inflorescence.flower_offset = 0.;
+
543 phytomer_parameters.inflorescence.pitch.uniformDistribution(50, 70);
+
544 phytomer_parameters.inflorescence.roll.uniformDistribution(-20, 20);
+
545 phytomer_parameters.inflorescence.flower_prototype_scale = 0.015;
+
546 phytomer_parameters.inflorescence.fruit_prototype_scale.uniformDistribution(0.02, 0.025);
+
547 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0., 0.5);
548
-
549 shoot_parameters.max_nodes = 20;
-
550 shoot_parameters.insertion_angle_tip.uniformDistribution(40, 70);
-
551// shoot_parameters.child_insertion_angle_decay_rate = 0; (default)
-
552 shoot_parameters.internode_length_max = 0.015;
-
553// shoot_parameters.child_internode_length_min = 0.0; (default)
-
554// shoot_parameters.child_internode_length_decay_rate = 0; (default)
-
555 shoot_parameters.base_roll = 90;
-
556 shoot_parameters.base_yaw.uniformDistribution(-20, 20);
-
557 shoot_parameters.gravitropic_curvature = -200;
-
558
-
559 shoot_parameters.phyllochron_min = 1;
-
560 shoot_parameters.elongation_rate = 0.15;
-
561// shoot_parameters.girth_growth_rate = 0.00005;
-
562 shoot_parameters.girth_area_factor = 30;
-
563 shoot_parameters.vegetative_bud_break_time = 5;
-
564 shoot_parameters.vegetative_bud_break_probability_min = 0.25;
-
565// shoot_parameters.max_terminal_floral_buds = 0; (default)
-
566// shoot_parameters.flower_bud_break_probability.uniformDistribution(0.1, 0.2);
-
567 shoot_parameters.fruit_set_probability = 0.;
-
568// shoot_parameters.flowers_require_dormancy = false; (default)
-
569// shoot_parameters.growth_requires_dormancy = false; (default)
-
570// shoot_parameters.determinate_shoot_growth = true; (default)
-
571
-
572 shoot_parameters.defineChildShootTypes({"main"}, {1.0});
-
573
-
574 defineShootType("main", shoot_parameters);
-
575
-
576}
+
549 // ---- Shoot Parameters ---- //
+
550
+
551 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
552 shoot_parameters.phytomer_parameters = phytomer_parameters;
+
553 shoot_parameters.phytomer_parameters.phytomer_creation_function = AsparagusPhytomerCreationFunction;
+
554
+
555 shoot_parameters.max_nodes = 20;
+
556 shoot_parameters.insertion_angle_tip.uniformDistribution(40, 70);
+
557// shoot_parameters.child_insertion_angle_decay_rate = 0; (default)
+
558 shoot_parameters.internode_length_max = 0.015;
+
559// shoot_parameters.child_internode_length_min = 0.0; (default)
+
560// shoot_parameters.child_internode_length_decay_rate = 0; (default)
+
561 shoot_parameters.base_roll = 90;
+
562 shoot_parameters.base_yaw.uniformDistribution(-20, 20);
+
563 shoot_parameters.gravitropic_curvature = -200;
+
564
+
565 shoot_parameters.phyllochron_min = 1;
+
566 shoot_parameters.elongation_rate_max = 0.15;
+
567// shoot_parameters.girth_growth_rate = 0.00005;
+
568 shoot_parameters.girth_area_factor = 30;
+
569 shoot_parameters.vegetative_bud_break_time = 5;
+
570 shoot_parameters.vegetative_bud_break_probability_min = 0.25;
+
571// shoot_parameters.max_terminal_floral_buds = 0; (default)
+
572// shoot_parameters.flower_bud_break_probability.uniformDistribution(0.1, 0.2);
+
573 shoot_parameters.fruit_set_probability = 0.;
+
574// shoot_parameters.flowers_require_dormancy = false; (default)
+
575// shoot_parameters.growth_requires_dormancy = false; (default)
+
576// shoot_parameters.determinate_shoot_growth = true; (default)
577
-
578uint PlantArchitecture::buildAsparagusPlant(const helios::vec3 &base_position) {
+
578 shoot_parameters.defineChildShootTypes({"main"}, {1.0});
579
-
580 if (shoot_types.empty()) {
-
581 //automatically initialize asparagus plant shoots
-
582 initializeAsparagusShoots();
-
583 }
-
584
-
585 uint plantID = addPlantInstance(base_position, 0);
-
586
-
587 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(0, 0.f, 0.f), 0.0003, 0.015, 1, 0.1, 0.1, "main");
-
588
-
589 breakPlantDormancy(plantID);
+
580 defineShootType("main", shoot_parameters);
+
581
+
582}
+
583
+
584uint PlantArchitecture::buildAsparagusPlant(const helios::vec3 &base_position) {
+
585
+
586 if (shoot_types.empty()) {
+
587 //automatically initialize asparagus plant shoots
+
588 initializeAsparagusShoots();
+
589 }
590
-
591 setPlantPhenologicalThresholds(plantID, 0, -1, -1, -1, 5, 100, false);
+
591 uint plantID = addPlantInstance(base_position, 0);
592
-
593 plant_instances.at(plantID).max_age = 20;
+
593 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(0, 0.f, 0.f), 0.0003, 0.015, 1, 0.1, 0.1, "main");
594
-
595 return plantID;
+
595 breakPlantDormancy(plantID);
596
-
597}
+
597 setPlantPhenologicalThresholds(plantID, 0, -1, -1, -1, 5, 100, false);
598
-
599void PlantArchitecture::initializeBindweedShoots() {
+
599 plant_instances.at(plantID).max_age = 20;
600
-
601 // ---- Phytomer Parameters ---- //
+
601 return plantID;
602
-
603 PhytomerParameters phytomer_parameters_bindweed(context_ptr->getRandomGenerator());
+
603}
604
-
605 phytomer_parameters_bindweed.internode.pitch.uniformDistribution(0,15);
-
606 phytomer_parameters_bindweed.internode.phyllotactic_angle = 180.f;
-
607 phytomer_parameters_bindweed.internode.radius_initial = 0.0012;
-
608 phytomer_parameters_bindweed.internode.color = make_RGBcolor(0.3,0.38,0.21);
-
609 phytomer_parameters_bindweed.internode.length_segments = 1;
+
605void PlantArchitecture::initializeBindweedShoots() {
+
606
+
607 // ---- Phytomer Parameters ---- //
+
608
+
609 PhytomerParameters phytomer_parameters_bindweed(context_ptr->getRandomGenerator());
610
-
611 phytomer_parameters_bindweed.petiole.petioles_per_internode = 1;
-
612 phytomer_parameters_bindweed.petiole.pitch.uniformDistribution(80, 100);
-
613 phytomer_parameters_bindweed.petiole.radius = 0.001;
-
614 phytomer_parameters_bindweed.petiole.length = 0.006;
-
615 phytomer_parameters_bindweed.petiole.taper = 0;
-
616 phytomer_parameters_bindweed.petiole.curvature = 0;
-
617 phytomer_parameters_bindweed.petiole.color = phytomer_parameters_bindweed.internode.color;
-
618 phytomer_parameters_bindweed.petiole.length_segments = 1;
-
619
-
620 phytomer_parameters_bindweed.leaf.leaves_per_petiole = 1;
-
621 phytomer_parameters_bindweed.leaf.pitch.uniformDistribution(5, 30);
-
622 phytomer_parameters_bindweed.leaf.yaw = 0;
-
623 phytomer_parameters_bindweed.leaf.roll = 90;
-
624 phytomer_parameters_bindweed.leaf.prototype_scale = 0.05;
-
625 phytomer_parameters_bindweed.leaf.prototype.OBJ_model_file = "plugins/plantarchitecture/assets/obj/BindweedLeaf.obj";
-
626
-
627 phytomer_parameters_bindweed.peduncle.length = 0.01;
-
628 phytomer_parameters_bindweed.peduncle.radius = 0.0005;
-
629 phytomer_parameters_bindweed.peduncle.color = phytomer_parameters_bindweed.internode.color;
-
630
-
631 phytomer_parameters_bindweed.inflorescence.flowers_per_peduncle = 1;
-
632 phytomer_parameters_bindweed.inflorescence.pitch = -90.f;
-
633 phytomer_parameters_bindweed.inflorescence.flower_prototype_function = BindweedFlowerPrototype;
-
634 phytomer_parameters_bindweed.inflorescence.flower_prototype_scale = 0.045;
-
635
-
636 // ---- Shoot Parameters ---- //
-
637
-
638 ShootParameters shoot_parameters_primary(context_ptr->getRandomGenerator());
-
639 shoot_parameters_primary.phytomer_parameters = phytomer_parameters_bindweed;
-
640 shoot_parameters_primary.vegetative_bud_break_probability_min = 0.15;
-
641 shoot_parameters_primary.vegetative_bud_break_probability_decay_rate = -1.;
-
642 shoot_parameters_primary.vegetative_bud_break_time = 3;
-
643 shoot_parameters_primary.base_roll = 90;
-
644 shoot_parameters_primary.phyllochron_min = 1;
-
645 shoot_parameters_primary.elongation_rate = 0.25;
-
646 shoot_parameters_primary.girth_area_factor = 0;
-
647 shoot_parameters_primary.internode_length_max = 0.03;
-
648 shoot_parameters_primary.internode_length_decay_rate = 0;
-
649 shoot_parameters_primary.insertion_angle_tip.uniformDistribution(50, 80);
-
650 shoot_parameters_primary.flowers_require_dormancy = false;
-
651 shoot_parameters_primary.growth_requires_dormancy = false;
-
652 shoot_parameters_primary.flower_bud_break_probability = 0.2;
-
653 shoot_parameters_primary.determinate_shoot_growth = false;
-
654 shoot_parameters_primary.max_nodes = 15;
-
655 shoot_parameters_primary.gravitropic_curvature = 40;
-
656 shoot_parameters_primary.tortuosity = 0;
-
657 shoot_parameters_primary.defineChildShootTypes({"secondary_bindweed"}, {1.f});
-
658
-
659 ShootParameters shoot_parameters_base = shoot_parameters_primary;
-
660 shoot_parameters_base.phytomer_parameters = phytomer_parameters_bindweed;
-
661 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
-
662 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
-
663 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
-
664 shoot_parameters_base.vegetative_bud_break_probability_min = 1.0;
-
665 shoot_parameters_base.vegetative_bud_break_time = 2;
-
666 shoot_parameters_base.phyllochron_min = 2;
-
667 shoot_parameters_base.elongation_rate = 0.15;
-
668 shoot_parameters_base.girth_area_factor = 0.f;
-
669 shoot_parameters_base.gravitropic_curvature = 0;
-
670 shoot_parameters_base.internode_length_max = 0.01;
-
671 shoot_parameters_base.internode_length_decay_rate = 0;
-
672 shoot_parameters_base.insertion_angle_tip = 95;
-
673 shoot_parameters_base.insertion_angle_decay_rate = 0;
-
674 shoot_parameters_base.flowers_require_dormancy = false;
-
675 shoot_parameters_base.growth_requires_dormancy = false;
-
676 shoot_parameters_base.flower_bud_break_probability = 0.0;
-
677 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
-
678 shoot_parameters_base.defineChildShootTypes({"primary_bindweed"},{1.f});
-
679
-
680 ShootParameters shoot_parameters_children = shoot_parameters_primary;
-
681 shoot_parameters_children.base_roll = 0;
-
682
-
683 defineShootType("base_bindweed", shoot_parameters_base);
-
684 defineShootType("primary_bindweed", shoot_parameters_primary);
-
685 defineShootType("secondary_bindweed", shoot_parameters_children);
-
686
-
687}
+
611 phytomer_parameters_bindweed.internode.pitch.uniformDistribution(0,15);
+
612 phytomer_parameters_bindweed.internode.phyllotactic_angle = 180.f;
+
613 phytomer_parameters_bindweed.internode.radius_initial = 0.0012;
+
614 phytomer_parameters_bindweed.internode.color = make_RGBcolor(0.3,0.38,0.21);
+
615 phytomer_parameters_bindweed.internode.length_segments = 1;
+
616
+
617 phytomer_parameters_bindweed.petiole.petioles_per_internode = 1;
+
618 phytomer_parameters_bindweed.petiole.pitch.uniformDistribution(80, 100);
+
619 phytomer_parameters_bindweed.petiole.radius = 0.001;
+
620 phytomer_parameters_bindweed.petiole.length = 0.006;
+
621 phytomer_parameters_bindweed.petiole.taper = 0;
+
622 phytomer_parameters_bindweed.petiole.curvature = 0;
+
623 phytomer_parameters_bindweed.petiole.color = phytomer_parameters_bindweed.internode.color;
+
624 phytomer_parameters_bindweed.petiole.length_segments = 1;
+
625
+
626 phytomer_parameters_bindweed.leaf.leaves_per_petiole = 1;
+
627 phytomer_parameters_bindweed.leaf.pitch.uniformDistribution(5, 30);
+
628 phytomer_parameters_bindweed.leaf.yaw = 0;
+
629 phytomer_parameters_bindweed.leaf.roll = 90;
+
630 phytomer_parameters_bindweed.leaf.prototype_scale = 0.05;
+
631 phytomer_parameters_bindweed.leaf.prototype.OBJ_model_file = "plugins/plantarchitecture/assets/obj/BindweedLeaf.obj";
+
632
+
633 phytomer_parameters_bindweed.peduncle.length = 0.01;
+
634 phytomer_parameters_bindweed.peduncle.radius = 0.0005;
+
635 phytomer_parameters_bindweed.peduncle.color = phytomer_parameters_bindweed.internode.color;
+
636
+
637 phytomer_parameters_bindweed.inflorescence.flowers_per_peduncle = 1;
+
638 phytomer_parameters_bindweed.inflorescence.pitch = -90.f;
+
639 phytomer_parameters_bindweed.inflorescence.flower_prototype_function = BindweedFlowerPrototype;
+
640 phytomer_parameters_bindweed.inflorescence.flower_prototype_scale = 0.045;
+
641
+
642 // ---- Shoot Parameters ---- //
+
643
+
644 ShootParameters shoot_parameters_primary(context_ptr->getRandomGenerator());
+
645 shoot_parameters_primary.phytomer_parameters = phytomer_parameters_bindweed;
+
646 shoot_parameters_primary.vegetative_bud_break_probability_min = 0.15;
+
647 shoot_parameters_primary.vegetative_bud_break_probability_decay_rate = -1.;
+
648 shoot_parameters_primary.vegetative_bud_break_time = 3;
+
649 shoot_parameters_primary.base_roll = 90;
+
650 shoot_parameters_primary.phyllochron_min = 1;
+
651 shoot_parameters_primary.elongation_rate_max = 0.3;
+
652 shoot_parameters_primary.girth_area_factor = 0;
+
653 shoot_parameters_primary.internode_length_max = 0.03;
+
654 shoot_parameters_primary.internode_length_decay_rate = 0;
+
655 shoot_parameters_primary.insertion_angle_tip.uniformDistribution(50, 80);
+
656 shoot_parameters_primary.flowers_require_dormancy = false;
+
657 shoot_parameters_primary.growth_requires_dormancy = false;
+
658 shoot_parameters_primary.flower_bud_break_probability = 0.2;
+
659 shoot_parameters_primary.determinate_shoot_growth = false;
+
660 shoot_parameters_primary.max_nodes = 15;
+
661 shoot_parameters_primary.gravitropic_curvature = 40;
+
662 shoot_parameters_primary.tortuosity = 0;
+
663 shoot_parameters_primary.defineChildShootTypes({"secondary_bindweed"}, {1.f});
+
664
+
665 ShootParameters shoot_parameters_base = shoot_parameters_primary;
+
666 shoot_parameters_base.phytomer_parameters = phytomer_parameters_bindweed;
+
667 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
+
668 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
+
669 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
+
670 shoot_parameters_base.vegetative_bud_break_probability_min = 1.0;
+
671 shoot_parameters_base.vegetative_bud_break_time = 2;
+
672 shoot_parameters_base.phyllochron_min = 2;
+
673 shoot_parameters_base.elongation_rate_max = 0.15;
+
674 shoot_parameters_base.girth_area_factor = 0.f;
+
675 shoot_parameters_base.gravitropic_curvature = 0;
+
676 shoot_parameters_base.internode_length_max = 0.01;
+
677 shoot_parameters_base.internode_length_decay_rate = 0;
+
678 shoot_parameters_base.insertion_angle_tip = 95;
+
679 shoot_parameters_base.insertion_angle_decay_rate = 0;
+
680 shoot_parameters_base.flowers_require_dormancy = false;
+
681 shoot_parameters_base.growth_requires_dormancy = false;
+
682 shoot_parameters_base.flower_bud_break_probability = 0.0;
+
683 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
+
684 shoot_parameters_base.defineChildShootTypes({"primary_bindweed"},{1.f});
+
685
+
686 ShootParameters shoot_parameters_children = shoot_parameters_primary;
+
687 shoot_parameters_children.base_roll = 0;
688
-
689uint PlantArchitecture::buildBindweedPlant(const helios::vec3 &base_position) {
-
690
-
691 if (shoot_types.empty()) {
-
692 //automatically initialize bindweed plant shoots
-
693 initializeBindweedShoots();
-
694 }
-
695
-
696 uint plantID = addPlantInstance(base_position, 0);
-
697
-
698 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, 0, "base_bindweed");
-
699
-
700 breakPlantDormancy(plantID);
+
689 defineShootType("base_bindweed", shoot_parameters_base);
+
690 defineShootType("primary_bindweed", shoot_parameters_primary);
+
691 defineShootType("secondary_bindweed", shoot_parameters_children);
+
692
+
693}
+
694
+
695uint PlantArchitecture::buildBindweedPlant(const helios::vec3 &base_position) {
+
696
+
697 if (shoot_types.empty()) {
+
698 //automatically initialize bindweed plant shoots
+
699 initializeBindweedShoots();
+
700 }
701
-
702 setPlantPhenologicalThresholds(plantID, 0, -1, 14, -1, -1, 1000, false);
+
702 uint plantID = addPlantInstance(base_position, 0);
703
-
704 plant_instances.at(plantID).max_age = 50;
+
704 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, 0, "base_bindweed");
705
-
706 return plantID;
+
706 breakPlantDormancy(plantID);
707
-
708}
+
708 setPlantPhenologicalThresholds(plantID, 0, -1, 14, -1, -1, 1000, false);
709
-
710void PlantArchitecture::initializeBeanShoots() {
+
710 plant_instances.at(plantID).max_age = 50;
711
-
712 // ---- Leaf Prototype ---- //
+
712 return plantID;
713
-
714 LeafPrototype leaf_prototype_trifoliate(context_ptr->getRandomGenerator());
-
715 leaf_prototype_trifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/BeanLeaf_tip.png";
-
716 leaf_prototype_trifoliate.leaf_texture_file[-1] = "plugins/plantarchitecture/assets/textures/BeanLeaf_left_centered.png";
-
717 leaf_prototype_trifoliate.leaf_texture_file[1] = "plugins/plantarchitecture/assets/textures/BeanLeaf_right_centered.png";
-
718 leaf_prototype_trifoliate.leaf_aspect_ratio = 1.f;
-
719 leaf_prototype_trifoliate.midrib_fold_fraction = 0.2;
-
720 leaf_prototype_trifoliate.longitudinal_curvature.uniformDistribution(-0.3f, -0.2f);
-
721 leaf_prototype_trifoliate.lateral_curvature = -1.f;
-
722 leaf_prototype_trifoliate.subdivisions = 6;
-
723 leaf_prototype_trifoliate.unique_prototypes = 5;
-
724 leaf_prototype_trifoliate.build_petiolule = true;
-
725
-
726 LeafPrototype leaf_prototype_unifoliate = leaf_prototype_trifoliate;
-
727 leaf_prototype_unifoliate.leaf_texture_file.clear();
-
728 leaf_prototype_unifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/BeanLeaf_unifoliate_centered.png";
-
729 leaf_prototype_unifoliate.unique_prototypes = 2;
-
730
-
731 // ---- Phytomer Parameters ---- //
-
732
-
733 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
-
734
-
735 phytomer_parameters_trifoliate.internode.pitch = 20;
-
736 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
-
737 phytomer_parameters_trifoliate.internode.radius_initial = 0.001;
-
738 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
-
739 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
-
740 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.2,0.25,0.05);
-
741 phytomer_parameters_trifoliate.internode.length_segments = 2;
-
742
-
743 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
-
744 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(20,50);
-
745 phytomer_parameters_trifoliate.petiole.radius = 0.0015;
-
746 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.1,0.14);
-
747 phytomer_parameters_trifoliate.petiole.taper = 0.;
-
748 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-100,200);
-
749 phytomer_parameters_trifoliate.petiole.color = make_RGBcolor(0.28,0.35,0.07);
-
750 phytomer_parameters_trifoliate.petiole.length_segments = 5;
-
751 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
-
752
-
753 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
-
754 phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 20);
-
755 phytomer_parameters_trifoliate.leaf.yaw = 10;
-
756 phytomer_parameters_trifoliate.leaf.roll = -15;
-
757 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.3;
-
758 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
-
759 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.09,0.11);
-
760 phytomer_parameters_trifoliate.leaf.prototype = leaf_prototype_trifoliate;
-
761
-
762 phytomer_parameters_trifoliate.peduncle.length = 0.04;
-
763 phytomer_parameters_trifoliate.peduncle.radius = 0.00075;
-
764 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
-
765 phytomer_parameters_trifoliate.peduncle.roll = 90;
-
766 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
-
767 phytomer_parameters_trifoliate.peduncle.color = phytomer_parameters_trifoliate.petiole.color;
-
768 phytomer_parameters_trifoliate.peduncle.length_segments = 1;
-
769 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
-
770
-
771 phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle.uniformDistribution(1, 4);
-
772 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
-
773 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
-
774 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
-
775 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.03;
-
776 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = BeanFlowerPrototype;
-
777 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.15,0.2);
-
778 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = BeanFruitPrototype;
-
779 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
-
780
-
781 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
-
782 phytomer_parameters_unifoliate.internode.pitch = 0;
-
783 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 1;
-
784 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
-
785 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
-
786 phytomer_parameters_unifoliate.petiole.length = 0.0001;
-
787 phytomer_parameters_unifoliate.petiole.radius = 0.0004;
-
788 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(50,70);
-
789 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
-
790 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.04;
-
791 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
-
792 phytomer_parameters_unifoliate.leaf.prototype = leaf_prototype_unifoliate;
-
793
-
794 // ---- Shoot Parameters ---- //
-
795
-
796 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
-
797 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
-
798 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
+
714}
+
715
+
716void PlantArchitecture::initializeBeanShoots() {
+
717
+
718 // ---- Leaf Prototype ---- //
+
719
+
720 LeafPrototype leaf_prototype_trifoliate(context_ptr->getRandomGenerator());
+
721 leaf_prototype_trifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/BeanLeaf_tip.png";
+
722 leaf_prototype_trifoliate.leaf_texture_file[-1] = "plugins/plantarchitecture/assets/textures/BeanLeaf_left_centered.png";
+
723 leaf_prototype_trifoliate.leaf_texture_file[1] = "plugins/plantarchitecture/assets/textures/BeanLeaf_right_centered.png";
+
724 leaf_prototype_trifoliate.leaf_aspect_ratio = 1.f;
+
725 leaf_prototype_trifoliate.midrib_fold_fraction = 0.2;
+
726 leaf_prototype_trifoliate.longitudinal_curvature.uniformDistribution(-0.3f, -0.2f);
+
727 leaf_prototype_trifoliate.lateral_curvature = -1.f;
+
728 leaf_prototype_trifoliate.subdivisions = 6;
+
729 leaf_prototype_trifoliate.unique_prototypes = 5;
+
730 leaf_prototype_trifoliate.build_petiolule = true;
+
731
+
732 LeafPrototype leaf_prototype_unifoliate = leaf_prototype_trifoliate;
+
733 leaf_prototype_unifoliate.leaf_texture_file.clear();
+
734 leaf_prototype_unifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/BeanLeaf_unifoliate_centered.png";
+
735 leaf_prototype_unifoliate.unique_prototypes = 2;
+
736
+
737 // ---- Phytomer Parameters ---- //
+
738
+
739 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
740
+
741 phytomer_parameters_trifoliate.internode.pitch = 20;
+
742 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
743 phytomer_parameters_trifoliate.internode.radius_initial = 0.001;
+
744 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
745 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
746 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.2,0.25,0.05);
+
747 phytomer_parameters_trifoliate.internode.length_segments = 2;
+
748
+
749 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
750 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(20,50);
+
751 phytomer_parameters_trifoliate.petiole.radius = 0.0015;
+
752 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.1,0.14);
+
753 phytomer_parameters_trifoliate.petiole.taper = 0.;
+
754 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-100,200);
+
755 phytomer_parameters_trifoliate.petiole.color = make_RGBcolor(0.28,0.35,0.07);
+
756 phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
757 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
758
+
759 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
760 phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 20);
+
761 phytomer_parameters_trifoliate.leaf.yaw = 10;
+
762 phytomer_parameters_trifoliate.leaf.roll = -15;
+
763 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.3;
+
764 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
765 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.09,0.11);
+
766 phytomer_parameters_trifoliate.leaf.prototype = leaf_prototype_trifoliate;
+
767
+
768 phytomer_parameters_trifoliate.peduncle.length = 0.04;
+
769 phytomer_parameters_trifoliate.peduncle.radius = 0.00075;
+
770 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
+
771 phytomer_parameters_trifoliate.peduncle.roll = 90;
+
772 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
+
773 phytomer_parameters_trifoliate.peduncle.color = phytomer_parameters_trifoliate.petiole.color;
+
774 phytomer_parameters_trifoliate.peduncle.length_segments = 1;
+
775 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
776
+
777 phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle.uniformDistribution(1, 4);
+
778 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
+
779 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
780 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
781 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.03;
+
782 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = BeanFlowerPrototype;
+
783 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.15,0.2);
+
784 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = BeanFruitPrototype;
+
785 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
+
786
+
787 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
788 phytomer_parameters_unifoliate.internode.pitch = 0;
+
789 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
790 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
791 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
792 phytomer_parameters_unifoliate.petiole.length = 0.0001;
+
793 phytomer_parameters_unifoliate.petiole.radius = 0.0004;
+
794 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(50,70);
+
795 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
796 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.04;
+
797 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
798 phytomer_parameters_unifoliate.leaf.prototype = leaf_prototype_unifoliate;
799
-
800 shoot_parameters_trifoliate.max_nodes = 25;
-
801 shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(40,60);
-
802// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
-
803 shoot_parameters_trifoliate.internode_length_max = 0.025;
-
804// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
-
805// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
-
806 shoot_parameters_trifoliate.base_roll = 90;
-
807 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
-
808 shoot_parameters_trifoliate.gravitropic_curvature = 200;
-
809
-
810 shoot_parameters_trifoliate.phyllochron_min = 2;
-
811 shoot_parameters_trifoliate.elongation_rate = 0.1;
-
812 shoot_parameters_trifoliate.girth_area_factor = 1.5f;
-
813 shoot_parameters_trifoliate.vegetative_bud_break_time = 15;
-
814 shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.1;
-
815 shoot_parameters_trifoliate.vegetative_bud_break_probability_decay_rate = -0.4;
-
816// shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default)
-
817 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.3,0.4);
-
818 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
-
819// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
-
820// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
-
821// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
-
822
-
823 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
824
-
825
-
826 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
-
827 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
-
828 shoot_parameters_unifoliate.phytomer_parameters.phytomer_creation_function = nullptr;
-
829 shoot_parameters_unifoliate.max_nodes = 1;
-
830 shoot_parameters_unifoliate.girth_area_factor = 1.f;
-
831 shoot_parameters_unifoliate.vegetative_bud_break_probability_min = 1.0;
-
832 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
-
833 shoot_parameters_unifoliate.insertion_angle_tip = 50;
-
834 shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
-
835 shoot_parameters_unifoliate.vegetative_bud_break_time = 8;
-
836 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
837
-
838 defineShootType("unifoliate",shoot_parameters_unifoliate);
-
839 defineShootType("trifoliate",shoot_parameters_trifoliate);
-
840
-
841
-
842}
+
800 // ---- Shoot Parameters ---- //
+
801
+
802 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
803 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
804 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
+
805
+
806 shoot_parameters_trifoliate.max_nodes = 25;
+
807 shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(40,60);
+
808// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
+
809 shoot_parameters_trifoliate.internode_length_max = 0.025;
+
810// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
+
811// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
+
812 shoot_parameters_trifoliate.base_roll = 90;
+
813 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
814 shoot_parameters_trifoliate.gravitropic_curvature = 200;
+
815
+
816 shoot_parameters_trifoliate.phyllochron_min = 2;
+
817 shoot_parameters_trifoliate.elongation_rate_max = 0.1;
+
818 shoot_parameters_trifoliate.girth_area_factor = 1.5f;
+
819 shoot_parameters_trifoliate.vegetative_bud_break_time = 15;
+
820 shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.1;
+
821 shoot_parameters_trifoliate.vegetative_bud_break_probability_decay_rate = -0.4;
+
822// shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default)
+
823 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.3,0.4);
+
824 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
+
825// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
+
826// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
+
827// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
+
828
+
829 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
830
+
831
+
832 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
833 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
834 shoot_parameters_unifoliate.phytomer_parameters.phytomer_creation_function = nullptr;
+
835 shoot_parameters_unifoliate.max_nodes = 1;
+
836 shoot_parameters_unifoliate.girth_area_factor = 1.f;
+
837 shoot_parameters_unifoliate.vegetative_bud_break_probability_min = 1.0;
+
838 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
839 shoot_parameters_unifoliate.insertion_angle_tip = 50;
+
840 shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
+
841 shoot_parameters_unifoliate.vegetative_bud_break_time = 8;
+
842 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
843
-
844uint PlantArchitecture::buildBeanPlant(const helios::vec3 &base_position) {
-
845
-
846 if (shoot_types.empty()) {
-
847 //automatically initialize bean plant shoots
-
848 initializeBeanShoots();
-
849 }
-
850
-
851 uint plantID = addPlantInstance(base_position, 0);
-
852
-
853 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));
-
854 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.03, 0.01, 0.01, 0, "unifoliate");
-
855
-
856 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f * M_PI), shoot_types.at("trifoliate").phytomer_parameters.internode.radius_initial.val(), shoot_types.at("trifoliate").internode_length_max.val(), 0.1, 0.1, 0, "trifoliate");
-
857
-
858 breakPlantDormancy(plantID);
-
859
-
860 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 1000, false);
+
844 defineShootType("unifoliate",shoot_parameters_unifoliate);
+
845 defineShootType("trifoliate",shoot_parameters_trifoliate);
+
846
+
847
+
848}
+
849
+
850uint PlantArchitecture::buildBeanPlant(const helios::vec3 &base_position) {
+
851
+
852 if (shoot_types.empty()) {
+
853 //automatically initialize bean plant shoots
+
854 initializeBeanShoots();
+
855 }
+
856
+
857 uint plantID = addPlantInstance(base_position, 0);
+
858
+
859 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));
+
860 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.03, 0.01, 0.01, 0, "unifoliate");
861
-
862 plant_instances.at(plantID).max_age = 365;
+
862 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f * M_PI), shoot_types.at("trifoliate").phytomer_parameters.internode.radius_initial.val(), shoot_types.at("trifoliate").internode_length_max.val(), 0.1, 0.1, 0, "trifoliate");
863
-
864 return plantID;
+
864 breakPlantDormancy(plantID);
865
-
866}
+
866 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 1000, false);
867
-
868void PlantArchitecture::initializeCheeseweedShoots() {
+
868 plant_instances.at(plantID).max_age = 365;
869
-
870 // ---- Leaf Prototype ---- //
+
870 return plantID;
871
-
872 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
873 leaf_prototype.OBJ_model_file = "plugins/plantarchitecture/assets/obj/CheeseweedLeaf.obj";
-
874
-
875 // ---- Phytomer Parameters ---- //
-
876
-
877 PhytomerParameters phytomer_parameters_cheeseweed(context_ptr->getRandomGenerator());
-
878
-
879 phytomer_parameters_cheeseweed.internode.pitch = 0;
-
880 phytomer_parameters_cheeseweed.internode.phyllotactic_angle.uniformDistribution( 127.5f, 147.5);
-
881 phytomer_parameters_cheeseweed.internode.radius_initial = 0.0005;
-
882 phytomer_parameters_cheeseweed.internode.color = make_RGBcolor(0.60, 0.65, 0.40);
-
883 phytomer_parameters_cheeseweed.internode.length_segments = 1;
+
872}
+
873
+
874void PlantArchitecture::initializeCheeseweedShoots() {
+
875
+
876 // ---- Leaf Prototype ---- //
+
877
+
878 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
879 leaf_prototype.OBJ_model_file = "plugins/plantarchitecture/assets/obj/CheeseweedLeaf.obj";
+
880
+
881 // ---- Phytomer Parameters ---- //
+
882
+
883 PhytomerParameters phytomer_parameters_cheeseweed(context_ptr->getRandomGenerator());
884
-
885 phytomer_parameters_cheeseweed.petiole.petioles_per_internode = 1;
-
886 phytomer_parameters_cheeseweed.petiole.pitch.uniformDistribution(45, 75);
-
887 phytomer_parameters_cheeseweed.petiole.radius = 0.0005;
-
888 phytomer_parameters_cheeseweed.petiole.length.uniformDistribution(0.02,0.06);
-
889 phytomer_parameters_cheeseweed.petiole.taper = 0;
-
890 phytomer_parameters_cheeseweed.petiole.curvature = -300;
-
891 phytomer_parameters_cheeseweed.petiole.length_segments = 5;
-
892 phytomer_parameters_cheeseweed.petiole.color = phytomer_parameters_cheeseweed.internode.color;
-
893
-
894 phytomer_parameters_cheeseweed.leaf.leaves_per_petiole = 1;
-
895 phytomer_parameters_cheeseweed.leaf.pitch.uniformDistribution(-30, 0);
-
896 phytomer_parameters_cheeseweed.leaf.yaw = 0;
-
897 phytomer_parameters_cheeseweed.leaf.roll = 0;
-
898 phytomer_parameters_cheeseweed.leaf.prototype_scale = 0.035;
-
899 phytomer_parameters_cheeseweed.leaf.prototype = leaf_prototype;
-
900
-
901 // ---- Shoot Parameters ---- //
-
902
-
903 ShootParameters shoot_parameters_base(context_ptr->getRandomGenerator());
-
904 shoot_parameters_base.phytomer_parameters = phytomer_parameters_cheeseweed;
-
905 shoot_parameters_base.vegetative_bud_break_probability_min = 0.2;
-
906 shoot_parameters_base.vegetative_bud_break_time = 6;
-
907 shoot_parameters_base.phyllochron_min = 2;
-
908 shoot_parameters_base.elongation_rate = 0.1;
-
909 shoot_parameters_base.girth_area_factor = 10.f;
-
910 shoot_parameters_base.gravitropic_curvature = 0;
-
911 shoot_parameters_base.internode_length_max = 0.0015;
-
912 shoot_parameters_base.internode_length_decay_rate = 0;
-
913 shoot_parameters_base.flowers_require_dormancy = false;
-
914 shoot_parameters_base.growth_requires_dormancy = false;
-
915 shoot_parameters_base.flower_bud_break_probability = 0.;
-
916 shoot_parameters_base.max_nodes = 8;
-
917
-
918 defineShootType("base", shoot_parameters_base);
-
919
-
920}
-
921
-
922uint PlantArchitecture::buildCheeseweedPlant(const helios::vec3 &base_position) {
+
885 phytomer_parameters_cheeseweed.internode.pitch = 0;
+
886 phytomer_parameters_cheeseweed.internode.phyllotactic_angle.uniformDistribution( 127.5f, 147.5);
+
887 phytomer_parameters_cheeseweed.internode.radius_initial = 0.0005;
+
888 phytomer_parameters_cheeseweed.internode.color = make_RGBcolor(0.60, 0.65, 0.40);
+
889 phytomer_parameters_cheeseweed.internode.length_segments = 1;
+
890
+
891 phytomer_parameters_cheeseweed.petiole.petioles_per_internode = 1;
+
892 phytomer_parameters_cheeseweed.petiole.pitch.uniformDistribution(45, 75);
+
893 phytomer_parameters_cheeseweed.petiole.radius = 0.0005;
+
894 phytomer_parameters_cheeseweed.petiole.length.uniformDistribution(0.02,0.06);
+
895 phytomer_parameters_cheeseweed.petiole.taper = 0;
+
896 phytomer_parameters_cheeseweed.petiole.curvature = -300;
+
897 phytomer_parameters_cheeseweed.petiole.length_segments = 5;
+
898 phytomer_parameters_cheeseweed.petiole.color = phytomer_parameters_cheeseweed.internode.color;
+
899
+
900 phytomer_parameters_cheeseweed.leaf.leaves_per_petiole = 1;
+
901 phytomer_parameters_cheeseweed.leaf.pitch.uniformDistribution(-30, 0);
+
902 phytomer_parameters_cheeseweed.leaf.yaw = 0;
+
903 phytomer_parameters_cheeseweed.leaf.roll = 0;
+
904 phytomer_parameters_cheeseweed.leaf.prototype_scale = 0.035;
+
905 phytomer_parameters_cheeseweed.leaf.prototype = leaf_prototype;
+
906
+
907 // ---- Shoot Parameters ---- //
+
908
+
909 ShootParameters shoot_parameters_base(context_ptr->getRandomGenerator());
+
910 shoot_parameters_base.phytomer_parameters = phytomer_parameters_cheeseweed;
+
911 shoot_parameters_base.vegetative_bud_break_probability_min = 0.2;
+
912 shoot_parameters_base.vegetative_bud_break_time = 6;
+
913 shoot_parameters_base.phyllochron_min = 2;
+
914 shoot_parameters_base.elongation_rate_max = 0.1;
+
915 shoot_parameters_base.girth_area_factor = 10.f;
+
916 shoot_parameters_base.gravitropic_curvature = 0;
+
917 shoot_parameters_base.internode_length_max = 0.0015;
+
918 shoot_parameters_base.internode_length_decay_rate = 0;
+
919 shoot_parameters_base.flowers_require_dormancy = false;
+
920 shoot_parameters_base.growth_requires_dormancy = false;
+
921 shoot_parameters_base.flower_bud_break_probability = 0.;
+
922 shoot_parameters_base.max_nodes = 8;
923
-
924 if (shoot_types.empty()) {
-
925 //automatically initialize cheeseweed plant shoots
-
926 initializeCheeseweedShoots();
-
927 }
-
928
-
929 uint plantID = addPlantInstance(base_position, 0);
-
930
-
931 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(0, 0.f, 0.f), 0.0001, 0.0025, 0.1, 0.1, 0, "base");
-
932
-
933 breakPlantDormancy(plantID);
+
924 defineShootType("base", shoot_parameters_base);
+
925
+
926}
+
927
+
928uint PlantArchitecture::buildCheeseweedPlant(const helios::vec3 &base_position) {
+
929
+
930 if (shoot_types.empty()) {
+
931 //automatically initialize cheeseweed plant shoots
+
932 initializeCheeseweedShoots();
+
933 }
934
-
935 setPlantPhenologicalThresholds(plantID, 0, -1, -1, -1, -1, 1000, false);
+
935 uint plantID = addPlantInstance(base_position, 0);
936
-
937 plant_instances.at(plantID).max_age = 40;
+
937 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(0, 0.f, 0.f), 0.0001, 0.0025, 0.1, 0.1, 0, "base");
938
-
939 return plantID;
+
939 breakPlantDormancy(plantID);
940
-
941}
+
941 setPlantPhenologicalThresholds(plantID, 0, -1, -1, -1, -1, 1000, false);
942
-
943void PlantArchitecture::initializeCowpeaShoots() {
+
943 plant_instances.at(plantID).max_age = 40;
944
-
945 // ---- Leaf Prototype ---- //
+
945 return plantID;
946
-
947 LeafPrototype leaf_prototype_trifoliate(context_ptr->getRandomGenerator());
-
948 leaf_prototype_trifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_tip_centered.png";
-
949 leaf_prototype_trifoliate.leaf_texture_file[-1] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_left_centered.png";
-
950 leaf_prototype_trifoliate.leaf_texture_file[1] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_right_centered.png";
-
951 leaf_prototype_trifoliate.leaf_aspect_ratio = 0.8f;
-
952 leaf_prototype_trifoliate.midrib_fold_fraction = 0.2;
-
953 leaf_prototype_trifoliate.longitudinal_curvature.uniformDistribution(-0.4f, -0.1f);
-
954 leaf_prototype_trifoliate.lateral_curvature = -0.4f;
-
955 leaf_prototype_trifoliate.subdivisions = 6;
-
956 leaf_prototype_trifoliate.unique_prototypes = 5;
-
957 leaf_prototype_trifoliate.build_petiolule = true;
-
958
-
959 LeafPrototype leaf_prototype_unifoliate = leaf_prototype_trifoliate;
-
960 leaf_prototype_unifoliate.leaf_texture_file.clear();
-
961 leaf_prototype_unifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_unifoliate_centered.png";
-
962
-
963 // ---- Phytomer Parameters ---- //
+
947}
+
948
+
949void PlantArchitecture::initializeCowpeaShoots() {
+
950
+
951 // ---- Leaf Prototype ---- //
+
952
+
953 LeafPrototype leaf_prototype_trifoliate(context_ptr->getRandomGenerator());
+
954 leaf_prototype_trifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_tip_centered.png";
+
955 leaf_prototype_trifoliate.leaf_texture_file[-1] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_left_centered.png";
+
956 leaf_prototype_trifoliate.leaf_texture_file[1] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_right_centered.png";
+
957 leaf_prototype_trifoliate.leaf_aspect_ratio = 0.7f;
+
958 leaf_prototype_trifoliate.midrib_fold_fraction = 0.2;
+
959 leaf_prototype_trifoliate.longitudinal_curvature.uniformDistribution(-0.3f, -0.1f);
+
960 leaf_prototype_trifoliate.lateral_curvature = -0.4f;
+
961 leaf_prototype_trifoliate.subdivisions = 6;
+
962 leaf_prototype_trifoliate.unique_prototypes = 5;
+
963 leaf_prototype_trifoliate.build_petiolule = true;
964
-
965 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
-
966
-
967 phytomer_parameters_trifoliate.internode.pitch = 20;
-
968 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
-
969 phytomer_parameters_trifoliate.internode.radius_initial = 0.0015;
-
970 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
-
971 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
-
972 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.15, 0.2, 0.1);
-
973 phytomer_parameters_trifoliate.internode.length_segments = 2;
-
974
-
975 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
-
976 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(45,60);
-
977 phytomer_parameters_trifoliate.petiole.radius = 0.0018;
-
978 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.08,0.1);
-
979 phytomer_parameters_trifoliate.petiole.taper = 0.25;
-
980 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-200,-50);
-
981 phytomer_parameters_trifoliate.petiole.color = make_RGBcolor(0.17,0.25,0.07);
-
982 phytomer_parameters_trifoliate.petiole.length_segments = 5;
-
983 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
-
984
-
985 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
-
986 phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10);
-
987 phytomer_parameters_trifoliate.leaf.yaw = 10;
-
988 phytomer_parameters_trifoliate.leaf.roll = -15;
-
989 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.4;
-
990 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
-
991 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.09,0.12);
-
992 phytomer_parameters_trifoliate.leaf.prototype = leaf_prototype_trifoliate;
-
993
-
994 phytomer_parameters_trifoliate.peduncle.length.uniformDistribution(0.25,0.27);
-
995 phytomer_parameters_trifoliate.peduncle.radius = 0.0025;
-
996 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 30);
-
997 phytomer_parameters_trifoliate.peduncle.roll = 90;
-
998 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(50, 250);
-
999 phytomer_parameters_trifoliate.peduncle.color = make_RGBcolor(0.15, 0.25, 0.1);
-
1000 phytomer_parameters_trifoliate.peduncle.length_segments = 6;
-
1001 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
-
1002
-
1003 phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle = 4;//.uniformDistribution(1, 3);
-
1004 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.05;
-
1005 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
-
1006 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
-
1007 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.03;
-
1008 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = CowpeaFlowerPrototype;
-
1009 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.11,0.13);
-
1010 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = CowpeaFruitPrototype;
-
1011 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.,0.7);
-
1012
-
1013 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
-
1014 phytomer_parameters_unifoliate.internode.pitch = 0;
-
1015 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 1;
-
1016 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
-
1017 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
-
1018 phytomer_parameters_unifoliate.petiole.length = 0.0001;
-
1019 phytomer_parameters_unifoliate.petiole.radius = 0.0004;
-
1020 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
-
1021 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
-
1022 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
-
1023 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
-
1024 phytomer_parameters_unifoliate.leaf.prototype = leaf_prototype_unifoliate;
-
1025
-
1026 // ---- Shoot Parameters ---- //
-
1027
-
1028 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
-
1029 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
-
1030 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = CowpeaPhytomerCreationFunction;
-
1031
-
1032 shoot_parameters_trifoliate.max_nodes = 20;
-
1033 shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(40,60);
-
1034// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
-
1035 shoot_parameters_trifoliate.internode_length_max = 0.025;
-
1036// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
-
1037// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
-
1038 shoot_parameters_trifoliate.base_roll = 90;
-
1039 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
-
1040 shoot_parameters_trifoliate.gravitropic_curvature = 200;
-
1041
-
1042 shoot_parameters_trifoliate.phyllochron_min = 2;
-
1043 shoot_parameters_trifoliate.elongation_rate = 0.1;
-
1044 shoot_parameters_trifoliate.girth_area_factor = 1.5f;
-
1045 shoot_parameters_trifoliate.vegetative_bud_break_time = 15;
-
1046 shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.1;
-
1047 shoot_parameters_trifoliate.vegetative_bud_break_probability_decay_rate = -0.4;
-
1048// shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default)
-
1049 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.1,0.15);
-
1050 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
-
1051// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
-
1052// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
-
1053// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
-
1054
-
1055 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
1056
-
1057
-
1058 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
-
1059 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
-
1060 shoot_parameters_unifoliate.max_nodes = 1;
-
1061 shoot_parameters_unifoliate.girth_area_factor = 1.f;
-
1062 shoot_parameters_unifoliate.vegetative_bud_break_probability_min = 1;
-
1063 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
-
1064 shoot_parameters_unifoliate.insertion_angle_tip = 40;
-
1065 shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
-
1066 shoot_parameters_unifoliate.vegetative_bud_break_time = 8;
-
1067 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
1068
-
1069 defineShootType("unifoliate",shoot_parameters_unifoliate);
-
1070 defineShootType("trifoliate",shoot_parameters_trifoliate);
-
1071
-
1072}
-
1073
-
1074uint PlantArchitecture::buildCowpeaPlant(const helios::vec3 &base_position) {
+
965 LeafPrototype leaf_prototype_unifoliate = leaf_prototype_trifoliate;
+
966 leaf_prototype_unifoliate.leaf_texture_file.clear();
+
967 leaf_prototype_unifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_unifoliate_centered.png";
+
968
+
969 // ---- Phytomer Parameters ---- //
+
970
+
971 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
972
+
973 phytomer_parameters_trifoliate.internode.pitch = 20;
+
974 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
975 phytomer_parameters_trifoliate.internode.radius_initial = 0.0015;
+
976 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
977 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
978 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.15, 0.2, 0.1);
+
979 phytomer_parameters_trifoliate.internode.length_segments = 2;
+
980
+
981 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
982 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(45,60);
+
983 phytomer_parameters_trifoliate.petiole.radius = 0.0018;
+
984 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.06,0.08);
+
985 phytomer_parameters_trifoliate.petiole.taper = 0.25;
+
986 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-200,-50);
+
987 phytomer_parameters_trifoliate.petiole.color = make_RGBcolor(0.17,0.25,0.07);
+
988 phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
989 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
990
+
991 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
992// phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10);
+
993 phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(45, 20);
+
994 phytomer_parameters_trifoliate.leaf.yaw = 10;
+
995 phytomer_parameters_trifoliate.leaf.roll = -15;
+
996 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.4;
+
997 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
998 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.09,0.12);
+
999 phytomer_parameters_trifoliate.leaf.prototype = leaf_prototype_trifoliate;
+
1000
+
1001 phytomer_parameters_trifoliate.peduncle.length.uniformDistribution(0.25,0.27);
+
1002 phytomer_parameters_trifoliate.peduncle.radius = 0.0025;
+
1003 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 30);
+
1004 phytomer_parameters_trifoliate.peduncle.roll = 90;
+
1005 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(50, 250);
+
1006 phytomer_parameters_trifoliate.peduncle.color = make_RGBcolor(0.15, 0.25, 0.1);
+
1007 phytomer_parameters_trifoliate.peduncle.length_segments = 6;
+
1008 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
1009
+
1010 phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle = 4;//.uniformDistribution(1, 3);
+
1011 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.025;
+
1012 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
1013 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
1014 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.03;
+
1015 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = CowpeaFlowerPrototype;
+
1016 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.11,0.13);
+
1017 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = CowpeaFruitPrototype;
+
1018 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.,0.7);
+
1019
+
1020 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
1021 phytomer_parameters_unifoliate.internode.pitch = 0;
+
1022 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
1023 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
1024 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
1025 phytomer_parameters_unifoliate.petiole.length = 0.0001;
+
1026 phytomer_parameters_unifoliate.petiole.radius = 0.0004;
+
1027 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
+
1028 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
1029 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
+
1030 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
1031 phytomer_parameters_unifoliate.leaf.prototype = leaf_prototype_unifoliate;
+
1032
+
1033 // ---- Shoot Parameters ---- //
+
1034
+
1035 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
1036 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
1037 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = CowpeaPhytomerCreationFunction;
+
1038
+
1039 shoot_parameters_trifoliate.max_nodes = 20;
+
1040 shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(40,60);
+
1041// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
+
1042 shoot_parameters_trifoliate.internode_length_max = 0.025;
+
1043// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
+
1044// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
+
1045 shoot_parameters_trifoliate.base_roll = 90;
+
1046 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
1047 shoot_parameters_trifoliate.gravitropic_curvature = 200;
+
1048
+
1049 shoot_parameters_trifoliate.phyllochron_min = 2;
+
1050 shoot_parameters_trifoliate.elongation_rate_max = 0.1;
+
1051 shoot_parameters_trifoliate.girth_area_factor = 1.5f;
+
1052 shoot_parameters_trifoliate.vegetative_bud_break_time = 10;
+
1053 shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.2;
+
1054 shoot_parameters_trifoliate.vegetative_bud_break_probability_decay_rate = -0.4;
+
1055// shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default)
+
1056 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.1,0.15);
+
1057 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
+
1058// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
+
1059// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
+
1060// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
+
1061
+
1062 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
1063
+
1064
+
1065 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
1066 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
1067 shoot_parameters_unifoliate.max_nodes = 1;
+
1068 shoot_parameters_unifoliate.girth_area_factor = 1.f;
+
1069 shoot_parameters_unifoliate.vegetative_bud_break_probability_min = 1;
+
1070 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
1071 shoot_parameters_unifoliate.insertion_angle_tip = 40;
+
1072 shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
+
1073 shoot_parameters_unifoliate.vegetative_bud_break_time = 8;
+
1074 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
1075
-
1076 if (shoot_types.empty()) {
-
1077 //automatically initialize cowpea plant shoots
-
1078 initializeCowpeaShoots();
-
1079 }
+
1076 defineShootType("unifoliate",shoot_parameters_unifoliate);
+
1077 defineShootType("trifoliate",shoot_parameters_trifoliate);
+
1078
+
1079}
1080
-
1081 uint plantID = addPlantInstance(base_position, 0);
+
1081uint PlantArchitecture::buildCowpeaPlant(const helios::vec3 &base_position) {
1082
-
1083 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));
-
1084 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.03, 0.01, 0.01, 0, "unifoliate");
-
1085
-
1086 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f * M_PI), shoot_types.at("trifoliate").phytomer_parameters.internode.radius_initial.val(), shoot_types.at("trifoliate").internode_length_max.val(), 0.1, 0.1, 0, "trifoliate");
+
1083 if (shoot_types.empty()) {
+
1084 //automatically initialize cowpea plant shoots
+
1085 initializeCowpeaShoots();
+
1086 }
1087
-
1088 breakPlantDormancy(plantID);
+
1088 uint plantID = addPlantInstance(base_position, 0);
1089
-
1090 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 1000, false);
-
1091
-
1092 plant_instances.at(plantID).max_age = 365;
-
1093
-
1094 return plantID;
-
1095
-
1096}
-
1097
-
1098void PlantArchitecture::initializeGrapevineVSPShoots() {
-
1099
-
1100 // ---- Leaf Prototype ---- //
-
1101
-
1102 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
1103 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/GrapeLeaf.png";
-
1104 leaf_prototype.leaf_aspect_ratio = 1.f;
-
1105 leaf_prototype.midrib_fold_fraction = 0.3f;
-
1106 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.4,0.4);
-
1107 leaf_prototype.lateral_curvature = 0;
-
1108 leaf_prototype.wave_period = 0.3f;
-
1109 leaf_prototype.wave_amplitude = 0.1f;
-
1110 leaf_prototype.subdivisions = 5;
-
1111 leaf_prototype.unique_prototypes = 10;
-
1112 leaf_prototype.leaf_offset = make_vec3(-0.3,0,0);
-
1113
-
1114 // ---- Phytomer Parameters ---- //
-
1115
-
1116 PhytomerParameters phytomer_parameters_grapevine(context_ptr->getRandomGenerator());
-
1117
-
1118 phytomer_parameters_grapevine.internode.pitch = 20;
-
1119 phytomer_parameters_grapevine.internode.phyllotactic_angle.uniformDistribution(160, 200);
-
1120 phytomer_parameters_grapevine.internode.radius_initial = 0.003;
-
1121 phytomer_parameters_grapevine.internode.color = make_RGBcolor(0.23,0.13,0.062);
-
1122 phytomer_parameters_grapevine.internode.length_segments = 1;
-
1123 phytomer_parameters_grapevine.internode.max_floral_buds_per_petiole = 1;
-
1124 phytomer_parameters_grapevine.internode.max_vegetative_buds_per_petiole = 1;
-
1125
-
1126 phytomer_parameters_grapevine.petiole.petioles_per_internode = 1;
-
1127 phytomer_parameters_grapevine.petiole.color = make_RGBcolor(0.13, 0.066, 0.03);
-
1128 phytomer_parameters_grapevine.petiole.pitch.uniformDistribution(45, 70);
-
1129 phytomer_parameters_grapevine.petiole.radius = 0.0025;
-
1130 phytomer_parameters_grapevine.petiole.length = 0.1;
-
1131 phytomer_parameters_grapevine.petiole.taper = 0;
-
1132 phytomer_parameters_grapevine.petiole.curvature = 0;
-
1133 phytomer_parameters_grapevine.petiole.length_segments = 1;
-
1134
-
1135 phytomer_parameters_grapevine.leaf.leaves_per_petiole = 1;
-
1136 phytomer_parameters_grapevine.leaf.pitch.uniformDistribution(-110, -80);
-
1137 phytomer_parameters_grapevine.leaf.yaw.uniformDistribution(-20, 20);
-
1138 phytomer_parameters_grapevine.leaf.roll.uniformDistribution(-5, 5);
-
1139 phytomer_parameters_grapevine.leaf.prototype_scale = 0.2;
-
1140 phytomer_parameters_grapevine.leaf.prototype = leaf_prototype;
+
1090 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));
+
1091 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.03, 0.01, 0.01, 0, "unifoliate");
+
1092
+
1093 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f * M_PI), shoot_types.at("trifoliate").phytomer_parameters.internode.radius_initial.val(), shoot_types.at("trifoliate").internode_length_max.val(), 0.1, 0.1, 0, "trifoliate");
+
1094
+
1095 breakPlantDormancy(plantID);
+
1096
+
1097 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 1000, false);
+
1098
+
1099 plant_instances.at(plantID).max_age = 365;
+
1100
+
1101 return plantID;
+
1102
+
1103}
+
1104
+
1105void PlantArchitecture::initializeGrapevineVSPShoots() {
+
1106
+
1107 // ---- Leaf Prototype ---- //
+
1108
+
1109 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
1110 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/GrapeLeaf.png";
+
1111 leaf_prototype.leaf_aspect_ratio = 1.f;
+
1112 leaf_prototype.midrib_fold_fraction = 0.3f;
+
1113 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.4,0.4);
+
1114 leaf_prototype.lateral_curvature = 0;
+
1115 leaf_prototype.wave_period = 0.3f;
+
1116 leaf_prototype.wave_amplitude = 0.1f;
+
1117 leaf_prototype.subdivisions = 5;
+
1118 leaf_prototype.unique_prototypes = 10;
+
1119 leaf_prototype.leaf_offset = make_vec3(-0.3,0,0);
+
1120
+
1121 // ---- Phytomer Parameters ---- //
+
1122
+
1123 PhytomerParameters phytomer_parameters_grapevine(context_ptr->getRandomGenerator());
+
1124
+
1125 phytomer_parameters_grapevine.internode.pitch = 20;
+
1126 phytomer_parameters_grapevine.internode.phyllotactic_angle.uniformDistribution(160, 200);
+
1127 phytomer_parameters_grapevine.internode.radius_initial = 0.003;
+
1128 phytomer_parameters_grapevine.internode.color = make_RGBcolor(0.23,0.13,0.062);
+
1129 phytomer_parameters_grapevine.internode.length_segments = 1;
+
1130 phytomer_parameters_grapevine.internode.max_floral_buds_per_petiole = 1;
+
1131 phytomer_parameters_grapevine.internode.max_vegetative_buds_per_petiole = 1;
+
1132
+
1133 phytomer_parameters_grapevine.petiole.petioles_per_internode = 1;
+
1134 phytomer_parameters_grapevine.petiole.color = make_RGBcolor(0.13, 0.066, 0.03);
+
1135 phytomer_parameters_grapevine.petiole.pitch.uniformDistribution(45, 70);
+
1136 phytomer_parameters_grapevine.petiole.radius = 0.0025;
+
1137 phytomer_parameters_grapevine.petiole.length = 0.1;
+
1138 phytomer_parameters_grapevine.petiole.taper = 0;
+
1139 phytomer_parameters_grapevine.petiole.curvature = 0;
+
1140 phytomer_parameters_grapevine.petiole.length_segments = 1;
1141
-
1142 phytomer_parameters_grapevine.peduncle.length = 0.08;
-
1143 phytomer_parameters_grapevine.peduncle.pitch.uniformDistribution(50, 90);
-
1144 phytomer_parameters_grapevine.peduncle.color = make_RGBcolor(0.32, 0.05, 0.13);
-
1145
-
1146 phytomer_parameters_grapevine.inflorescence.flowers_per_peduncle = 1;
-
1147 phytomer_parameters_grapevine.inflorescence.pitch = 0;
-
1148// phytomer_parameters_grapevine.inflorescence.flower_prototype_function = GrapevineFlowerPrototype;
-
1149 phytomer_parameters_grapevine.inflorescence.flower_prototype_scale = 0.04;
-
1150 phytomer_parameters_grapevine.inflorescence.fruit_prototype_function = GrapevineFruitPrototype;
-
1151 phytomer_parameters_grapevine.inflorescence.fruit_prototype_scale = 0.04;
-
1152 phytomer_parameters_grapevine.inflorescence.fruit_gravity_factor_fraction = 0.7;
-
1153
-
1154 phytomer_parameters_grapevine.phytomer_creation_function = GrapevinePhytomerCreationFunction;
-
1155// phytomer_parameters_grapevine.phytomer_callback_function = GrapevinePhytomerCallbackFunction;
-
1156
-
1157 // ---- Shoot Parameters ---- //
-
1158
-
1159 ShootParameters shoot_parameters_main(context_ptr->getRandomGenerator());
-
1160 shoot_parameters_main.phytomer_parameters = phytomer_parameters_grapevine;
-
1161 shoot_parameters_main.vegetative_bud_break_probability_min = 0.075;
-
1162 shoot_parameters_main.vegetative_bud_break_probability_decay_rate = 1.;
-
1163 shoot_parameters_main.vegetative_bud_break_time = 30;
-
1164 shoot_parameters_main.phyllochron_min.uniformDistribution(1.75,2.25);
-
1165 shoot_parameters_main.elongation_rate = 0.15;
-
1166 shoot_parameters_main.girth_area_factor = 1.f;
-
1167 shoot_parameters_main.gravitropic_curvature = 400;
-
1168 shoot_parameters_main.tortuosity = 15;
-
1169 shoot_parameters_main.internode_length_max.uniformDistribution(0.06,0.08);
-
1170 shoot_parameters_main.internode_length_decay_rate = 0;
-
1171 shoot_parameters_main.insertion_angle_tip = 45;
-
1172 shoot_parameters_main.insertion_angle_decay_rate = 0;
-
1173 shoot_parameters_main.flowers_require_dormancy = false;
-
1174 shoot_parameters_main.growth_requires_dormancy = false;
-
1175 shoot_parameters_main.determinate_shoot_growth = false;
-
1176 shoot_parameters_main.max_terminal_floral_buds = 0;
-
1177 shoot_parameters_main.flower_bud_break_probability = 0.5;
-
1178 shoot_parameters_main.fruit_set_probability = 0.2;
-
1179 shoot_parameters_main.max_nodes = 20;
-
1180 shoot_parameters_main.base_roll.uniformDistribution(90-25,90+25);
-
1181 shoot_parameters_main.base_yaw = 0;
-
1182
-
1183 ShootParameters shoot_parameters_cane = shoot_parameters_main;
-
1184// shoot_parameters_cane.phytomer_parameters.internode.image_texture = "plugins/plantarchitecture/assets/textures/GrapeBark.jpg";
-
1185 shoot_parameters_cane.phytomer_parameters.internode.pitch = 0;
-
1186 shoot_parameters_cane.phytomer_parameters.internode.radial_subdivisions = 15;
-
1187 shoot_parameters_cane.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
-
1188 shoot_parameters_cane.phytomer_parameters.internode.phyllotactic_angle = 0;
-
1189 shoot_parameters_cane.insertion_angle_tip.uniformDistribution(60, 120);
-
1190 shoot_parameters_cane.girth_area_factor = 0.7f;
-
1191 shoot_parameters_cane.max_nodes = 9;
-
1192 shoot_parameters_cane.gravitropic_curvature.uniformDistribution(-20,20);
-
1193 shoot_parameters_cane.tortuosity = 1;
-
1194 shoot_parameters_cane.gravitropic_curvature = 10;
-
1195 shoot_parameters_cane.vegetative_bud_break_probability_min = 0.9;
-
1196 shoot_parameters_cane.defineChildShootTypes({"grapevine_shoot"},{1.f});
-
1197
-
1198 ShootParameters shoot_parameters_trunk = shoot_parameters_main;
-
1199 shoot_parameters_trunk.phytomer_parameters.internode.image_texture = "plugins/plantarchitecture/assets/textures/GrapeBark.jpg";
-
1200 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
-
1201 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
-
1202 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.05;
-
1203 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 25;
-
1204 shoot_parameters_trunk.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
-
1205 shoot_parameters_trunk.phyllochron_min = 2.5;
-
1206 shoot_parameters_trunk.insertion_angle_tip = 90;
-
1207 shoot_parameters_trunk.girth_area_factor = 0;
-
1208 shoot_parameters_trunk.max_nodes = 18;
-
1209 shoot_parameters_trunk.tortuosity = 0;
-
1210 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
-
1211 shoot_parameters_trunk.defineChildShootTypes({"grapevine_shoot"},{1.f});
-
1212
-
1213 defineShootType("grapevine_trunk", shoot_parameters_trunk);
-
1214 defineShootType("grapevine_cane", shoot_parameters_cane);
-
1215 defineShootType("grapevine_shoot", shoot_parameters_main);
-
1216
-
1217}
-
1218
-
1219uint PlantArchitecture::buildGrapevineVSP(const helios::vec3 &base_position) {
-
1220
-
1221 if (shoot_types.empty()) {
-
1222 //automatically initialize grapevine plant shoots
-
1223 initializeGrapevineVSPShoots();
-
1224 }
+
1142 phytomer_parameters_grapevine.leaf.leaves_per_petiole = 1;
+
1143 phytomer_parameters_grapevine.leaf.pitch.uniformDistribution(-110, -80);
+
1144 phytomer_parameters_grapevine.leaf.yaw.uniformDistribution(-20, 20);
+
1145 phytomer_parameters_grapevine.leaf.roll.uniformDistribution(-5, 5);
+
1146 phytomer_parameters_grapevine.leaf.prototype_scale = 0.2;
+
1147 phytomer_parameters_grapevine.leaf.prototype = leaf_prototype;
+
1148
+
1149 phytomer_parameters_grapevine.peduncle.length = 0.08;
+
1150 phytomer_parameters_grapevine.peduncle.pitch.uniformDistribution(50, 90);
+
1151 phytomer_parameters_grapevine.peduncle.color = make_RGBcolor(0.32, 0.05, 0.13);
+
1152
+
1153 phytomer_parameters_grapevine.inflorescence.flowers_per_peduncle = 1;
+
1154 phytomer_parameters_grapevine.inflorescence.pitch = 0;
+
1155// phytomer_parameters_grapevine.inflorescence.flower_prototype_function = GrapevineFlowerPrototype;
+
1156 phytomer_parameters_grapevine.inflorescence.flower_prototype_scale = 0.04;
+
1157 phytomer_parameters_grapevine.inflorescence.fruit_prototype_function = GrapevineFruitPrototype;
+
1158 phytomer_parameters_grapevine.inflorescence.fruit_prototype_scale = 0.04;
+
1159 phytomer_parameters_grapevine.inflorescence.fruit_gravity_factor_fraction = 0.7;
+
1160
+
1161 phytomer_parameters_grapevine.phytomer_creation_function = GrapevinePhytomerCreationFunction;
+
1162// phytomer_parameters_grapevine.phytomer_callback_function = GrapevinePhytomerCallbackFunction;
+
1163
+
1164 // ---- Shoot Parameters ---- //
+
1165
+
1166 ShootParameters shoot_parameters_main(context_ptr->getRandomGenerator());
+
1167 shoot_parameters_main.phytomer_parameters = phytomer_parameters_grapevine;
+
1168 shoot_parameters_main.vegetative_bud_break_probability_min = 0.075;
+
1169 shoot_parameters_main.vegetative_bud_break_probability_decay_rate = 1.;
+
1170 shoot_parameters_main.vegetative_bud_break_time = 30;
+
1171 shoot_parameters_main.phyllochron_min.uniformDistribution(1.75,2.25);
+
1172 shoot_parameters_main.elongation_rate_max = 0.15;
+
1173 shoot_parameters_main.girth_area_factor = 1.f;
+
1174 shoot_parameters_main.gravitropic_curvature = 400;
+
1175 shoot_parameters_main.tortuosity = 15;
+
1176 shoot_parameters_main.internode_length_max.uniformDistribution(0.06,0.08);
+
1177 shoot_parameters_main.internode_length_decay_rate = 0;
+
1178 shoot_parameters_main.insertion_angle_tip = 45;
+
1179 shoot_parameters_main.insertion_angle_decay_rate = 0;
+
1180 shoot_parameters_main.flowers_require_dormancy = false;
+
1181 shoot_parameters_main.growth_requires_dormancy = false;
+
1182 shoot_parameters_main.determinate_shoot_growth = false;
+
1183 shoot_parameters_main.max_terminal_floral_buds = 0;
+
1184 shoot_parameters_main.flower_bud_break_probability = 0.5;
+
1185 shoot_parameters_main.fruit_set_probability = 0.2;
+
1186 shoot_parameters_main.max_nodes = 20;
+
1187 shoot_parameters_main.base_roll.uniformDistribution(90-25,90+25);
+
1188 shoot_parameters_main.base_yaw = 0;
+
1189
+
1190 ShootParameters shoot_parameters_cane = shoot_parameters_main;
+
1191// shoot_parameters_cane.phytomer_parameters.internode.image_texture = "plugins/plantarchitecture/assets/textures/GrapeBark.jpg";
+
1192 shoot_parameters_cane.phytomer_parameters.internode.pitch = 0;
+
1193 shoot_parameters_cane.phytomer_parameters.internode.radial_subdivisions = 15;
+
1194 shoot_parameters_cane.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
+
1195 shoot_parameters_cane.phytomer_parameters.internode.phyllotactic_angle = 0;
+
1196 shoot_parameters_cane.insertion_angle_tip.uniformDistribution(60, 120);
+
1197 shoot_parameters_cane.girth_area_factor = 0.7f;
+
1198 shoot_parameters_cane.max_nodes = 9;
+
1199 shoot_parameters_cane.gravitropic_curvature.uniformDistribution(-20,20);
+
1200 shoot_parameters_cane.tortuosity = 1;
+
1201 shoot_parameters_cane.gravitropic_curvature = 10;
+
1202 shoot_parameters_cane.vegetative_bud_break_probability_min = 0.9;
+
1203 shoot_parameters_cane.defineChildShootTypes({"grapevine_shoot"},{1.f});
+
1204
+
1205 ShootParameters shoot_parameters_trunk = shoot_parameters_main;
+
1206 shoot_parameters_trunk.phytomer_parameters.internode.image_texture = "plugins/plantarchitecture/assets/textures/GrapeBark.jpg";
+
1207 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
+
1208 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
+
1209 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.05;
+
1210 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 25;
+
1211 shoot_parameters_trunk.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
+
1212 shoot_parameters_trunk.phyllochron_min = 2.5;
+
1213 shoot_parameters_trunk.insertion_angle_tip = 90;
+
1214 shoot_parameters_trunk.girth_area_factor = 0;
+
1215 shoot_parameters_trunk.max_nodes = 18;
+
1216 shoot_parameters_trunk.tortuosity = 0;
+
1217 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
+
1218 shoot_parameters_trunk.defineChildShootTypes({"grapevine_shoot"},{1.f});
+
1219
+
1220 defineShootType("grapevine_trunk", shoot_parameters_trunk);
+
1221 defineShootType("grapevine_cane", shoot_parameters_cane);
+
1222 defineShootType("grapevine_shoot", shoot_parameters_main);
+
1223
+
1224}
1225
-
1226 uint plantID = addPlantInstance(base_position, 0);
+
1226uint PlantArchitecture::buildGrapevineVSP(const helios::vec3 &base_position) {
1227
-
1228 uint uID_stem = addBaseStemShoot(plantID, 8, make_AxisRotation(context_ptr->randu(0,0.05*M_PI), 0, 0), shoot_types.at("grapevine_trunk").phytomer_parameters.internode.radius_initial.val(), 0.1, 1, 1, 0.1, "grapevine_trunk");
-
1229
-
1230 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" );
-
1231 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" );
+
1228 if (shoot_types.empty()) {
+
1229 //automatically initialize grapevine plant shoots
+
1230 initializeGrapevineVSPShoots();
+
1231 }
1232
-
1233// makePlantDormant(plantID);
+
1233 uint plantID = addPlantInstance(base_position, 0);
1234
-
1235 removeShootLeaves( plantID, uID_stem );
-
1236 removeShootLeaves( plantID, uID_cane_L );
-
1237 removeShootLeaves( plantID, uID_cane_R );
-
1238
-
1239 setPlantPhenologicalThresholds(plantID, 165, -1, -1, 45, 45, 200, false);
-
1240
-
1241 plant_instances.at(plantID).max_age = 365;
-
1242
-
1243 return plantID;
-
1244
-
1245}
-
1246
-
1247void PlantArchitecture::initializeMaizeShoots() {
-
1248
-
1249 // ---- Leaf Prototype ---- //
-
1250
-
1251 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
1252 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
-
1253 leaf_prototype.leaf_aspect_ratio = 0.25f;
-
1254 leaf_prototype.midrib_fold_fraction = 0.3f;
-
1255 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.45,-0.3);
-
1256 leaf_prototype.lateral_curvature = -0.3f;;
-
1257 leaf_prototype.petiole_roll = 0.04f;
-
1258 leaf_prototype.wave_period = 0.1f;
-
1259 leaf_prototype.wave_amplitude = 0.1f;
-
1260 leaf_prototype.leaf_buckle_length.uniformDistribution(0.4,0.6);
-
1261 leaf_prototype.leaf_buckle_angle.uniformDistribution(40,50);
-
1262 leaf_prototype.subdivisions = 50;
-
1263 leaf_prototype.unique_prototypes = 10;
-
1264
-
1265 // ---- Phytomer Parameters ---- //
-
1266
-
1267 PhytomerParameters phytomer_parameters_maize(context_ptr->getRandomGenerator());
+
1235 uint uID_stem = addBaseStemShoot(plantID, 8, make_AxisRotation(context_ptr->randu(0,0.05*M_PI), 0, 0), shoot_types.at("grapevine_trunk").phytomer_parameters.internode.radius_initial.val(), 0.1, 1, 1, 0.1, "grapevine_trunk");
+
1236
+
1237 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" );
+
1238 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" );
+
1239
+
1240// makePlantDormant(plantID);
+
1241
+
1242 removeShootLeaves( plantID, uID_stem );
+
1243 removeShootLeaves( plantID, uID_cane_L );
+
1244 removeShootLeaves( plantID, uID_cane_R );
+
1245
+
1246 setPlantPhenologicalThresholds(plantID, 165, -1, -1, 45, 45, 200, false);
+
1247
+
1248 plant_instances.at(plantID).max_age = 365;
+
1249
+
1250 return plantID;
+
1251
+
1252}
+
1253
+
1254void PlantArchitecture::initializeGroundCherryWeedShoots() {
+
1255
+
1256 // ---- Leaf Prototype ---- //
+
1257
+
1258 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
1259 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/GroundCherryLeaf.png";
+
1260 leaf_prototype.leaf_aspect_ratio.uniformDistribution(0.3,0.5);
+
1261 leaf_prototype.midrib_fold_fraction = 0.2f;
+
1262 leaf_prototype.longitudinal_curvature = 0.1f;;
+
1263 leaf_prototype.lateral_curvature = -0.3f;
+
1264 leaf_prototype.wave_period = 0.35f;
+
1265 leaf_prototype.wave_amplitude = 0.08f;
+
1266 leaf_prototype.subdivisions = 6;
+
1267 leaf_prototype.unique_prototypes = 5;
1268
-
1269 phytomer_parameters_maize.internode.pitch = 0;
-
1270 phytomer_parameters_maize.internode.phyllotactic_angle.uniformDistribution(170, 190);
-
1271 phytomer_parameters_maize.internode.radius_initial = 0.0075;
-
1272 phytomer_parameters_maize.internode.color = make_RGBcolor(0.09, 0.13, 0.06);
-
1273 phytomer_parameters_maize.internode.length_segments = 2;
-
1274 phytomer_parameters_maize.internode.radial_subdivisions = 10;
-
1275 phytomer_parameters_maize.internode.max_floral_buds_per_petiole = 1;
-
1276 phytomer_parameters_maize.internode.max_vegetative_buds_per_petiole = 0;
-
1277
-
1278 phytomer_parameters_maize.petiole.petioles_per_internode = 1;
-
1279 phytomer_parameters_maize.petiole.pitch.uniformDistribution(-40, -20);
-
1280 phytomer_parameters_maize.petiole.radius = 0.0;
-
1281 phytomer_parameters_maize.petiole.length = 0.05;
-
1282 phytomer_parameters_maize.petiole.taper = 0;
-
1283 phytomer_parameters_maize.petiole.curvature = 0;
-
1284 phytomer_parameters_maize.petiole.length_segments = 1;
-
1285
-
1286 phytomer_parameters_maize.leaf.leaves_per_petiole = 1;
-
1287 phytomer_parameters_maize.leaf.pitch = 0;
-
1288 phytomer_parameters_maize.leaf.yaw = 0;
-
1289 phytomer_parameters_maize.leaf.roll = 0;
-
1290 phytomer_parameters_maize.leaf.prototype_scale = 0.6;
-
1291 phytomer_parameters_maize.leaf.prototype = leaf_prototype;
-
1292
-
1293 phytomer_parameters_maize.peduncle.length = 0.14f;
-
1294 phytomer_parameters_maize.peduncle.radius = 0.004;
-
1295 phytomer_parameters_maize.peduncle.curvature = 0;
-
1296 phytomer_parameters_maize.peduncle.color = phytomer_parameters_maize.internode.color;
-
1297 phytomer_parameters_maize.peduncle.radial_subdivisions = 6;
-
1298 phytomer_parameters_maize.peduncle.length_segments = 2;
-
1299
-
1300 phytomer_parameters_maize.inflorescence.flowers_per_peduncle = 7;
-
1301 phytomer_parameters_maize.inflorescence.pitch.uniformDistribution(0,30);
-
1302 phytomer_parameters_maize.inflorescence.roll = 0;
-
1303 phytomer_parameters_maize.inflorescence.flower_offset = 0.1;
-
1304 phytomer_parameters_maize.inflorescence.fruit_prototype_scale = 0.15;
-
1305 phytomer_parameters_maize.inflorescence.fruit_prototype_function = MaizeTasselPrototype;
-
1306
-
1307 phytomer_parameters_maize.phytomer_creation_function = MaizePhytomerCreationFunction;
-
1308
-
1309 // ---- Shoot Parameters ---- //
-
1310
-
1311 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
1312 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_maize;
-
1313 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0.5;
-
1314 shoot_parameters_mainstem.flower_bud_break_probability = 1;
-
1315 shoot_parameters_mainstem.phyllochron_min = 2;
-
1316 shoot_parameters_mainstem.elongation_rate = 0.1;
-
1317 shoot_parameters_mainstem.girth_area_factor = 8.f;
-
1318 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-500,0);
-
1319 shoot_parameters_mainstem.internode_length_max = 0.22;
-
1320 shoot_parameters_mainstem.tortuosity = 1.f;
-
1321 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
1322 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
1323 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
1324 shoot_parameters_mainstem.determinate_shoot_growth = false;
-
1325 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
-
1326 shoot_parameters_mainstem.fruit_set_probability = 1.0;
-
1327 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
-
1328 shoot_parameters_mainstem.max_nodes = 17;
-
1329 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
-
1330
-
1331 defineShootType("mainstem",shoot_parameters_mainstem);
-
1332
-
1333}
-
1334
-
1335uint PlantArchitecture::buildMaizePlant(const helios::vec3 &base_position) {
-
1336
-
1337 if (shoot_types.empty()) {
-
1338 //automatically initialize maize plant shoots
-
1339 initializeMaizeShoots();
-
1340 }
+
1269 // ---- Phytomer Parameters ---- //
+
1270
+
1271 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
1272
+
1273 phytomer_parameters.internode.pitch = 5;
+
1274 phytomer_parameters.internode.phyllotactic_angle = 137.5;
+
1275 phytomer_parameters.internode.radius_initial = 0.0005;
+
1276 phytomer_parameters.internode.color = make_RGBcolor(0.213, 0.270, 0.056);
+
1277 phytomer_parameters.internode.length_segments = 1;
+
1278
+
1279 phytomer_parameters.petiole.petioles_per_internode = 1;
+
1280 phytomer_parameters.petiole.pitch.uniformDistribution(45,60);
+
1281 phytomer_parameters.petiole.radius = 0.0005;
+
1282 phytomer_parameters.petiole.length = 0.025;
+
1283 phytomer_parameters.petiole.taper = 0.15;
+
1284 phytomer_parameters.petiole.curvature.uniformDistribution(-150,-50);
+
1285 phytomer_parameters.petiole.color = phytomer_parameters.internode.color;
+
1286 phytomer_parameters.petiole.length_segments = 2;
+
1287
+
1288 phytomer_parameters.leaf.leaves_per_petiole = 1;
+
1289 phytomer_parameters.leaf.pitch.uniformDistribution(-30, 5);
+
1290 phytomer_parameters.leaf.yaw = 10;
+
1291 phytomer_parameters.leaf.roll = 0;
+
1292 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.06,0.08);
+
1293 phytomer_parameters.leaf.prototype = leaf_prototype;
+
1294
+
1295 phytomer_parameters.peduncle.length = 0.01;
+
1296 phytomer_parameters.peduncle.radius = 0.001;
+
1297 phytomer_parameters.peduncle.pitch = 20;
+
1298 phytomer_parameters.peduncle.roll = 0;
+
1299 phytomer_parameters.peduncle.curvature = -700;
+
1300 phytomer_parameters.peduncle.color = phytomer_parameters.internode.color;
+
1301 phytomer_parameters.peduncle.length_segments = 2;
+
1302 phytomer_parameters.peduncle.radial_subdivisions = 6;
+
1303
+
1304 phytomer_parameters.inflorescence.flowers_per_peduncle = 1;
+
1305 phytomer_parameters.inflorescence.pitch = 0;
+
1306 phytomer_parameters.inflorescence.roll.uniformDistribution(-30,30);
+
1307 phytomer_parameters.inflorescence.flower_prototype_scale = 0.01;
+
1308 phytomer_parameters.inflorescence.flower_prototype_function = BindweedFlowerPrototype;
+
1309 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.06;
+
1310 // phytomer_parameters.inflorescence.fruit_prototype_function = GroundCherryFruitPrototype;
+
1311 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.75;
+
1312
+
1313 // ---- Shoot Parameters ---- //
+
1314
+
1315 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
1316 shoot_parameters.phytomer_parameters = phytomer_parameters;
+
1317 // shoot_parameters.phytomer_parameters.phytomer_creation_function = TomatoPhytomerCreationFunction;
+
1318
+
1319 shoot_parameters.max_nodes = 26;
+
1320 shoot_parameters.insertion_angle_tip = 50;
+
1321 shoot_parameters.insertion_angle_decay_rate = 0;
+
1322 shoot_parameters.internode_length_max = 0.015;
+
1323 shoot_parameters.internode_length_min = 0.0;
+
1324 shoot_parameters.internode_length_decay_rate = 0;
+
1325 shoot_parameters.base_roll = 90;
+
1326 shoot_parameters.base_yaw.uniformDistribution(-20,20);
+
1327 shoot_parameters.gravitropic_curvature = 700;
+
1328 shoot_parameters.tortuosity = 3;
+
1329
+
1330 shoot_parameters.phyllochron_min = 1;
+
1331 shoot_parameters.elongation_rate_max = 0.1;
+
1332 shoot_parameters.girth_area_factor = 3.f;
+
1333 shoot_parameters.vegetative_bud_break_time = 7;
+
1334 shoot_parameters.vegetative_bud_break_probability_min = 0.2;
+
1335 shoot_parameters.vegetative_bud_break_probability_decay_rate = -0.5;
+
1336 shoot_parameters.flower_bud_break_probability = 0.25;
+
1337 shoot_parameters.fruit_set_probability = 0.5;
+
1338 shoot_parameters.flowers_require_dormancy = false;
+
1339 shoot_parameters.growth_requires_dormancy = false;
+
1340 shoot_parameters.determinate_shoot_growth = false;
1341
-
1342 uint plantID = addPlantInstance(base_position, 0);
+
1342 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
1343
-
1344 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(context_ptr->randu(0.f, 0.035f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)), 0.003, 0.08, 0.01, 0.01, 0, "mainstem");
+
1344 defineShootType("mainstem",shoot_parameters);
1345
-
1346 breakPlantDormancy(plantID);
+
1346}
1347
-
1348 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 10, 100, false);
+
1348uint PlantArchitecture::buildGroundCherryWeedPlant(const helios::vec3 &base_position) {
1349
-
1350 plant_instances.at(plantID).max_age = 365;
-
1351
-
1352 return plantID;
-
1353
-
1354}
-
1355
-
1356void PlantArchitecture::initializeOliveTreeShoots(){
-
1357
-
1358 // ---- Leaf Prototype ---- //
+
1350 if (shoot_types.empty()) {
+
1351 //automatically initialize ground cherry plant shoots
+
1352 initializeGroundCherryWeedShoots();
+
1353 }
+
1354
+
1355 uint plantID = addPlantInstance(base_position, 0);
+
1356
+
1357 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
1358 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.0025, 0.018, 0.01, 0.01, 0, "mainstem");
1359
-
1360 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
1361 leaf_prototype.prototype_function = OliveLeafPrototype;
-
1362 leaf_prototype.unique_prototypes = 1;
+
1360 breakPlantDormancy(plantID);
+
1361
+
1362 setPlantPhenologicalThresholds(plantID, 0, 20, -1, 20, 30, 1000, false);
1363
-
1364 // ---- Phytomer Parameters ---- //
+
1364 plant_instances.at(plantID).max_age = 50;
1365
-
1366 PhytomerParameters phytomer_parameters_olive(context_ptr->getRandomGenerator());
+
1366 return plantID;
1367
-
1368 phytomer_parameters_olive.internode.pitch = 0;
-
1369 phytomer_parameters_olive.internode.phyllotactic_angle.uniformDistribution(80, 100 );
-
1370 phytomer_parameters_olive.internode.radius_initial = 0.002;
-
1371 phytomer_parameters_olive.internode.length_segments = 1;
-
1372 phytomer_parameters_olive.internode.image_texture = "plugins/plantarchitecture/assets/textures/OliveBark.jpg";
-
1373 phytomer_parameters_olive.internode.max_floral_buds_per_petiole = 3;
-
1374
-
1375 phytomer_parameters_olive.petiole.petioles_per_internode = 2;
-
1376 phytomer_parameters_olive.petiole.pitch.uniformDistribution(-40,-20);
-
1377 phytomer_parameters_olive.petiole.taper = 0.1;
-
1378 phytomer_parameters_olive.petiole.curvature = 0;
-
1379 phytomer_parameters_olive.petiole.length = 0.01;
-
1380 phytomer_parameters_olive.petiole.radius = 0.0005;
-
1381 phytomer_parameters_olive.petiole.length_segments = 1;
-
1382 phytomer_parameters_olive.petiole.radial_subdivisions = 3;
-
1383 phytomer_parameters_olive.petiole.color = make_RGBcolor(0.61, 0.5, 0.24);
-
1384
-
1385 phytomer_parameters_olive.leaf.leaves_per_petiole = 1;
-
1386 phytomer_parameters_olive.leaf.prototype_scale = 0.06;
-
1387 phytomer_parameters_olive.leaf.prototype = leaf_prototype;
-
1388
-
1389 phytomer_parameters_olive.peduncle.length = 0.065;
-
1390 phytomer_parameters_olive.peduncle.radius = 0.001;
-
1391 phytomer_parameters_olive.peduncle.pitch = 60;
-
1392 phytomer_parameters_olive.peduncle.roll = 0;
-
1393 phytomer_parameters_olive.peduncle.length_segments = 1;
-
1394 phytomer_parameters_olive.peduncle.color = make_RGBcolor(0.7, 0.72, 0.7);
-
1395
-
1396 phytomer_parameters_olive.inflorescence.flowers_per_peduncle = 10;
-
1397 phytomer_parameters_olive.inflorescence.flower_offset = 0.13;
-
1398 phytomer_parameters_olive.inflorescence.pitch.uniformDistribution(80,100);
-
1399 phytomer_parameters_olive.inflorescence.roll.uniformDistribution(0,360);
-
1400 phytomer_parameters_olive.inflorescence.flower_prototype_scale = 0.01;
-
1401// phytomer_parameters_olive.inflorescence.flower_prototype_function = OliveFlowerPrototype;
-
1402 phytomer_parameters_olive.inflorescence.fruit_prototype_scale = 0.025;
-
1403 phytomer_parameters_olive.inflorescence.fruit_prototype_function = OliveFruitPrototype;
-
1404
-
1405 // ---- Shoot Parameters ---- //
-
1406
-
1407 // Trunk
-
1408 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
-
1409 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_olive;
-
1410 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
-
1411 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.015;
-
1412 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 20;
-
1413 shoot_parameters_trunk.max_nodes = 20;
-
1414 shoot_parameters_trunk.girth_area_factor = 3.f;
-
1415 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
-
1416 shoot_parameters_trunk.vegetative_bud_break_time = 0;
-
1417 shoot_parameters_trunk.tortuosity = 1;
-
1418 shoot_parameters_trunk.internode_length_max = 0.05;
-
1419 shoot_parameters_trunk.internode_length_decay_rate = 0;
-
1420 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
-
1421
-
1422 // Proleptic shoots
-
1423 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
-
1424 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_olive;
-
1425// shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = OlivePhytomerCreationFunction;
-
1426 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = OlivePhytomerCallbackFunction;
-
1427 shoot_parameters_proleptic.max_nodes.uniformDistribution(16,24);
-
1428 shoot_parameters_proleptic.max_nodes_per_season.uniformDistribution(8,12);
-
1429 shoot_parameters_proleptic.phyllochron_min = 2.0;
-
1430 shoot_parameters_proleptic.elongation_rate = 0.25;
-
1431 shoot_parameters_proleptic.girth_area_factor = 5.f;
-
1432 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.025;
-
1433 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 1.0;
-
1434 shoot_parameters_proleptic.vegetative_bud_break_time = 30;
-
1435 shoot_parameters_proleptic.gravitropic_curvature.uniformDistribution(550,650);
-
1436 shoot_parameters_proleptic.tortuosity = 5;
-
1437 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 35, 40);
-
1438 shoot_parameters_proleptic.insertion_angle_decay_rate = 2;
-
1439 shoot_parameters_proleptic.internode_length_max = 0.05;
-
1440 shoot_parameters_proleptic.internode_length_min = 0.03;
-
1441 shoot_parameters_proleptic.internode_length_decay_rate = 0.004;
-
1442 shoot_parameters_proleptic.fruit_set_probability = 0.25;
-
1443 shoot_parameters_proleptic.flower_bud_break_probability = 0.25;
-
1444 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
-
1445 shoot_parameters_proleptic.flowers_require_dormancy = true;
-
1446 shoot_parameters_proleptic.growth_requires_dormancy = true;
-
1447 shoot_parameters_proleptic.determinate_shoot_growth = false;
-
1448 shoot_parameters_proleptic.defineChildShootTypes({"proleptic"},{1.0});
-
1449
-
1450 // Main scaffolds
-
1451 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
-
1452 shoot_parameters_scaffold.phytomer_parameters.internode.radial_subdivisions = 10;
-
1453 shoot_parameters_scaffold.max_nodes = 30;
-
1454 shoot_parameters_scaffold.max_nodes_per_season = 10;
-
1455 shoot_parameters_scaffold.gravitropic_curvature = 700;
-
1456 shoot_parameters_scaffold.internode_length_max = 0.04;
-
1457 shoot_parameters_scaffold.tortuosity = 3;
-
1458 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
+
1368}
+
1369
+
1370void PlantArchitecture::initializeMaizeShoots() {
+
1371
+
1372 // ---- Leaf Prototype ---- //
+
1373
+
1374 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
1375 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
+
1376 leaf_prototype.leaf_aspect_ratio = 0.25f;
+
1377 leaf_prototype.midrib_fold_fraction = 0.3f;
+
1378 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.45,-0.3);
+
1379 leaf_prototype.lateral_curvature = -0.3f;;
+
1380 leaf_prototype.petiole_roll = 0.04f;
+
1381 leaf_prototype.wave_period = 0.1f;
+
1382 leaf_prototype.wave_amplitude = 0.1f;
+
1383 leaf_prototype.leaf_buckle_length.uniformDistribution(0.4,0.6);
+
1384 leaf_prototype.leaf_buckle_angle.uniformDistribution(40,50);
+
1385 leaf_prototype.subdivisions = 50;
+
1386 leaf_prototype.unique_prototypes = 10;
+
1387
+
1388 // ---- Phytomer Parameters ---- //
+
1389
+
1390 PhytomerParameters phytomer_parameters_maize(context_ptr->getRandomGenerator());
+
1391
+
1392 phytomer_parameters_maize.internode.pitch = 0;
+
1393 phytomer_parameters_maize.internode.phyllotactic_angle.uniformDistribution(170, 190);
+
1394 phytomer_parameters_maize.internode.radius_initial = 0.0075;
+
1395 phytomer_parameters_maize.internode.color = make_RGBcolor(0.09, 0.13, 0.06);
+
1396 phytomer_parameters_maize.internode.length_segments = 2;
+
1397 phytomer_parameters_maize.internode.radial_subdivisions = 10;
+
1398 phytomer_parameters_maize.internode.max_floral_buds_per_petiole = 1;
+
1399 phytomer_parameters_maize.internode.max_vegetative_buds_per_petiole = 0;
+
1400
+
1401 phytomer_parameters_maize.petiole.petioles_per_internode = 1;
+
1402 phytomer_parameters_maize.petiole.pitch.uniformDistribution(-40, -20);
+
1403 phytomer_parameters_maize.petiole.radius = 0.0;
+
1404 phytomer_parameters_maize.petiole.length = 0.05;
+
1405 phytomer_parameters_maize.petiole.taper = 0;
+
1406 phytomer_parameters_maize.petiole.curvature = 0;
+
1407 phytomer_parameters_maize.petiole.length_segments = 1;
+
1408
+
1409 phytomer_parameters_maize.leaf.leaves_per_petiole = 1;
+
1410 phytomer_parameters_maize.leaf.pitch = 0;
+
1411 phytomer_parameters_maize.leaf.yaw = 0;
+
1412 phytomer_parameters_maize.leaf.roll = 0;
+
1413 phytomer_parameters_maize.leaf.prototype_scale = 0.6;
+
1414 phytomer_parameters_maize.leaf.prototype = leaf_prototype;
+
1415
+
1416 phytomer_parameters_maize.peduncle.length = 0.14f;
+
1417 phytomer_parameters_maize.peduncle.radius = 0.004;
+
1418 phytomer_parameters_maize.peduncle.curvature = 0;
+
1419 phytomer_parameters_maize.peduncle.color = phytomer_parameters_maize.internode.color;
+
1420 phytomer_parameters_maize.peduncle.radial_subdivisions = 6;
+
1421 phytomer_parameters_maize.peduncle.length_segments = 2;
+
1422
+
1423 phytomer_parameters_maize.inflorescence.flowers_per_peduncle = 7;
+
1424 phytomer_parameters_maize.inflorescence.pitch.uniformDistribution(0,30);
+
1425 phytomer_parameters_maize.inflorescence.roll = 0;
+
1426 phytomer_parameters_maize.inflorescence.flower_offset = 0.1;
+
1427 phytomer_parameters_maize.inflorescence.fruit_prototype_scale = 0.15;
+
1428 phytomer_parameters_maize.inflorescence.fruit_prototype_function = MaizeTasselPrototype;
+
1429
+
1430 phytomer_parameters_maize.phytomer_creation_function = MaizePhytomerCreationFunction;
+
1431
+
1432 // ---- Shoot Parameters ---- //
+
1433
+
1434 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
1435 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_maize;
+
1436 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0.5;
+
1437 shoot_parameters_mainstem.flower_bud_break_probability = 1;
+
1438 shoot_parameters_mainstem.phyllochron_min = 2;
+
1439 shoot_parameters_mainstem.elongation_rate_max = 0.1;
+
1440 shoot_parameters_mainstem.girth_area_factor = 8.f;
+
1441 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-500,0);
+
1442 shoot_parameters_mainstem.internode_length_max = 0.22;
+
1443 shoot_parameters_mainstem.tortuosity = 1.f;
+
1444 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
1445 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
1446 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
1447 shoot_parameters_mainstem.determinate_shoot_growth = false;
+
1448 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
+
1449 shoot_parameters_mainstem.fruit_set_probability = 1.0;
+
1450 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
+
1451 shoot_parameters_mainstem.max_nodes = 17;
+
1452 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
+
1453
+
1454 defineShootType("mainstem",shoot_parameters_mainstem);
+
1455
+
1456}
+
1457
+
1458uint PlantArchitecture::buildMaizePlant(const helios::vec3 &base_position) {
1459
-
1460 defineShootType("trunk", shoot_parameters_trunk);
-
1461 defineShootType("scaffold", shoot_parameters_scaffold);
-
1462 defineShootType("proleptic", shoot_parameters_proleptic);
-
1463
-
1464}
-
1465
-
1466uint PlantArchitecture::buildOliveTree(const helios::vec3 &base_position) {
-
1467
-
1468 if( shoot_types.empty() ){
-
1469 //automatically initialize olive tree shoots
-
1470 initializeOliveTreeShoots();
-
1471 }
+
1460 if (shoot_types.empty()) {
+
1461 //automatically initialize maize plant shoots
+
1462 initializeMaizeShoots();
+
1463 }
+
1464
+
1465 uint plantID = addPlantInstance(base_position, 0);
+
1466
+
1467 uint uID_stem = addBaseStemShoot(plantID, 1, make_AxisRotation(context_ptr->randu(0.f, 0.035f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)), 0.003, 0.08, 0.01, 0.01, 0, "mainstem");
+
1468
+
1469 breakPlantDormancy(plantID);
+
1470
+
1471 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 10, 100, false);
1472
-
1473 uint plantID = addPlantInstance(base_position, 0);
+
1473 plant_instances.at(plantID).max_age = 365;
1474
-
1475 uint uID_trunk = addBaseStemShoot(plantID, 19, make_AxisRotation(context_ptr->randu(0.f, 0.025f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)), shoot_types.at("trunk").phytomer_parameters.internode.radius_initial.val(), 0.01, 1.f, 1.f, 0, "trunk");
-
1476 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
-
1477
-
1478 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
-
1479
-
1480 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
-
1481 for( const auto & phytomer : phytomers ){
-
1482 phytomer->removeLeaf();
-
1483 phytomer->setVegetativeBudState(BUD_DEAD);
-
1484 phytomer->setFloralBudState(BUD_DEAD);
-
1485 }
+
1475 return plantID;
+
1476
+
1477}
+
1478
+
1479void PlantArchitecture::initializeOliveTreeShoots(){
+
1480
+
1481 // ---- Leaf Prototype ---- //
+
1482
+
1483 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
1484 leaf_prototype.prototype_function = OliveLeafPrototype;
+
1485 leaf_prototype.unique_prototypes = 1;
1486
-
1487 uint Nscaffolds = 4;//context_ptr->randu(4,5);
+
1487 // ---- Phytomer Parameters ---- //
1488
-
1489 for( int i=0; i<Nscaffolds; i++ ) {
-
1490 float pitch = context_ptr->randu(deg2rad(30), deg2rad(35));
-
1491 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, shoot_types.at("scaffold").internode_length_max.val(), 1.f, 1.f, 0.5, "scaffold", 0);
-
1492
-
1493 }
-
1494
-
1495 makePlantDormant(plantID);
-
1496
-
1497 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 20, 200, 600, true);
-
1498 plant_instances.at(plantID).max_age = 1825;
-
1499
-
1500 return plantID;
-
1501
-
1502}
-
1503
-
1504void PlantArchitecture::initializePistachioTreeShoots(){
-
1505
-
1506 // ---- Leaf Prototype ---- //
+
1489 PhytomerParameters phytomer_parameters_olive(context_ptr->getRandomGenerator());
+
1490
+
1491 phytomer_parameters_olive.internode.pitch = 0;
+
1492 phytomer_parameters_olive.internode.phyllotactic_angle.uniformDistribution(80, 100 );
+
1493 phytomer_parameters_olive.internode.radius_initial = 0.002;
+
1494 phytomer_parameters_olive.internode.length_segments = 1;
+
1495 phytomer_parameters_olive.internode.image_texture = "plugins/plantarchitecture/assets/textures/OliveBark.jpg";
+
1496 phytomer_parameters_olive.internode.max_floral_buds_per_petiole = 3;
+
1497
+
1498 phytomer_parameters_olive.petiole.petioles_per_internode = 2;
+
1499 phytomer_parameters_olive.petiole.pitch.uniformDistribution(-40,-20);
+
1500 phytomer_parameters_olive.petiole.taper = 0.1;
+
1501 phytomer_parameters_olive.petiole.curvature = 0;
+
1502 phytomer_parameters_olive.petiole.length = 0.01;
+
1503 phytomer_parameters_olive.petiole.radius = 0.0005;
+
1504 phytomer_parameters_olive.petiole.length_segments = 1;
+
1505 phytomer_parameters_olive.petiole.radial_subdivisions = 3;
+
1506 phytomer_parameters_olive.petiole.color = make_RGBcolor(0.61, 0.5, 0.24);
1507
-
1508 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
1509 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/PistachioLeaf.png";
-
1510 leaf_prototype.leaf_aspect_ratio = 0.6f;
-
1511 leaf_prototype.midrib_fold_fraction = 0.;
-
1512 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.4, 0.4 );
-
1513 leaf_prototype.lateral_curvature = 0.;
-
1514 leaf_prototype.wave_period = 0.3f;
-
1515 leaf_prototype.wave_amplitude = 0.1f;
-
1516 leaf_prototype.subdivisions = 3;
-
1517 leaf_prototype.unique_prototypes = 5;
+
1508 phytomer_parameters_olive.leaf.leaves_per_petiole = 1;
+
1509 phytomer_parameters_olive.leaf.prototype_scale = 0.06;
+
1510 phytomer_parameters_olive.leaf.prototype = leaf_prototype;
+
1511
+
1512 phytomer_parameters_olive.peduncle.length = 0.065;
+
1513 phytomer_parameters_olive.peduncle.radius = 0.001;
+
1514 phytomer_parameters_olive.peduncle.pitch = 60;
+
1515 phytomer_parameters_olive.peduncle.roll = 0;
+
1516 phytomer_parameters_olive.peduncle.length_segments = 1;
+
1517 phytomer_parameters_olive.peduncle.color = make_RGBcolor(0.7, 0.72, 0.7);
1518
-
1519 // ---- Phytomer Parameters ---- //
-
1520
-
1521 PhytomerParameters phytomer_parameters_pistachio(context_ptr->getRandomGenerator());
-
1522
-
1523 phytomer_parameters_pistachio.internode.pitch = 0;
-
1524 phytomer_parameters_pistachio.internode.phyllotactic_angle.uniformDistribution(160, 200);
-
1525 phytomer_parameters_pistachio.internode.radius_initial = 0.002;
-
1526 phytomer_parameters_pistachio.internode.length_segments = 1;
-
1527 phytomer_parameters_pistachio.internode.image_texture = "plugins/plantarchitecture/assets/textures/OliveBark.jpg";
-
1528 phytomer_parameters_pistachio.internode.max_floral_buds_per_petiole = 3;
+
1519 phytomer_parameters_olive.inflorescence.flowers_per_peduncle = 10;
+
1520 phytomer_parameters_olive.inflorescence.flower_offset = 0.13;
+
1521 phytomer_parameters_olive.inflorescence.pitch.uniformDistribution(80,100);
+
1522 phytomer_parameters_olive.inflorescence.roll.uniformDistribution(0,360);
+
1523 phytomer_parameters_olive.inflorescence.flower_prototype_scale = 0.01;
+
1524// phytomer_parameters_olive.inflorescence.flower_prototype_function = OliveFlowerPrototype;
+
1525 phytomer_parameters_olive.inflorescence.fruit_prototype_scale = 0.025;
+
1526 phytomer_parameters_olive.inflorescence.fruit_prototype_function = OliveFruitPrototype;
+
1527
+
1528 // ---- Shoot Parameters ---- //
1529
-
1530 phytomer_parameters_pistachio.petiole.petioles_per_internode = 2;
-
1531 phytomer_parameters_pistachio.petiole.pitch.uniformDistribution(-60, -45);
-
1532 phytomer_parameters_pistachio.petiole.taper = 0.1;
-
1533 phytomer_parameters_pistachio.petiole.curvature.uniformDistribution(-800,800);
-
1534 phytomer_parameters_pistachio.petiole.length = 0.075;
-
1535 phytomer_parameters_pistachio.petiole.radius = 0.001;
-
1536 phytomer_parameters_pistachio.petiole.length_segments = 1;
-
1537 phytomer_parameters_pistachio.petiole.radial_subdivisions = 3;
-
1538 phytomer_parameters_pistachio.petiole.color = make_RGBcolor(0.6, 0.6, 0.4);
-
1539
-
1540 phytomer_parameters_pistachio.leaf.leaves_per_petiole = 3;
-
1541 phytomer_parameters_pistachio.leaf.prototype_scale = 0.08;
-
1542 phytomer_parameters_pistachio.leaf.leaflet_offset = 0.3;
-
1543 phytomer_parameters_pistachio.leaf.leaflet_scale = 0.75;
-
1544 phytomer_parameters_pistachio.leaf.pitch.uniformDistribution(-20,20);
-
1545 phytomer_parameters_pistachio.leaf.roll.uniformDistribution(-20,20);
-
1546 phytomer_parameters_pistachio.leaf.prototype = leaf_prototype;
-
1547
-
1548 phytomer_parameters_pistachio.peduncle.length = 0.1;
-
1549 phytomer_parameters_pistachio.peduncle.radius = 0.001;
-
1550 phytomer_parameters_pistachio.peduncle.pitch = 60;
-
1551 phytomer_parameters_pistachio.peduncle.roll = 0;
-
1552 phytomer_parameters_pistachio.peduncle.length_segments = 1;
-
1553 phytomer_parameters_pistachio.peduncle.curvature.uniformDistribution(500,900);
-
1554 phytomer_parameters_pistachio.peduncle.color = make_RGBcolor(0.7, 0.72, 0.7);
-
1555
-
1556 phytomer_parameters_pistachio.inflorescence.flowers_per_peduncle = 16;
-
1557 phytomer_parameters_pistachio.inflorescence.flower_offset = 0.08;
-
1558 phytomer_parameters_pistachio.inflorescence.pitch.uniformDistribution(50, 70);
-
1559 phytomer_parameters_pistachio.inflorescence.roll.uniformDistribution(0, 360);
-
1560 phytomer_parameters_pistachio.inflorescence.flower_prototype_scale = 0.025;
-
1561// phytomer_parameters_pistachio.inflorescence.flower_prototype_function = PistachioFlowerPrototype;
-
1562 phytomer_parameters_pistachio.inflorescence.fruit_prototype_scale = 0.025;
-
1563 phytomer_parameters_pistachio.inflorescence.fruit_prototype_function = PistachioFruitPrototype;
-
1564
-
1565 // ---- Shoot Parameters ---- //
-
1566
-
1567 // Trunk
-
1568 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
-
1569 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_pistachio;
-
1570 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 180;
-
1571 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.015;
-
1572 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 20;
-
1573 shoot_parameters_trunk.max_nodes = 20;
-
1574 shoot_parameters_trunk.girth_area_factor = 3.f;
-
1575 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
-
1576 shoot_parameters_trunk.vegetative_bud_break_time = 0;
-
1577 shoot_parameters_trunk.tortuosity = 1;
-
1578 shoot_parameters_trunk.internode_length_max = 0.05;
-
1579 shoot_parameters_trunk.internode_length_decay_rate = 0;
-
1580 shoot_parameters_trunk.defineChildShootTypes({"proleptic"},{1});
-
1581
-
1582 // Proleptic shoots
-
1583 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
-
1584 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_pistachio;
-
1585 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = PistachioPhytomerCreationFunction;
-
1586 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = PistachioPhytomerCallbackFunction;
-
1587 shoot_parameters_proleptic.max_nodes.uniformDistribution(16,24);
-
1588 shoot_parameters_proleptic.max_nodes_per_season.uniformDistribution(8,12);
-
1589 shoot_parameters_proleptic.phyllochron_min = 2.0;
-
1590 shoot_parameters_proleptic.elongation_rate = 0.25;
-
1591 shoot_parameters_proleptic.girth_area_factor = 8.f;
-
1592 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.025;
-
1593 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.7;
-
1594 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
-
1595 shoot_parameters_proleptic.gravitropic_curvature = 500;
-
1596 shoot_parameters_proleptic.tortuosity = 10;
-
1597 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 45, 55);
-
1598 shoot_parameters_proleptic.insertion_angle_decay_rate = 10;
-
1599 shoot_parameters_proleptic.internode_length_max = 0.06;
-
1600 shoot_parameters_proleptic.internode_length_min = 0.03;
-
1601 shoot_parameters_proleptic.internode_length_decay_rate = 0.005;
-
1602 shoot_parameters_proleptic.fruit_set_probability = 0.35;
-
1603 shoot_parameters_proleptic.flower_bud_break_probability = 0.35;
-
1604 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
-
1605 shoot_parameters_proleptic.flowers_require_dormancy = true;
-
1606 shoot_parameters_proleptic.growth_requires_dormancy = true;
-
1607 shoot_parameters_proleptic.determinate_shoot_growth = false;
-
1608
-
1609 defineShootType("trunk", shoot_parameters_trunk);
-
1610 defineShootType("proleptic", shoot_parameters_proleptic);
+
1530 // Trunk
+
1531 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
+
1532 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_olive;
+
1533 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
+
1534 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.015;
+
1535 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 20;
+
1536 shoot_parameters_trunk.max_nodes = 20;
+
1537 shoot_parameters_trunk.girth_area_factor = 3.f;
+
1538 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
+
1539 shoot_parameters_trunk.vegetative_bud_break_time = 0;
+
1540 shoot_parameters_trunk.tortuosity = 1;
+
1541 shoot_parameters_trunk.internode_length_max = 0.05;
+
1542 shoot_parameters_trunk.internode_length_decay_rate = 0;
+
1543 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
+
1544
+
1545 // Proleptic shoots
+
1546 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
+
1547 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_olive;
+
1548// shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = OlivePhytomerCreationFunction;
+
1549 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = OlivePhytomerCallbackFunction;
+
1550 shoot_parameters_proleptic.max_nodes.uniformDistribution(16,24);
+
1551 shoot_parameters_proleptic.max_nodes_per_season.uniformDistribution(8,12);
+
1552 shoot_parameters_proleptic.phyllochron_min = 2.0;
+
1553 shoot_parameters_proleptic.elongation_rate_max = 0.25;
+
1554 shoot_parameters_proleptic.girth_area_factor = 5.f;
+
1555 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.025;
+
1556 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 1.0;
+
1557 shoot_parameters_proleptic.vegetative_bud_break_time = 30;
+
1558 shoot_parameters_proleptic.gravitropic_curvature.uniformDistribution(550,650);
+
1559 shoot_parameters_proleptic.tortuosity = 5;
+
1560 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 35, 40);
+
1561 shoot_parameters_proleptic.insertion_angle_decay_rate = 2;
+
1562 shoot_parameters_proleptic.internode_length_max = 0.05;
+
1563 shoot_parameters_proleptic.internode_length_min = 0.03;
+
1564 shoot_parameters_proleptic.internode_length_decay_rate = 0.004;
+
1565 shoot_parameters_proleptic.fruit_set_probability = 0.25;
+
1566 shoot_parameters_proleptic.flower_bud_break_probability = 0.25;
+
1567 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
+
1568 shoot_parameters_proleptic.flowers_require_dormancy = true;
+
1569 shoot_parameters_proleptic.growth_requires_dormancy = true;
+
1570 shoot_parameters_proleptic.determinate_shoot_growth = false;
+
1571 shoot_parameters_proleptic.defineChildShootTypes({"proleptic"},{1.0});
+
1572
+
1573 // Main scaffolds
+
1574 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
+
1575 shoot_parameters_scaffold.phytomer_parameters.internode.radial_subdivisions = 10;
+
1576 shoot_parameters_scaffold.max_nodes = 30;
+
1577 shoot_parameters_scaffold.max_nodes_per_season = 10;
+
1578 shoot_parameters_scaffold.gravitropic_curvature = 700;
+
1579 shoot_parameters_scaffold.internode_length_max = 0.04;
+
1580 shoot_parameters_scaffold.tortuosity = 3;
+
1581 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
+
1582
+
1583 defineShootType("trunk", shoot_parameters_trunk);
+
1584 defineShootType("scaffold", shoot_parameters_scaffold);
+
1585 defineShootType("proleptic", shoot_parameters_proleptic);
+
1586
+
1587}
+
1588
+
1589uint PlantArchitecture::buildOliveTree(const helios::vec3 &base_position) {
+
1590
+
1591 if( shoot_types.empty() ){
+
1592 //automatically initialize olive tree shoots
+
1593 initializeOliveTreeShoots();
+
1594 }
+
1595
+
1596 uint plantID = addPlantInstance(base_position, 0);
+
1597
+
1598 uint uID_trunk = addBaseStemShoot(plantID, 19, make_AxisRotation(context_ptr->randu(0.f, 0.025f * M_PI), context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)), shoot_types.at("trunk").phytomer_parameters.internode.radius_initial.val(), 0.01, 1.f, 1.f, 0, "trunk");
+
1599 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
+
1600
+
1601 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
+
1602
+
1603 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
+
1604 for( const auto & phytomer : phytomers ){
+
1605 phytomer->removeLeaf();
+
1606 phytomer->setVegetativeBudState(BUD_DEAD);
+
1607 phytomer->setFloralBudState(BUD_DEAD);
+
1608 }
+
1609
+
1610 uint Nscaffolds = 4;//context_ptr->randu(4,5);
1611
-
1612}
-
1613
-
1614uint PlantArchitecture::buildPistachioTree(const helios::vec3 &base_position) {
+
1612 for( int i=0; i<Nscaffolds; i++ ) {
+
1613 float pitch = context_ptr->randu(deg2rad(30), deg2rad(35));
+
1614 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, shoot_types.at("scaffold").internode_length_max.val(), 1.f, 1.f, 0.5, "scaffold", 0);
1615
-
1616 if( shoot_types.empty() ){
-
1617 //automatically initialize pistachio tree shoots
-
1618 initializePistachioTreeShoots();
-
1619 }
-
1620
-
1621 uint plantID = addPlantInstance(base_position, 0);
+
1616 }
+
1617
+
1618 makePlantDormant(plantID);
+
1619
+
1620 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 20, 200, 600, true);
+
1621 plant_instances.at(plantID).max_age = 1825;
1622
-
1623 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)), shoot_types.at("trunk").phytomer_parameters.internode.radius_initial.val(), 0.05, 1.f, 1.f, 0, "trunk");
-
1624 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
-
1625
-
1626 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
-
1627
-
1628 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
-
1629 for( const auto & phytomer : phytomers ){
-
1630 phytomer->removeLeaf();
-
1631 phytomer->setVegetativeBudState(BUD_DEAD);
-
1632 phytomer->setFloralBudState(BUD_DEAD);
-
1633 }
-
1634
-
1635 uint Nscaffolds = 4;//context_ptr->randu(4,5);
-
1636
-
1637 for( int i=0; i<Nscaffolds; i++ ) {
-
1638 float pitch = context_ptr->randu(deg2rad(65), deg2rad(80));
-
1639 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, 1, make_AxisRotation(pitch, (float(i) + context_ptr->randu(-0.1f, 0.1f)) / float(Nscaffolds) * 2 * M_PI, 0.5*M_PI), 0.007, 0.06, 1.f, 1.f, 0.5, "proleptic", 0);
-
1640
-
1641 }
-
1642
-
1643 makePlantDormant(plantID);
-
1644
-
1645 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 20, 200, false);
-
1646 plant_instances.at(plantID).max_age = 1095;
-
1647
-
1648 return plantID;
-
1649
-
1650}
-
1651
-
1652void PlantArchitecture::initializePuncturevineShoots() {
-
1653
-
1654 // ---- Leaf Prototype ---- //
-
1655
-
1656 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
1657 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/PuncturevineLeaf.png";
-
1658 leaf_prototype.leaf_aspect_ratio = 0.4f;
-
1659 leaf_prototype.midrib_fold_fraction = 0.2f;
-
1660 leaf_prototype.longitudinal_curvature = -0.1f;
-
1661 leaf_prototype.lateral_curvature = 0.4f;
-
1662 leaf_prototype.subdivisions = 1;
-
1663 leaf_prototype.unique_prototypes = 1;
-
1664
-
1665 // ---- Phytomer Parameters ---- //
-
1666
-
1667 PhytomerParameters phytomer_parameters_puncturevine(context_ptr->getRandomGenerator());
-
1668
-
1669 phytomer_parameters_puncturevine.internode.pitch.uniformDistribution(0,15);
-
1670 phytomer_parameters_puncturevine.internode.phyllotactic_angle = 180.f;
-
1671 phytomer_parameters_puncturevine.internode.radius_initial = 0.001;
-
1672 phytomer_parameters_puncturevine.internode.color = make_RGBcolor(0.28, 0.18, 0.13);
-
1673 phytomer_parameters_puncturevine.internode.length_segments = 1;
-
1674
-
1675 phytomer_parameters_puncturevine.petiole.petioles_per_internode = 1;
-
1676 phytomer_parameters_puncturevine.petiole.pitch.uniformDistribution(60, 80);
-
1677 phytomer_parameters_puncturevine.petiole.radius = 0.0005;
-
1678 phytomer_parameters_puncturevine.petiole.length = 0.03;
-
1679 phytomer_parameters_puncturevine.petiole.taper = 0;
-
1680 phytomer_parameters_puncturevine.petiole.curvature = 0;
-
1681 phytomer_parameters_puncturevine.petiole.color = phytomer_parameters_puncturevine.internode.color;
-
1682 phytomer_parameters_puncturevine.petiole.length_segments = 1;
-
1683
-
1684 phytomer_parameters_puncturevine.leaf.leaves_per_petiole = 11;
-
1685 phytomer_parameters_puncturevine.leaf.pitch.uniformDistribution(0,40);
-
1686 phytomer_parameters_puncturevine.leaf.yaw = 30;
-
1687 phytomer_parameters_puncturevine.leaf.roll.uniformDistribution(-5,5);
-
1688 phytomer_parameters_puncturevine.leaf.prototype_scale = 0.012;
-
1689 phytomer_parameters_puncturevine.leaf.leaflet_offset = 0.18;
-
1690 phytomer_parameters_puncturevine.leaf.leaflet_scale = 1;
-
1691 phytomer_parameters_puncturevine.leaf.prototype = leaf_prototype;
-
1692
-
1693 phytomer_parameters_puncturevine.peduncle.length = 0.001;
-
1694 phytomer_parameters_puncturevine.peduncle.color = phytomer_parameters_puncturevine.internode.color;
-
1695
-
1696 phytomer_parameters_puncturevine.inflorescence.flowers_per_peduncle = 1;
-
1697 phytomer_parameters_puncturevine.inflorescence.pitch = -90.f;
-
1698 phytomer_parameters_puncturevine.inflorescence.flower_prototype_function = PuncturevineFlowerPrototype;
-
1699 phytomer_parameters_puncturevine.inflorescence.flower_prototype_scale = 0.01;
-
1700
-
1701 // ---- Shoot Parameters ---- //
-
1702
-
1703 ShootParameters shoot_parameters_primary(context_ptr->getRandomGenerator());
-
1704 shoot_parameters_primary.phytomer_parameters = phytomer_parameters_puncturevine;
-
1705 shoot_parameters_primary.vegetative_bud_break_probability_min = 0.1;
-
1706 shoot_parameters_primary.vegetative_bud_break_probability_decay_rate = 1.f;
-
1707 shoot_parameters_primary.vegetative_bud_break_time = 3;
-
1708 shoot_parameters_primary.base_roll = 90;
-
1709 shoot_parameters_primary.phyllochron_min = 1;
-
1710 shoot_parameters_primary.elongation_rate = 0.2;
-
1711 shoot_parameters_primary.girth_area_factor = 0.f;
-
1712 shoot_parameters_primary.internode_length_max = 0.02;
-
1713 shoot_parameters_primary.internode_length_decay_rate = 0;
-
1714 shoot_parameters_primary.insertion_angle_tip.uniformDistribution(50, 80);
-
1715 shoot_parameters_primary.flowers_require_dormancy = false;
-
1716 shoot_parameters_primary.growth_requires_dormancy = false;
-
1717 shoot_parameters_primary.flower_bud_break_probability = 0.2;
-
1718 shoot_parameters_primary.determinate_shoot_growth = false;
-
1719 shoot_parameters_primary.max_nodes = 15;
-
1720 shoot_parameters_primary.gravitropic_curvature = 50;
-
1721 shoot_parameters_primary.tortuosity = 0;
-
1722 shoot_parameters_primary.defineChildShootTypes({"secondary_puncturevine"}, {1.f});
-
1723
-
1724 ShootParameters shoot_parameters_base = shoot_parameters_primary;
-
1725 shoot_parameters_base.phytomer_parameters = phytomer_parameters_puncturevine;
-
1726 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
-
1727 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
-
1728 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
-
1729 shoot_parameters_base.vegetative_bud_break_probability_min = 1;
-
1730 shoot_parameters_base.vegetative_bud_break_time = 2;
-
1731 shoot_parameters_base.phyllochron_min = 2;
-
1732 shoot_parameters_base.elongation_rate = 0.15;
-
1733 shoot_parameters_base.gravitropic_curvature = 0;
-
1734 shoot_parameters_base.internode_length_max = 0.01;
-
1735 shoot_parameters_base.internode_length_decay_rate = 0;
-
1736 shoot_parameters_base.insertion_angle_tip = 90;
-
1737 shoot_parameters_base.insertion_angle_decay_rate = 0;
-
1738 shoot_parameters_base.flowers_require_dormancy = false;
-
1739 shoot_parameters_base.growth_requires_dormancy = false;
-
1740 shoot_parameters_base.flower_bud_break_probability = 0.0;
-
1741 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
-
1742 shoot_parameters_base.defineChildShootTypes({"primary_puncturevine"},{1.f});
+
1623 return plantID;
+
1624
+
1625}
+
1626
+
1627void PlantArchitecture::initializePistachioTreeShoots(){
+
1628
+
1629 // ---- Leaf Prototype ---- //
+
1630
+
1631 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
1632 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/PistachioLeaf.png";
+
1633 leaf_prototype.leaf_aspect_ratio = 0.6f;
+
1634 leaf_prototype.midrib_fold_fraction = 0.;
+
1635 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.4, 0.4 );
+
1636 leaf_prototype.lateral_curvature = 0.;
+
1637 leaf_prototype.wave_period = 0.3f;
+
1638 leaf_prototype.wave_amplitude = 0.1f;
+
1639 leaf_prototype.subdivisions = 3;
+
1640 leaf_prototype.unique_prototypes = 5;
+
1641
+
1642 // ---- Phytomer Parameters ---- //
+
1643
+
1644 PhytomerParameters phytomer_parameters_pistachio(context_ptr->getRandomGenerator());
+
1645
+
1646 phytomer_parameters_pistachio.internode.pitch = 0;
+
1647 phytomer_parameters_pistachio.internode.phyllotactic_angle.uniformDistribution(160, 200);
+
1648 phytomer_parameters_pistachio.internode.radius_initial = 0.002;
+
1649 phytomer_parameters_pistachio.internode.length_segments = 1;
+
1650 phytomer_parameters_pistachio.internode.image_texture = "plugins/plantarchitecture/assets/textures/OliveBark.jpg";
+
1651 phytomer_parameters_pistachio.internode.max_floral_buds_per_petiole = 3;
+
1652
+
1653 phytomer_parameters_pistachio.petiole.petioles_per_internode = 2;
+
1654 phytomer_parameters_pistachio.petiole.pitch.uniformDistribution(-60, -45);
+
1655 phytomer_parameters_pistachio.petiole.taper = 0.1;
+
1656 phytomer_parameters_pistachio.petiole.curvature.uniformDistribution(-800,800);
+
1657 phytomer_parameters_pistachio.petiole.length = 0.075;
+
1658 phytomer_parameters_pistachio.petiole.radius = 0.001;
+
1659 phytomer_parameters_pistachio.petiole.length_segments = 1;
+
1660 phytomer_parameters_pistachio.petiole.radial_subdivisions = 3;
+
1661 phytomer_parameters_pistachio.petiole.color = make_RGBcolor(0.6, 0.6, 0.4);
+
1662
+
1663 phytomer_parameters_pistachio.leaf.leaves_per_petiole = 3;
+
1664 phytomer_parameters_pistachio.leaf.prototype_scale = 0.08;
+
1665 phytomer_parameters_pistachio.leaf.leaflet_offset = 0.3;
+
1666 phytomer_parameters_pistachio.leaf.leaflet_scale = 0.75;
+
1667 phytomer_parameters_pistachio.leaf.pitch.uniformDistribution(-20,20);
+
1668 phytomer_parameters_pistachio.leaf.roll.uniformDistribution(-20,20);
+
1669 phytomer_parameters_pistachio.leaf.prototype = leaf_prototype;
+
1670
+
1671 phytomer_parameters_pistachio.peduncle.length = 0.1;
+
1672 phytomer_parameters_pistachio.peduncle.radius = 0.001;
+
1673 phytomer_parameters_pistachio.peduncle.pitch = 60;
+
1674 phytomer_parameters_pistachio.peduncle.roll = 0;
+
1675 phytomer_parameters_pistachio.peduncle.length_segments = 1;
+
1676 phytomer_parameters_pistachio.peduncle.curvature.uniformDistribution(500,900);
+
1677 phytomer_parameters_pistachio.peduncle.color = make_RGBcolor(0.7, 0.72, 0.7);
+
1678
+
1679 phytomer_parameters_pistachio.inflorescence.flowers_per_peduncle = 16;
+
1680 phytomer_parameters_pistachio.inflorescence.flower_offset = 0.08;
+
1681 phytomer_parameters_pistachio.inflorescence.pitch.uniformDistribution(50, 70);
+
1682 phytomer_parameters_pistachio.inflorescence.roll.uniformDistribution(0, 360);
+
1683 phytomer_parameters_pistachio.inflorescence.flower_prototype_scale = 0.025;
+
1684// phytomer_parameters_pistachio.inflorescence.flower_prototype_function = PistachioFlowerPrototype;
+
1685 phytomer_parameters_pistachio.inflorescence.fruit_prototype_scale = 0.025;
+
1686 phytomer_parameters_pistachio.inflorescence.fruit_prototype_function = PistachioFruitPrototype;
+
1687
+
1688 // ---- Shoot Parameters ---- //
+
1689
+
1690 // Trunk
+
1691 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
+
1692 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_pistachio;
+
1693 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 180;
+
1694 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.015;
+
1695 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 20;
+
1696 shoot_parameters_trunk.max_nodes = 20;
+
1697 shoot_parameters_trunk.girth_area_factor = 3.f;
+
1698 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
+
1699 shoot_parameters_trunk.vegetative_bud_break_time = 0;
+
1700 shoot_parameters_trunk.tortuosity = 1;
+
1701 shoot_parameters_trunk.internode_length_max = 0.05;
+
1702 shoot_parameters_trunk.internode_length_decay_rate = 0;
+
1703 shoot_parameters_trunk.defineChildShootTypes({"proleptic"},{1});
+
1704
+
1705 // Proleptic shoots
+
1706 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
+
1707 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_pistachio;
+
1708 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = PistachioPhytomerCreationFunction;
+
1709 shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = PistachioPhytomerCallbackFunction;
+
1710 shoot_parameters_proleptic.max_nodes.uniformDistribution(16,24);
+
1711 shoot_parameters_proleptic.max_nodes_per_season.uniformDistribution(8,12);
+
1712 shoot_parameters_proleptic.phyllochron_min = 2.0;
+
1713 shoot_parameters_proleptic.elongation_rate_max = 0.25;
+
1714 shoot_parameters_proleptic.girth_area_factor = 8.f;
+
1715 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.025;
+
1716 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.7;
+
1717 shoot_parameters_proleptic.vegetative_bud_break_time = 0;
+
1718 shoot_parameters_proleptic.gravitropic_curvature = 500;
+
1719 shoot_parameters_proleptic.tortuosity = 10;
+
1720 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 45, 55);
+
1721 shoot_parameters_proleptic.insertion_angle_decay_rate = 10;
+
1722 shoot_parameters_proleptic.internode_length_max = 0.06;
+
1723 shoot_parameters_proleptic.internode_length_min = 0.03;
+
1724 shoot_parameters_proleptic.internode_length_decay_rate = 0.005;
+
1725 shoot_parameters_proleptic.fruit_set_probability = 0.35;
+
1726 shoot_parameters_proleptic.flower_bud_break_probability = 0.35;
+
1727 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
+
1728 shoot_parameters_proleptic.flowers_require_dormancy = true;
+
1729 shoot_parameters_proleptic.growth_requires_dormancy = true;
+
1730 shoot_parameters_proleptic.determinate_shoot_growth = false;
+
1731
+
1732 defineShootType("trunk", shoot_parameters_trunk);
+
1733 defineShootType("proleptic", shoot_parameters_proleptic);
+
1734
+
1735}
+
1736
+
1737uint PlantArchitecture::buildPistachioTree(const helios::vec3 &base_position) {
+
1738
+
1739 if( shoot_types.empty() ){
+
1740 //automatically initialize pistachio tree shoots
+
1741 initializePistachioTreeShoots();
+
1742 }
1743
-
1744 ShootParameters shoot_parameters_children = shoot_parameters_primary;
-
1745 shoot_parameters_children.base_roll = 0;
-
1746
-
1747 defineShootType("base_puncturevine", shoot_parameters_base);
-
1748 defineShootType("primary_puncturevine", shoot_parameters_primary);
-
1749 defineShootType("secondary_puncturevine", shoot_parameters_children);
+
1744 uint plantID = addPlantInstance(base_position, 0);
+
1745
+
1746 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)), shoot_types.at("trunk").phytomer_parameters.internode.radius_initial.val(), 0.05, 1.f, 1.f, 0, "trunk");
+
1747 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
+
1748
+
1749 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
1750
-
1751}
-
1752
-
1753uint PlantArchitecture::buildPuncturevinePlant(const helios::vec3 &base_position) {
-
1754
-
1755 if (shoot_types.empty()) {
-
1756 //automatically initialize puncturevine plant shoots
-
1757 initializePuncturevineShoots();
-
1758 }
+
1751 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
+
1752 for( const auto & phytomer : phytomers ){
+
1753 phytomer->removeLeaf();
+
1754 phytomer->setVegetativeBudState(BUD_DEAD);
+
1755 phytomer->setFloralBudState(BUD_DEAD);
+
1756 }
+
1757
+
1758 uint Nscaffolds = 4;//context_ptr->randu(4,5);
1759
-
1760 uint plantID = addPlantInstance(base_position, 0);
-
1761
-
1762 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, 0, "base_puncturevine");
+
1760 for( int i=0; i<Nscaffolds; i++ ) {
+
1761 float pitch = context_ptr->randu(deg2rad(65), deg2rad(80));
+
1762 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, 1, make_AxisRotation(pitch, (float(i) + context_ptr->randu(-0.1f, 0.1f)) / float(Nscaffolds) * 2 * M_PI, 0.5*M_PI), 0.007, 0.06, 1.f, 1.f, 0.5, "proleptic", 0);
1763
-
1764 breakPlantDormancy(plantID);
+
1764 }
1765
-
1766 plant_instances.at(plantID).max_age = 45;
+
1766 makePlantDormant(plantID);
1767
-
1768 setPlantPhenologicalThresholds(plantID, 0, -1, 14, -1, -1, 1000, false);
-
1769
-
1770 return plantID;
-
1771
-
1772}
-
1773
-
1774void PlantArchitecture::initializeEasternRedbudShoots() {
-
1775
-
1776 // ---- Leaf Prototype ---- //
-
1777
-
1778 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
1779 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/RedbudLeaf.png";
-
1780 leaf_prototype.leaf_aspect_ratio = 1.f;
-
1781 leaf_prototype.midrib_fold_fraction = 0.2f;
-
1782 leaf_prototype.longitudinal_curvature = -0.15f;
-
1783 leaf_prototype.lateral_curvature = -0.1f;
-
1784 leaf_prototype.wave_period = 0.3f;
-
1785 leaf_prototype.wave_amplitude = 0.025f;
-
1786 leaf_prototype.subdivisions = 5;
-
1787 leaf_prototype.unique_prototypes = 5;
-
1788 leaf_prototype.leaf_offset = make_vec3(-0.3, 0, 0);
+
1768 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 20, 200, false);
+
1769 plant_instances.at(plantID).max_age = 1095;
+
1770
+
1771 return plantID;
+
1772
+
1773}
+
1774
+
1775void PlantArchitecture::initializePuncturevineShoots() {
+
1776
+
1777 // ---- Leaf Prototype ---- //
+
1778
+
1779 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
1780 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/PuncturevineLeaf.png";
+
1781 leaf_prototype.leaf_aspect_ratio = 0.4f;
+
1782 leaf_prototype.midrib_fold_fraction = 0.2f;
+
1783 leaf_prototype.longitudinal_curvature = -0.1f;
+
1784 leaf_prototype.lateral_curvature = 0.4f;
+
1785 leaf_prototype.subdivisions = 1;
+
1786 leaf_prototype.unique_prototypes = 1;
+
1787
+
1788 // ---- Phytomer Parameters ---- //
1789
-
1790 // ---- Phytomer Parameters ---- //
+
1790 PhytomerParameters phytomer_parameters_puncturevine(context_ptr->getRandomGenerator());
1791
-
1792 PhytomerParameters phytomer_parameters_redbud(context_ptr->getRandomGenerator());
-
1793
-
1794 phytomer_parameters_redbud.internode.pitch = 15;
-
1795 phytomer_parameters_redbud.internode.phyllotactic_angle.uniformDistribution(170,190);
-
1796 phytomer_parameters_redbud.internode.radius_initial = 0.0015;
-
1797 phytomer_parameters_redbud.internode.image_texture = "plugins/plantarchitecture/assets/textures/WesternRedbudBark.jpg";
-
1798 phytomer_parameters_redbud.internode.color.scale(0.3);
-
1799 phytomer_parameters_redbud.internode.length_segments = 1;
-
1800 phytomer_parameters_redbud.internode.max_floral_buds_per_petiole = 5;
-
1801
-
1802 phytomer_parameters_redbud.petiole.petioles_per_internode = 1;
-
1803 phytomer_parameters_redbud.petiole.color = make_RGBcolor(0.65, 0.52, 0.39);
-
1804 phytomer_parameters_redbud.petiole.pitch.uniformDistribution(20, 40);
-
1805 phytomer_parameters_redbud.petiole.radius = 0.002;
-
1806 phytomer_parameters_redbud.petiole.length = 0.075;
-
1807 phytomer_parameters_redbud.petiole.taper = 0;
-
1808 phytomer_parameters_redbud.petiole.curvature = 0;
-
1809 phytomer_parameters_redbud.petiole.length_segments = 1;
-
1810
-
1811 phytomer_parameters_redbud.leaf.leaves_per_petiole = 1;
-
1812 phytomer_parameters_redbud.leaf.pitch.uniformDistribution(-110, -80);
-
1813 phytomer_parameters_redbud.leaf.yaw = 0;
-
1814 phytomer_parameters_redbud.leaf.roll.uniformDistribution(-5, 5);
-
1815 phytomer_parameters_redbud.leaf.prototype_scale = 0.1;
-
1816 phytomer_parameters_redbud.leaf.prototype = leaf_prototype;
-
1817
-
1818 phytomer_parameters_redbud.peduncle.length = 0.02;
-
1819 phytomer_parameters_redbud.peduncle.pitch.uniformDistribution(50,90);
-
1820 phytomer_parameters_redbud.peduncle.color = make_RGBcolor(0.32, 0.05, 0.13);
-
1821
-
1822 phytomer_parameters_redbud.inflorescence.flowers_per_peduncle = 1;
-
1823 phytomer_parameters_redbud.inflorescence.pitch = 0;
-
1824 phytomer_parameters_redbud.inflorescence.flower_prototype_function = RedbudFlowerPrototype;
-
1825 phytomer_parameters_redbud.inflorescence.flower_prototype_scale = 0.04;
-
1826 phytomer_parameters_redbud.inflorescence.fruit_prototype_function = RedbudFruitPrototype;
-
1827 phytomer_parameters_redbud.inflorescence.fruit_prototype_scale = 0.1;
-
1828 phytomer_parameters_redbud.inflorescence.fruit_gravity_factor_fraction = 0.7;
-
1829
-
1830 phytomer_parameters_redbud.phytomer_creation_function = RedbudPhytomerCreationFunction;
-
1831 phytomer_parameters_redbud.phytomer_callback_function = RedbudPhytomerCallbackFunction;
-
1832
-
1833 // ---- Shoot Parameters ---- //
-
1834
-
1835 ShootParameters shoot_parameters_main(context_ptr->getRandomGenerator());
-
1836 shoot_parameters_main.phytomer_parameters = phytomer_parameters_redbud;
-
1837 shoot_parameters_main.vegetative_bud_break_probability_min = 1.0;
-
1838 shoot_parameters_main.vegetative_bud_break_time = 2;
-
1839 shoot_parameters_main.phyllochron_min = 2;
-
1840 shoot_parameters_main.elongation_rate = 0.1;
-
1841 shoot_parameters_main.girth_area_factor = 4.f;
-
1842 shoot_parameters_main.gravitropic_curvature = 300;
-
1843 shoot_parameters_main.tortuosity = 5;
-
1844 shoot_parameters_main.internode_length_max = 0.04;
-
1845 shoot_parameters_main.internode_length_decay_rate = 0.005;
-
1846 shoot_parameters_main.internode_length_min = 0.01;
-
1847 shoot_parameters_main.insertion_angle_tip = 75;
-
1848 shoot_parameters_main.insertion_angle_decay_rate = 10;
-
1849 shoot_parameters_main.flowers_require_dormancy = true;
-
1850 shoot_parameters_main.growth_requires_dormancy = true;
-
1851 shoot_parameters_main.determinate_shoot_growth = false;
-
1852 shoot_parameters_main.max_terminal_floral_buds = 0;
-
1853 shoot_parameters_main.flower_bud_break_probability = 0.8;
-
1854 shoot_parameters_main.fruit_set_probability = 0.3;
-
1855 shoot_parameters_main.max_nodes = 25;
-
1856 shoot_parameters_main.max_nodes_per_season = 10;
-
1857 shoot_parameters_main.base_roll = 90;
-
1858
-
1859 ShootParameters shoot_parameters_trunk = shoot_parameters_main;
-
1860 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
-
1861 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 15;
-
1862 shoot_parameters_trunk.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
-
1863 shoot_parameters_trunk.insertion_angle_tip = 60;
-
1864 shoot_parameters_trunk.max_nodes = 75;
-
1865 shoot_parameters_trunk.max_nodes_per_season = 10;
-
1866 shoot_parameters_trunk.tortuosity = 1.5;
-
1867 shoot_parameters_trunk.defineChildShootTypes({"eastern_redbud_shoot"},{1.f});
-
1868
-
1869 defineShootType("eastern_redbud_trunk", shoot_parameters_trunk);
-
1870 defineShootType("eastern_redbud_shoot", shoot_parameters_main);
-
1871
-
1872}
+
1792 phytomer_parameters_puncturevine.internode.pitch.uniformDistribution(0,15);
+
1793 phytomer_parameters_puncturevine.internode.phyllotactic_angle = 180.f;
+
1794 phytomer_parameters_puncturevine.internode.radius_initial = 0.001;
+
1795 phytomer_parameters_puncturevine.internode.color = make_RGBcolor(0.28, 0.18, 0.13);
+
1796 phytomer_parameters_puncturevine.internode.length_segments = 1;
+
1797
+
1798 phytomer_parameters_puncturevine.petiole.petioles_per_internode = 1;
+
1799 phytomer_parameters_puncturevine.petiole.pitch.uniformDistribution(60, 80);
+
1800 phytomer_parameters_puncturevine.petiole.radius = 0.0005;
+
1801 phytomer_parameters_puncturevine.petiole.length = 0.03;
+
1802 phytomer_parameters_puncturevine.petiole.taper = 0;
+
1803 phytomer_parameters_puncturevine.petiole.curvature = 0;
+
1804 phytomer_parameters_puncturevine.petiole.color = phytomer_parameters_puncturevine.internode.color;
+
1805 phytomer_parameters_puncturevine.petiole.length_segments = 1;
+
1806
+
1807 phytomer_parameters_puncturevine.leaf.leaves_per_petiole = 11;
+
1808 phytomer_parameters_puncturevine.leaf.pitch.uniformDistribution(0,40);
+
1809 phytomer_parameters_puncturevine.leaf.yaw = 30;
+
1810 phytomer_parameters_puncturevine.leaf.roll.uniformDistribution(-5,5);
+
1811 phytomer_parameters_puncturevine.leaf.prototype_scale = 0.012;
+
1812 phytomer_parameters_puncturevine.leaf.leaflet_offset = 0.18;
+
1813 phytomer_parameters_puncturevine.leaf.leaflet_scale = 1;
+
1814 phytomer_parameters_puncturevine.leaf.prototype = leaf_prototype;
+
1815
+
1816 phytomer_parameters_puncturevine.peduncle.length = 0.001;
+
1817 phytomer_parameters_puncturevine.peduncle.color = phytomer_parameters_puncturevine.internode.color;
+
1818
+
1819 phytomer_parameters_puncturevine.inflorescence.flowers_per_peduncle = 1;
+
1820 phytomer_parameters_puncturevine.inflorescence.pitch = -90.f;
+
1821 phytomer_parameters_puncturevine.inflorescence.flower_prototype_function = PuncturevineFlowerPrototype;
+
1822 phytomer_parameters_puncturevine.inflorescence.flower_prototype_scale = 0.01;
+
1823
+
1824 // ---- Shoot Parameters ---- //
+
1825
+
1826 ShootParameters shoot_parameters_primary(context_ptr->getRandomGenerator());
+
1827 shoot_parameters_primary.phytomer_parameters = phytomer_parameters_puncturevine;
+
1828 shoot_parameters_primary.vegetative_bud_break_probability_min = 0.1;
+
1829 shoot_parameters_primary.vegetative_bud_break_probability_decay_rate = 1.f;
+
1830 shoot_parameters_primary.vegetative_bud_break_time = 3;
+
1831 shoot_parameters_primary.base_roll = 90;
+
1832 shoot_parameters_primary.phyllochron_min = 1;
+
1833 shoot_parameters_primary.elongation_rate_max = 0.2;
+
1834 shoot_parameters_primary.girth_area_factor = 0.f;
+
1835 shoot_parameters_primary.internode_length_max = 0.02;
+
1836 shoot_parameters_primary.internode_length_decay_rate = 0;
+
1837 shoot_parameters_primary.insertion_angle_tip.uniformDistribution(50, 80);
+
1838 shoot_parameters_primary.flowers_require_dormancy = false;
+
1839 shoot_parameters_primary.growth_requires_dormancy = false;
+
1840 shoot_parameters_primary.flower_bud_break_probability = 0.2;
+
1841 shoot_parameters_primary.determinate_shoot_growth = false;
+
1842 shoot_parameters_primary.max_nodes = 15;
+
1843 shoot_parameters_primary.gravitropic_curvature = 50;
+
1844 shoot_parameters_primary.tortuosity = 0;
+
1845 shoot_parameters_primary.defineChildShootTypes({"secondary_puncturevine"}, {1.f});
+
1846
+
1847 ShootParameters shoot_parameters_base = shoot_parameters_primary;
+
1848 shoot_parameters_base.phytomer_parameters = phytomer_parameters_puncturevine;
+
1849 shoot_parameters_base.phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(137.5-10,137.5+10);
+
1850 shoot_parameters_base.phytomer_parameters.internode.pitch = 0;
+
1851 shoot_parameters_base.phytomer_parameters.petiole.pitch = 0;
+
1852 shoot_parameters_base.vegetative_bud_break_probability_min = 1;
+
1853 shoot_parameters_base.vegetative_bud_break_time = 2;
+
1854 shoot_parameters_base.phyllochron_min = 2;
+
1855 shoot_parameters_base.elongation_rate_max = 0.15;
+
1856 shoot_parameters_base.gravitropic_curvature = 0;
+
1857 shoot_parameters_base.internode_length_max = 0.01;
+
1858 shoot_parameters_base.internode_length_decay_rate = 0;
+
1859 shoot_parameters_base.insertion_angle_tip = 90;
+
1860 shoot_parameters_base.insertion_angle_decay_rate = 0;
+
1861 shoot_parameters_base.flowers_require_dormancy = false;
+
1862 shoot_parameters_base.growth_requires_dormancy = false;
+
1863 shoot_parameters_base.flower_bud_break_probability = 0.0;
+
1864 shoot_parameters_base.max_nodes.uniformDistribution(3,5);
+
1865 shoot_parameters_base.defineChildShootTypes({"primary_puncturevine"},{1.f});
+
1866
+
1867 ShootParameters shoot_parameters_children = shoot_parameters_primary;
+
1868 shoot_parameters_children.base_roll = 0;
+
1869
+
1870 defineShootType("base_puncturevine", shoot_parameters_base);
+
1871 defineShootType("primary_puncturevine", shoot_parameters_primary);
+
1872 defineShootType("secondary_puncturevine", shoot_parameters_children);
1873
-
1874uint PlantArchitecture::buildEasternRedbudPlant(const helios::vec3 &base_position) {
+
1874}
1875
-
1876 if (shoot_types.empty()) {
-
1877 //automatically initialize redbud plant shoots
-
1878 initializeEasternRedbudShoots();
-
1879 }
-
1880
-
1881 uint plantID = addPlantInstance(base_position, 0);
+
1876uint PlantArchitecture::buildPuncturevinePlant(const helios::vec3 &base_position) {
+
1877
+
1878 if (shoot_types.empty()) {
+
1879 //automatically initialize puncturevine plant shoots
+
1880 initializePuncturevineShoots();
+
1881 }
1882
-
1883 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");
+
1883 uint plantID = addPlantInstance(base_position, 0);
1884
-
1885 makePlantDormant(plantID);
-
1886 breakPlantDormancy(plantID);
-
1887
-
1888 //leave four vegetative buds on the trunk and remove the rest
-
1889 for (auto &phytomer: this->plant_instances.at(plantID).shoot_tree.at(uID_stem)->phytomers ) {
-
1890 if ( phytomer->shoot_index.x < 12 ) {
-
1891 for (auto &petiole: phytomer->axillary_vegetative_buds) {
-
1892 for (auto &vbud: petiole) {
-
1893 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
-
1894 }
-
1895 }
-
1896 }
-
1897 }
+
1885 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(0, 0.f, 0.f), 0.001, 0.001, 1, 1, 0, "base_puncturevine");
+
1886
+
1887 breakPlantDormancy(plantID);
+
1888
+
1889 plant_instances.at(plantID).max_age = 45;
+
1890
+
1891 setPlantPhenologicalThresholds(plantID, 0, -1, 14, -1, -1, 1000, false);
+
1892
+
1893 return plantID;
+
1894
+
1895}
+
1896
+
1897void PlantArchitecture::initializeEasternRedbudShoots() {
1898
-
1899 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 30, 200, false);
+
1899 // ---- Leaf Prototype ---- //
1900
-
1901 plant_instances.at(plantID).max_age = 1460;
-
1902
-
1903 return plantID;
-
1904
-
1905}
-
1906
-
1907void PlantArchitecture::initializeRiceShoots() {
-
1908
-
1909 // ---- Leaf Prototype ---- //
-
1910
-
1911 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
1912 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
-
1913 leaf_prototype.leaf_aspect_ratio = 0.06f;
-
1914 leaf_prototype.midrib_fold_fraction = 0.3f;
-
1915 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.2, 0);
-
1916 leaf_prototype.lateral_curvature = -0.3;
-
1917 leaf_prototype.wave_period = 0.1f;
-
1918 leaf_prototype.wave_amplitude = 0.1f;
-
1919 leaf_prototype.subdivisions = 20;
-
1920 leaf_prototype.unique_prototypes = 10;
-
1921
-
1922 // ---- Phytomer Parameters ---- //
-
1923
-
1924 PhytomerParameters phytomer_parameters_rice(context_ptr->getRandomGenerator());
-
1925
-
1926 phytomer_parameters_rice.internode.pitch = 0;
-
1927 phytomer_parameters_rice.internode.phyllotactic_angle.uniformDistribution(67, 77);
-
1928 phytomer_parameters_rice.internode.radius_initial = 0.001;
-
1929 phytomer_parameters_rice.internode.color = make_RGBcolor(0.27, 0.31, 0.16);
-
1930 phytomer_parameters_rice.internode.length_segments = 1;
-
1931 phytomer_parameters_rice.internode.radial_subdivisions = 6;
-
1932 phytomer_parameters_rice.internode.max_floral_buds_per_petiole = 0;
-
1933 phytomer_parameters_rice.internode.max_vegetative_buds_per_petiole = 0;
-
1934
-
1935 phytomer_parameters_rice.petiole.petioles_per_internode = 1;
-
1936 phytomer_parameters_rice.petiole.pitch.uniformDistribution(-40, 0);
-
1937 phytomer_parameters_rice.petiole.radius = 0.0;
-
1938 phytomer_parameters_rice.petiole.length = 0.01;
-
1939 phytomer_parameters_rice.petiole.taper = 0;
-
1940 phytomer_parameters_rice.petiole.curvature = 0;
-
1941 phytomer_parameters_rice.petiole.length_segments = 1;
-
1942
-
1943 phytomer_parameters_rice.leaf.leaves_per_petiole = 1;
-
1944 phytomer_parameters_rice.leaf.pitch = 0;
-
1945 phytomer_parameters_rice.leaf.yaw = 0;
-
1946 phytomer_parameters_rice.leaf.roll = 0;
-
1947 phytomer_parameters_rice.leaf.prototype_scale = 0.15;
-
1948 phytomer_parameters_rice.leaf.prototype = leaf_prototype;
-
1949
-
1950 phytomer_parameters_rice.peduncle.pitch = 0;
-
1951 phytomer_parameters_rice.peduncle.length.uniformDistribution(0.14,0.18);
-
1952 phytomer_parameters_rice.peduncle.radius = 0.0005;
-
1953 phytomer_parameters_rice.peduncle.color = phytomer_parameters_rice.internode.color;
-
1954 phytomer_parameters_rice.peduncle.curvature.uniformDistribution(-800,-50);
-
1955 phytomer_parameters_rice.peduncle.radial_subdivisions = 6;
-
1956 phytomer_parameters_rice.peduncle.length_segments = 8;
+
1901 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
1902 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/RedbudLeaf.png";
+
1903 leaf_prototype.leaf_aspect_ratio = 1.f;
+
1904 leaf_prototype.midrib_fold_fraction = 0.2f;
+
1905 leaf_prototype.longitudinal_curvature = -0.15f;
+
1906 leaf_prototype.lateral_curvature = -0.1f;
+
1907 leaf_prototype.wave_period = 0.3f;
+
1908 leaf_prototype.wave_amplitude = 0.025f;
+
1909 leaf_prototype.subdivisions = 5;
+
1910 leaf_prototype.unique_prototypes = 5;
+
1911 leaf_prototype.leaf_offset = make_vec3(-0.3, 0, 0);
+
1912
+
1913 // ---- Phytomer Parameters ---- //
+
1914
+
1915 PhytomerParameters phytomer_parameters_redbud(context_ptr->getRandomGenerator());
+
1916
+
1917 phytomer_parameters_redbud.internode.pitch = 15;
+
1918 phytomer_parameters_redbud.internode.phyllotactic_angle.uniformDistribution(170,190);
+
1919 phytomer_parameters_redbud.internode.radius_initial = 0.0015;
+
1920 phytomer_parameters_redbud.internode.image_texture = "plugins/plantarchitecture/assets/textures/WesternRedbudBark.jpg";
+
1921 phytomer_parameters_redbud.internode.color.scale(0.3);
+
1922 phytomer_parameters_redbud.internode.length_segments = 1;
+
1923 phytomer_parameters_redbud.internode.max_floral_buds_per_petiole = 5;
+
1924
+
1925 phytomer_parameters_redbud.petiole.petioles_per_internode = 1;
+
1926 phytomer_parameters_redbud.petiole.color = make_RGBcolor(0.65, 0.52, 0.39);
+
1927 phytomer_parameters_redbud.petiole.pitch.uniformDistribution(20, 40);
+
1928 phytomer_parameters_redbud.petiole.radius = 0.002;
+
1929 phytomer_parameters_redbud.petiole.length = 0.075;
+
1930 phytomer_parameters_redbud.petiole.taper = 0;
+
1931 phytomer_parameters_redbud.petiole.curvature = 0;
+
1932 phytomer_parameters_redbud.petiole.length_segments = 1;
+
1933
+
1934 phytomer_parameters_redbud.leaf.leaves_per_petiole = 1;
+
1935 phytomer_parameters_redbud.leaf.pitch.uniformDistribution(-110, -80);
+
1936 phytomer_parameters_redbud.leaf.yaw = 0;
+
1937 phytomer_parameters_redbud.leaf.roll.uniformDistribution(-5, 5);
+
1938 phytomer_parameters_redbud.leaf.prototype_scale = 0.1;
+
1939 phytomer_parameters_redbud.leaf.prototype = leaf_prototype;
+
1940
+
1941 phytomer_parameters_redbud.peduncle.length = 0.02;
+
1942 phytomer_parameters_redbud.peduncle.pitch.uniformDistribution(50,90);
+
1943 phytomer_parameters_redbud.peduncle.color = make_RGBcolor(0.32, 0.05, 0.13);
+
1944
+
1945 phytomer_parameters_redbud.inflorescence.flowers_per_peduncle = 1;
+
1946 phytomer_parameters_redbud.inflorescence.pitch = 0;
+
1947 phytomer_parameters_redbud.inflorescence.flower_prototype_function = RedbudFlowerPrototype;
+
1948 phytomer_parameters_redbud.inflorescence.flower_prototype_scale = 0.04;
+
1949 phytomer_parameters_redbud.inflorescence.fruit_prototype_function = RedbudFruitPrototype;
+
1950 phytomer_parameters_redbud.inflorescence.fruit_prototype_scale = 0.1;
+
1951 phytomer_parameters_redbud.inflorescence.fruit_gravity_factor_fraction = 0.7;
+
1952
+
1953 phytomer_parameters_redbud.phytomer_creation_function = RedbudPhytomerCreationFunction;
+
1954 phytomer_parameters_redbud.phytomer_callback_function = RedbudPhytomerCallbackFunction;
+
1955
+
1956 // ---- Shoot Parameters ---- //
1957
-
1958 phytomer_parameters_rice.inflorescence.flowers_per_peduncle = 60;
-
1959 phytomer_parameters_rice.inflorescence.pitch.uniformDistribution(20,25);
-
1960 phytomer_parameters_rice.inflorescence.roll = 0;
-
1961 phytomer_parameters_rice.inflorescence.fruit_prototype_scale = 0.008;
-
1962 phytomer_parameters_rice.inflorescence.flower_offset = 0.012;
-
1963 phytomer_parameters_rice.inflorescence.fruit_prototype_function = RiceSpikePrototype;
-
1964
-
1965// phytomer_parameters_rice.phytomer_creation_function = RicePhytomerCreationFunction;
-
1966
-
1967 // ---- Shoot Parameters ---- //
-
1968
-
1969 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
1970 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_rice;
-
1971 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
-
1972 shoot_parameters_mainstem.flower_bud_break_probability = 1;
-
1973 shoot_parameters_mainstem.phyllochron_min = 2;
-
1974 shoot_parameters_mainstem.elongation_rate = 0.1;
-
1975 shoot_parameters_mainstem.girth_area_factor = 5.f;
-
1976 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-1000,-400);
-
1977 shoot_parameters_mainstem.internode_length_max = 0.0075;
-
1978 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
1979 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
1980 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
1981 shoot_parameters_mainstem.determinate_shoot_growth = false;
-
1982 shoot_parameters_mainstem.fruit_set_probability = 1.0;
-
1983 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
-
1984 shoot_parameters_mainstem.max_nodes = 30;
-
1985 shoot_parameters_mainstem.max_terminal_floral_buds = 5;
-
1986
-
1987 defineShootType("mainstem",shoot_parameters_mainstem);
-
1988
-
1989}
-
1990
-
1991uint PlantArchitecture::buildRicePlant(const helios::vec3 &base_position) {
-
1992
-
1993 if (shoot_types.empty()) {
-
1994 //automatically initialize rice plant shoots
-
1995 initializeRiceShoots();
-
1996 }
-
1997
-
1998 uint plantID = addPlantInstance(base_position, 0);
-
1999
-
2000 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.0075, 0.01, 0.01, 0, "mainstem");
-
2001
-
2002 breakPlantDormancy(plantID);
+
1958 ShootParameters shoot_parameters_main(context_ptr->getRandomGenerator());
+
1959 shoot_parameters_main.phytomer_parameters = phytomer_parameters_redbud;
+
1960 shoot_parameters_main.vegetative_bud_break_probability_min = 1.0;
+
1961 shoot_parameters_main.vegetative_bud_break_time = 2;
+
1962 shoot_parameters_main.phyllochron_min = 2;
+
1963 shoot_parameters_main.elongation_rate_max = 0.1;
+
1964 shoot_parameters_main.girth_area_factor = 4.f;
+
1965 shoot_parameters_main.gravitropic_curvature = 300;
+
1966 shoot_parameters_main.tortuosity = 5;
+
1967 shoot_parameters_main.internode_length_max = 0.04;
+
1968 shoot_parameters_main.internode_length_decay_rate = 0.005;
+
1969 shoot_parameters_main.internode_length_min = 0.01;
+
1970 shoot_parameters_main.insertion_angle_tip = 75;
+
1971 shoot_parameters_main.insertion_angle_decay_rate = 10;
+
1972 shoot_parameters_main.flowers_require_dormancy = true;
+
1973 shoot_parameters_main.growth_requires_dormancy = true;
+
1974 shoot_parameters_main.determinate_shoot_growth = false;
+
1975 shoot_parameters_main.max_terminal_floral_buds = 0;
+
1976 shoot_parameters_main.flower_bud_break_probability = 0.8;
+
1977 shoot_parameters_main.fruit_set_probability = 0.3;
+
1978 shoot_parameters_main.max_nodes = 25;
+
1979 shoot_parameters_main.max_nodes_per_season = 10;
+
1980 shoot_parameters_main.base_roll = 90;
+
1981
+
1982 ShootParameters shoot_parameters_trunk = shoot_parameters_main;
+
1983 shoot_parameters_trunk.phytomer_parameters.internode.pitch = 0;
+
1984 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 15;
+
1985 shoot_parameters_trunk.phytomer_parameters.internode.max_floral_buds_per_petiole = 0;
+
1986 shoot_parameters_trunk.insertion_angle_tip = 60;
+
1987 shoot_parameters_trunk.max_nodes = 75;
+
1988 shoot_parameters_trunk.max_nodes_per_season = 10;
+
1989 shoot_parameters_trunk.tortuosity = 1.5;
+
1990 shoot_parameters_trunk.defineChildShootTypes({"eastern_redbud_shoot"},{1.f});
+
1991
+
1992 defineShootType("eastern_redbud_trunk", shoot_parameters_trunk);
+
1993 defineShootType("eastern_redbud_shoot", shoot_parameters_main);
+
1994
+
1995}
+
1996
+
1997uint PlantArchitecture::buildEasternRedbudPlant(const helios::vec3 &base_position) {
+
1998
+
1999 if (shoot_types.empty()) {
+
2000 //automatically initialize redbud plant shoots
+
2001 initializeEasternRedbudShoots();
+
2002 }
2003
-
2004 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 10, 1000, false);
+
2004 uint plantID = addPlantInstance(base_position, 0);
2005
-
2006 plant_instances.at(plantID).max_age = 365;
+
2006 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");
2007
-
2008 return plantID;
-
2009
-
2010}
-
2011
-
2012void PlantArchitecture::initializeButterLettuceShoots() {
-
2013
-
2014 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
2015 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/RomaineLettuceLeaf.png";
-
2016 leaf_prototype.leaf_aspect_ratio = 0.85f;
-
2017 leaf_prototype.midrib_fold_fraction = 0.2f;
-
2018 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.2, 0.05);
-
2019 leaf_prototype.lateral_curvature = -0.4f;
-
2020 leaf_prototype.wave_period.uniformDistribution(0.15, 0.25);
-
2021 leaf_prototype.wave_amplitude.uniformDistribution(0.05,0.1);
-
2022 leaf_prototype.subdivisions = 30;
-
2023 leaf_prototype.unique_prototypes = 10;
-
2024
-
2025 // ---- Phytomer Parameters ---- //
-
2026
-
2027 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
-
2028
-
2029 phytomer_parameters.internode.pitch = 0;
-
2030 phytomer_parameters.internode.phyllotactic_angle = 137.5;
-
2031 phytomer_parameters.internode.radius_initial = 0.02;
-
2032 phytomer_parameters.internode.color = make_RGBcolor(0.402,0.423,0.413);
-
2033 phytomer_parameters.internode.length_segments = 1;
-
2034 phytomer_parameters.internode.radial_subdivisions = 10;
-
2035
-
2036 phytomer_parameters.petiole.petioles_per_internode = 1;
-
2037 phytomer_parameters.petiole.pitch.uniformDistribution(0,30);
-
2038 phytomer_parameters.petiole.radius = 0.001;
-
2039 phytomer_parameters.petiole.length = 0.001;
-
2040 phytomer_parameters.petiole.length_segments = 1;
-
2041 phytomer_parameters.petiole.radial_subdivisions = 3;
-
2042 phytomer_parameters.petiole.color = RGB::red;
-
2043
-
2044 phytomer_parameters.leaf.leaves_per_petiole = 1;
-
2045 phytomer_parameters.leaf.pitch = 10;
-
2046 phytomer_parameters.leaf.yaw = 0;
-
2047 phytomer_parameters.leaf.roll = 0;
-
2048 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.15,0.25);
-
2049 phytomer_parameters.leaf.prototype = leaf_prototype;
-
2050
-
2051 phytomer_parameters.phytomer_creation_function = ButterLettucePhytomerCreationFunction;
-
2052
-
2053 // ---- Shoot Parameters ---- //
-
2054
-
2055 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
2056 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters;
-
2057 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
-
2058 shoot_parameters_mainstem.phyllochron_min = 2;
-
2059 shoot_parameters_mainstem.elongation_rate = 0.15;
-
2060 shoot_parameters_mainstem.girth_area_factor = 0.f;
-
2061 shoot_parameters_mainstem.gravitropic_curvature = 10;
-
2062 shoot_parameters_mainstem.internode_length_max = 0.001;
-
2063 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
2064 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
2065 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
2066 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
-
2067 shoot_parameters_mainstem.max_nodes = 25;
-
2068
-
2069 defineShootType("mainstem",shoot_parameters_mainstem);
-
2070
-
2071
-
2072}
-
2073
-
2074uint PlantArchitecture::buildButterLettucePlant(const helios::vec3 &base_position) {
-
2075
-
2076 if (shoot_types.empty()) {
-
2077 //automatically initialize lettuce plant shoots
-
2078 initializeButterLettuceShoots();
-
2079 }
+
2008 makePlantDormant(plantID);
+
2009 breakPlantDormancy(plantID);
+
2010
+
2011 //leave four vegetative buds on the trunk and remove the rest
+
2012 for (auto &phytomer: this->plant_instances.at(plantID).shoot_tree.at(uID_stem)->phytomers ) {
+
2013 if ( phytomer->shoot_index.x < 12 ) {
+
2014 for (auto &petiole: phytomer->axillary_vegetative_buds) {
+
2015 for (auto &vbud: petiole) {
+
2016 phytomer->setVegetativeBudState(BUD_DEAD, vbud);
+
2017 }
+
2018 }
+
2019 }
+
2020 }
+
2021
+
2022 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 30, 200, false);
+
2023
+
2024 plant_instances.at(plantID).max_age = 1460;
+
2025
+
2026 return plantID;
+
2027
+
2028}
+
2029
+
2030void PlantArchitecture::initializeRiceShoots() {
+
2031
+
2032 // ---- Leaf Prototype ---- //
+
2033
+
2034 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2035 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
+
2036 leaf_prototype.leaf_aspect_ratio = 0.06f;
+
2037 leaf_prototype.midrib_fold_fraction = 0.3f;
+
2038 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.2, 0);
+
2039 leaf_prototype.lateral_curvature = -0.3;
+
2040 leaf_prototype.wave_period = 0.1f;
+
2041 leaf_prototype.wave_amplitude = 0.1f;
+
2042 leaf_prototype.subdivisions = 20;
+
2043 leaf_prototype.unique_prototypes = 10;
+
2044
+
2045 // ---- Phytomer Parameters ---- //
+
2046
+
2047 PhytomerParameters phytomer_parameters_rice(context_ptr->getRandomGenerator());
+
2048
+
2049 phytomer_parameters_rice.internode.pitch = 0;
+
2050 phytomer_parameters_rice.internode.phyllotactic_angle.uniformDistribution(67, 77);
+
2051 phytomer_parameters_rice.internode.radius_initial = 0.001;
+
2052 phytomer_parameters_rice.internode.color = make_RGBcolor(0.27, 0.31, 0.16);
+
2053 phytomer_parameters_rice.internode.length_segments = 1;
+
2054 phytomer_parameters_rice.internode.radial_subdivisions = 6;
+
2055 phytomer_parameters_rice.internode.max_floral_buds_per_petiole = 0;
+
2056 phytomer_parameters_rice.internode.max_vegetative_buds_per_petiole = 0;
+
2057
+
2058 phytomer_parameters_rice.petiole.petioles_per_internode = 1;
+
2059 phytomer_parameters_rice.petiole.pitch.uniformDistribution(-40, 0);
+
2060 phytomer_parameters_rice.petiole.radius = 0.0;
+
2061 phytomer_parameters_rice.petiole.length = 0.01;
+
2062 phytomer_parameters_rice.petiole.taper = 0;
+
2063 phytomer_parameters_rice.petiole.curvature = 0;
+
2064 phytomer_parameters_rice.petiole.length_segments = 1;
+
2065
+
2066 phytomer_parameters_rice.leaf.leaves_per_petiole = 1;
+
2067 phytomer_parameters_rice.leaf.pitch = 0;
+
2068 phytomer_parameters_rice.leaf.yaw = 0;
+
2069 phytomer_parameters_rice.leaf.roll = 0;
+
2070 phytomer_parameters_rice.leaf.prototype_scale = 0.15;
+
2071 phytomer_parameters_rice.leaf.prototype = leaf_prototype;
+
2072
+
2073 phytomer_parameters_rice.peduncle.pitch = 0;
+
2074 phytomer_parameters_rice.peduncle.length.uniformDistribution(0.14,0.18);
+
2075 phytomer_parameters_rice.peduncle.radius = 0.0005;
+
2076 phytomer_parameters_rice.peduncle.color = phytomer_parameters_rice.internode.color;
+
2077 phytomer_parameters_rice.peduncle.curvature.uniformDistribution(-800,-50);
+
2078 phytomer_parameters_rice.peduncle.radial_subdivisions = 6;
+
2079 phytomer_parameters_rice.peduncle.length_segments = 8;
2080
-
2081 uint plantID = addPlantInstance(base_position, 0);
-
2082
-
2083 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(context_ptr->randu(0.f, 0.03f * M_PI), 0.f, context_ptr->randu(0.f, 2.f * M_PI)), 0.005, 0.001, 1, 1, 0, "mainstem");
-
2084
-
2085 breakPlantDormancy(plantID);
-
2086
-
2087 setPlantPhenologicalThresholds(plantID, 0, -1, -1, -1, -1, 1000, false);
-
2088
-
2089 plant_instances.at(plantID).max_age = 365;
-
2090
-
2091 return plantID;
-
2092
-
2093}
-
2094
-
2095void PlantArchitecture::initializeSorghumShoots() {
-
2096
-
2097 // ---- Leaf Prototype ---- //
-
2098
-
2099 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
2100 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
-
2101 leaf_prototype.leaf_aspect_ratio = 0.2f;
-
2102 leaf_prototype.midrib_fold_fraction = 0.3f;
-
2103 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.4, -0.2);
-
2104 leaf_prototype.lateral_curvature = -0.3f;
-
2105 leaf_prototype.petiole_roll = 0.04f;
-
2106 leaf_prototype.wave_period = 0.1f;
-
2107 leaf_prototype.wave_amplitude = 0.1f;
-
2108 leaf_prototype.leaf_buckle_length.uniformDistribution(0.4,0.6);
-
2109 leaf_prototype.leaf_buckle_angle.uniformDistribution(45,55);
-
2110 leaf_prototype.subdivisions = 50;
-
2111 leaf_prototype.unique_prototypes = 10;
-
2112
-
2113 // ---- Phytomer Parameters ---- //
-
2114
-
2115 PhytomerParameters phytomer_parameters_sorghum(context_ptr->getRandomGenerator());
-
2116
-
2117 phytomer_parameters_sorghum.internode.pitch = 0;
-
2118 phytomer_parameters_sorghum.internode.phyllotactic_angle.uniformDistribution(170,190);
-
2119 phytomer_parameters_sorghum.internode.radius_initial = 0.003;
-
2120 phytomer_parameters_sorghum.internode.color = make_RGBcolor(0.09,0.13,0.06);
-
2121 phytomer_parameters_sorghum.internode.length_segments = 2;
-
2122 phytomer_parameters_sorghum.internode.radial_subdivisions = 10;
-
2123 phytomer_parameters_sorghum.internode.max_floral_buds_per_petiole = 0;
-
2124 phytomer_parameters_sorghum.internode.max_vegetative_buds_per_petiole = 0;
-
2125
-
2126 phytomer_parameters_sorghum.petiole.petioles_per_internode = 1;
-
2127 phytomer_parameters_sorghum.petiole.pitch.uniformDistribution(-40,-20);
-
2128 phytomer_parameters_sorghum.petiole.radius = 0.0;
-
2129 phytomer_parameters_sorghum.petiole.length = 0.05;
-
2130 phytomer_parameters_sorghum.petiole.taper = 0;
-
2131 phytomer_parameters_sorghum.petiole.curvature = 0;
-
2132 phytomer_parameters_sorghum.petiole.length_segments = 1;
-
2133
-
2134 phytomer_parameters_sorghum.leaf.leaves_per_petiole = 1;
-
2135 phytomer_parameters_sorghum.leaf.pitch = 0;
-
2136 phytomer_parameters_sorghum.leaf.yaw = 0;
-
2137 phytomer_parameters_sorghum.leaf.roll = 0;
-
2138 phytomer_parameters_sorghum.leaf.prototype_scale = 0.6;
-
2139 phytomer_parameters_sorghum.leaf.prototype = leaf_prototype;
-
2140
-
2141 phytomer_parameters_sorghum.peduncle.length = 0.3;
-
2142 phytomer_parameters_sorghum.peduncle.radius = 0.008;
-
2143 phytomer_parameters_sorghum.peduncle.color = phytomer_parameters_sorghum.internode.color;
-
2144 phytomer_parameters_sorghum.peduncle.radial_subdivisions = 10;
-
2145
-
2146 phytomer_parameters_sorghum.inflorescence.flowers_per_peduncle = 1;
-
2147 phytomer_parameters_sorghum.inflorescence.pitch = 0;
-
2148 phytomer_parameters_sorghum.inflorescence.roll = 0;
-
2149 phytomer_parameters_sorghum.inflorescence.fruit_prototype_scale = 0.18;
-
2150 phytomer_parameters_sorghum.inflorescence.fruit_prototype_function = SorghumPaniclePrototype;
+
2081 phytomer_parameters_rice.inflorescence.flowers_per_peduncle = 60;
+
2082 phytomer_parameters_rice.inflorescence.pitch.uniformDistribution(20,25);
+
2083 phytomer_parameters_rice.inflorescence.roll = 0;
+
2084 phytomer_parameters_rice.inflorescence.fruit_prototype_scale = 0.008;
+
2085 phytomer_parameters_rice.inflorescence.flower_offset = 0.012;
+
2086 phytomer_parameters_rice.inflorescence.fruit_prototype_function = RiceSpikePrototype;
+
2087
+
2088// phytomer_parameters_rice.phytomer_creation_function = RicePhytomerCreationFunction;
+
2089
+
2090 // ---- Shoot Parameters ---- //
+
2091
+
2092 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
2093 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_rice;
+
2094 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
+
2095 shoot_parameters_mainstem.flower_bud_break_probability = 1;
+
2096 shoot_parameters_mainstem.phyllochron_min = 2;
+
2097 shoot_parameters_mainstem.elongation_rate_max = 0.1;
+
2098 shoot_parameters_mainstem.girth_area_factor = 5.f;
+
2099 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-1000,-400);
+
2100 shoot_parameters_mainstem.internode_length_max = 0.0075;
+
2101 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
2102 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
2103 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
2104 shoot_parameters_mainstem.determinate_shoot_growth = false;
+
2105 shoot_parameters_mainstem.fruit_set_probability = 1.0;
+
2106 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
+
2107 shoot_parameters_mainstem.max_nodes = 30;
+
2108 shoot_parameters_mainstem.max_terminal_floral_buds = 5;
+
2109
+
2110 defineShootType("mainstem",shoot_parameters_mainstem);
+
2111
+
2112}
+
2113
+
2114uint PlantArchitecture::buildRicePlant(const helios::vec3 &base_position) {
+
2115
+
2116 if (shoot_types.empty()) {
+
2117 //automatically initialize rice plant shoots
+
2118 initializeRiceShoots();
+
2119 }
+
2120
+
2121 uint plantID = addPlantInstance(base_position, 0);
+
2122
+
2123 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.0075, 0.01, 0.01, 0, "mainstem");
+
2124
+
2125 breakPlantDormancy(plantID);
+
2126
+
2127 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 10, 1000, false);
+
2128
+
2129 plant_instances.at(plantID).max_age = 365;
+
2130
+
2131 return plantID;
+
2132
+
2133}
+
2134
+
2135void PlantArchitecture::initializeButterLettuceShoots() {
+
2136
+
2137 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2138 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/RomaineLettuceLeaf.png";
+
2139 leaf_prototype.leaf_aspect_ratio = 0.85f;
+
2140 leaf_prototype.midrib_fold_fraction = 0.2f;
+
2141 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.2, 0.05);
+
2142 leaf_prototype.lateral_curvature = -0.4f;
+
2143 leaf_prototype.wave_period.uniformDistribution(0.15, 0.25);
+
2144 leaf_prototype.wave_amplitude.uniformDistribution(0.05,0.1);
+
2145 leaf_prototype.subdivisions = 30;
+
2146 leaf_prototype.unique_prototypes = 10;
+
2147
+
2148 // ---- Phytomer Parameters ---- //
+
2149
+
2150 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
2151
-
2152 phytomer_parameters_sorghum.phytomer_creation_function = SorghumPhytomerCreationFunction;
-
2153
-
2154 // ---- Shoot Parameters ---- //
-
2155
-
2156 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
2157 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sorghum;
-
2158 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
-
2159 shoot_parameters_mainstem.flower_bud_break_probability = 1;
-
2160 shoot_parameters_mainstem.phyllochron_min = 2;
-
2161 shoot_parameters_mainstem.elongation_rate = 0.1;
-
2162 shoot_parameters_mainstem.girth_area_factor = 5.f;
-
2163 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-1000,-400);
-
2164 shoot_parameters_mainstem.internode_length_max = 0.26;
-
2165 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
2166 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
2167 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
2168 shoot_parameters_mainstem.determinate_shoot_growth = false;
-
2169 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
-
2170 shoot_parameters_mainstem.fruit_set_probability = 1.0;
-
2171 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
-
2172 shoot_parameters_mainstem.max_nodes = 16;
-
2173 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
-
2174
-
2175 defineShootType("mainstem",shoot_parameters_mainstem);
-
2176
-
2177}
-
2178
-
2179uint PlantArchitecture::buildSorghumPlant(const helios::vec3 &base_position) {
-
2180
-
2181 if (shoot_types.empty()) {
-
2182 //automatically initialize sorghum plant shoots
-
2183 initializeSorghumShoots();
-
2184 }
-
2185
-
2186 uint plantID = addPlantInstance(base_position - make_vec3(0,0,0.025), 0);
-
2187
-
2188 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");
-
2189
-
2190 breakPlantDormancy(plantID);
+
2152 phytomer_parameters.internode.pitch = 0;
+
2153 phytomer_parameters.internode.phyllotactic_angle = 137.5;
+
2154 phytomer_parameters.internode.radius_initial = 0.02;
+
2155 phytomer_parameters.internode.color = make_RGBcolor(0.402,0.423,0.413);
+
2156 phytomer_parameters.internode.length_segments = 1;
+
2157 phytomer_parameters.internode.radial_subdivisions = 10;
+
2158
+
2159 phytomer_parameters.petiole.petioles_per_internode = 1;
+
2160 phytomer_parameters.petiole.pitch.uniformDistribution(0,30);
+
2161 phytomer_parameters.petiole.radius = 0.001;
+
2162 phytomer_parameters.petiole.length = 0.001;
+
2163 phytomer_parameters.petiole.length_segments = 1;
+
2164 phytomer_parameters.petiole.radial_subdivisions = 3;
+
2165 phytomer_parameters.petiole.color = RGB::red;
+
2166
+
2167 phytomer_parameters.leaf.leaves_per_petiole = 1;
+
2168 phytomer_parameters.leaf.pitch = 10;
+
2169 phytomer_parameters.leaf.yaw = 0;
+
2170 phytomer_parameters.leaf.roll = 0;
+
2171 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.15,0.25);
+
2172 phytomer_parameters.leaf.prototype = leaf_prototype;
+
2173
+
2174 phytomer_parameters.phytomer_creation_function = ButterLettucePhytomerCreationFunction;
+
2175
+
2176 // ---- Shoot Parameters ---- //
+
2177
+
2178 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
2179 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters;
+
2180 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
+
2181 shoot_parameters_mainstem.phyllochron_min = 2;
+
2182 shoot_parameters_mainstem.elongation_rate_max = 0.15;
+
2183 shoot_parameters_mainstem.girth_area_factor = 0.f;
+
2184 shoot_parameters_mainstem.gravitropic_curvature = 10;
+
2185 shoot_parameters_mainstem.internode_length_max = 0.001;
+
2186 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
2187 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
2188 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
2189 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
+
2190 shoot_parameters_mainstem.max_nodes = 25;
2191
-
2192 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 15, 1000, false);
+
2192 defineShootType("mainstem",shoot_parameters_mainstem);
2193
-
2194 plant_instances.at(plantID).max_age = 365;
-
2195
-
2196 return plantID;
-
2197
-
2198}
-
2199
-
2200void PlantArchitecture::initializeSoybeanShoots() {
-
2201
-
2202 // ---- Leaf Prototype ---- //
+
2194
+
2195}
+
2196
+
2197uint PlantArchitecture::buildButterLettucePlant(const helios::vec3 &base_position) {
+
2198
+
2199 if (shoot_types.empty()) {
+
2200 //automatically initialize lettuce plant shoots
+
2201 initializeButterLettuceShoots();
+
2202 }
2203
-
2204 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
2205 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SoybeanLeaf.png";
-
2206 leaf_prototype.leaf_aspect_ratio = 1.f;
-
2207 leaf_prototype.midrib_fold_fraction = 0.1f;
-
2208 leaf_prototype.longitudinal_curvature.uniformDistribution(0.1,0.2);
-
2209 leaf_prototype.lateral_curvature = 0.45;
-
2210 leaf_prototype.subdivisions = 8;
-
2211 leaf_prototype.unique_prototypes = 5;
-
2212 leaf_prototype.build_petiolule = true;
+
2204 uint plantID = addPlantInstance(base_position, 0);
+
2205
+
2206 uint uID_stem = addBaseStemShoot(plantID, 3, make_AxisRotation(context_ptr->randu(0.f, 0.03f * M_PI), 0.f, context_ptr->randu(0.f, 2.f * M_PI)), 0.005, 0.001, 1, 1, 0, "mainstem");
+
2207
+
2208 breakPlantDormancy(plantID);
+
2209
+
2210 setPlantPhenologicalThresholds(plantID, 0, -1, -1, -1, -1, 1000, false);
+
2211
+
2212 plant_instances.at(plantID).max_age = 365;
2213
-
2214 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
+
2214 return plantID;
2215
-
2216 phytomer_parameters_trifoliate.internode.pitch = 20;
-
2217 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
-
2218 phytomer_parameters_trifoliate.internode.radius_initial = 0.002;
-
2219 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
-
2220 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
-
2221 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.2,0.25,0.05);
-
2222 phytomer_parameters_trifoliate.internode.length_segments = 5;
-
2223
-
2224 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
-
2225 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(15,40);
-
2226 phytomer_parameters_trifoliate.petiole.radius = 0.002;
-
2227 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.12,0.16);
-
2228 phytomer_parameters_trifoliate.petiole.taper = 0.25;
-
2229 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-250,50);
-
2230 phytomer_parameters_trifoliate.petiole.color = phytomer_parameters_trifoliate.internode.color;
-
2231 phytomer_parameters_trifoliate.petiole.length_segments = 5;
-
2232 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
-
2233
-
2234 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
-
2235 phytomer_parameters_trifoliate.leaf.pitch.uniformDistribution(-30, 10);
-
2236 phytomer_parameters_trifoliate.leaf.yaw = 10;
-
2237 phytomer_parameters_trifoliate.leaf.roll.uniformDistribution(-25,5);
-
2238 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.5;
-
2239 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
-
2240 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.1,0.14);
-
2241 phytomer_parameters_trifoliate.leaf.prototype = leaf_prototype;
-
2242
-
2243 phytomer_parameters_trifoliate.peduncle.length = 0.01;
-
2244 phytomer_parameters_trifoliate.peduncle.radius = 0.0005;
-
2245 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
-
2246 phytomer_parameters_trifoliate.peduncle.roll = 90;
-
2247 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
-
2248 phytomer_parameters_trifoliate.peduncle.color = phytomer_parameters_trifoliate.internode.color;
-
2249 phytomer_parameters_trifoliate.peduncle.length_segments = 1;
-
2250 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
-
2251
-
2252 phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle.uniformDistribution(1, 4);
-
2253 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
-
2254 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
-
2255 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
-
2256 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.015;
-
2257 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = SoybeanFlowerPrototype;
-
2258 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.1,0.12);
-
2259 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = SoybeanFruitPrototype;
-
2260 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
-
2261
-
2262 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
-
2263 phytomer_parameters_unifoliate.internode.pitch = 0;
-
2264 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
-
2265 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
-
2266 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
-
2267 phytomer_parameters_unifoliate.petiole.length = 0.01;
-
2268 phytomer_parameters_unifoliate.petiole.radius = 0.001;
-
2269 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
-
2270 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
-
2271 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
-
2272 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
-
2273 phytomer_parameters_unifoliate.leaf.prototype = leaf_prototype;
+
2216}
+
2217
+
2218void PlantArchitecture::initializeSorghumShoots() {
+
2219
+
2220 // ---- Leaf Prototype ---- //
+
2221
+
2222 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2223 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
+
2224 leaf_prototype.leaf_aspect_ratio = 0.2f;
+
2225 leaf_prototype.midrib_fold_fraction = 0.3f;
+
2226 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.4, -0.2);
+
2227 leaf_prototype.lateral_curvature = -0.3f;
+
2228 leaf_prototype.petiole_roll = 0.04f;
+
2229 leaf_prototype.wave_period = 0.1f;
+
2230 leaf_prototype.wave_amplitude = 0.1f;
+
2231 leaf_prototype.leaf_buckle_length.uniformDistribution(0.4,0.6);
+
2232 leaf_prototype.leaf_buckle_angle.uniformDistribution(45,55);
+
2233 leaf_prototype.subdivisions = 50;
+
2234 leaf_prototype.unique_prototypes = 10;
+
2235
+
2236 // ---- Phytomer Parameters ---- //
+
2237
+
2238 PhytomerParameters phytomer_parameters_sorghum(context_ptr->getRandomGenerator());
+
2239
+
2240 phytomer_parameters_sorghum.internode.pitch = 0;
+
2241 phytomer_parameters_sorghum.internode.phyllotactic_angle.uniformDistribution(170,190);
+
2242 phytomer_parameters_sorghum.internode.radius_initial = 0.003;
+
2243 phytomer_parameters_sorghum.internode.color = make_RGBcolor(0.09,0.13,0.06);
+
2244 phytomer_parameters_sorghum.internode.length_segments = 2;
+
2245 phytomer_parameters_sorghum.internode.radial_subdivisions = 10;
+
2246 phytomer_parameters_sorghum.internode.max_floral_buds_per_petiole = 0;
+
2247 phytomer_parameters_sorghum.internode.max_vegetative_buds_per_petiole = 0;
+
2248
+
2249 phytomer_parameters_sorghum.petiole.petioles_per_internode = 1;
+
2250 phytomer_parameters_sorghum.petiole.pitch.uniformDistribution(-40,-20);
+
2251 phytomer_parameters_sorghum.petiole.radius = 0.0;
+
2252 phytomer_parameters_sorghum.petiole.length = 0.05;
+
2253 phytomer_parameters_sorghum.petiole.taper = 0;
+
2254 phytomer_parameters_sorghum.petiole.curvature = 0;
+
2255 phytomer_parameters_sorghum.petiole.length_segments = 1;
+
2256
+
2257 phytomer_parameters_sorghum.leaf.leaves_per_petiole = 1;
+
2258 phytomer_parameters_sorghum.leaf.pitch = 0;
+
2259 phytomer_parameters_sorghum.leaf.yaw = 0;
+
2260 phytomer_parameters_sorghum.leaf.roll = 0;
+
2261 phytomer_parameters_sorghum.leaf.prototype_scale = 0.6;
+
2262 phytomer_parameters_sorghum.leaf.prototype = leaf_prototype;
+
2263
+
2264 phytomer_parameters_sorghum.peduncle.length = 0.3;
+
2265 phytomer_parameters_sorghum.peduncle.radius = 0.008;
+
2266 phytomer_parameters_sorghum.peduncle.color = phytomer_parameters_sorghum.internode.color;
+
2267 phytomer_parameters_sorghum.peduncle.radial_subdivisions = 10;
+
2268
+
2269 phytomer_parameters_sorghum.inflorescence.flowers_per_peduncle = 1;
+
2270 phytomer_parameters_sorghum.inflorescence.pitch = 0;
+
2271 phytomer_parameters_sorghum.inflorescence.roll = 0;
+
2272 phytomer_parameters_sorghum.inflorescence.fruit_prototype_scale = 0.18;
+
2273 phytomer_parameters_sorghum.inflorescence.fruit_prototype_function = SorghumPaniclePrototype;
2274
-
2275 // ---- Shoot Parameters ---- //
+
2275 phytomer_parameters_sorghum.phytomer_creation_function = SorghumPhytomerCreationFunction;
2276
-
2277 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
-
2278 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
-
2279 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
-
2280
-
2281 shoot_parameters_trifoliate.max_nodes = 25;
-
2282 shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(20,30);
-
2283// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
-
2284 shoot_parameters_trifoliate.internode_length_max = 0.035;
-
2285// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
-
2286// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
-
2287 shoot_parameters_trifoliate.base_roll = 90;
-
2288 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
-
2289 shoot_parameters_trifoliate.gravitropic_curvature = 400;
-
2290
-
2291 shoot_parameters_trifoliate.phyllochron_min = 2;
-
2292 shoot_parameters_trifoliate.elongation_rate = 0.1;
-
2293 shoot_parameters_trifoliate.girth_area_factor = 2.f;
-
2294 shoot_parameters_trifoliate.vegetative_bud_break_time = 15;
-
2295 shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.05;
-
2296 shoot_parameters_trifoliate.vegetative_bud_break_probability_decay_rate = 0.6;
-
2297// shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default)
-
2298 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.8,1.0);
-
2299 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
-
2300// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
-
2301// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
-
2302// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
+
2277 // ---- Shoot Parameters ---- //
+
2278
+
2279 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
2280 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sorghum;
+
2281 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
+
2282 shoot_parameters_mainstem.flower_bud_break_probability = 1;
+
2283 shoot_parameters_mainstem.phyllochron_min = 2;
+
2284 shoot_parameters_mainstem.elongation_rate_max = 0.1;
+
2285 shoot_parameters_mainstem.girth_area_factor = 5.f;
+
2286 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-1000,-400);
+
2287 shoot_parameters_mainstem.internode_length_max = 0.26;
+
2288 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
2289 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
2290 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
2291 shoot_parameters_mainstem.determinate_shoot_growth = false;
+
2292 shoot_parameters_mainstem.flower_bud_break_probability = 1.0;
+
2293 shoot_parameters_mainstem.fruit_set_probability = 1.0;
+
2294 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
+
2295 shoot_parameters_mainstem.max_nodes = 16;
+
2296 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
+
2297
+
2298 defineShootType("mainstem",shoot_parameters_mainstem);
+
2299
+
2300}
+
2301
+
2302uint PlantArchitecture::buildSorghumPlant(const helios::vec3 &base_position) {
2303
-
2304 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
2305
-
2306
-
2307 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
-
2308 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
-
2309 shoot_parameters_unifoliate.max_nodes = 1;
-
2310 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
-
2311 shoot_parameters_unifoliate.insertion_angle_tip = 0;
-
2312 shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
-
2313 shoot_parameters_unifoliate.vegetative_bud_break_time = 8;
-
2314 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
-
2315
-
2316 defineShootType("unifoliate",shoot_parameters_unifoliate);
-
2317 defineShootType("trifoliate",shoot_parameters_trifoliate);
+
2304 if (shoot_types.empty()) {
+
2305 //automatically initialize sorghum plant shoots
+
2306 initializeSorghumShoots();
+
2307 }
+
2308
+
2309 uint plantID = addPlantInstance(base_position - make_vec3(0,0,0.025), 0);
+
2310
+
2311 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");
+
2312
+
2313 breakPlantDormancy(plantID);
+
2314
+
2315 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 15, 1000, false);
+
2316
+
2317 plant_instances.at(plantID).max_age = 365;
2318
-
2319}
+
2319 return plantID;
2320
-
2321uint PlantArchitecture::buildSoybeanPlant(const helios::vec3 &base_position) {
+
2321}
2322
-
2323 if (shoot_types.empty()) {
-
2324 //automatically initialize bean plant shoots
-
2325 initializeSoybeanShoots();
-
2326 }
-
2327
-
2328 uint plantID = addPlantInstance(base_position, 0);
-
2329
-
2330 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));
-
2331 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.04, 0.01, 0.01, 0, "unifoliate");
-
2332
-
2333 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f * M_PI), shoot_types.at("trifoliate").phytomer_parameters.internode.radius_initial.val(), shoot_types.at("trifoliate").internode_length_max.val(), 0.1, 0.1, 0, "trifoliate");
-
2334
-
2335 breakPlantDormancy(plantID);
+
2323void PlantArchitecture::initializeSoybeanShoots() {
+
2324
+
2325 // ---- Leaf Prototype ---- //
+
2326
+
2327 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2328 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SoybeanLeaf.png";
+
2329 leaf_prototype.leaf_aspect_ratio = 1.f;
+
2330 leaf_prototype.midrib_fold_fraction = 0.1f;
+
2331 leaf_prototype.longitudinal_curvature.uniformDistribution(0.1,0.2);
+
2332 leaf_prototype.lateral_curvature = 0.45;
+
2333 leaf_prototype.subdivisions = 8;
+
2334 leaf_prototype.unique_prototypes = 5;
+
2335 leaf_prototype.build_petiolule = true;
2336
-
2337 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 1000, false);
+
2337 PhytomerParameters phytomer_parameters_trifoliate(context_ptr->getRandomGenerator());
2338
-
2339 plant_instances.at(plantID).max_age = 365;
-
2340
-
2341 return plantID;
-
2342
-
2343}
-
2344
-
2345void PlantArchitecture::initializeStrawberryShoots() {
+
2339 phytomer_parameters_trifoliate.internode.pitch = 20;
+
2340 phytomer_parameters_trifoliate.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
2341 phytomer_parameters_trifoliate.internode.radius_initial = 0.002;
+
2342 phytomer_parameters_trifoliate.internode.max_floral_buds_per_petiole = 1;
+
2343 phytomer_parameters_trifoliate.internode.max_vegetative_buds_per_petiole = 1;
+
2344 phytomer_parameters_trifoliate.internode.color = make_RGBcolor(0.2,0.25,0.05);
+
2345 phytomer_parameters_trifoliate.internode.length_segments = 5;
2346
-
2347 // ---- Leaf Prototype ---- //
-
2348
-
2349 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
2350 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/StrawberryLeaf.png";
-
2351 leaf_prototype.leaf_aspect_ratio = 1.f;
-
2352 leaf_prototype.midrib_fold_fraction = 0.2f;
-
2353 leaf_prototype.longitudinal_curvature = 0.15f;
-
2354 leaf_prototype.lateral_curvature = 0.4f;
-
2355 leaf_prototype.wave_period = 0.3f;
-
2356 leaf_prototype.wave_amplitude = 0.01f;
-
2357 leaf_prototype.subdivisions = 6;
-
2358 leaf_prototype.unique_prototypes = 10;
-
2359
-
2360 // ---- Phytomer Parameters ---- //
-
2361
-
2362 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
-
2363
-
2364 phytomer_parameters.internode.pitch = 10;
-
2365 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(80,100);
-
2366 phytomer_parameters.internode.radius_initial = 0.001;
-
2367 phytomer_parameters.internode.color = make_RGBcolor(0.38, 0.48, 0.1);
-
2368 phytomer_parameters.internode.length_segments = 1;
-
2369
-
2370 phytomer_parameters.petiole.petioles_per_internode = 1;
-
2371 phytomer_parameters.petiole.pitch.uniformDistribution(0,45);
-
2372 phytomer_parameters.petiole.radius = 0.0025;
-
2373 phytomer_parameters.petiole.length.uniformDistribution(0.15,0.25);
-
2374 phytomer_parameters.petiole.taper = 0.5;
-
2375 phytomer_parameters.petiole.curvature.uniformDistribution(-300,100);
-
2376 phytomer_parameters.petiole.color = make_RGBcolor(0.24, 0.28, 0.08);
-
2377 phytomer_parameters.petiole.length_segments = 5;
-
2378
-
2379 phytomer_parameters.leaf.leaves_per_petiole = 3;
-
2380 phytomer_parameters.leaf.pitch.uniformDistribution(-30,10);
-
2381 phytomer_parameters.leaf.yaw = 20;
-
2382 phytomer_parameters.leaf.roll = -30;
-
2383 phytomer_parameters.leaf.leaflet_offset = 0.01;
-
2384 phytomer_parameters.leaf.leaflet_scale = 1.0;
-
2385 phytomer_parameters.leaf.prototype_scale = 0.1;
-
2386 phytomer_parameters.leaf.prototype = leaf_prototype;
-
2387
-
2388 phytomer_parameters.peduncle.length = 0.17;
-
2389 phytomer_parameters.peduncle.radius = 0.00075;
-
2390 phytomer_parameters.peduncle.pitch = 35;
-
2391 phytomer_parameters.peduncle.roll = 0;
-
2392 phytomer_parameters.peduncle.curvature = -200;
-
2393 phytomer_parameters.peduncle.length_segments = 5;
-
2394 phytomer_parameters.peduncle.radial_subdivisions = 6;
-
2395 phytomer_parameters.peduncle.color = phytomer_parameters.petiole.color;
-
2396
-
2397 phytomer_parameters.inflorescence.flowers_per_peduncle.uniformDistribution(1, 3);
-
2398 phytomer_parameters.inflorescence.flower_offset = 0.2;
-
2399 phytomer_parameters.inflorescence.pitch = 70;
-
2400 phytomer_parameters.inflorescence.roll = 90;
-
2401 phytomer_parameters.inflorescence.flower_prototype_scale = 0.04;
-
2402 phytomer_parameters.inflorescence.flower_prototype_function = StrawberryFlowerPrototype;
-
2403 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.06;
-
2404 phytomer_parameters.inflorescence.fruit_prototype_function = StrawberryFruitPrototype;
-
2405 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.65;
-
2406
-
2407 // ---- Shoot Parameters ---- //
-
2408
-
2409 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
-
2410 shoot_parameters.phytomer_parameters = phytomer_parameters;
-
2411
-
2412 shoot_parameters.max_nodes = 15;
-
2413 shoot_parameters.insertion_angle_tip = 40;
-
2414 shoot_parameters.insertion_angle_decay_rate = 0;
-
2415 shoot_parameters.internode_length_max = 0.015;
-
2416 shoot_parameters.internode_length_decay_rate = 0;
-
2417 shoot_parameters.internode_length_min = 0.0;
-
2418 shoot_parameters.base_roll = 90;
-
2419 shoot_parameters.base_yaw.uniformDistribution(-20,20);
-
2420 shoot_parameters.gravitropic_curvature.uniformDistribution(-10,0);
-
2421 shoot_parameters.tortuosity = 0;
-
2422
-
2423 shoot_parameters.phyllochron_min = 2;
-
2424 shoot_parameters.elongation_rate = 0.1;
-
2425 shoot_parameters.girth_area_factor = 2.f;
-
2426 shoot_parameters.vegetative_bud_break_time = 15;
-
2427 shoot_parameters.vegetative_bud_break_probability_min = 0.1;
-
2428 shoot_parameters.vegetative_bud_break_probability_decay_rate = -0.4;
-
2429 shoot_parameters.flower_bud_break_probability = 1;
-
2430 shoot_parameters.fruit_set_probability = 0.5;
-
2431 shoot_parameters.flowers_require_dormancy = false;
-
2432 shoot_parameters.growth_requires_dormancy = false;
-
2433 shoot_parameters.determinate_shoot_growth = true;
-
2434
-
2435 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
-
2436
-
2437 defineShootType("mainstem",shoot_parameters);
+
2347 phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1;
+
2348 phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(15,40);
+
2349 phytomer_parameters_trifoliate.petiole.radius = 0.002;
+
2350 phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.12,0.16);
+
2351 phytomer_parameters_trifoliate.petiole.taper = 0.25;
+
2352 phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-250,50);
+
2353 phytomer_parameters_trifoliate.petiole.color = phytomer_parameters_trifoliate.internode.color;
+
2354 phytomer_parameters_trifoliate.petiole.length_segments = 5;
+
2355 phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6;
+
2356
+
2357 phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3;
+
2358 phytomer_parameters_trifoliate.leaf.pitch.uniformDistribution(-30, 10);
+
2359 phytomer_parameters_trifoliate.leaf.yaw = 10;
+
2360 phytomer_parameters_trifoliate.leaf.roll.uniformDistribution(-25,5);
+
2361 phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.5;
+
2362 phytomer_parameters_trifoliate.leaf.leaflet_scale = 0.9;
+
2363 phytomer_parameters_trifoliate.leaf.prototype_scale.uniformDistribution(0.1,0.14);
+
2364 phytomer_parameters_trifoliate.leaf.prototype = leaf_prototype;
+
2365
+
2366 phytomer_parameters_trifoliate.peduncle.length = 0.01;
+
2367 phytomer_parameters_trifoliate.peduncle.radius = 0.0005;
+
2368 phytomer_parameters_trifoliate.peduncle.pitch.uniformDistribution(0, 40);
+
2369 phytomer_parameters_trifoliate.peduncle.roll = 90;
+
2370 phytomer_parameters_trifoliate.peduncle.curvature.uniformDistribution(-500, 500);
+
2371 phytomer_parameters_trifoliate.peduncle.color = phytomer_parameters_trifoliate.internode.color;
+
2372 phytomer_parameters_trifoliate.peduncle.length_segments = 1;
+
2373 phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6;
+
2374
+
2375 phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle.uniformDistribution(1, 4);
+
2376 phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.2;
+
2377 phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70);
+
2378 phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20);
+
2379 phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.015;
+
2380 phytomer_parameters_trifoliate.inflorescence.flower_prototype_function = SoybeanFlowerPrototype;
+
2381 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_scale.uniformDistribution(0.1,0.12);
+
2382 phytomer_parameters_trifoliate.inflorescence.fruit_prototype_function = SoybeanFruitPrototype;
+
2383 phytomer_parameters_trifoliate.inflorescence.fruit_gravity_factor_fraction.uniformDistribution(0.8,1.0);
+
2384
+
2385 PhytomerParameters phytomer_parameters_unifoliate = phytomer_parameters_trifoliate;
+
2386 phytomer_parameters_unifoliate.internode.pitch = 0;
+
2387 phytomer_parameters_unifoliate.internode.max_vegetative_buds_per_petiole = 0;
+
2388 phytomer_parameters_unifoliate.internode.max_floral_buds_per_petiole = 0;
+
2389 phytomer_parameters_unifoliate.petiole.petioles_per_internode = 2;
+
2390 phytomer_parameters_unifoliate.petiole.length = 0.01;
+
2391 phytomer_parameters_unifoliate.petiole.radius = 0.001;
+
2392 phytomer_parameters_unifoliate.petiole.pitch.uniformDistribution(60,80);
+
2393 phytomer_parameters_unifoliate.leaf.leaves_per_petiole = 1;
+
2394 phytomer_parameters_unifoliate.leaf.prototype_scale = 0.02;
+
2395 phytomer_parameters_unifoliate.leaf.pitch.uniformDistribution(-10, 10);
+
2396 phytomer_parameters_unifoliate.leaf.prototype = leaf_prototype;
+
2397
+
2398 // ---- Shoot Parameters ---- //
+
2399
+
2400 ShootParameters shoot_parameters_trifoliate(context_ptr->getRandomGenerator());
+
2401 shoot_parameters_trifoliate.phytomer_parameters = phytomer_parameters_trifoliate;
+
2402 shoot_parameters_trifoliate.phytomer_parameters.phytomer_creation_function = BeanPhytomerCreationFunction;
+
2403
+
2404 shoot_parameters_trifoliate.max_nodes = 25;
+
2405 shoot_parameters_trifoliate.insertion_angle_tip.uniformDistribution(20,30);
+
2406// shoot_parameters_trifoliate.child_insertion_angle_decay_rate = 0; (default)
+
2407 shoot_parameters_trifoliate.internode_length_max = 0.035;
+
2408// shoot_parameters_trifoliate.child_internode_length_min = 0.0; (default)
+
2409// shoot_parameters_trifoliate.child_internode_length_decay_rate = 0; (default)
+
2410 shoot_parameters_trifoliate.base_roll = 90;
+
2411 shoot_parameters_trifoliate.base_yaw.uniformDistribution(-20,20);
+
2412 shoot_parameters_trifoliate.gravitropic_curvature = 400;
+
2413
+
2414 shoot_parameters_trifoliate.phyllochron_min = 2;
+
2415 shoot_parameters_trifoliate.elongation_rate_max = 0.1;
+
2416 shoot_parameters_trifoliate.girth_area_factor = 2.f;
+
2417 shoot_parameters_trifoliate.vegetative_bud_break_time = 15;
+
2418 shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.05;
+
2419 shoot_parameters_trifoliate.vegetative_bud_break_probability_decay_rate = 0.6;
+
2420// shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default)
+
2421 shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.8,1.0);
+
2422 shoot_parameters_trifoliate.fruit_set_probability = 0.4;
+
2423// shoot_parameters_trifoliate.flowers_require_dormancy = false; (default)
+
2424// shoot_parameters_trifoliate.growth_requires_dormancy = false; (default)
+
2425// shoot_parameters_trifoliate.determinate_shoot_growth = true; (default)
+
2426
+
2427 shoot_parameters_trifoliate.defineChildShootTypes({"trifoliate"},{1.0});
+
2428
+
2429
+
2430 ShootParameters shoot_parameters_unifoliate = shoot_parameters_trifoliate;
+
2431 shoot_parameters_unifoliate.phytomer_parameters = phytomer_parameters_unifoliate;
+
2432 shoot_parameters_unifoliate.max_nodes = 1;
+
2433 shoot_parameters_unifoliate.flower_bud_break_probability = 0;
+
2434 shoot_parameters_unifoliate.insertion_angle_tip = 0;
+
2435 shoot_parameters_unifoliate.insertion_angle_decay_rate = 0;
+
2436 shoot_parameters_unifoliate.vegetative_bud_break_time = 8;
+
2437 shoot_parameters_unifoliate.defineChildShootTypes({"trifoliate"},{1.0});
2438
-
2439}
-
2440
-
2441uint PlantArchitecture::buildStrawberryPlant(const helios::vec3 &base_position) {
-
2442
-
2443 if (shoot_types.empty()) {
-
2444 //automatically initialize strawberry plant shoots
-
2445 initializeStrawberryShoots();
-
2446 }
-
2447
-
2448 uint plantID = addPlantInstance(base_position, 0);
-
2449
-
2450 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
-
2451 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.001, 0.004, 0.01, 0.01, 0, "mainstem");
+
2439 defineShootType("unifoliate",shoot_parameters_unifoliate);
+
2440 defineShootType("trifoliate",shoot_parameters_trifoliate);
+
2441
+
2442}
+
2443
+
2444uint PlantArchitecture::buildSoybeanPlant(const helios::vec3 &base_position) {
+
2445
+
2446 if (shoot_types.empty()) {
+
2447 //automatically initialize bean plant shoots
+
2448 initializeSoybeanShoots();
+
2449 }
+
2450
+
2451 uint plantID = addPlantInstance(base_position, 0);
2452
-
2453 breakPlantDormancy(plantID);
-
2454
-
2455 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 100, false);
-
2456
-
2457 plant_instances.at(plantID).max_age = 365;
-
2458
-
2459 return plantID;
-
2460
-
2461}
-
2462
-
2463void PlantArchitecture::initializeSugarbeetShoots() {
-
2464
-
2465 // ---- Leaf Prototype ---- //
-
2466
-
2467 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
2468 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SugarbeetLeaf.png";
-
2469 leaf_prototype.leaf_aspect_ratio = 0.4f;
-
2470 leaf_prototype.midrib_fold_fraction = 0.1f;
-
2471 leaf_prototype.longitudinal_curvature = -0.2f;
-
2472 leaf_prototype.lateral_curvature = -0.4f;
-
2473 leaf_prototype.petiole_roll = 0.75f;
-
2474 leaf_prototype.wave_period.uniformDistribution( 0.08f, 0.15f);
-
2475 leaf_prototype.wave_amplitude.uniformDistribution(0.02, 0.04);
-
2476 leaf_prototype.subdivisions = 20;;
-
2477 leaf_prototype.unique_prototypes = 10;
-
2478
-
2479 // ---- Phytomer Parameters ---- //
-
2480
-
2481 PhytomerParameters phytomer_parameters_sugarbeet(context_ptr->getRandomGenerator());
+
2453 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));
+
2454 uint uID_unifoliate = addBaseStemShoot(plantID, 1, base_rotation, 0.0005, 0.04, 0.01, 0.01, 0, "unifoliate");
+
2455
+
2456 appendShoot(plantID, uID_unifoliate, 1, make_AxisRotation(0, 0, 0.5f * M_PI), shoot_types.at("trifoliate").phytomer_parameters.internode.radius_initial.val(), shoot_types.at("trifoliate").internode_length_max.val(), 0.1, 0.1, 0, "trifoliate");
+
2457
+
2458 breakPlantDormancy(plantID);
+
2459
+
2460 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 1000, false);
+
2461
+
2462 plant_instances.at(plantID).max_age = 365;
+
2463
+
2464 return plantID;
+
2465
+
2466}
+
2467
+
2468void PlantArchitecture::initializeStrawberryShoots() {
+
2469
+
2470 // ---- Leaf Prototype ---- //
+
2471
+
2472 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2473 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/StrawberryLeaf.png";
+
2474 leaf_prototype.leaf_aspect_ratio = 1.f;
+
2475 leaf_prototype.midrib_fold_fraction = 0.2f;
+
2476 leaf_prototype.longitudinal_curvature = 0.15f;
+
2477 leaf_prototype.lateral_curvature = 0.4f;
+
2478 leaf_prototype.wave_period = 0.3f;
+
2479 leaf_prototype.wave_amplitude = 0.01f;
+
2480 leaf_prototype.subdivisions = 6;
+
2481 leaf_prototype.unique_prototypes = 10;
2482
-
2483 phytomer_parameters_sugarbeet.internode.pitch = 0;
-
2484 phytomer_parameters_sugarbeet.internode.phyllotactic_angle = 137.5;
-
2485 phytomer_parameters_sugarbeet.internode.radius_initial = 0.005;
-
2486 phytomer_parameters_sugarbeet.internode.color = make_RGBcolor(0.44,0.58,0.19);
-
2487 phytomer_parameters_sugarbeet.internode.length_segments = 1;
-
2488 phytomer_parameters_sugarbeet.internode.max_vegetative_buds_per_petiole = 0;
-
2489 phytomer_parameters_sugarbeet.internode.max_floral_buds_per_petiole = 0;
-
2490
-
2491 phytomer_parameters_sugarbeet.petiole.petioles_per_internode = 1;
-
2492 phytomer_parameters_sugarbeet.petiole.pitch.uniformDistribution(0,40);
-
2493 phytomer_parameters_sugarbeet.petiole.radius = 0.005;
-
2494 phytomer_parameters_sugarbeet.petiole.length.uniformDistribution(0.15,0.2);
-
2495 phytomer_parameters_sugarbeet.petiole.taper = 0.6;
-
2496 phytomer_parameters_sugarbeet.petiole.curvature.uniformDistribution(-300,100);
-
2497 phytomer_parameters_sugarbeet.petiole.color = phytomer_parameters_sugarbeet.internode.color;
-
2498 phytomer_parameters_sugarbeet.petiole.length_segments = 8;
-
2499
-
2500 phytomer_parameters_sugarbeet.leaf.leaves_per_petiole = 1;
-
2501 phytomer_parameters_sugarbeet.leaf.pitch.uniformDistribution(-10,0);
-
2502 phytomer_parameters_sugarbeet.leaf.yaw.uniformDistribution(-5,5);
-
2503 phytomer_parameters_sugarbeet.leaf.roll.uniformDistribution(-15,15);
-
2504 phytomer_parameters_sugarbeet.leaf.prototype_scale.uniformDistribution(0.15,0.25);
-
2505 phytomer_parameters_sugarbeet.leaf.prototype = leaf_prototype;
-
2506
-
2507 // ---- Shoot Parameters ---- //
-
2508
-
2509 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
2510 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sugarbeet;
-
2511 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
-
2512 shoot_parameters_mainstem.phyllochron_min = 2;
-
2513 shoot_parameters_mainstem.elongation_rate = 0.1;
-
2514 shoot_parameters_mainstem.girth_area_factor = 20.f;
-
2515 shoot_parameters_mainstem.gravitropic_curvature = 10;
-
2516 shoot_parameters_mainstem.internode_length_max = 0.001;
-
2517 shoot_parameters_mainstem.internode_length_decay_rate = 0;
-
2518 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
2519 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
2520 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
-
2521 shoot_parameters_mainstem.max_nodes = 30;
-
2522
-
2523 defineShootType("mainstem",shoot_parameters_mainstem);
-
2524
-
2525
-
2526}
-
2527
-
2528uint PlantArchitecture::buildSugarbeetPlant(const helios::vec3 &base_position) {
+
2483 // ---- Phytomer Parameters ---- //
+
2484
+
2485 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
2486
+
2487 phytomer_parameters.internode.pitch = 10;
+
2488 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(80,100);
+
2489 phytomer_parameters.internode.radius_initial = 0.001;
+
2490 phytomer_parameters.internode.color = make_RGBcolor(0.38, 0.48, 0.1);
+
2491 phytomer_parameters.internode.length_segments = 1;
+
2492
+
2493 phytomer_parameters.petiole.petioles_per_internode = 1;
+
2494 phytomer_parameters.petiole.pitch.uniformDistribution(0,45);
+
2495 phytomer_parameters.petiole.radius = 0.0025;
+
2496 phytomer_parameters.petiole.length.uniformDistribution(0.15,0.25);
+
2497 phytomer_parameters.petiole.taper = 0.5;
+
2498 phytomer_parameters.petiole.curvature.uniformDistribution(-300,100);
+
2499 phytomer_parameters.petiole.color = make_RGBcolor(0.24, 0.28, 0.08);
+
2500 phytomer_parameters.petiole.length_segments = 5;
+
2501
+
2502 phytomer_parameters.leaf.leaves_per_petiole = 3;
+
2503 phytomer_parameters.leaf.pitch.uniformDistribution(-30,10);
+
2504 phytomer_parameters.leaf.yaw = 20;
+
2505 phytomer_parameters.leaf.roll = -30;
+
2506 phytomer_parameters.leaf.leaflet_offset = 0.01;
+
2507 phytomer_parameters.leaf.leaflet_scale = 1.0;
+
2508 phytomer_parameters.leaf.prototype_scale = 0.1;
+
2509 phytomer_parameters.leaf.prototype = leaf_prototype;
+
2510
+
2511 phytomer_parameters.peduncle.length = 0.17;
+
2512 phytomer_parameters.peduncle.radius = 0.00075;
+
2513 phytomer_parameters.peduncle.pitch = 35;
+
2514 phytomer_parameters.peduncle.roll = 0;
+
2515 phytomer_parameters.peduncle.curvature = -200;
+
2516 phytomer_parameters.peduncle.length_segments = 5;
+
2517 phytomer_parameters.peduncle.radial_subdivisions = 6;
+
2518 phytomer_parameters.peduncle.color = phytomer_parameters.petiole.color;
+
2519
+
2520 phytomer_parameters.inflorescence.flowers_per_peduncle.uniformDistribution(1, 3);
+
2521 phytomer_parameters.inflorescence.flower_offset = 0.2;
+
2522 phytomer_parameters.inflorescence.pitch = 70;
+
2523 phytomer_parameters.inflorescence.roll = 90;
+
2524 phytomer_parameters.inflorescence.flower_prototype_scale = 0.04;
+
2525 phytomer_parameters.inflorescence.flower_prototype_function = StrawberryFlowerPrototype;
+
2526 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.06;
+
2527 phytomer_parameters.inflorescence.fruit_prototype_function = StrawberryFruitPrototype;
+
2528 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.65;
2529
-
2530 if (shoot_types.empty()) {
-
2531 //automatically initialize sugarbeet plant shoots
-
2532 initializeSugarbeetShoots();
-
2533 }
+
2530 // ---- Shoot Parameters ---- //
+
2531
+
2532 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
2533 shoot_parameters.phytomer_parameters = phytomer_parameters;
2534
-
2535 uint plantID = addPlantInstance(base_position, 0);
-
2536
-
2537 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");
-
2538
-
2539 breakPlantDormancy(plantID);
-
2540
-
2541 setPlantPhenologicalThresholds(plantID, 0, -1, -1, -1, -1, 1000, false);
-
2542
-
2543 plant_instances.at(plantID).max_age = 365;
-
2544
-
2545 return plantID;
-
2546
-
2547}
-
2548
-
2549void PlantArchitecture::initializeTomatoShoots() {
-
2550
-
2551 // ---- Leaf Prototype ---- //
-
2552
-
2553 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
2554 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/TomatoLeaf_centered.png";
-
2555 leaf_prototype.leaf_aspect_ratio = 0.5f;
-
2556 leaf_prototype.midrib_fold_fraction = 0.1f;
-
2557 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.45, -0.2f);
-
2558 leaf_prototype.lateral_curvature = -0.3f;
-
2559 leaf_prototype.wave_period = 0.35f;
-
2560 leaf_prototype.wave_amplitude = 0.08f;
-
2561 leaf_prototype.subdivisions = 6;
-
2562 leaf_prototype.unique_prototypes = 5;
+
2535 shoot_parameters.max_nodes = 15;
+
2536 shoot_parameters.insertion_angle_tip = 40;
+
2537 shoot_parameters.insertion_angle_decay_rate = 0;
+
2538 shoot_parameters.internode_length_max = 0.015;
+
2539 shoot_parameters.internode_length_decay_rate = 0;
+
2540 shoot_parameters.internode_length_min = 0.0;
+
2541 shoot_parameters.base_roll = 90;
+
2542 shoot_parameters.base_yaw.uniformDistribution(-20,20);
+
2543 shoot_parameters.gravitropic_curvature.uniformDistribution(-10,0);
+
2544 shoot_parameters.tortuosity = 0;
+
2545
+
2546 shoot_parameters.phyllochron_min = 2;
+
2547 shoot_parameters.elongation_rate_max = 0.1;
+
2548 shoot_parameters.girth_area_factor = 2.f;
+
2549 shoot_parameters.vegetative_bud_break_time = 15;
+
2550 shoot_parameters.vegetative_bud_break_probability_min = 0.1;
+
2551 shoot_parameters.vegetative_bud_break_probability_decay_rate = -0.4;
+
2552 shoot_parameters.flower_bud_break_probability = 1;
+
2553 shoot_parameters.fruit_set_probability = 0.5;
+
2554 shoot_parameters.flowers_require_dormancy = false;
+
2555 shoot_parameters.growth_requires_dormancy = false;
+
2556 shoot_parameters.determinate_shoot_growth = true;
+
2557
+
2558 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
+
2559
+
2560 defineShootType("mainstem",shoot_parameters);
+
2561
+
2562}
2563
-
2564 // ---- Phytomer Parameters ---- //
+
2564uint PlantArchitecture::buildStrawberryPlant(const helios::vec3 &base_position) {
2565
-
2566 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
-
2567
-
2568 phytomer_parameters.internode.pitch = 10;
-
2569 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(145, 215);
-
2570 phytomer_parameters.internode.radius_initial = 0.001;
-
2571 phytomer_parameters.internode.color = make_RGBcolor(0.213, 0.270, 0.056);
-
2572 phytomer_parameters.internode.length_segments = 1;
-
2573
-
2574 phytomer_parameters.petiole.petioles_per_internode = 1;
-
2575 phytomer_parameters.petiole.pitch.uniformDistribution(45,60);
-
2576 phytomer_parameters.petiole.radius = 0.002;
-
2577 phytomer_parameters.petiole.length = 0.2;
-
2578 phytomer_parameters.petiole.taper = 0.15;
-
2579 phytomer_parameters.petiole.curvature.uniformDistribution(-150,-50);
-
2580 phytomer_parameters.petiole.color = phytomer_parameters.internode.color;
-
2581 phytomer_parameters.petiole.length_segments = 5;
-
2582
-
2583 phytomer_parameters.leaf.leaves_per_petiole = 7;
-
2584 phytomer_parameters.leaf.pitch.uniformDistribution(-30, 5);
-
2585 phytomer_parameters.leaf.yaw = 10;
-
2586 phytomer_parameters.leaf.roll = 0;
-
2587 phytomer_parameters.leaf.leaflet_offset = 0.15;
-
2588 phytomer_parameters.leaf.leaflet_scale = 0.7;
-
2589 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.12,0.18);
-
2590 phytomer_parameters.leaf.prototype = leaf_prototype;
-
2591
-
2592 phytomer_parameters.peduncle.length = 0.16;
-
2593 phytomer_parameters.peduncle.radius = 0.0015;
-
2594 phytomer_parameters.peduncle.pitch = 20;
-
2595 phytomer_parameters.peduncle.roll = 0;
-
2596 phytomer_parameters.peduncle.curvature = -700;
-
2597 phytomer_parameters.peduncle.color = phytomer_parameters.internode.color;
-
2598 phytomer_parameters.peduncle.length_segments = 5;
-
2599 phytomer_parameters.peduncle.radial_subdivisions = 8;
-
2600
-
2601 phytomer_parameters.inflorescence.flowers_per_peduncle = 8;
-
2602 phytomer_parameters.inflorescence.flower_offset = 0.15;
-
2603 phytomer_parameters.inflorescence.pitch = 90;
-
2604 phytomer_parameters.inflorescence.roll.uniformDistribution(-30,30);
-
2605 phytomer_parameters.inflorescence.flower_prototype_scale = 0.03;
-
2606 phytomer_parameters.inflorescence.flower_prototype_function = TomatoFlowerPrototype;
-
2607 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.08;
-
2608 phytomer_parameters.inflorescence.fruit_prototype_function = TomatoFruitPrototype;
-
2609 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.5;
-
2610
-
2611 // ---- Shoot Parameters ---- //
-
2612
-
2613 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
-
2614 shoot_parameters.phytomer_parameters = phytomer_parameters;
-
2615 shoot_parameters.phytomer_parameters.phytomer_creation_function = TomatoPhytomerCreationFunction;
-
2616
-
2617 shoot_parameters.max_nodes = 16;
-
2618 shoot_parameters.insertion_angle_tip = 30;
-
2619 shoot_parameters.insertion_angle_decay_rate = 0;
-
2620 shoot_parameters.internode_length_max = 0.04;
-
2621 shoot_parameters.internode_length_min = 0.0;
-
2622 shoot_parameters.internode_length_decay_rate = 0;
-
2623 shoot_parameters.base_roll = 90;
-
2624 shoot_parameters.base_yaw.uniformDistribution(-20,20);
-
2625 shoot_parameters.gravitropic_curvature = -200;
-
2626 shoot_parameters.tortuosity = 3;
-
2627
-
2628 shoot_parameters.phyllochron_min = 2;
-
2629 shoot_parameters.elongation_rate = 0.1;
-
2630 shoot_parameters.girth_area_factor = 3.f;
-
2631 shoot_parameters.vegetative_bud_break_time = 10;
-
2632 shoot_parameters.vegetative_bud_break_probability_min = 0.15;
-
2633 shoot_parameters.vegetative_bud_break_probability_decay_rate = -0.5;
-
2634 shoot_parameters.flower_bud_break_probability = 0.5;
-
2635 shoot_parameters.fruit_set_probability = 0.5;
-
2636 shoot_parameters.flowers_require_dormancy = false;
-
2637 shoot_parameters.growth_requires_dormancy = false;
-
2638 shoot_parameters.determinate_shoot_growth = true;
-
2639
-
2640 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
-
2641
-
2642 defineShootType("mainstem",shoot_parameters);
-
2643
-
2644}
+
2566 if (shoot_types.empty()) {
+
2567 //automatically initialize strawberry plant shoots
+
2568 initializeStrawberryShoots();
+
2569 }
+
2570
+
2571 uint plantID = addPlantInstance(base_position, 0);
+
2572
+
2573 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
2574 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.001, 0.004, 0.01, 0.01, 0, "mainstem");
+
2575
+
2576 breakPlantDormancy(plantID);
+
2577
+
2578 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 100, false);
+
2579
+
2580 plant_instances.at(plantID).max_age = 365;
+
2581
+
2582 return plantID;
+
2583
+
2584}
+
2585
+
2586void PlantArchitecture::initializeSugarbeetShoots() {
+
2587
+
2588 // ---- Leaf Prototype ---- //
+
2589
+
2590 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2591 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SugarbeetLeaf.png";
+
2592 leaf_prototype.leaf_aspect_ratio = 0.4f;
+
2593 leaf_prototype.midrib_fold_fraction = 0.1f;
+
2594 leaf_prototype.longitudinal_curvature = -0.2f;
+
2595 leaf_prototype.lateral_curvature = -0.4f;
+
2596 leaf_prototype.petiole_roll = 0.75f;
+
2597 leaf_prototype.wave_period.uniformDistribution( 0.08f, 0.15f);
+
2598 leaf_prototype.wave_amplitude.uniformDistribution(0.02, 0.04);
+
2599 leaf_prototype.subdivisions = 20;;
+
2600 leaf_prototype.unique_prototypes = 10;
+
2601
+
2602 // ---- Phytomer Parameters ---- //
+
2603
+
2604 PhytomerParameters phytomer_parameters_sugarbeet(context_ptr->getRandomGenerator());
+
2605
+
2606 phytomer_parameters_sugarbeet.internode.pitch = 0;
+
2607 phytomer_parameters_sugarbeet.internode.phyllotactic_angle = 137.5;
+
2608 phytomer_parameters_sugarbeet.internode.radius_initial = 0.005;
+
2609 phytomer_parameters_sugarbeet.internode.color = make_RGBcolor(0.44,0.58,0.19);
+
2610 phytomer_parameters_sugarbeet.internode.length_segments = 1;
+
2611 phytomer_parameters_sugarbeet.internode.max_vegetative_buds_per_petiole = 0;
+
2612 phytomer_parameters_sugarbeet.internode.max_floral_buds_per_petiole = 0;
+
2613
+
2614 phytomer_parameters_sugarbeet.petiole.petioles_per_internode = 1;
+
2615 phytomer_parameters_sugarbeet.petiole.pitch.uniformDistribution(0,40);
+
2616 phytomer_parameters_sugarbeet.petiole.radius = 0.005;
+
2617 phytomer_parameters_sugarbeet.petiole.length.uniformDistribution(0.15,0.2);
+
2618 phytomer_parameters_sugarbeet.petiole.taper = 0.6;
+
2619 phytomer_parameters_sugarbeet.petiole.curvature.uniformDistribution(-300,100);
+
2620 phytomer_parameters_sugarbeet.petiole.color = phytomer_parameters_sugarbeet.internode.color;
+
2621 phytomer_parameters_sugarbeet.petiole.length_segments = 8;
+
2622
+
2623 phytomer_parameters_sugarbeet.leaf.leaves_per_petiole = 1;
+
2624 phytomer_parameters_sugarbeet.leaf.pitch.uniformDistribution(-10,0);
+
2625 phytomer_parameters_sugarbeet.leaf.yaw.uniformDistribution(-5,5);
+
2626 phytomer_parameters_sugarbeet.leaf.roll.uniformDistribution(-15,15);
+
2627 phytomer_parameters_sugarbeet.leaf.prototype_scale.uniformDistribution(0.15,0.25);
+
2628 phytomer_parameters_sugarbeet.leaf.prototype = leaf_prototype;
+
2629
+
2630 // ---- Shoot Parameters ---- //
+
2631
+
2632 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
2633 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sugarbeet;
+
2634 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
+
2635 shoot_parameters_mainstem.phyllochron_min = 2;
+
2636 shoot_parameters_mainstem.elongation_rate_max = 0.1;
+
2637 shoot_parameters_mainstem.girth_area_factor = 20.f;
+
2638 shoot_parameters_mainstem.gravitropic_curvature = 10;
+
2639 shoot_parameters_mainstem.internode_length_max = 0.001;
+
2640 shoot_parameters_mainstem.internode_length_decay_rate = 0;
+
2641 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
2642 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
2643 shoot_parameters_mainstem.flower_bud_break_probability = 0.0;
+
2644 shoot_parameters_mainstem.max_nodes = 30;
2645
-
2646uint PlantArchitecture::buildTomatoPlant(const helios::vec3 &base_position) {
+
2646 defineShootType("mainstem",shoot_parameters_mainstem);
2647
-
2648 if (shoot_types.empty()) {
-
2649 //automatically initialize tomato plant shoots
-
2650 initializeTomatoShoots();
-
2651 }
+
2648
+
2649}
+
2650
+
2651uint PlantArchitecture::buildSugarbeetPlant(const helios::vec3 &base_position) {
2652
-
2653 uint plantID = addPlantInstance(base_position, 0);
-
2654
-
2655 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
-
2656 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.002, 0.06, 0.01, 0.01, 0, "mainstem");
+
2653 if (shoot_types.empty()) {
+
2654 //automatically initialize sugarbeet plant shoots
+
2655 initializeSugarbeetShoots();
+
2656 }
2657
-
2658 breakPlantDormancy(plantID);
+
2658 uint plantID = addPlantInstance(base_position, 0);
2659
-
2660 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 1000, false);
+
2660 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");
2661
-
2662 plant_instances.at(plantID).max_age = 365;
+
2662 breakPlantDormancy(plantID);
2663
-
2664 return plantID;
+
2664 setPlantPhenologicalThresholds(plantID, 0, -1, -1, -1, -1, 1000, false);
2665
-
2666}
+
2666 plant_instances.at(plantID).max_age = 365;
2667
-
2668void PlantArchitecture::initializeWalnutTreeShoots(){
+
2668 return plantID;
2669
-
2670 // ---- Leaf Prototype ---- //
+
2670}
2671
-
2672 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
2673 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/WalnutLeaf.png";
-
2674 leaf_prototype.leaf_aspect_ratio = 0.5f;
-
2675 leaf_prototype.midrib_fold_fraction = 0.15f;
-
2676 leaf_prototype.longitudinal_curvature = -0.2f;
-
2677 leaf_prototype.lateral_curvature = 0.1f;
-
2678 leaf_prototype.wave_period.uniformDistribution(0.08, 0.15);
-
2679 leaf_prototype.wave_amplitude.uniformDistribution(0.02, 0.04);
-
2680 leaf_prototype.subdivisions = 3;
-
2681 leaf_prototype.unique_prototypes = 5;
-
2682
-
2683 // ---- Phytomer Parameters ---- //
-
2684
-
2685 PhytomerParameters phytomer_parameters_walnut(context_ptr->getRandomGenerator());
+
2672void PlantArchitecture::initializeTomatoShoots() {
+
2673
+
2674 // ---- Leaf Prototype ---- //
+
2675
+
2676 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2677 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/TomatoLeaf_centered.png";
+
2678 leaf_prototype.leaf_aspect_ratio = 0.5f;
+
2679 leaf_prototype.midrib_fold_fraction = 0.1f;
+
2680 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.45, -0.2f);
+
2681 leaf_prototype.lateral_curvature = -0.3f;
+
2682 leaf_prototype.wave_period = 0.35f;
+
2683 leaf_prototype.wave_amplitude = 0.08f;
+
2684 leaf_prototype.subdivisions = 6;
+
2685 leaf_prototype.unique_prototypes = 5;
2686
-
2687 phytomer_parameters_walnut.internode.pitch = 0;
-
2688 phytomer_parameters_walnut.internode.phyllotactic_angle.uniformDistribution( 160, 200 );
-
2689 phytomer_parameters_walnut.internode.radius_initial = 0.004;
-
2690 phytomer_parameters_walnut.internode.length_segments = 1;
-
2691 phytomer_parameters_walnut.internode.image_texture = "plugins/plantarchitecture/assets/textures/AppleBark.jpg";
-
2692 phytomer_parameters_walnut.internode.max_floral_buds_per_petiole = 3;
-
2693
-
2694 phytomer_parameters_walnut.petiole.petioles_per_internode = 2;
-
2695 phytomer_parameters_walnut.petiole.pitch.uniformDistribution(-80,-70);
-
2696 phytomer_parameters_walnut.petiole.taper = 0.2;
-
2697 phytomer_parameters_walnut.petiole.curvature.uniformDistribution(-1000,0);
-
2698 phytomer_parameters_walnut.petiole.length = 0.15;
-
2699 phytomer_parameters_walnut.petiole.radius = 0.0015;
-
2700 phytomer_parameters_walnut.petiole.length_segments = 5;
-
2701 phytomer_parameters_walnut.petiole.radial_subdivisions = 3;
-
2702 phytomer_parameters_walnut.petiole.color = make_RGBcolor(0.61,0.5,0.24);
-
2703
-
2704 phytomer_parameters_walnut.leaf.leaves_per_petiole = 5;
-
2705 phytomer_parameters_walnut.leaf.pitch.uniformDistribution(-40,0);
-
2706 phytomer_parameters_walnut.leaf.prototype_scale = 0.14;
-
2707 phytomer_parameters_walnut.leaf.leaflet_scale = 0.7;
-
2708 phytomer_parameters_walnut.leaf.leaflet_offset = 0.35;
-
2709 phytomer_parameters_walnut.leaf.prototype = leaf_prototype;
-
2710
-
2711 phytomer_parameters_walnut.peduncle.length = 0.02;
-
2712 phytomer_parameters_walnut.peduncle.radius = 0.0005;
-
2713 phytomer_parameters_walnut.peduncle.pitch = 90;
-
2714 phytomer_parameters_walnut.peduncle.roll = 90;
-
2715 phytomer_parameters_walnut.peduncle.length_segments = 1;
-
2716
-
2717 phytomer_parameters_walnut.inflorescence.flowers_per_peduncle = 1;
-
2718 phytomer_parameters_walnut.inflorescence.pitch = 0;
-
2719 phytomer_parameters_walnut.inflorescence.roll = 0;
-
2720 phytomer_parameters_walnut.inflorescence.flower_prototype_scale = 0.03;
-
2721 phytomer_parameters_walnut.inflorescence.flower_prototype_function = WalnutFlowerPrototype;
-
2722 phytomer_parameters_walnut.inflorescence.fruit_prototype_scale = 0.075;
-
2723 phytomer_parameters_walnut.inflorescence.fruit_prototype_function = WalnutFruitPrototype;
-
2724
-
2725 // ---- Shoot Parameters ---- //
-
2726
-
2727 // Trunk
-
2728 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
-
2729 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_walnut;
-
2730 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
-
2731 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.01;
-
2732 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24;
-
2733 shoot_parameters_trunk.max_nodes = 20;
-
2734 shoot_parameters_trunk.girth_area_factor = 3.f;
-
2735 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
-
2736 shoot_parameters_trunk.vegetative_bud_break_time = 0;
-
2737 shoot_parameters_trunk.tortuosity = 1;
-
2738 shoot_parameters_trunk.internode_length_max = 0.05;
-
2739 shoot_parameters_trunk.internode_length_decay_rate = 0;
-
2740 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
-
2741
-
2742 // Proleptic shoots
-
2743 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
-
2744 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_walnut;
-
2745 shoot_parameters_proleptic.phytomer_parameters.internode.color = make_RGBcolor(0.3,0.2,0.2);
-
2746 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = WalnutPhytomerCreationFunction;
-
2747 // shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = WalnutPhytomerCallbackFunction;
-
2748 shoot_parameters_proleptic.max_nodes = 30;
-
2749 shoot_parameters_proleptic.max_nodes_per_season = 15;
-
2750 shoot_parameters_proleptic.phyllochron_min = 2.;
-
2751 shoot_parameters_proleptic.elongation_rate = 0.15;
-
2752 shoot_parameters_proleptic.girth_area_factor = 10.f;
-
2753 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.05;
-
2754 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.6;
-
2755 shoot_parameters_proleptic.vegetative_bud_break_time = 3;
-
2756 shoot_parameters_proleptic.gravitropic_curvature = 200;
-
2757 shoot_parameters_proleptic.tortuosity = 5;
-
2758 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 20, 25);
-
2759 shoot_parameters_proleptic.insertion_angle_decay_rate = 15;
-
2760 shoot_parameters_proleptic.internode_length_max = 0.08;
-
2761 shoot_parameters_proleptic.internode_length_min = 0.01;
-
2762 shoot_parameters_proleptic.internode_length_decay_rate = 0.006;
-
2763 shoot_parameters_proleptic.fruit_set_probability = 0.5;
-
2764 shoot_parameters_proleptic.flower_bud_break_probability = 0.3;
-
2765 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
-
2766 shoot_parameters_proleptic.flowers_require_dormancy = true;
-
2767 shoot_parameters_proleptic.growth_requires_dormancy = true;
-
2768 shoot_parameters_proleptic.determinate_shoot_growth = false;
-
2769 shoot_parameters_proleptic.defineChildShootTypes({"proleptic"},{1.0});
+
2687 // ---- Phytomer Parameters ---- //
+
2688
+
2689 PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator());
+
2690
+
2691 phytomer_parameters.internode.pitch = 10;
+
2692 phytomer_parameters.internode.phyllotactic_angle.uniformDistribution(145, 215);
+
2693 phytomer_parameters.internode.radius_initial = 0.001;
+
2694 phytomer_parameters.internode.color = make_RGBcolor(0.213, 0.270, 0.056);
+
2695 phytomer_parameters.internode.length_segments = 1;
+
2696
+
2697 phytomer_parameters.petiole.petioles_per_internode = 1;
+
2698 phytomer_parameters.petiole.pitch.uniformDistribution(45,60);
+
2699 phytomer_parameters.petiole.radius = 0.002;
+
2700 phytomer_parameters.petiole.length = 0.2;
+
2701 phytomer_parameters.petiole.taper = 0.15;
+
2702 phytomer_parameters.petiole.curvature.uniformDistribution(-150,-50);
+
2703 phytomer_parameters.petiole.color = phytomer_parameters.internode.color;
+
2704 phytomer_parameters.petiole.length_segments = 5;
+
2705
+
2706 phytomer_parameters.leaf.leaves_per_petiole = 7;
+
2707 phytomer_parameters.leaf.pitch.uniformDistribution(-30, 5);
+
2708 phytomer_parameters.leaf.yaw = 10;
+
2709 phytomer_parameters.leaf.roll = 0;
+
2710 phytomer_parameters.leaf.leaflet_offset = 0.15;
+
2711 phytomer_parameters.leaf.leaflet_scale = 0.7;
+
2712 phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.12,0.18);
+
2713 phytomer_parameters.leaf.prototype = leaf_prototype;
+
2714
+
2715 phytomer_parameters.peduncle.length = 0.16;
+
2716 phytomer_parameters.peduncle.radius = 0.0015;
+
2717 phytomer_parameters.peduncle.pitch = 20;
+
2718 phytomer_parameters.peduncle.roll = 0;
+
2719 phytomer_parameters.peduncle.curvature = -700;
+
2720 phytomer_parameters.peduncle.color = phytomer_parameters.internode.color;
+
2721 phytomer_parameters.peduncle.length_segments = 5;
+
2722 phytomer_parameters.peduncle.radial_subdivisions = 8;
+
2723
+
2724 phytomer_parameters.inflorescence.flowers_per_peduncle = 8;
+
2725 phytomer_parameters.inflorescence.flower_offset = 0.15;
+
2726 phytomer_parameters.inflorescence.pitch = 90;
+
2727 phytomer_parameters.inflorescence.roll.uniformDistribution(-30,30);
+
2728 phytomer_parameters.inflorescence.flower_prototype_scale = 0.03;
+
2729 phytomer_parameters.inflorescence.flower_prototype_function = TomatoFlowerPrototype;
+
2730 phytomer_parameters.inflorescence.fruit_prototype_scale = 0.08;
+
2731 phytomer_parameters.inflorescence.fruit_prototype_function = TomatoFruitPrototype;
+
2732 phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.5;
+
2733
+
2734 // ---- Shoot Parameters ---- //
+
2735
+
2736 ShootParameters shoot_parameters(context_ptr->getRandomGenerator());
+
2737 shoot_parameters.phytomer_parameters = phytomer_parameters;
+
2738 shoot_parameters.phytomer_parameters.phytomer_creation_function = TomatoPhytomerCreationFunction;
+
2739
+
2740 shoot_parameters.max_nodes = 16;
+
2741 shoot_parameters.insertion_angle_tip = 30;
+
2742 shoot_parameters.insertion_angle_decay_rate = 0;
+
2743 shoot_parameters.internode_length_max = 0.04;
+
2744 shoot_parameters.internode_length_min = 0.0;
+
2745 shoot_parameters.internode_length_decay_rate = 0;
+
2746 shoot_parameters.base_roll = 90;
+
2747 shoot_parameters.base_yaw.uniformDistribution(-20,20);
+
2748 shoot_parameters.gravitropic_curvature = -200;
+
2749 shoot_parameters.tortuosity = 3;
+
2750
+
2751 shoot_parameters.phyllochron_min = 2;
+
2752 shoot_parameters.elongation_rate_max = 0.1;
+
2753 shoot_parameters.girth_area_factor = 3.f;
+
2754 shoot_parameters.vegetative_bud_break_time = 10;
+
2755 shoot_parameters.vegetative_bud_break_probability_min = 0.15;
+
2756 shoot_parameters.vegetative_bud_break_probability_decay_rate = -0.5;
+
2757 shoot_parameters.flower_bud_break_probability = 0.5;
+
2758 shoot_parameters.fruit_set_probability = 0.5;
+
2759 shoot_parameters.flowers_require_dormancy = false;
+
2760 shoot_parameters.growth_requires_dormancy = false;
+
2761 shoot_parameters.determinate_shoot_growth = true;
+
2762
+
2763 shoot_parameters.defineChildShootTypes({"mainstem"},{1.0});
+
2764
+
2765 defineShootType("mainstem",shoot_parameters);
+
2766
+
2767}
+
2768
+
2769uint PlantArchitecture::buildTomatoPlant(const helios::vec3 &base_position) {
2770
-
2771 // Main scaffolds
-
2772 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
-
2773 shoot_parameters_scaffold.phytomer_parameters.internode.radial_subdivisions = 10;
-
2774 shoot_parameters_scaffold.max_nodes = 30;
-
2775 shoot_parameters_scaffold.gravitropic_curvature = 300;
-
2776 shoot_parameters_scaffold.internode_length_max = 0.06;
-
2777 shoot_parameters_scaffold.tortuosity = 4;
-
2778 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
-
2779
-
2780 defineShootType("trunk", shoot_parameters_trunk);
-
2781 defineShootType("scaffold", shoot_parameters_scaffold);
-
2782 defineShootType("proleptic", shoot_parameters_proleptic);
-
2783
-
2784}
-
2785
-
2786uint PlantArchitecture::buildWalnutTree(const helios::vec3 &base_position) {
-
2787
-
2788 if( shoot_types.empty() ){
-
2789 //automatically initialize walnut tree shoots
-
2790 initializeWalnutTreeShoots();
-
2791 }
+
2771 if (shoot_types.empty()) {
+
2772 //automatically initialize tomato plant shoots
+
2773 initializeTomatoShoots();
+
2774 }
+
2775
+
2776 uint plantID = addPlantInstance(base_position, 0);
+
2777
+
2778 AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI));
+
2779 uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.002, 0.06, 0.01, 0.01, 0, "mainstem");
+
2780
+
2781 breakPlantDormancy(plantID);
+
2782
+
2783 setPlantPhenologicalThresholds(plantID, 0, 40, 5, 5, 30, 1000, false);
+
2784
+
2785 plant_instances.at(plantID).max_age = 365;
+
2786
+
2787 return plantID;
+
2788
+
2789}
+
2790
+
2791void PlantArchitecture::initializeWalnutTreeShoots(){
2792
-
2793 uint plantID = addPlantInstance(base_position, 0);
+
2793 // ---- Leaf Prototype ---- //
2794
-
2795 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), 0.f * M_PI), shoot_types.at("trunk").phytomer_parameters.internode.radius_initial.val(), 0.04, 1.f, 1.f, 0, "trunk");
-
2796 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
-
2797
-
2798 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
-
2799
-
2800 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
-
2801 for( const auto & phytomer : phytomers ){
-
2802 phytomer->removeLeaf();
-
2803 phytomer->setVegetativeBudState(BUD_DEAD);
-
2804 phytomer->setFloralBudState(BUD_DEAD);
-
2805 }
-
2806
-
2807 uint Nscaffolds = 4;//context_ptr->randu(4,5);
-
2808
-
2809 for( int i=0; i<Nscaffolds; i++ ) {
-
2810// float pitch = context_ptr->randu(deg2rad(25), deg2rad(35))+i*deg2rad(7.f);
-
2811 float pitch = context_ptr->randu(deg2rad(45), deg2rad(55));
-
2812 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, context_ptr->randu(7, 9), 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);
-
2813
-
2814 }
-
2815
-
2816 makePlantDormant(plantID);
-
2817
-
2818 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 20, 200, false);
-
2819
-
2820 plant_instances.at(plantID).max_age = 1095;
-
2821
-
2822 return plantID;
-
2823
-
2824}
-
2825
-
2826void PlantArchitecture::initializeWheatShoots() {
-
2827
-
2828 // ---- Leaf Prototype ---- //
-
2829
-
2830 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
-
2831 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
-
2832 leaf_prototype.leaf_aspect_ratio = 0.1f;
-
2833 leaf_prototype.midrib_fold_fraction = 0.3f;
-
2834 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.5, -0.1);
-
2835 leaf_prototype.lateral_curvature = -0.3;
-
2836 leaf_prototype.petiole_roll = 0.04f;
-
2837 leaf_prototype.wave_period = 0.1f;
-
2838 leaf_prototype.wave_amplitude = 0.1f;
-
2839 leaf_prototype.leaf_buckle_length.uniformDistribution(0.5,0.6);
-
2840 leaf_prototype.leaf_buckle_angle.uniformDistribution(25,35);
-
2841 leaf_prototype.subdivisions = 20;
-
2842 leaf_prototype.unique_prototypes = 10;
-
2843
-
2844 // ---- Phytomer Parameters ---- //
-
2845
-
2846 PhytomerParameters phytomer_parameters_wheat(context_ptr->getRandomGenerator());
+
2795 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2796 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/WalnutLeaf.png";
+
2797 leaf_prototype.leaf_aspect_ratio = 0.5f;
+
2798 leaf_prototype.midrib_fold_fraction = 0.15f;
+
2799 leaf_prototype.longitudinal_curvature = -0.2f;
+
2800 leaf_prototype.lateral_curvature = 0.1f;
+
2801 leaf_prototype.wave_period.uniformDistribution(0.08, 0.15);
+
2802 leaf_prototype.wave_amplitude.uniformDistribution(0.02, 0.04);
+
2803 leaf_prototype.subdivisions = 3;
+
2804 leaf_prototype.unique_prototypes = 5;
+
2805
+
2806 // ---- Phytomer Parameters ---- //
+
2807
+
2808 PhytomerParameters phytomer_parameters_walnut(context_ptr->getRandomGenerator());
+
2809
+
2810 phytomer_parameters_walnut.internode.pitch = 0;
+
2811 phytomer_parameters_walnut.internode.phyllotactic_angle.uniformDistribution( 160, 200 );
+
2812 phytomer_parameters_walnut.internode.radius_initial = 0.004;
+
2813 phytomer_parameters_walnut.internode.length_segments = 1;
+
2814 phytomer_parameters_walnut.internode.image_texture = "plugins/plantarchitecture/assets/textures/AppleBark.jpg";
+
2815 phytomer_parameters_walnut.internode.max_floral_buds_per_petiole = 3;
+
2816
+
2817 phytomer_parameters_walnut.petiole.petioles_per_internode = 2;
+
2818 phytomer_parameters_walnut.petiole.pitch.uniformDistribution(-80,-70);
+
2819 phytomer_parameters_walnut.petiole.taper = 0.2;
+
2820 phytomer_parameters_walnut.petiole.curvature.uniformDistribution(-1000,0);
+
2821 phytomer_parameters_walnut.petiole.length = 0.15;
+
2822 phytomer_parameters_walnut.petiole.radius = 0.0015;
+
2823 phytomer_parameters_walnut.petiole.length_segments = 5;
+
2824 phytomer_parameters_walnut.petiole.radial_subdivisions = 3;
+
2825 phytomer_parameters_walnut.petiole.color = make_RGBcolor(0.61,0.5,0.24);
+
2826
+
2827 phytomer_parameters_walnut.leaf.leaves_per_petiole = 5;
+
2828 phytomer_parameters_walnut.leaf.pitch.uniformDistribution(-40,0);
+
2829 phytomer_parameters_walnut.leaf.prototype_scale = 0.14;
+
2830 phytomer_parameters_walnut.leaf.leaflet_scale = 0.7;
+
2831 phytomer_parameters_walnut.leaf.leaflet_offset = 0.35;
+
2832 phytomer_parameters_walnut.leaf.prototype = leaf_prototype;
+
2833
+
2834 phytomer_parameters_walnut.peduncle.length = 0.02;
+
2835 phytomer_parameters_walnut.peduncle.radius = 0.0005;
+
2836 phytomer_parameters_walnut.peduncle.pitch = 90;
+
2837 phytomer_parameters_walnut.peduncle.roll = 90;
+
2838 phytomer_parameters_walnut.peduncle.length_segments = 1;
+
2839
+
2840 phytomer_parameters_walnut.inflorescence.flowers_per_peduncle = 1;
+
2841 phytomer_parameters_walnut.inflorescence.pitch = 0;
+
2842 phytomer_parameters_walnut.inflorescence.roll = 0;
+
2843 phytomer_parameters_walnut.inflorescence.flower_prototype_scale = 0.03;
+
2844 phytomer_parameters_walnut.inflorescence.flower_prototype_function = WalnutFlowerPrototype;
+
2845 phytomer_parameters_walnut.inflorescence.fruit_prototype_scale = 0.075;
+
2846 phytomer_parameters_walnut.inflorescence.fruit_prototype_function = WalnutFruitPrototype;
2847
-
2848 phytomer_parameters_wheat.internode.pitch = 0;
-
2849 phytomer_parameters_wheat.internode.phyllotactic_angle.uniformDistribution(67,77);
-
2850 phytomer_parameters_wheat.internode.radius_initial = 0.001;
-
2851 phytomer_parameters_wheat.internode.color = make_RGBcolor(0.27,0.31,0.16);
-
2852 phytomer_parameters_wheat.internode.length_segments = 1;
-
2853 phytomer_parameters_wheat.internode.radial_subdivisions = 6;
-
2854 phytomer_parameters_wheat.internode.max_floral_buds_per_petiole = 0;
-
2855 phytomer_parameters_wheat.internode.max_vegetative_buds_per_petiole = 0;
-
2856
-
2857 phytomer_parameters_wheat.petiole.petioles_per_internode = 1;
-
2858 phytomer_parameters_wheat.petiole.pitch.uniformDistribution(-40,-20);
-
2859 phytomer_parameters_wheat.petiole.radius = 0.0;
-
2860 phytomer_parameters_wheat.petiole.length = 0.005;
-
2861 phytomer_parameters_wheat.petiole.taper = 0;
-
2862 phytomer_parameters_wheat.petiole.curvature = 0;
-
2863 phytomer_parameters_wheat.petiole.length_segments = 1;
+
2848 // ---- Shoot Parameters ---- //
+
2849
+
2850 // Trunk
+
2851 ShootParameters shoot_parameters_trunk(context_ptr->getRandomGenerator());
+
2852 shoot_parameters_trunk.phytomer_parameters = phytomer_parameters_walnut;
+
2853 shoot_parameters_trunk.phytomer_parameters.internode.phyllotactic_angle = 0;
+
2854 shoot_parameters_trunk.phytomer_parameters.internode.radius_initial = 0.01;
+
2855 shoot_parameters_trunk.phytomer_parameters.internode.radial_subdivisions = 24;
+
2856 shoot_parameters_trunk.max_nodes = 20;
+
2857 shoot_parameters_trunk.girth_area_factor = 3.f;
+
2858 shoot_parameters_trunk.vegetative_bud_break_probability_min = 0;
+
2859 shoot_parameters_trunk.vegetative_bud_break_time = 0;
+
2860 shoot_parameters_trunk.tortuosity = 1;
+
2861 shoot_parameters_trunk.internode_length_max = 0.05;
+
2862 shoot_parameters_trunk.internode_length_decay_rate = 0;
+
2863 shoot_parameters_trunk.defineChildShootTypes({"scaffold"},{1});
2864
-
2865 phytomer_parameters_wheat.leaf.leaves_per_petiole = 1;
-
2866 phytomer_parameters_wheat.leaf.pitch = 0;
-
2867 phytomer_parameters_wheat.leaf.yaw = 0;
-
2868 phytomer_parameters_wheat.leaf.roll = 0;
-
2869 phytomer_parameters_wheat.leaf.prototype_scale = 0.22;
-
2870 phytomer_parameters_wheat.leaf.prototype = leaf_prototype;
-
2871
-
2872 phytomer_parameters_wheat.peduncle.length = 0.1;
-
2873 phytomer_parameters_wheat.peduncle.radius = 0.002;
-
2874 phytomer_parameters_wheat.peduncle.color = phytomer_parameters_wheat.internode.color;
-
2875 phytomer_parameters_wheat.peduncle.curvature = -100;
-
2876 phytomer_parameters_wheat.peduncle.radial_subdivisions = 6;
-
2877
-
2878 phytomer_parameters_wheat.inflorescence.flowers_per_peduncle = 1;
-
2879 phytomer_parameters_wheat.inflorescence.pitch = 0;
-
2880 phytomer_parameters_wheat.inflorescence.roll = 0;
-
2881 phytomer_parameters_wheat.inflorescence.fruit_prototype_scale = 0.1;
-
2882 phytomer_parameters_wheat.inflorescence.fruit_prototype_function = WheatSpikePrototype;
-
2883
-
2884 phytomer_parameters_wheat.phytomer_creation_function = WheatPhytomerCreationFunction;
-
2885
-
2886 // ---- Shoot Parameters ---- //
-
2887
-
2888 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
-
2889 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_wheat;
-
2890 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
-
2891 shoot_parameters_mainstem.flower_bud_break_probability = 1;
-
2892 shoot_parameters_mainstem.phyllochron_min = 2;
-
2893 shoot_parameters_mainstem.elongation_rate = 0.1;
-
2894 shoot_parameters_mainstem.girth_area_factor = 6.f;
-
2895 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-500,-200);
-
2896 shoot_parameters_mainstem.flowers_require_dormancy = false;
-
2897 shoot_parameters_mainstem.growth_requires_dormancy = false;
-
2898 shoot_parameters_mainstem.determinate_shoot_growth = false;
-
2899 shoot_parameters_mainstem.fruit_set_probability = 1.0;
-
2900 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
-
2901 shoot_parameters_mainstem.max_nodes = 20;
-
2902 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
-
2903
-
2904 defineShootType("mainstem",shoot_parameters_mainstem);
-
2905
-
2906}
-
2907
-
2908uint PlantArchitecture::buildWheatPlant(const helios::vec3 &base_position) {
-
2909
-
2910 if (shoot_types.empty()) {
-
2911 //automatically initialize wheat plant shoots
-
2912 initializeWheatShoots();
-
2913 }
-
2914
-
2915 uint plantID = addPlantInstance(base_position - make_vec3(0,0,0.025), 0);
-
2916
-
2917 uint uID_stem = addBaseStemShoot(plantID, 1, 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.001, 0.025, 0.01, 0.01, 0, "mainstem");
-
2918
-
2919 breakPlantDormancy(plantID);
+
2865 // Proleptic shoots
+
2866 ShootParameters shoot_parameters_proleptic(context_ptr->getRandomGenerator());
+
2867 shoot_parameters_proleptic.phytomer_parameters = phytomer_parameters_walnut;
+
2868 shoot_parameters_proleptic.phytomer_parameters.internode.color = make_RGBcolor(0.3,0.2,0.2);
+
2869 shoot_parameters_proleptic.phytomer_parameters.phytomer_creation_function = WalnutPhytomerCreationFunction;
+
2870 // shoot_parameters_proleptic.phytomer_parameters.phytomer_callback_function = WalnutPhytomerCallbackFunction;
+
2871 shoot_parameters_proleptic.max_nodes = 30;
+
2872 shoot_parameters_proleptic.max_nodes_per_season = 15;
+
2873 shoot_parameters_proleptic.phyllochron_min = 2.;
+
2874 shoot_parameters_proleptic.elongation_rate_max = 0.15;
+
2875 shoot_parameters_proleptic.girth_area_factor = 10.f;
+
2876 shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.05;
+
2877 shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.6;
+
2878 shoot_parameters_proleptic.vegetative_bud_break_time = 3;
+
2879 shoot_parameters_proleptic.gravitropic_curvature = 200;
+
2880 shoot_parameters_proleptic.tortuosity = 5;
+
2881 shoot_parameters_proleptic.insertion_angle_tip.uniformDistribution( 20, 25);
+
2882 shoot_parameters_proleptic.insertion_angle_decay_rate = 15;
+
2883 shoot_parameters_proleptic.internode_length_max = 0.08;
+
2884 shoot_parameters_proleptic.internode_length_min = 0.01;
+
2885 shoot_parameters_proleptic.internode_length_decay_rate = 0.006;
+
2886 shoot_parameters_proleptic.fruit_set_probability = 0.5;
+
2887 shoot_parameters_proleptic.flower_bud_break_probability = 0.3;
+
2888 shoot_parameters_proleptic.max_terminal_floral_buds = 4;
+
2889 shoot_parameters_proleptic.flowers_require_dormancy = true;
+
2890 shoot_parameters_proleptic.growth_requires_dormancy = true;
+
2891 shoot_parameters_proleptic.determinate_shoot_growth = false;
+
2892 shoot_parameters_proleptic.defineChildShootTypes({"proleptic"},{1.0});
+
2893
+
2894 // Main scaffolds
+
2895 ShootParameters shoot_parameters_scaffold = shoot_parameters_proleptic;
+
2896 shoot_parameters_scaffold.phytomer_parameters.internode.radial_subdivisions = 10;
+
2897 shoot_parameters_scaffold.max_nodes = 30;
+
2898 shoot_parameters_scaffold.gravitropic_curvature = 300;
+
2899 shoot_parameters_scaffold.internode_length_max = 0.06;
+
2900 shoot_parameters_scaffold.tortuosity = 4;
+
2901 shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0});
+
2902
+
2903 defineShootType("trunk", shoot_parameters_trunk);
+
2904 defineShootType("scaffold", shoot_parameters_scaffold);
+
2905 defineShootType("proleptic", shoot_parameters_proleptic);
+
2906
+
2907}
+
2908
+
2909uint PlantArchitecture::buildWalnutTree(const helios::vec3 &base_position) {
+
2910
+
2911 if( shoot_types.empty() ){
+
2912 //automatically initialize walnut tree shoots
+
2913 initializeWalnutTreeShoots();
+
2914 }
+
2915
+
2916 uint plantID = addPlantInstance(base_position, 0);
+
2917
+
2918 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), 0.f * M_PI), shoot_types.at("trunk").phytomer_parameters.internode.radius_initial.val(), 0.04, 1.f, 1.f, 0, "trunk");
+
2919 appendPhytomerToShoot( plantID, uID_trunk, shoot_types.at("trunk").phytomer_parameters, 0, 0.01, 1, 1);
2920
-
2921 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 10, 1000, false);
+
2921 plant_instances.at(plantID).shoot_tree.at(uID_trunk)->meristem_is_alive = false;
2922
-
2923 plant_instances.at(plantID).max_age = 365;
-
2924
-
2925 return plantID;
-
2926
-
2927}
+
2923 auto phytomers = plant_instances.at(plantID).shoot_tree.at(uID_trunk)->phytomers;
+
2924 for( const auto & phytomer : phytomers ){
+
2925 phytomer->removeLeaf();
+
2926 phytomer->setVegetativeBudState(BUD_DEAD);
+
2927 phytomer->setFloralBudState(BUD_DEAD);
+
2928 }
+
2929
+
2930 uint Nscaffolds = 4;//context_ptr->randu(4,5);
+
2931
+
2932 for( int i=0; i<Nscaffolds; i++ ) {
+
2933// float pitch = context_ptr->randu(deg2rad(25), deg2rad(35))+i*deg2rad(7.f);
+
2934 float pitch = context_ptr->randu(deg2rad(45), deg2rad(55));
+
2935 uint uID_shoot = addChildShoot( plantID, uID_trunk, getShootNodeCount(plantID,uID_trunk)-i-1, context_ptr->randu(7, 9), 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);
+
2936
+
2937 }
+
2938
+
2939 makePlantDormant(plantID);
+
2940
+
2941 setPlantPhenologicalThresholds(plantID, 165, -1, 3, 7, 20, 200, false);
+
2942
+
2943 plant_instances.at(plantID).max_age = 1095;
+
2944
+
2945 return plantID;
+
2946
+
2947}
+
2948
+
2949void PlantArchitecture::initializeWheatShoots() {
+
2950
+
2951 // ---- Leaf Prototype ---- //
+
2952
+
2953 LeafPrototype leaf_prototype(context_ptr->getRandomGenerator());
+
2954 leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/SorghumLeaf.png";
+
2955 leaf_prototype.leaf_aspect_ratio = 0.1f;
+
2956 leaf_prototype.midrib_fold_fraction = 0.3f;
+
2957 leaf_prototype.longitudinal_curvature.uniformDistribution(-0.5, -0.1);
+
2958 leaf_prototype.lateral_curvature = -0.3;
+
2959 leaf_prototype.petiole_roll = 0.04f;
+
2960 leaf_prototype.wave_period = 0.1f;
+
2961 leaf_prototype.wave_amplitude = 0.1f;
+
2962 leaf_prototype.leaf_buckle_length.uniformDistribution(0.5,0.6);
+
2963 leaf_prototype.leaf_buckle_angle.uniformDistribution(25,35);
+
2964 leaf_prototype.subdivisions = 20;
+
2965 leaf_prototype.unique_prototypes = 10;
+
2966
+
2967 // ---- Phytomer Parameters ---- //
+
2968
+
2969 PhytomerParameters phytomer_parameters_wheat(context_ptr->getRandomGenerator());
+
2970
+
2971 phytomer_parameters_wheat.internode.pitch = 0;
+
2972 phytomer_parameters_wheat.internode.phyllotactic_angle.uniformDistribution(67,77);
+
2973 phytomer_parameters_wheat.internode.radius_initial = 0.001;
+
2974 phytomer_parameters_wheat.internode.color = make_RGBcolor(0.27,0.31,0.16);
+
2975 phytomer_parameters_wheat.internode.length_segments = 1;
+
2976 phytomer_parameters_wheat.internode.radial_subdivisions = 6;
+
2977 phytomer_parameters_wheat.internode.max_floral_buds_per_petiole = 0;
+
2978 phytomer_parameters_wheat.internode.max_vegetative_buds_per_petiole = 0;
+
2979
+
2980 phytomer_parameters_wheat.petiole.petioles_per_internode = 1;
+
2981 phytomer_parameters_wheat.petiole.pitch.uniformDistribution(-40,-20);
+
2982 phytomer_parameters_wheat.petiole.radius = 0.0;
+
2983 phytomer_parameters_wheat.petiole.length = 0.005;
+
2984 phytomer_parameters_wheat.petiole.taper = 0;
+
2985 phytomer_parameters_wheat.petiole.curvature = 0;
+
2986 phytomer_parameters_wheat.petiole.length_segments = 1;
+
2987
+
2988 phytomer_parameters_wheat.leaf.leaves_per_petiole = 1;
+
2989 phytomer_parameters_wheat.leaf.pitch = 0;
+
2990 phytomer_parameters_wheat.leaf.yaw = 0;
+
2991 phytomer_parameters_wheat.leaf.roll = 0;
+
2992 phytomer_parameters_wheat.leaf.prototype_scale = 0.22;
+
2993 phytomer_parameters_wheat.leaf.prototype = leaf_prototype;
+
2994
+
2995 phytomer_parameters_wheat.peduncle.length = 0.1;
+
2996 phytomer_parameters_wheat.peduncle.radius = 0.002;
+
2997 phytomer_parameters_wheat.peduncle.color = phytomer_parameters_wheat.internode.color;
+
2998 phytomer_parameters_wheat.peduncle.curvature = -100;
+
2999 phytomer_parameters_wheat.peduncle.radial_subdivisions = 6;
+
3000
+
3001 phytomer_parameters_wheat.inflorescence.flowers_per_peduncle = 1;
+
3002 phytomer_parameters_wheat.inflorescence.pitch = 0;
+
3003 phytomer_parameters_wheat.inflorescence.roll = 0;
+
3004 phytomer_parameters_wheat.inflorescence.fruit_prototype_scale = 0.1;
+
3005 phytomer_parameters_wheat.inflorescence.fruit_prototype_function = WheatSpikePrototype;
+
3006
+
3007 phytomer_parameters_wheat.phytomer_creation_function = WheatPhytomerCreationFunction;
+
3008
+
3009 // ---- Shoot Parameters ---- //
+
3010
+
3011 ShootParameters shoot_parameters_mainstem(context_ptr->getRandomGenerator());
+
3012 shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_wheat;
+
3013 shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0;
+
3014 shoot_parameters_mainstem.flower_bud_break_probability = 1;
+
3015 shoot_parameters_mainstem.phyllochron_min = 2;
+
3016 shoot_parameters_mainstem.elongation_rate_max = 0.1;
+
3017 shoot_parameters_mainstem.girth_area_factor = 6.f;
+
3018 shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-500,-200);
+
3019 shoot_parameters_mainstem.flowers_require_dormancy = false;
+
3020 shoot_parameters_mainstem.growth_requires_dormancy = false;
+
3021 shoot_parameters_mainstem.determinate_shoot_growth = false;
+
3022 shoot_parameters_mainstem.fruit_set_probability = 1.0;
+
3023 shoot_parameters_mainstem.defineChildShootTypes({"mainstem"},{1.0});
+
3024 shoot_parameters_mainstem.max_nodes = 20;
+
3025 shoot_parameters_mainstem.max_terminal_floral_buds = 1;
+
3026
+
3027 defineShootType("mainstem",shoot_parameters_mainstem);
+
3028
+
3029}
+
3030
+
3031uint PlantArchitecture::buildWheatPlant(const helios::vec3 &base_position) {
+
3032
+
3033 if (shoot_types.empty()) {
+
3034 //automatically initialize wheat plant shoots
+
3035 initializeWheatShoots();
+
3036 }
+
3037
+
3038 uint plantID = addPlantInstance(base_position - make_vec3(0,0,0.025), 0);
+
3039
+
3040 uint uID_stem = addBaseStemShoot(plantID, 1, 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.001, 0.025, 0.01, 0.01, 0, "mainstem");
+
3041
+
3042 breakPlantDormancy(plantID);
+
3043
+
3044 setPlantPhenologicalThresholds(plantID, 0, -1, -1, 4, 10, 1000, false);
+
3045
+
3046 plant_instances.at(plantID).max_age = 365;
+
3047
+
3048 return plantID;
+
3049
+
3050}
-
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_dormancy, float max_leaf_lifespan=1e6, bool is_evergreen=false)
Specify the threshold values for plant phenological stages.
-
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 advanceTime(float time_step_days)
Advance plant growth by a specified time interval for all plants.
-
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_dormancy, float max_leaf_lifespan=1e6, bool is_evergreen=false)
Specify the threshold values for plant phenological stages.
+
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 advanceTime(float time_step_days)
Advance plant growth by a specified time interval for all plants.
+
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 defineShootType(const std::string &shoot_type_label, const ShootParameters &shoot_params)
Define a new shoot type based on a set of ShootParameters.
-
std::map< std::string, PhytomerParameters > getCurrentPhytomerParameters()
Get the phytomer parameters structure for all shoot types in the current plant model.
+
std::map< std::string, PhytomerParameters > getCurrentPhytomerParameters()
Get the phytomer parameters structure for all shoot types in the current plant model.
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.
-
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
-
std::minstd_rand0 * getRandomGenerator()
Get the random number generator engine.
Definition Context.cpp:49
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
float deg2rad(float deg)
Convert degrees to radians.
Definition global.cpp:576
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor vector.
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
- -
std::map< int, std::string > leaf_texture_file
Image texture file for the leaf.
uint unique_prototypes
Number of unique prototypes to generate.
-
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)
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_plug_ins.html b/doc/html/_plug_ins.html index 967da26b0..831efe3a3 100644 --- a/doc/html/_plug_ins.html +++ b/doc/html/_plug_ins.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Plug-ins
@@ -126,10 +136,12 @@
- - + + diff --git a/doc/html/_plug_ins.js b/doc/html/_plug_ins.js new file mode 100644 index 000000000..79ba92f25 --- /dev/null +++ b/doc/html/_plug_ins.js @@ -0,0 +1,320 @@ +var _plug_ins = +[ + [ "Visualizer Plugin Documentation", "_visualizer_doc.html", [ + [ "Dependencies", "_visualizer_doc.html#VisDepends", null ], + [ "Known Issues", "_visualizer_doc.html#VisIssues", null ], + [ "Introduction", "_visualizer_doc.html#VisIntro", null ], + [ "Class Constructor(s)", "_visualizer_doc.html#VisClass", null ], + [ "Using the Visualizer Plug-in", "_visualizer_doc.html#UseVis", [ + [ "Coordinate Systems", "_visualizer_doc.html#coord", null ], + [ "Visualization Window", "_visualizer_doc.html#Window", null ], + [ "Window background", "_visualizer_doc.html#Background", null ], + [ "Adding Geometry", "_visualizer_doc.html#AddGeom", [ + [ "Automatically importing Context geometry", "_visualizer_doc.html#ContextGeom", null ] + ] ], + [ "Plotting Geometry", "_visualizer_doc.html#PlotWindow", [ + [ "plotInteractive()", "_visualizer_doc.html#PlotInteractive", null ], + [ "View Controls", "_visualizer_doc.html#ViewControls", null ], + [ "plotUpdate()", "_visualizer_doc.html#PlotUpdate", null ] + ] ], + [ "Colors and Shading", "_visualizer_doc.html#ColorShade", [ + [ "Coloring by r-g-b code", "_visualizer_doc.html#ColoringRGB", null ], + [ "Coloring by texture map", "_visualizer_doc.html#ColoringTexture", null ], + [ "Coloring by pseudocolor map", "_visualizer_doc.html#ColoringPseudo", null ], + [ "Colorbar", "_visualizer_doc.html#Cbar", null ], + [ "Shading", "_visualizer_doc.html#Shading", null ] + ] ], + [ "View Options", "_visualizer_doc.html#Options", null ] + ] ], + [ "Acknowledgements", "_visualizer_doc.html#VisAcklowledgements", null ] + ] ], + [ "Weber-Penn Tree Plugin Documentation", "_weber_penn_doc.html", [ + [ "Known Issues", "_weber_penn_doc.html#WPTissues", null ], + [ "Introduction", "_weber_penn_doc.html#WPTreeIntro", null ], + [ "WeberPennTree Class Constructor", "_weber_penn_doc.html#WPTConstructor", null ], + [ "Using the Weber-Penn Tree Plug-in", "_weber_penn_doc.html#WPTreeUse", [ + [ "The XML Tree Library File", "_weber_penn_doc.html#WPTLibrary", null ], + [ "Adding Trees from the Tree Library", "_weber_penn_doc.html#WPTadd", null ], + [ "Custom Tree Library Files", "_weber_penn_doc.html#WPTCustom", null ] + ] ], + [ "Creating Custom XML Files", "_weber_penn_doc.html#WPTreeXML", [ + [ "General Overview", "_weber_penn_doc.html#WPTOverview", null ], + [ "Trunk and general tree shape", "_weber_penn_doc.html#WPTreeShape", null ], + [ "Recursive Branches", "_weber_penn_doc.html#WPTreeR1", null ], + [ "Leaves", "_weber_penn_doc.html#WPTreeLeaves", [ + [ "Leaf mask", "_weber_penn_doc.html#WPTreeMask", null ] + ] ], + [ "User-Defined Leaf Angle Distribution Functions", "_weber_penn_doc.html#WPTgL", null ] + ] ] + ] ], + [ "Radiation Model Plugin Documentation", "_radiation_doc.html", [ + [ "Dependencies", "_radiation_doc.html#RadDepends", null ], + [ "Introduction", "_radiation_doc.html#RadIntro", null ], + [ "RadiationModel Class Constructor", "_radiation_doc.html#RadConstructor", null ], + [ "Input/Output Primitive Data", "_radiation_doc.html#RadVarsAndProps", [ + [ "Input Primitive Data", "_radiation_doc.html#RadInputData", null ], + [ "Output Primitive Data", "_radiation_doc.html#RadOutputData", null ] + ] ], + [ "Using the Radiation Model Plug-In", "_radiation_doc.html#RadUse", [ + [ "Model Class Constructor", "_radiation_doc.html#RadConst", null ], + [ "Area Basis for Calculating Fluxes", "_radiation_doc.html#RadTwoSided", null ], + [ "Defining Wavelength Bands", "_radiation_doc.html#RadBands", null ], + [ "Input Spectral Data", "_radiation_doc.html#InputSpectra", null ], + [ "Radiative Properties", "_radiation_doc.html#RadProps", null ], + [ "Radiative Emission", "_radiation_doc.html#RadEmission", null ], + [ "External Radiation Sources", "_radiation_doc.html#RadSources", [ + [ "Adding Collimated Sources", "_radiation_doc.html#ColSource", null ], + [ "Adding Spherical Sun Source", "_radiation_doc.html#SunSphereSource", null ], + [ "Adding Spherical Radiation Sources", "_radiation_doc.html#PointSource", null ], + [ "Adding Disk Radiation Sources", "_radiation_doc.html#DiskSource", null ], + [ "Adding Rectangular Radiation Sources", "_radiation_doc.html#RectSource", null ], + [ "Setting the Radiation Source Spectral Distribution and Normalization", "_radiation_doc.html#SourceDist", null ], + [ "Adding Diffuse/Ambient Sources", "_radiation_doc.html#AmbSource", null ] + ] ], + [ "Scattering Iterations", "_radiation_doc.html#RadScatter", null ], + [ "Periodic Boundary Conditions", "_radiation_doc.html#RadPeriodic", null ], + [ "Radiation Cameras", "_radiation_doc.html#RadCam", [ + [ "Adding a Radiation Camera", "_radiation_doc.html#RadCamAdd", null ], + [ "Radiation Camera Color Calibration", "_radiation_doc.html#RadCamCalibColor", null ] + ] ], + [ "Running Simulations", "_radiation_doc.html#RadRun", null ], + [ "Integrating with the SolarPosition Plug-in", "_radiation_doc.html#RadSolar", null ], + [ "Model Outputs", "_radiation_doc.html#ModelOutputs", [ + [ "Visualizing Model Outputs using the Visualizer Plug-In", "_radiation_doc.html#RadVis", null ], + [ "Integrating Fluxes", "_radiation_doc.html#RadDataInt", null ], + [ "Writing Camera Images to File", "_radiation_doc.html#RadCamOut", null ] + ] ] + ] ] + ] ], + [ "Energy Balance Model Plugin Documentation", "_energy_balance_doc.html", [ + [ "Dependencies", "_energy_balance_doc.html#EBDepends", null ], + [ "Known Issues", "_energy_balance_doc.html#EBissues", null ], + [ "Introduction", "_energy_balance_doc.html#EBIntro", null ], + [ "EnergyBalanceModel Class Constructor", "_energy_balance_doc.html#EBConstructor", null ], + [ "Input/Output Primitive Data", "_energy_balance_doc.html#EBData", [ + [ "Input Primitive Data", "_energy_balance_doc.html#EBInputData", null ], + [ "Default Output Primitive Data", "_energy_balance_doc.html#EBOutputData", null ], + [ "Optional Output Primitive Data", "_energy_balance_doc.html#EBOptionalOutputData", null ] + ] ], + [ "Using the Energy Balance Model Plug-in", "_energy_balance_doc.html#EBUse", [ + [ "Input Variables", "_energy_balance_doc.html#EBPrimData", null ], + [ "Input Radiative Bands", "_energy_balance_doc.html#EBRad", null ], + [ "Boundary-layer Conductance Model", "_energy_balance_doc.html#EBblc", null ], + [ "Moisture Conductance", "_energy_balance_doc.html#EBgm", null ], + [ "Running the Steady-State Model", "_energy_balance_doc.html#EBRun", [ + [ "Unsteady model with heat storage", "_energy_balance_doc.html#EBRunUS", null ] + ] ] + ] ] + ] ], + [ "Boundary-Layer Conductance Model Plugin Documentation", "_b_l_conductance_doc.html", [ + [ "Known Issues", "_b_l_conductance_doc.html#BLCissues", null ], + [ "Introduction", "_b_l_conductance_doc.html#BLCIntro", null ], + [ "BLConductanceModel Class Constructor", "_b_l_conductance_doc.html#BLCConstructor", null ], + [ "Input/Output Primitive Data", "_b_l_conductance_doc.html#BLCData", [ + [ "Input Primitive Data", "_b_l_conductance_doc.html#BLCInputData", null ], + [ "Default Output Primitive Data", "_b_l_conductance_doc.html#BLOutputData", null ] + ] ], + [ "Using the Boundary Layer Conductance Model Plug-in", "_b_l_conductance_doc.html#BLUse", [ + [ "Input Variables", "_b_l_conductance_doc.html#BLPrimData", null ], + [ "Boundary-layer Conductance Models", "_b_l_conductance_doc.html#BLCModels", [ + [ "The Polhausen Equation (Laminar Flat Plate, Forced Convection)", "_b_l_conductance_doc.html#BLC1", null ], + [ "Laminar Inclined Plate, Mixed Free-Forced Convection", "_b_l_conductance_doc.html#BLC2", null ], + [ "Laminar flow around a sphere", "_b_l_conductance_doc.html#BLC3", null ], + [ "Flow over bare ground", "_b_l_conductance_doc.html#BLC4", null ] + ] ], + [ "Setting the Boundary-layer Conductance Model To Be Used", "_b_l_conductance_doc.html#BLCSet", null ], + [ "Running the Model", "_b_l_conductance_doc.html#BLCRun", null ] + ] ] + ] ], + [ "LiDAR Point Cloud Plugin Documentation", "_li_d_a_r_doc.html", [ + [ "Known Issues", "_li_d_a_r_doc.html#LiDARissues", null ], + [ "Introduction", "_li_d_a_r_doc.html#LiDARintro", null ], + [ "Dependencies", "_li_d_a_r_doc.html#LiDARdepends", null ], + [ "Class Constructor", "_li_d_a_r_doc.html#LiDARConstructor", null ], + [ "Input Primitive Data", "_li_d_a_r_doc.html#LiDARInputData", null ], + [ "Background information", "_li_d_a_r_doc.html#LiDARbg", [ + [ "Coordinates and scan pattern", "_li_d_a_r_doc.html#LiDARcoord", null ], + [ "Difference between discrete-return and full-waveform LiDAR data", "_li_d_a_r_doc.html#LiDARreturn", null ], + [ "Scan metadata", "_li_d_a_r_doc.html#ScanMetadata", null ], + [ "Hit point data", "_li_d_a_r_doc.html#AddHits", null ] + ] ], + [ "Loading scan data from file", "_li_d_a_r_doc.html#ScanIO", null ], + [ "Establishing grid cells", "_li_d_a_r_doc.html#LiDARgrid", null ], + [ "Processing LiDAR data", "_li_d_a_r_doc.html#LiDARprocess", [ + [ "Hit point triangulation", "_li_d_a_r_doc.html#LiDARtri", null ], + [ "Calculating leaf area for each grid cell", "_li_d_a_r_doc.html#LiDARleafarea", null ], + [ "Plant reconstruction", "_li_d_a_r_doc.html#LiDARresonstruction", null ] + ] ], + [ "Generating Synthetic (Simulated) LiDAR Data", "_li_d_a_r_doc.html#LiDARsynthetic", [ + [ "XML parameter file", "_li_d_a_r_doc.html#LiDARsynthxml", null ], + [ "Synthetic discrete-return data", "_li_d_a_r_doc.html#LiDARsynthdiscrete", null ], + [ "Synthetic waveform data", "_li_d_a_r_doc.html#LiDARsynthwaveform", null ] + ] ], + [ "Visualizing results", "_li_d_a_r_doc.html#LiDARvis", null ], + [ "Writing results to file", "_li_d_a_r_doc.html#LiDARoutput", null ] + ] ], + [ "Aerial LiDAR Point Cloud Plugin Documentation", "_aerial_li_d_a_r_doc.html", [ + [ "Known Issues", "_aerial_li_d_a_r_doc.html#AerialLiDARissues", null ], + [ "Introduction", "_aerial_li_d_a_r_doc.html#AerialLiDARintro", null ], + [ "Dependencies", "_aerial_li_d_a_r_doc.html#AerialLiDARdepends", null ], + [ "Class Constructor", "_aerial_li_d_a_r_doc.html#AerialLiDARConstructor", null ], + [ "Background information", "_aerial_li_d_a_r_doc.html#AerialLiDARbg", [ + [ "Coordinates and scan pattern", "_aerial_li_d_a_r_doc.html#AerialLiDARcoord", null ], + [ "Difference between discrete-return and full-waveform LiDAR data", "_aerial_li_d_a_r_doc.html#AerialLiDARreturn", null ] + ] ], + [ "Data processing setup", "_aerial_li_d_a_r_doc.html#AerialSetup", null ], + [ "Loading scan data from file", "_aerial_li_d_a_r_doc.html#AerialScanIO", null ], + [ "Establishing grid cells", "_aerial_li_d_a_r_doc.html#AerialLiDARgrid", null ], + [ "Processing LiDAR data", "_aerial_li_d_a_r_doc.html#AerialLiDARprocess", [ + [ "2D raster height maps", "_aerial_li_d_a_r_doc.html#AerialRasters", null ], + [ "2D raster ground cover fraction", "_aerial_li_d_a_r_doc.html#AerialGroundCover", null ], + [ "Leaf area", "_aerial_li_d_a_r_doc.html#AerialLeafArea", null ] + ] ] + ] ], + [ "Photosynthesis Model Plugin Documentation", "_photosynthesis_doc.html", [ + [ "Class Constructor", "_photosynthesis_doc.html#PhotoConstructor", null ], + [ "Primitive Data", "_photosynthesis_doc.html#PhotoVarsAndProps", [ + [ "Input Primitive Data", "_photosynthesis_doc.html#PhotoInputData", null ], + [ "Default Output Primitive Data", "_photosynthesis_doc.html#PhotoOutputData", null ], + [ "Optional Output Primitive Data", "_photosynthesis_doc.html#PhotoOptionalOutputData", null ] + ] ], + [ "Introduction", "_photosynthesis_doc.html#PhotoDescription", null ], + [ "Farquhar, von Caemmerer, Berry Model Description", "_photosynthesis_doc.html#FarquharDescription", [ + [ "Temperature response of model parameters", "_photosynthesis_doc.html#FvCBtemperature", [ + [ "Summary of FvCB Model Independent Variables", "_photosynthesis_doc.html#FvCBPhotoVars", null ], + [ "Summary of FvCB Model Parameters", "_photosynthesis_doc.html#FvCBPhotoParams", null ], + [ "Setting FvCB Model Parameters", "_photosynthesis_doc.html#FvCBSettingPhotoParams", null ] + ] ] + ] ], + [ "Empirical Model Description", "_photosynthesis_doc.html#EmpiricalDescription", [ + [ "Light Response Function", "_photosynthesis_doc.html#LightResponse", null ], + [ "Temperature Response", "_photosynthesis_doc.html#TempResponse", null ], + [ "CO2 Response Function", "_photosynthesis_doc.html#CO2Response", null ], + [ "Intercellular CO2 Concentration", "_photosynthesis_doc.html#Ci", null ], + [ "Empirical Model Calibration Procedure", "_photosynthesis_doc.html#PhotoCalib", [ + [ "Summary of Empirical Model Independent Variables", "_photosynthesis_doc.html#PhotoVars", null ], + [ "Summary of Empirical Model Parameters", "_photosynthesis_doc.html#PhotoParams", null ], + [ "Response of Assimilation Rate to Light", "_photosynthesis_doc.html#PhotoLightParam", null ], + [ "Response of Assimilation Rate to Temperature", "_photosynthesis_doc.html#PhotoTempParam", null ], + [ "Response of Respiration Rate to Temperature", "_photosynthesis_doc.html#PhotoRespParam", null ], + [ "Response of Assimilation Rate to CO2", "_photosynthesis_doc.html#PhotoCO2Param", null ] + ] ] + ] ] + ] ], + [ "Stomatal Conductance Model Plugin Documentation", "_stomatal_doc.html", [ + [ "Class Constructor", "_stomatal_doc.html#StomataConstructor", null ], + [ "Primitive Data", "_stomatal_doc.html#VarsAndProps", [ + [ "Input Primitive Data", "_stomatal_doc.html#StomatalInputData", null ], + [ "Output Primitive Data", "_stomatal_doc.html#StomatalOutputData", null ] + ] ], + [ "Introduction", "_stomatal_doc.html#StomatalIntro", null ], + [ "Ball, Woodrow, Berry (1987) Model Theory", "_stomatal_doc.html#BWBTheory", null ], + [ "Ball-Berry-Leuning Model Theory", "_stomatal_doc.html#BBLTheory", null ], + [ "Medlyn et al. (2011) Optimality-Based Model", "_stomatal_doc.html#MoptTheory", null ], + [ "Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull,...", "_stomatal_doc.html#BMFTheory", null ], + [ "Using the Stomatal Conductance Model", "_stomatal_doc.html#StomatalUse", [ + [ "Setting the Model Coefficients", "_stomatal_doc.html#StomatalCoeffs", null ], + [ "Running the Model (steady-state mode)", "_stomatal_doc.html#StomatalRun", null ], + [ "Running the Model in Dynamic Mode", "_stomatal_doc.html#StomatalRunDyn", null ] + ] ] + ] ], + [ "Solar Position Plugin Documentation", "_solar_position_doc.html", [ + [ "Introduction", "_solar_position_doc.html#SolarIntro", null ], + [ "SolarPosition Class Constructor", "_solar_position_doc.html#SolarConstructor", null ], + [ "Model Theory", "_solar_position_doc.html#SolarTheory", [ + [ "Position of the Sun", "_solar_position_doc.html#SolarPosTheory", null ], + [ "Direct and Diffuse Solar Flux", "_solar_position_doc.html#SolarFluxTheory", null ], + [ "Ambient Longwave Flux", "_solar_position_doc.html#LWTheory", null ] + ] ], + [ "Using the SolarPosition Plug-in", "_solar_position_doc.html#SolarLib", [ + [ "Getting the Direction of the Sun", "_solar_position_doc.html#SolarPos", null ], + [ "Getting the Solar Flux", "_solar_position_doc.html#SolarFlux", [ + [ "Calibrating the turbidity using weather station (radiometer) data", "_solar_position_doc.html#SolarFluxTurb", null ], + [ "Incorporating the effects of clouds", "_solar_position_doc.html#SolarFluxClouds", null ] + ] ], + [ "Getting the Sky Longwave Flux", "_solar_position_doc.html#LWFlux", null ] + ] ] + ] ], + [ "Voxel Intersection Plugin Documentation", "_voxel_intersection_doc.html", [ + [ "Dependencies", "_voxel_intersection_doc.html#VoxelIntersectionDepends", null ], + [ "Known Issues", "_voxel_intersection_doc.html#VoxelIssues", null ], + [ "Class Constructor", "_voxel_intersection_doc.html#VoxelIntersectionConstructor", null ], + [ "Variables and Primitive Data", "_voxel_intersection_doc.html#VoxVarsAndProps", [ + [ "Output Primitive Data", "_voxel_intersection_doc.html#VoxelIntersectionOutputData", null ] + ] ], + [ "Introduction", "_voxel_intersection_doc.html#VoxelIntersectionIntro", null ], + [ "Using the Plug-In", "_voxel_intersection_doc.html#VoxelIntersectionUse", null ] + ] ], + [ "Canopy Generator Plugin Documentation", "_canopy_generator_doc.html", [ + [ "Introduction", "_canopy_generator_doc.html#Introduction", null ], + [ "CanopyGenerator Class Constructor", "_canopy_generator_doc.html#CGenConstructor", null ], + [ "Available Geometries and Parameters", "_canopy_generator_doc.html#CGenGeometries", [ + [ "Spatially Homogeneous Canopy", "_canopy_generator_doc.html#CGenHomogeneous", null ], + [ "Canopy of Spherical Crowns", "_canopy_generator_doc.html#CGenSphere", null ], + [ "Canopy of Conical Crowns", "_canopy_generator_doc.html#CGenCone", null ], + [ "Grapevine Canopy with VSP Trellis", "_canopy_generator_doc.html#CGenVSP", null ], + [ "Grapevine Canopy with a Split Trellis", "_canopy_generator_doc.html#CGenSplit", null ], + [ "Grapevine Canopy with a Unilateral VSP Trellis", "_canopy_generator_doc.html#CGenUnilateral", null ], + [ "Grapevine Canopy with a Goblet Trellis", "_canopy_generator_doc.html#CGenGoblet", null ], + [ "Strawberry Canopy", "_canopy_generator_doc.html#CGenStrawberry", null ], + [ "Walnut Canopy", "_canopy_generator_doc.html#CGenWalnut", null ], + [ "sorghum Canopy", "_canopy_generator_doc.html#CGenSorghum", null ] + ] ], + [ "Building the Ground", "_canopy_generator_doc.html#CGenBuildGround", null ], + [ "Building an Individual Plant", "_canopy_generator_doc.html#CGenBuildPlant", null ], + [ "Building a Canopy", "_canopy_generator_doc.html#CGenBuildCanopy", null ], + [ "Retrieving UUIDs for Primitives", "_canopy_generator_doc.html#CGenUUIDs", null ], + [ "Modifying Geometric Parameters from Default Values", "_canopy_generator_doc.html#CGenParameterMod", null ], + [ "Seeding the Random Number Generator", "_canopy_generator_doc.html#CGenSeed", null ] + ] ], + [ "Plant Architecture Model Plugin Documentation", "_plant_architecture_doc.html", [ + [ "Class Constructor", "_plant_architecture_doc.html#PlantArchConstructor", null ], + [ "Primitive Data", "_plant_architecture_doc.html#PlantArchVarsAndProps", [ + [ "Optional Output Object Data", "_plant_architecture_doc.html#PlantArchOutputData", null ] + ] ], + [ "Plug-in Overview", "_plant_architecture_doc.html#PlantArchOverview", null ], + [ "Getting Started with the Existing Plant Library", "_plant_architecture_doc.html#PlantArchGettingStarted", [ + [ "Existing Plant Library", "_plant_architecture_doc.html#PlantArchBuild", null ], + [ "Loading a Plant from the Library with Default Parameters", "_plant_architecture_doc.html#PlantArchBuild_default", null ], + [ "Growing the Model over Time", "_plant_architecture_doc.html#PlantArchGrowth", null ], + [ "Growth Phenology", "_plant_architecture_doc.html#PlantArchPheno", null ], + [ "Ground Collision Detection", "_plant_architecture_doc.html#PlantArchCollision", null ] + ] ], + [ "Background Theory", "_plant_architecture_doc.html#PlantArchDescription", [ + [ "The Phytomer: Basic unit of a plant shoot", "_plant_architecture_doc.html#PlantArchPhytomer", null ], + [ "Coordinate System", "_plant_architecture_doc.html#PlantArchCoord", null ], + [ "Randomization of Parameters", "_plant_architecture_doc.html#PlantArchRandParam", null ] + ] ], + [ "Defining the Phytomer and its Parameters", "_plant_architecture_doc.html#PlantArchPhytomerParams", [ + [ "Creating Plant Organ Prototypes", "_plant_architecture_doc.html#PlantArchOrgans", [ + [ "Leaf Prototypes", "_plant_architecture_doc.html#LeafPrototypes", null ], + [ "Flower Prototypes", "_plant_architecture_doc.html#FlowerPrototypes", null ], + [ "Fruit Prototypes", "_plant_architecture_doc.html#FruitPrototypes", null ] + ] ], + [ "Compound Leaves", "_plant_architecture_doc.html#PlantArch_compound", null ], + [ "Inflorescence", "_plant_architecture_doc.html#PlantArch_flowers", null ] + ] ], + [ "Defining Shoots and their Parameters", "_plant_architecture_doc.html#PlantArchShoot", [ + [ "Geometric Parameters of the Shoot", "_plant_architecture_doc.html#ShootParametersGeom", [ + [ "max_nodes and max_nodes_per_season", "_plant_architecture_doc.html#ShootParam_max_nodes", null ], + [ "base_roll", "_plant_architecture_doc.html#ShootParam_base_roll", null ], + [ "insertion_angle_tip and insertion_angle_decay_rate", "_plant_architecture_doc.html#ShootParam_insertion", null ], + [ "internode_length_max, internode_length_min, and internode_length_decay_rate", "_plant_architecture_doc.html#ShootParam_length", null ], + [ "vegetative_bud_break_probability_min and vegetative_bud_break_probability_decay_rate", "_plant_architecture_doc.html#ShootParam_vegetative_prob", null ], + [ "gravitropic_curvature", "_plant_architecture_doc.html#ShootParam_gravitropic", null ], + [ "tortuosity", "_plant_architecture_doc.html#ShootParam_tortuosity", null ] + ] ], + [ "Growth Parameters of the Shoot", "_plant_architecture_doc.html#ShootParametersGrowth", [ + [ "phyllochron_min", "_plant_architecture_doc.html#ShootParam_phyllochron", null ], + [ "elongation_rate", "_plant_architecture_doc.html#ShootParam_elongation_rate", null ], + [ "girth_area_factor", "_plant_architecture_doc.html#ShootParam_girth_area_factor", null ], + [ "Modifying Parameters of a Plant from the Library", "_plant_architecture_doc.html#PlantArchBuild_custom", null ] + ] ], + [ "Modifying Phenological Threshold Parameters", "_plant_architecture_doc.html#PlantArchPhenoMod", null ] + ] ], + [ "Retrieving Information from the Model", "_plant_architecture_doc.html#PlantArchQuery", [ + [ "Getting Object IDs and Primitive UUIDs of Model Geometry", "_plant_architecture_doc.html#PlantArchQueryobjIDs", null ], + [ "Getting Primitive UUIDs for Organ Sub-Components", "_plant_architecture_doc.html#PlantArchQueryUUIDs", null ] + ] ] + ] ] +]; \ No newline at end of file diff --git a/doc/html/_plugins.html b/doc/html/_plugins.html index 0e0446624..343291ed1 100644 --- a/doc/html/_plugins.html +++ b/doc/html/_plugins.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Writing Plugins
@@ -141,10 +151,12 @@

This command prepends the variable 'PLUGIN_INCLUDE_PATHS' with the path to the include file. Note that multiple paths are separated by a semicolon.

- - + + diff --git a/doc/html/_radiation_doc.html b/doc/html/_radiation_doc.html index 3a4a06091..d935ac8a8 100644 --- a/doc/html/_radiation_doc.html +++ b/doc/html/_radiation_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Radiation Model Plugin Documentation
@@ -618,9 +624,9 @@

Context context; //Initialize Context
// add some geometry
-
context.addTile( make_vec3(0,0,0), make_vec2(10,10), make_SphericalCoord(0,0), make_int2(500,500) );
+
context.addTile( make_vec3(0,0,0), make_vec2(10,10), make_SphericalCoord(0,0), make_int2(500,500) );
-
context.addSphere( 50, make_vec3(0,0,2), 1 );
+
context.addSphere( 50, make_vec3(0,0,2), 1 );
// --- 2. Initialize the solar position model --- //
@@ -688,14 +694,18 @@

Class for visualization of simulation results.
Definition Visualizer.h:275
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
void setDate(int day, int month, int year)
Set simulation date by day, month, year.
Definition Context.cpp:1059
void setTime(int minute, int hour)
Set simulation time.
Definition Context.cpp:1136
-
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5646
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
+
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5673
+
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5836
void wait(float seconds)
Wait/sleep for a specified amount of time.
Definition global.cpp:306
+
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.
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
+
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.

Model Outputs

@@ -753,9 +763,9 @@

Context context;
-
std::vector<uint> UUIDs_bunny = context.loadPLY( "../../../PLY/StanfordBunny.ply", nullorigin, 1.f );
+
std::vector<uint> UUIDs_bunny = context.loadPLY( "../../../PLY/StanfordBunny.ply", nullorigin, 1.f );
-
std::vector<uint> UUIDs_ground = context.addTile( nullorigin, make_vec2(3,3), nullrotation, make_int2(200,200) );
+
std::vector<uint> UUIDs_ground = context.addTile( nullorigin, make_vec2(3,3), nullrotation, make_int2(200,200) );
// Set labels that we'll use to label pixels
context.setPrimitiveData( UUIDs_bunny, "bunny", 1 );
@@ -769,7 +779,7 @@

RadiationModel radiationmodel(&context);
// Add a sun sphere radiation source
-
uint source = radiationmodel.addSunSphereRadiationSource(make_SphericalCoord(deg2rad(90-50), deg2rad(40)));
+
uint source = radiationmodel.addSunSphereRadiationSource(make_SphericalCoord(deg2rad(90-50), deg2rad(40)));
// Set the solar spectrum to ASTMG173 from the library
radiationmodel.setSourceSpectrum( source, "solar_spectrum_direct_ASTMG173" );
@@ -817,6 +827,9 @@

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.
+
vec3 nullorigin
Default null vec3 that gives the origin (0,0,0)
Definition global.cpp:58
+
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
+
float deg2rad(float deg)
Convert degrees to radians.
Definition global.cpp:576
float focal_plane_distance
Distance from the viewing plane to the focal plane.

The above code would produce an image in the build directory called "camera_visible_myimage.jpeg", which is shown below, along with a file labels.txt that contains the primitive data labels for each pixel.

@@ -827,10 +840,13 @@

- - + + diff --git a/doc/html/_radiation_model_8cpp.html b/doc/html/_radiation_model_8cpp.html index 05ad9feb8..b343e63a2 100644 --- a/doc/html/_radiation_model_8cpp.html +++ b/doc/html/_radiation_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
@@ -154,7 +160,7 @@

-

Definition at line 5770 of file RadiationModel.cpp.

+

Definition at line 5795 of file RadiationModel.cpp.

@@ -173,15 +179,18 @@

-

Definition at line 5780 of file RadiationModel.cpp.

+

Definition at line 5805 of file RadiationModel.cpp.

- - + + diff --git a/doc/html/_radiation_model_8cpp_source.html b/doc/html/_radiation_model_8cpp_source.html index bf367ecf1..24367c50e 100644 --- a/doc/html/_radiation_model_8cpp_source.html +++ b/doc/html/_radiation_model_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
RadiationModel.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "RadiationModel.h"
17
18using namespace helios;
@@ -328,36 +335,36 @@
207 source.source_fluxes[label] = -1.f;
208 }
209
-
210}
-
+
210 radiativepropertiesneedupdate = true;
211
-
-
212void RadiationModel::addRadiationBand( const std::string &label, float wavelength1, float wavelength2 ){
+
212}
+
213
-
214 if( radiation_bands.find(label)!=radiation_bands.end() ){
-
215 std::cerr << "WARNING (RadiationModel::addRadiationBand): Radiation band " << label << " has already been added. Skipping this call to addRadiationBand()." << std::endl;
-
216 return;
-
217 }else if( wavelength1>wavelength2 ){
-
218 helios_runtime_error("ERROR (RadiationModel::addRadiationBand): The upper wavelength bound for a band must be greater than the lower bound.");
-
219 }else if( wavelength2-wavelength1<1 ){
-
220 helios_runtime_error("ERROR (RadiationModel::addRadiationBand): The waveband range of a radiation band must be at least 1 nm.");
-
221
-
222 }
+
+
214void RadiationModel::addRadiationBand( const std::string &label, float wavelength1, float wavelength2 ){
+
215
+
216 if( radiation_bands.find(label)!=radiation_bands.end() ){
+
217 std::cerr << "WARNING (RadiationModel::addRadiationBand): Radiation band " << label << " has already been added. Skipping this call to addRadiationBand()." << std::endl;
+
218 return;
+
219 }else if( wavelength1>wavelength2 ){
+
220 helios_runtime_error("ERROR (RadiationModel::addRadiationBand): The upper wavelength bound for a band must be greater than the lower bound.");
+
221 }else if( wavelength2-wavelength1<1 ){
+
222 helios_runtime_error("ERROR (RadiationModel::addRadiationBand): The waveband range of a radiation band must be at least 1 nm.");
223
-
224 RadiationBand band(label, directRayCount_default, diffuseRayCount_default, diffuseFlux_default, scatteringDepth_default, minScatterEnergy_default);
+
224 }
225
-
226 band.wavebandBounds = make_vec2(wavelength1,wavelength2);
+
226 RadiationBand band(label, directRayCount_default, diffuseRayCount_default, diffuseFlux_default, scatteringDepth_default, minScatterEnergy_default);
227
-
228 radiation_bands.emplace(label,band);
+
228 band.wavebandBounds = make_vec2(wavelength1,wavelength2);
229
-
230 //Initialize all radiation source fluxes
-
231 for( auto &source : radiation_sources ) {
-
232 source.source_fluxes[label] = -1.f;
-
233 }
-
234
-
235
+
230 radiation_bands.emplace(label,band);
+
231
+
232 //Initialize all radiation source fluxes
+
233 for( auto &source : radiation_sources ) {
+
234 source.source_fluxes[label] = -1.f;
+
235 }
236
-
237
+
237 radiativepropertiesneedupdate = true;
238
239}
@@ -867,7 +874,7 @@
687 islightvisualizationenabled = false;
688 for (auto &UUIDs: source_model_UUIDs){
-
689 context->deletePrimitive(UUIDs.second);
+
689 context->deletePrimitive(UUIDs.second);
690 }
691}
@@ -888,7 +895,7 @@
704 iscameravisualizationenabled = false;
705 for (auto &UUIDs: camera_model_UUIDs){
-
706 context->deletePrimitive(UUIDs.second);
+
706 context->deletePrimitive(UUIDs.second);
707 }
708}
@@ -901,42 +908,42 @@
715 if( source.source_type == RADIATION_SOURCE_TYPE_SPHERE ) {
716 source_model_UUIDs[sourceID] = context->loadOBJ("plugins/radiation/camera_light_models/SphereLightSource.obj", true);
717 }else if( source.source_type == RADIATION_SOURCE_TYPE_SUN_SPHERE ){
-
718 source_model_UUIDs[sourceID] = context->loadOBJ( "plugins/radiation/camera_light_models/SphereLightSource.obj", true );
+
718 source_model_UUIDs[sourceID] = context->loadOBJ( "plugins/radiation/camera_light_models/SphereLightSource.obj", true );
719 }else if( source.source_type == RADIATION_SOURCE_TYPE_DISK ){
-
720 source_model_UUIDs[sourceID] = context->loadOBJ( "plugins/radiation/camera_light_models/DiskLightSource.obj", true );
-
721 context->scalePrimitive(source_model_UUIDs.at(sourceID), make_vec3(source.source_width.x, source.source_width.y, 0.05f*source.source_width.x));
-
722 std::vector<uint> UUIDs_arrow = context->loadOBJ( "plugins/radiation/camera_light_models/Arrow.obj", true );
+
720 source_model_UUIDs[sourceID] = context->loadOBJ( "plugins/radiation/camera_light_models/DiskLightSource.obj", true );
+
721 context->scalePrimitive(source_model_UUIDs.at(sourceID), make_vec3(source.source_width.x, source.source_width.y, 0.05f*source.source_width.x));
+
722 std::vector<uint> UUIDs_arrow = context->loadOBJ( "plugins/radiation/camera_light_models/Arrow.obj", true );
723 source_model_UUIDs.at(sourceID).insert( source_model_UUIDs.at(sourceID).begin(), UUIDs_arrow.begin(), UUIDs_arrow.end() );
-
724 context->scalePrimitive( UUIDs_arrow, make_vec3(1,1,1)*0.25f*source.source_width.x );
+
724 context->scalePrimitive( UUIDs_arrow, make_vec3(1,1,1)*0.25f*source.source_width.x );
725 }else if( source.source_type == RADIATION_SOURCE_TYPE_RECTANGLE ) {
-
726 source_model_UUIDs[sourceID] = context->loadOBJ( "plugins/radiation/camera_light_models/RectangularLightSource.obj", true);
-
727 context->scalePrimitive(source_model_UUIDs.at(sourceID), make_vec3(source.source_width.x, source.source_width.y, fmin(0.05f*(source.source_width.x+source.source_width.y),0.5f*fmin(source.source_width.x,source.source_width.y))));
-
728 std::vector<uint> UUIDs_arrow = context->loadOBJ( "plugins/radiation/camera_light_models/Arrow.obj", true );
+
726 source_model_UUIDs[sourceID] = context->loadOBJ( "plugins/radiation/camera_light_models/RectangularLightSource.obj", true);
+
727 context->scalePrimitive(source_model_UUIDs.at(sourceID), make_vec3(source.source_width.x, source.source_width.y, fmin(0.05f*(source.source_width.x+source.source_width.y),0.5f*fmin(source.source_width.x,source.source_width.y))));
+
728 std::vector<uint> UUIDs_arrow = context->loadOBJ( "plugins/radiation/camera_light_models/Arrow.obj", true );
729 source_model_UUIDs.at(sourceID).insert( source_model_UUIDs.at(sourceID).begin(), UUIDs_arrow.begin(), UUIDs_arrow.end() );
-
730 context->scalePrimitive( UUIDs_arrow, make_vec3(1,1,1)*0.15f*(source.source_width.x+source.source_width.y) );
+
730 context->scalePrimitive( UUIDs_arrow, make_vec3(1,1,1)*0.15f*(source.source_width.x+source.source_width.y) );
731 }else{
732 return;
733 }
734
735 if( source.source_type == RADIATION_SOURCE_TYPE_SPHERE ) {
-
736 context->scalePrimitive(source_model_UUIDs.at(sourceID), make_vec3(source.source_width.x, source.source_width.x, source.source_width.x));
-
737 context->translatePrimitive(source_model_UUIDs.at(sourceID), source.source_position);
+
736 context->scalePrimitive(source_model_UUIDs.at(sourceID), make_vec3(source.source_width.x, source.source_width.x, source.source_width.x));
+
737 context->translatePrimitive(source_model_UUIDs.at(sourceID), source.source_position);
738 }else if( source.source_type == RADIATION_SOURCE_TYPE_SUN_SPHERE ){
-
739 vec3 center;
+
739 vec3 center;
740 float radius;
-
741 context->getDomainBoundingSphere( center, radius );
-
742 context->scalePrimitive(source_model_UUIDs.at(sourceID), make_vec3(1,1,1)*0.1f*radius );
-
743 vec3 sunvec = source.source_position;
+
741 context->getDomainBoundingSphere( center, radius );
+
742 context->scalePrimitive(source_model_UUIDs.at(sourceID), make_vec3(1,1,1)*0.1f*radius );
+
743 vec3 sunvec = source.source_position;
744 sunvec.normalize();
-
745 context->translatePrimitive( source_model_UUIDs.at(sourceID), center + sunvec*radius );
+
745 context->translatePrimitive( source_model_UUIDs.at(sourceID), center + sunvec*radius );
746 }else {
-
747 context->rotatePrimitive( source_model_UUIDs.at(sourceID), source.source_rotation.x, "x" );
-
748 context->rotatePrimitive( source_model_UUIDs.at(sourceID), source.source_rotation.y, "y" );
-
749 context->rotatePrimitive( source_model_UUIDs.at(sourceID), source.source_rotation.z, "z" );
-
750 context->translatePrimitive( source_model_UUIDs.at(sourceID), source.source_position );
+
747 context->rotatePrimitive( source_model_UUIDs.at(sourceID), source.source_rotation.x, "x" );
+
748 context->rotatePrimitive( source_model_UUIDs.at(sourceID), source.source_rotation.y, "y" );
+
749 context->rotatePrimitive( source_model_UUIDs.at(sourceID), source.source_rotation.z, "z" );
+
750 context->translatePrimitive( source_model_UUIDs.at(sourceID), source.source_position );
751 }
752
-
753 context->setPrimitiveData( source_model_UUIDs.at(sourceID), "twosided_flag", uint(3)); //source model does not interact with radiation field
+
753 context->setPrimitiveData( source_model_UUIDs.at(sourceID), "twosided_flag", uint(3)); //source model does not interact with radiation field
754
755}
756
@@ -944,19 +951,19 @@
758
759 assert( cameras.find(cameralabel)!=cameras.end() );
760
-
761 RadiationCamera camera = cameras.at(cameralabel);
+
761 RadiationCamera camera = cameras.at(cameralabel);
762
-
763 vec3 viewvec = camera.lookat - camera.position;
-
764 SphericalCoord viewsph = cart2sphere(viewvec);
+
763 vec3 viewvec = camera.lookat - camera.position;
+
764 SphericalCoord viewsph = cart2sphere(viewvec);
765
-
766 camera_model_UUIDs[cameralabel] = context->loadOBJ( "plugins/radiation/camera_light_models/Camera.obj", true );
+
766 camera_model_UUIDs[cameralabel] = context->loadOBJ( "plugins/radiation/camera_light_models/Camera.obj", true );
767
-
768 context->rotatePrimitive( camera_model_UUIDs.at(cameralabel), viewsph.elevation, "x" );
-
769 context->rotatePrimitive( camera_model_UUIDs.at(cameralabel), -viewsph.azimuth, "z" );
+
768 context->rotatePrimitive( camera_model_UUIDs.at(cameralabel), viewsph.elevation, "x" );
+
769 context->rotatePrimitive( camera_model_UUIDs.at(cameralabel), -viewsph.azimuth, "z" );
770
-
771 context->translatePrimitive( camera_model_UUIDs.at(cameralabel), camera.position );
+
771 context->translatePrimitive( camera_model_UUIDs.at(cameralabel), camera.position );
772
-
773 context->setPrimitiveData( camera_model_UUIDs.at(cameralabel), "twosided_flag", uint(3)); //camera model does not interact with radiation field
+
773 context->setPrimitiveData( camera_model_UUIDs.at(cameralabel), "twosided_flag", uint(3)); //camera model does not interact with radiation field
774
775}
776
@@ -964,13 +971,13 @@
778
779 assert( sourceID < radiation_sources.size() );
780
-
781 RadiationSource source = radiation_sources.at(sourceID);
+
781 RadiationSource source = radiation_sources.at(sourceID);
782
783 if( source.source_type != RADIATION_SOURCE_TYPE_SPHERE && source.source_type != RADIATION_SOURCE_TYPE_DISK && source.source_type != RADIATION_SOURCE_TYPE_RECTANGLE ){
784 return;
785 }
786
-
787 context->translatePrimitive( source_model_UUIDs.at(sourceID), delta_position );
+
787 context->translatePrimitive( source_model_UUIDs.at(sourceID), delta_position );
788
789}
790
@@ -978,7 +985,7 @@
792
793 assert( cameras.find(cameralabel)!=cameras.end() );
794
-
795 context->deletePrimitive( camera_model_UUIDs.at(cameralabel) );
+
795 context->deletePrimitive( camera_model_UUIDs.at(cameralabel) );
796 buildCameraModelGeometry( cameralabel );
797
798}
@@ -1179,7 +1186,7 @@
980 s.y *= scale_factor;
981 }
982
-
983 context->setGlobalData( new_global_data_label.c_str(), HELIOS_TYPE_VEC2, spectrum.size(), &spectrum.at(0) );
+
983 context->setGlobalData( new_global_data_label.c_str(), HELIOS_TYPE_VEC2, spectrum.size(), &spectrum.at(0) );
984
985}
@@ -1193,7 +1200,7 @@
992 s.y *= scale_factor;
993 }
994
-
995 context->setGlobalData( global_data_label.c_str(), HELIOS_TYPE_VEC2, spectrum.size(), &spectrum.at(0) );
+
995 context->setGlobalData( global_data_label.c_str(), HELIOS_TYPE_VEC2, spectrum.size(), &spectrum.at(0) );
996
997}
@@ -1201,7 +1208,7 @@
999void RadiationModel::scaleSpectrumRandomly( const std::string &existing_global_data_label, const std::string &new_global_data_label, float minimum_scale_factor, float maximum_scale_factor ) const{
1000
-
1001 scaleSpectrum( existing_global_data_label, new_global_data_label, context->randu(minimum_scale_factor,maximum_scale_factor) );
+
1001 scaleSpectrum( existing_global_data_label, new_global_data_label, context->randu(minimum_scale_factor,maximum_scale_factor) );
1002
1003}
@@ -1283,7 +1290,7 @@
1078
1079 }
1080
-
1081 context->setGlobalData( new_spectrum_label.c_str(), HELIOS_TYPE_VEC2, new_spectrum.size(), &new_spectrum.front() );
+
1081 context->setGlobalData( new_spectrum_label.c_str(), HELIOS_TYPE_VEC2, new_spectrum.size(), &new_spectrum.front() );
1082
1083}
@@ -1294,7 +1301,7 @@
1087 std::vector<float> weights;
1088 weights.resize(spectrum_labels.size());
1089 for( uint i=0; i<spectrum_labels.size(); i++ ){
-
1090 weights.at(i) = context->randu();
+
1090 weights.at(i) = context->randu();
1091 }
1092 float sum_weights = sum(weights);
1093 for( uint i=0; i<spectrum_labels.size(); i++ ){
@@ -1370,16 +1377,16 @@
1151
1152 if( boundary=="x" ){
1153
-
1154 periodic_flag.x = 1;
+
1154 periodic_flag.x = 1;
1155
1156 }else if( boundary=="y" ){
1157
-
1158 periodic_flag.y = 1;
+
1158 periodic_flag.y = 1;
1159
1160 }else if( boundary=="xy" ){
1161
-
1162 periodic_flag.x = 1;
-
1163 periodic_flag.y = 1;
+
1162 periodic_flag.x = 1;
+
1163 periodic_flag.y = 1;
1164
1165 }else{
1166
@@ -1419,1360 +1426,1360 @@
1198 buildCameraModelGeometry(camera_label);
1199 }
1200
-
1201}
- +
1201 radiativepropertiesneedupdate = true;
1202
-
-
1203void RadiationModel::addRadiationCamera(const std::string &camera_label, const std::vector<std::string> &band_label, const helios::vec3 &position, const helios::SphericalCoord &viewing_direction, const CameraProperties &camera_properties, uint antialiasing_samples) {
-
1204
-
1205 vec3 lookat = position + sphere2cart(viewing_direction);
-
1206 addRadiationCamera( camera_label, band_label, position, lookat, camera_properties, antialiasing_samples );
-
1207
-
1208}
+
1203}
+
1204
+
+
1205void RadiationModel::addRadiationCamera(const std::string &camera_label, const std::vector<std::string> &band_label, const helios::vec3 &position, const helios::SphericalCoord &viewing_direction, const CameraProperties &camera_properties, uint antialiasing_samples) {
+
1206
+
1207 vec3 lookat = position + sphere2cart(viewing_direction);
+
1208 addRadiationCamera( camera_label, band_label, position, lookat, camera_properties, antialiasing_samples );
1209
-
-
1210void RadiationModel::setCameraSpectralResponse( const std::string &camera_label, const std::string &band_label, const std::string &global_data ){
-
1211 if(cameras.find(camera_label) == cameras.end() ){
-
1212 helios_runtime_error("ERROR (setCameraSpectralResponse): Camera '" + camera_label + "' does not exist.");
-
1213 }else if( !doesBandExist(band_label) ){
-
1214 helios_runtime_error("ERROR (setCameraSpectralResponse): Band '" + band_label + "' does not exist.");
-
1215 }
-
1216
-
1217 cameras.at(camera_label).band_spectral_response[band_label] = global_data;
-
1218
-
1219}
+
1210}
+
1211
+
+
1212void RadiationModel::setCameraSpectralResponse( const std::string &camera_label, const std::string &band_label, const std::string &global_data ){
+
1213 if(cameras.find(camera_label) == cameras.end() ){
+
1214 helios_runtime_error("ERROR (setCameraSpectralResponse): Camera '" + camera_label + "' does not exist.");
+
1215 }else if( !doesBandExist(band_label) ){
+
1216 helios_runtime_error("ERROR (setCameraSpectralResponse): Band '" + band_label + "' does not exist.");
+
1217 }
+
1218
+
1219 cameras.at(camera_label).band_spectral_response[band_label] = global_data;
1220
-
-
1221void RadiationModel::setCameraPosition( const std::string &camera_label, const helios::vec3& position ){
-
1222 if(cameras.find(camera_label) == cameras.end() ){
-
1223 helios_runtime_error("ERROR (RadiationModel::setCameraPosition): Camera '" + camera_label + "' does not exist.");
-
1224 }else if( position == cameras.at(camera_label).lookat ){
-
1225 helios_runtime_error("ERROR (RadiationModel::setCameraPosition): Camera position cannot be equal to the 'lookat' position.");
-
1226 }
-
1227
-
1228 cameras.at(camera_label).position = position;
-
1229
-
1230 if( iscameravisualizationenabled ){
-
1231 updateCameraModelPosition(camera_label);
-
1232 }
-
1233
-
1234}
+
1221}
+
1222
+
+
1223void RadiationModel::setCameraPosition( const std::string &camera_label, const helios::vec3& position ){
+
1224 if(cameras.find(camera_label) == cameras.end() ){
+
1225 helios_runtime_error("ERROR (RadiationModel::setCameraPosition): Camera '" + camera_label + "' does not exist.");
+
1226 }else if( position == cameras.at(camera_label).lookat ){
+
1227 helios_runtime_error("ERROR (RadiationModel::setCameraPosition): Camera position cannot be equal to the 'lookat' position.");
+
1228 }
+
1229
+
1230 cameras.at(camera_label).position = position;
+
1231
+
1232 if( iscameravisualizationenabled ){
+
1233 updateCameraModelPosition(camera_label);
+
1234 }
1235
-
-
1236helios::vec3 RadiationModel::getCameraPosition(const std::string &camera_label) const{
+
1236}
+
1237
-
1238 if(cameras.find(camera_label) == cameras.end() ){
-
1239 helios_runtime_error("ERROR (RadiationModel::getCameraPosition): Camera '" + camera_label + "' does not exist.");
-
1240 }
-
1241
-
1242 return cameras.at(camera_label).position;
+
+
1238helios::vec3 RadiationModel::getCameraPosition(const std::string &camera_label) const{
+
1239
+
1240 if(cameras.find(camera_label) == cameras.end() ){
+
1241 helios_runtime_error("ERROR (RadiationModel::getCameraPosition): Camera '" + camera_label + "' does not exist.");
+
1242 }
1243
-
1244}
-
+
1244 return cameras.at(camera_label).position;
1245
-
-
1246void RadiationModel::setCameraLookat( const std::string &camera_label, const helios::vec3& lookat ){
-
1247 if(cameras.find(camera_label) == cameras.end() ){
-
1248 helios_runtime_error("ERROR (RadiationModel::setCameraLookat): Camera '" + camera_label + "' does not exist.");
-
1249 }
-
1250
-
1251 cameras.at(camera_label).lookat = lookat;
-
1252
-
1253 if( iscameravisualizationenabled ){
-
1254 updateCameraModelPosition(camera_label);
-
1255 }
-
1256
-
1257}
+
1246}
+
1247
+
+
1248void RadiationModel::setCameraLookat( const std::string &camera_label, const helios::vec3& lookat ){
+
1249 if(cameras.find(camera_label) == cameras.end() ){
+
1250 helios_runtime_error("ERROR (RadiationModel::setCameraLookat): Camera '" + camera_label + "' does not exist.");
+
1251 }
+
1252
+
1253 cameras.at(camera_label).lookat = lookat;
+
1254
+
1255 if( iscameravisualizationenabled ){
+
1256 updateCameraModelPosition(camera_label);
+
1257 }
1258
-
-
1259helios::vec3 RadiationModel::getCameraLookat(const std::string &camera_label) const{
+
1259}
+
1260
-
1261 if(cameras.find(camera_label) == cameras.end() ){
-
1262 helios_runtime_error("ERROR (RadiationModel::getCameraLookat): Camera '" + camera_label + "' does not exist.");
-
1263 }
-
1264
-
1265 return cameras.at(camera_label).lookat;
+
+
1261helios::vec3 RadiationModel::getCameraLookat(const std::string &camera_label) const{
+
1262
+
1263 if(cameras.find(camera_label) == cameras.end() ){
+
1264 helios_runtime_error("ERROR (RadiationModel::getCameraLookat): Camera '" + camera_label + "' does not exist.");
+
1265 }
1266
-
1267}
-
+
1267 return cameras.at(camera_label).lookat;
1268
-
-
1269void RadiationModel::setCameraOrientation( const std::string &camera_label, const helios::vec3& direction ){
-
1270 if(cameras.find(camera_label) == cameras.end() ){
-
1271 helios_runtime_error("ERROR (RadiationModel::setCameraOrientation): Camera '" + camera_label + "' does not exist.");
-
1272 }
-
1273
-
1274 cameras.at(camera_label).lookat = cameras.at(camera_label).position + direction;
-
1275
-
1276 if( iscameravisualizationenabled ){
-
1277 updateCameraModelPosition(camera_label);
-
1278 }
-
1279
-
1280}
+
1269}
+
1270
+
+
1271void RadiationModel::setCameraOrientation( const std::string &camera_label, const helios::vec3& direction ){
+
1272 if(cameras.find(camera_label) == cameras.end() ){
+
1273 helios_runtime_error("ERROR (RadiationModel::setCameraOrientation): Camera '" + camera_label + "' does not exist.");
+
1274 }
+
1275
+
1276 cameras.at(camera_label).lookat = cameras.at(camera_label).position + direction;
+
1277
+
1278 if( iscameravisualizationenabled ){
+
1279 updateCameraModelPosition(camera_label);
+
1280 }
1281
-
- +
1282}
+
1283
-
1284 if(cameras.find(camera_label) == cameras.end() ){
-
1285 helios_runtime_error("ERROR (RadiationModel::getCameraOrientation): Camera '" + camera_label + "' does not exist.");
-
1286 }
-
1287
-
1288 return cart2sphere(cameras.at(camera_label).lookat - cameras.at(camera_label).position);
+
+ +
1285
+
1286 if(cameras.find(camera_label) == cameras.end() ){
+
1287 helios_runtime_error("ERROR (RadiationModel::getCameraOrientation): Camera '" + camera_label + "' does not exist.");
+
1288 }
1289
-
1290}
-
+
1290 return cart2sphere(cameras.at(camera_label).lookat - cameras.at(camera_label).position);
1291
-
-
1292void RadiationModel::setCameraOrientation( const std::string &camera_label, const helios::SphericalCoord& direction ){
-
1293 if(cameras.find(camera_label) == cameras.end() ){
-
1294 helios_runtime_error("ERROR (RadiationModel::setCameraOrientation): Camera '" + camera_label + "' does not exist.");
-
1295 }
-
1296
-
1297 cameras.at(camera_label).lookat = cameras.at(camera_label).position + sphere2cart(direction);
-
1298
-
1299 if( iscameravisualizationenabled ){
-
1300 updateCameraModelPosition(camera_label);
-
1301 }
-
1302
-
1303}
+
1292}
+
1293
+
+
1294void RadiationModel::setCameraOrientation( const std::string &camera_label, const helios::SphericalCoord& direction ){
+
1295 if(cameras.find(camera_label) == cameras.end() ){
+
1296 helios_runtime_error("ERROR (RadiationModel::setCameraOrientation): Camera '" + camera_label + "' does not exist.");
+
1297 }
+
1298
+
1299 cameras.at(camera_label).lookat = cameras.at(camera_label).position + sphere2cart(direction);
+
1300
+
1301 if( iscameravisualizationenabled ){
+
1302 updateCameraModelPosition(camera_label);
+
1303 }
1304
-
-
1305std::vector<std::string> RadiationModel::getAllCameraLabels(){
-
1306 std::vector<std::string> labels(cameras.size());
-
1307 uint cam=0;
-
1308 for( const auto &camera : cameras ){
-
1309 labels.at(cam) = camera.second.label;
-
1310 cam++;
-
1311 }
-
1312 return labels;
-
1313}
+
1305}
+
+
1306
+
+
1307std::vector<std::string> RadiationModel::getAllCameraLabels(){
+
1308 std::vector<std::string> labels(cameras.size());
+
1309 uint cam=0;
+
1310 for( const auto &camera : cameras ){
+
1311 labels.at(cam) = camera.second.label;
+
1312 cam++;
+
1313 }
+
1314 return labels;
+
1315}
-
1314
-
-
1315void RadiationModel::writeCameraImage(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path, int frame, float flux_to_pixel_conversion) {
1316
-
1317 //check if camera exists
-
1318 if( cameras.find(camera)==cameras.end() ){
-
1319 std::cout << "ERROR (RadiationModel::writeCameraImage): camera with label " << camera << " does not exist. Skipping image write for this camera." << std::endl;
-
1320 return;
-
1321 }
-
1322
-
1323 if( bands.size()!=1 && bands.size()!=3 ){
-
1324 std::cout << "ERROR (RadiationModel::writeCameraImage): input vector of band labels (""bands"") should either have length of 1 (grayscale image) or length of 3 (RGB image). Skipping image write for this camera." << std::endl;
-
1325 return;
-
1326 }
-
1327
-
1328 std::vector<std::vector<float> > camera_data(bands.size());
+
+
1317void RadiationModel::writeCameraImage(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path, int frame, float flux_to_pixel_conversion) {
+
1318
+
1319 //check if camera exists
+
1320 if( cameras.find(camera)==cameras.end() ){
+
1321 std::cout << "ERROR (RadiationModel::writeCameraImage): camera with label " << camera << " does not exist. Skipping image write for this camera." << std::endl;
+
1322 return;
+
1323 }
+
1324
+
1325 if( bands.size()!=1 && bands.size()!=3 ){
+
1326 std::cout << "ERROR (RadiationModel::writeCameraImage): input vector of band labels (""bands"") should either have length of 1 (grayscale image) or length of 3 (RGB image). Skipping image write for this camera." << std::endl;
+
1327 return;
+
1328 }
1329
-
1330 for (uint b = 0; b < bands.size(); b++) {
+
1330 std::vector<std::vector<float> > camera_data(bands.size());
1331
-
1332 //check if band exists
-
1333 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), bands.at(b)) == cameras.at(camera).band_labels.end()) {
-
1334 std::cout << "ERROR (RadiationModel::writeCameraImage): camera " << camera << " band with label " << bands.at(b) << " does not exist. Skipping image write for this camera." << std::endl;
-
1335 return;
-
1336 }
-
1337
-
1338 std::string global_data_label = "camera_" + camera + "_" + bands.at(b);
+
1332 for (uint b = 0; b < bands.size(); b++) {
+
1333
+
1334 //check if band exists
+
1335 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), bands.at(b)) == cameras.at(camera).band_labels.end()) {
+
1336 std::cout << "ERROR (RadiationModel::writeCameraImage): camera " << camera << " band with label " << bands.at(b) << " does not exist. Skipping image write for this camera." << std::endl;
+
1337 return;
+
1338 }
1339
-
1340 if (!context->doesGlobalDataExist(global_data_label.c_str())) {
-
1341 std::cout << "ERROR (RadiationModel::writeCameraImage): image data for camera " << camera << ", band " << bands.at(b) << " has not been created. Did you run the radiation model? Skipping image write for this camera." << std::endl;
-
1342 return;
-
1343 }
-
1344
-
1345 context->getGlobalData(global_data_label.c_str(), camera_data.at(b));
+
1340 std::string global_data_label = "camera_" + camera + "_" + bands.at(b);
+
1341
+
1342 if (!context->doesGlobalDataExist(global_data_label.c_str())) {
+
1343 std::cout << "ERROR (RadiationModel::writeCameraImage): image data for camera " << camera << ", band " << bands.at(b) << " has not been created. Did you run the radiation model? Skipping image write for this camera." << std::endl;
+
1344 return;
+
1345 }
1346
-
1347 }
+
1347 context->getGlobalData(global_data_label.c_str(), camera_data.at(b));
1348
-
1349 std::string frame_str;
-
1350 if( frame>=0 ) {
-
1351 frame_str = std::to_string(frame);
-
1352 }
-
1353
-
1354 std::string output_path = image_path;
-
1355 if( !image_path.empty() && !validateOutputPath(output_path) ){
-
1356 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
-
1357 }else if( !getFileName(output_path).empty() ){
-
1358 helios_runtime_error("ERROR(RadiationModel::writeCameraImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
-
1359 }
-
1360
-
1361 std::ostringstream outfile;
-
1362 outfile << output_path;
-
1363
-
1364 if( frame>=0 ) {
-
1365 outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg";
-
1366 }else{
-
1367 outfile << camera << "_" << imagefile_base << ".jpeg";
-
1368 }
-
1369 std::ofstream testfile(outfile.str());
-
1370
-
1371 if( !testfile.is_open() ){
-
1372 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;
-
1373 return;
-
1374 }
-
1375 testfile.close();
-
1376
-
1377 int2 camera_resolution = cameras.at(camera).resolution;
+
1349 }
+
1350
+
1351 std::string frame_str;
+
1352 if( frame>=0 ) {
+
1353 frame_str = std::to_string(frame);
+
1354 }
+
1355
+
1356 std::string output_path = image_path;
+
1357 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
1358 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
1359 }else if( !getFileName(output_path).empty() ){
+
1360 helios_runtime_error("ERROR(RadiationModel::writeCameraImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
1361 }
+
1362
+
1363 std::ostringstream outfile;
+
1364 outfile << output_path;
+
1365
+
1366 if( frame>=0 ) {
+
1367 outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg";
+
1368 }else{
+
1369 outfile << camera << "_" << imagefile_base << ".jpeg";
+
1370 }
+
1371 std::ofstream testfile(outfile.str());
+
1372
+
1373 if( !testfile.is_open() ){
+
1374 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;
+
1375 return;
+
1376 }
+
1377 testfile.close();
1378
-
1379 std::vector<RGBcolor> pixel_data(camera_resolution.x*camera_resolution.y);
+
1379 int2 camera_resolution = cameras.at(camera).resolution;
1380
-
1381 RGBcolor pixel_color;
-
1382 for (uint j = 0; j < camera_resolution.y; j++) {
-
1383 for (uint i=0; i < camera_resolution.x; i++) {
-
1384 if( camera_data.size()==1 ){
-
1385 float c = camera_data.front().at(j * camera_resolution.x + i);
-
1386 pixel_color = make_RGBcolor(c,c,c);
-
1387 }else{
-
1388 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));
-
1389 }
-
1390 pixel_color.scale( flux_to_pixel_conversion );
-
1391 uint ii = camera_resolution.x - i -1;
-
1392 uint jj = camera_resolution.y - j - 1;
-
1393 pixel_data.at(jj * camera_resolution.x + ii) = pixel_color;
-
1394 }
-
1395 }
-
1396
-
1397 writeJPEG( outfile.str(), camera_resolution.x, camera_resolution.y, pixel_data );
+
1381 std::vector<RGBcolor> pixel_data(camera_resolution.x*camera_resolution.y);
+
1382
+
1383 RGBcolor pixel_color;
+
1384 for (uint j = 0; j < camera_resolution.y; j++) {
+
1385 for (uint i=0; i < camera_resolution.x; i++) {
+
1386 if( camera_data.size()==1 ){
+
1387 float c = camera_data.front().at(j * camera_resolution.x + i);
+
1388 pixel_color = make_RGBcolor(c,c,c);
+
1389 }else{
+
1390 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));
+
1391 }
+
1392 pixel_color.scale( flux_to_pixel_conversion );
+
1393 uint ii = camera_resolution.x - i -1;
+
1394 uint jj = camera_resolution.y - j - 1;
+
1395 pixel_data.at(jj * camera_resolution.x + ii) = pixel_color;
+
1396 }
+
1397 }
1398
-
1399}
-
+
1399 writeJPEG( outfile.str(), camera_resolution.x, camera_resolution.y, pixel_data );
1400
-
-
1401void RadiationModel::writeNormCameraImage(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path, int frame){
-
1402 float maxval = 0;
-
1403 // Find maximum mean value over all bands
-
1404 for (const std::string& band: bands){
-
1405 std::string global_data_label = "camera_" + camera + "_" + band;
-
1406 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), band ) == cameras.at(camera).band_labels.end()) {
-
1407 std::cout << "ERROR (RadiationModel::writeNormCameraImage): camera " << camera << " band with label " << band << " does not exist. Skipping image write for this camera." << std::endl;
-
1408 return;
-
1409 }else if (!context->doesGlobalDataExist(global_data_label.c_str())) {
-
1410 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;
-
1411 return;
-
1412 }
-
1413 std::vector<float> cameradata;
-
1414 context->getGlobalData(global_data_label.c_str(), cameradata);
-
1415 for (float val: cameradata){
-
1416 if (val > maxval){
-
1417 maxval = val;
-
1418 }
-
1419 }
-
1420 }
-
1421 // Normalize all bands
-
1422 for (const std::string& band: bands) {
-
1423 std::string global_data_label = "camera_" + camera + "_" + band;
-
1424 std::vector<float> cameradata;
-
1425 context->getGlobalData(global_data_label.c_str(), cameradata);
-
1426 for (float &val: cameradata) {
-
1427 val = val / maxval;
-
1428 }
-
1429 context->setGlobalData(global_data_label.c_str(), HELIOS_TYPE_FLOAT, cameradata.size(), &cameradata[0]);
-
1430 }
-
1431
-
1432 RadiationModel::writeCameraImage(camera, bands, imagefile_base, image_path, frame);
-
1433}
+
1401}
+
+
1402
+
+
1403void RadiationModel::writeNormCameraImage(const std::string &camera, const std::vector<std::string> &bands, const std::string &imagefile_base, const std::string &image_path, int frame){
+
1404 float maxval = 0;
+
1405 // Find maximum mean value over all bands
+
1406 for (const std::string& band: bands){
+
1407 std::string global_data_label = "camera_" + camera + "_" + band;
+
1408 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), band ) == cameras.at(camera).band_labels.end()) {
+
1409 std::cout << "ERROR (RadiationModel::writeNormCameraImage): camera " << camera << " band with label " << band << " does not exist. Skipping image write for this camera." << std::endl;
+
1410 return;
+
1411 }else if (!context->doesGlobalDataExist(global_data_label.c_str())) {
+
1412 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;
+
1413 return;
+
1414 }
+
1415 std::vector<float> cameradata;
+
1416 context->getGlobalData(global_data_label.c_str(), cameradata);
+
1417 for (float val: cameradata){
+
1418 if (val > maxval){
+
1419 maxval = val;
+
1420 }
+
1421 }
+
1422 }
+
1423 // Normalize all bands
+
1424 for (const std::string& band: bands) {
+
1425 std::string global_data_label = "camera_" + camera + "_" + band;
+
1426 std::vector<float> cameradata;
+
1427 context->getGlobalData(global_data_label.c_str(), cameradata);
+
1428 for (float &val: cameradata) {
+
1429 val = val / maxval;
+
1430 }
+
1431 context->setGlobalData(global_data_label.c_str(), HELIOS_TYPE_FLOAT, cameradata.size(), &cameradata[0]);
+
1432 }
+
1433
+
1434 RadiationModel::writeCameraImage(camera, bands, imagefile_base, image_path, frame);
+
1435}
-
1434
-
-
1435void RadiationModel::writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path, int frame){
1436
-
1437 //check if camera exists
-
1438 if( cameras.find(camera)==cameras.end() ){
-
1439 std::cout << "ERROR (RadiationModel::writeCameraImageData): camera with label " << camera << " does not exist. Skipping image write for this camera." << std::endl;
-
1440 return;
-
1441 }
-
1442
-
1443 std::vector<float> camera_data;
+
+
1437void RadiationModel::writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path, int frame){
+
1438
+
1439 //check if camera exists
+
1440 if( cameras.find(camera)==cameras.end() ){
+
1441 std::cout << "ERROR (RadiationModel::writeCameraImageData): camera with label " << camera << " does not exist. Skipping image write for this camera." << std::endl;
+
1442 return;
+
1443 }
1444
-
1445 //check if band exists
-
1446 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), band) == cameras.at(camera).band_labels.end()) {
-
1447 std::cout << "ERROR (RadiationModel::writeCameraImageData): camera " << camera << " band with label " << band << " does not exist. Skipping image write for this camera." << std::endl;
-
1448 return;
-
1449 }
-
1450
-
1451 std::string global_data_label = "camera_" + camera + "_" + band;
+
1445 std::vector<float> camera_data;
+
1446
+
1447 //check if band exists
+
1448 if (std::find(cameras.at(camera).band_labels.begin(), cameras.at(camera).band_labels.end(), band) == cameras.at(camera).band_labels.end()) {
+
1449 std::cout << "ERROR (RadiationModel::writeCameraImageData): camera " << camera << " band with label " << band << " does not exist. Skipping image write for this camera." << std::endl;
+
1450 return;
+
1451 }
1452
-
1453 if (!context->doesGlobalDataExist(global_data_label.c_str())) {
-
1454 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;
-
1455 return;
-
1456 }
-
1457
-
1458 context->getGlobalData(global_data_label.c_str(), camera_data );
+
1453 std::string global_data_label = "camera_" + camera + "_" + band;
+
1454
+
1455 if (!context->doesGlobalDataExist(global_data_label.c_str())) {
+
1456 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;
+
1457 return;
+
1458 }
1459
-
1460 std::string frame_str;
-
1461 if( frame>=0 ) {
-
1462 frame_str = std::to_string(frame);
-
1463 }
-
1464
-
1465 std::string output_path = image_path;
-
1466 if( !image_path.empty() && !validateOutputPath(output_path) ){
-
1467 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
-
1468 }else if( !getFileName(output_path).empty() ){
-
1469 helios_runtime_error("ERROR(RadiationModel::writeCameraImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
-
1470 }
-
1471
-
1472 std::ostringstream outfile;
-
1473 outfile << output_path;
-
1474
-
1475 if( frame>=0 ) {
-
1476 outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
1477 }else{
-
1478 outfile << camera << "_" << imagefile_base << ".txt";
-
1479 }
-
1480
-
1481 std::ofstream outfilestream(outfile.str());
+
1460 context->getGlobalData(global_data_label.c_str(), camera_data );
+
1461
+
1462 std::string frame_str;
+
1463 if( frame>=0 ) {
+
1464 frame_str = std::to_string(frame);
+
1465 }
+
1466
+
1467 std::string output_path = image_path;
+
1468 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
1469 helios_runtime_error("ERROR (RadiationModel::writeCameraImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
1470 }else if( !getFileName(output_path).empty() ){
+
1471 helios_runtime_error("ERROR(RadiationModel::writeCameraImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
1472 }
+
1473
+
1474 std::ostringstream outfile;
+
1475 outfile << output_path;
+
1476
+
1477 if( frame>=0 ) {
+
1478 outfile << camera << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
1479 }else{
+
1480 outfile << camera << "_" << imagefile_base << ".txt";
+
1481 }
1482
-
1483 if( !outfilestream.is_open() ){
-
1484 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;
-
1485 return;
-
1486 }
-
1487
-
1488 int2 camera_resolution = cameras.at(camera).resolution;
+
1483 std::ofstream outfilestream(outfile.str());
+
1484
+
1485 if( !outfilestream.is_open() ){
+
1486 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;
+
1487 return;
+
1488 }
1489
-
1490 for ( int j = 0; j<camera_resolution.y; j++ ) {
-
1491 for ( int i = camera_resolution.x-1; i >= 0; i-- ) {
-
1492 outfilestream << camera_data.at(j*camera_resolution.x + i ) << " ";
-
1493 }
-
1494 outfilestream << "\n";
-
1495 }
-
1496
-
1497 outfilestream.close();
+
1490 int2 camera_resolution = cameras.at(camera).resolution;
+
1491
+
1492 for ( int j = 0; j<camera_resolution.y; j++ ) {
+
1493 for ( int i = camera_resolution.x-1; i >= 0; i-- ) {
+
1494 outfilestream << camera_data.at(j*camera_resolution.x + i ) << " ";
+
1495 }
+
1496 outfilestream << "\n";
+
1497 }
1498
-
1499}
-
+
1499 outfilestream.close();
1500
-
1501void RadiationModel::initializeOptiX() {
+
1501}
+
1502
-
1503 /* Context */
-
1504 RT_CHECK_ERROR( rtContextCreate( &OptiX_Context ) );
-
1505 RT_CHECK_ERROR( rtContextSetPrintEnabled( OptiX_Context, 1 ) );
-
1506
-
1507 RT_CHECK_ERROR( rtContextSetRayTypeCount( OptiX_Context, 4 ) );
-
1508 //ray types are:
-
1509 // 0: direct_ray_type
-
1510 // 1: diffuse_ray_type
-
1511 // 2: camera_ray_type
-
1512 // 3: pixel_label_ray_type
-
1513
-
1514 RT_CHECK_ERROR( rtContextSetEntryPointCount( OptiX_Context, 4 ) );
-
1515 //ray entery points are
-
1516 // 0: direct_raygen
-
1517 // 1: diffuse_raygen
-
1518 // 2: camera_raygen
-
1519 // 3: pixel_label_raygen
-
1520
-
1521 /* Ray Types */
-
1522 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "direct_ray_type", &direct_ray_type_RTvariable ) );
-
1523 RT_CHECK_ERROR( rtVariableSet1ui( direct_ray_type_RTvariable, RAYTYPE_DIRECT ) );
-
1524 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "diffuse_ray_type", &diffuse_ray_type_RTvariable ) );
-
1525 RT_CHECK_ERROR( rtVariableSet1ui( diffuse_ray_type_RTvariable, RAYTYPE_DIFFUSE ) );
-
1526 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_ray_type", &camera_ray_type_RTvariable ) );
-
1527 RT_CHECK_ERROR( rtVariableSet1ui( camera_ray_type_RTvariable, RAYTYPE_CAMERA ) );
-
1528 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "pixel_label_ray_type", &pixel_label_ray_type_RTvariable ) );
-
1529 RT_CHECK_ERROR( rtVariableSet1ui( pixel_label_ray_type_RTvariable, RAYTYPE_PIXEL_LABEL ) );
-
1530
-
1531 /* Ray Generation Program */
+
1503void RadiationModel::initializeOptiX() {
+
1504
+
1505 /* Context */
+
1506 RT_CHECK_ERROR( rtContextCreate( &OptiX_Context ) );
+
1507 RT_CHECK_ERROR( rtContextSetPrintEnabled( OptiX_Context, 1 ) );
+
1508
+
1509 RT_CHECK_ERROR( rtContextSetRayTypeCount( OptiX_Context, 4 ) );
+
1510 //ray types are:
+
1511 // 0: direct_ray_type
+
1512 // 1: diffuse_ray_type
+
1513 // 2: camera_ray_type
+
1514 // 3: pixel_label_ray_type
+
1515
+
1516 RT_CHECK_ERROR( rtContextSetEntryPointCount( OptiX_Context, 4 ) );
+
1517 //ray entery points are
+
1518 // 0: direct_raygen
+
1519 // 1: diffuse_raygen
+
1520 // 2: camera_raygen
+
1521 // 3: pixel_label_raygen
+
1522
+
1523 /* Ray Types */
+
1524 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "direct_ray_type", &direct_ray_type_RTvariable ) );
+
1525 RT_CHECK_ERROR( rtVariableSet1ui( direct_ray_type_RTvariable, RAYTYPE_DIRECT ) );
+
1526 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "diffuse_ray_type", &diffuse_ray_type_RTvariable ) );
+
1527 RT_CHECK_ERROR( rtVariableSet1ui( diffuse_ray_type_RTvariable, RAYTYPE_DIFFUSE ) );
+
1528 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_ray_type", &camera_ray_type_RTvariable ) );
+
1529 RT_CHECK_ERROR( rtVariableSet1ui( camera_ray_type_RTvariable, RAYTYPE_CAMERA ) );
+
1530 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "pixel_label_ray_type", &pixel_label_ray_type_RTvariable ) );
+
1531 RT_CHECK_ERROR( rtVariableSet1ui( pixel_label_ray_type_RTvariable, RAYTYPE_PIXEL_LABEL ) );
1532
-
1533 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "direct_raygen", &direct_raygen ) );
-
1534 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_DIRECT, direct_raygen ) );
-
1535 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "diffuse_raygen", &diffuse_raygen ) );
-
1536 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_DIFFUSE, diffuse_raygen ) );
-
1537 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "camera_raygen", &camera_raygen ) );
-
1538 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_CAMERA, camera_raygen ) );
-
1539 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "pixel_label_raygen", &pixel_label_raygen ) );
-
1540 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_PIXEL_LABEL, pixel_label_raygen ) );
-
1541
-
1542 /* Declare Buffers and Variables */
+
1533 /* Ray Generation Program */
+
1534
+
1535 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "direct_raygen", &direct_raygen ) );
+
1536 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_DIRECT, direct_raygen ) );
+
1537 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "diffuse_raygen", &diffuse_raygen ) );
+
1538 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_DIFFUSE, diffuse_raygen ) );
+
1539 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "camera_raygen", &camera_raygen ) );
+
1540 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_CAMERA, camera_raygen ) );
+
1541 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayGeneration.cu.ptx", "pixel_label_raygen", &pixel_label_raygen ) );
+
1542 RT_CHECK_ERROR( rtContextSetRayGenerationProgram( OptiX_Context, RAYTYPE_PIXEL_LABEL, pixel_label_raygen ) );
1543
-
1544 //primitive reflectivity buffer
-
1545 addBuffer( "rho", rho_RTbuffer, rho_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1546 //primitive transmissivity buffer
-
1547 addBuffer( "tau", tau_RTbuffer, tau_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1548
-
1549 //primitive reflectivity buffer
-
1550 addBuffer( "rho_cam", rho_cam_RTbuffer, rho_cam_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1551 //primitive transmissivity buffer
-
1552 addBuffer( "tau_cam", tau_cam_RTbuffer, tau_cam_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1553
-
1554 //primitive transformation matrix buffer
-
1555 addBuffer( "transform_matrix", transform_matrix_RTbuffer, transform_matrix_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 2 );
-
1556
-
1557 //primitive type buffer
-
1558 addBuffer( "primitive_type", primitive_type_RTbuffer, primitive_type_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1559
-
1560 //primitive area buffer
-
1561 addBuffer( "primitive_area", primitive_area_RTbuffer, primitive_area_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1562
-
1563 //primitive UUID buffers
-
1564 addBuffer( "patch_UUID", patch_UUID_RTbuffer, patch_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1565 addBuffer( "triangle_UUID", triangle_UUID_RTbuffer, triangle_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1566 addBuffer( "disk_UUID", disk_UUID_RTbuffer, disk_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1567 addBuffer( "tile_UUID", tile_UUID_RTbuffer, tile_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1568 addBuffer( "voxel_UUID", voxel_UUID_RTbuffer, voxel_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1569
-
1570 //Object ID Buffer
-
1571 addBuffer( "objectID", objectID_RTbuffer, objectID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1572
-
1573 //Primitive ID Buffer
-
1574 addBuffer( "primitiveID", primitiveID_RTbuffer, primitiveID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1575
-
1576 //primitive two-sided flag buffer
-
1577 addBuffer( "twosided_flag", twosided_flag_RTbuffer, twosided_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 );
-
1578
-
1579 //patch buffers
-
1580 addBuffer( "patch_vertices", patch_vertices_RTbuffer, patch_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
-
1581
-
1582 //triangle buffers
-
1583 addBuffer( "triangle_vertices", triangle_vertices_RTbuffer, triangle_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
-
1584
-
1585 //disk buffers
-
1586 addBuffer( "disk_centers", disk_centers_RTbuffer, disk_centers_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1587 addBuffer( "disk_radii", disk_radii_RTbuffer, disk_radii_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1588 addBuffer( "disk_normals", disk_normals_RTbuffer, disk_normals_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1589
-
1590 //tile buffers
-
1591 addBuffer( "tile_vertices", tile_vertices_RTbuffer, tile_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
-
1592
-
1593 //voxel buffers
-
1594 addBuffer( "voxel_vertices", voxel_vertices_RTbuffer, voxel_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
-
1595
-
1596 //object buffers
-
1597 addBuffer( "object_subdivisions", object_subdivisions_RTbuffer, object_subdivisions_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT2, 1 );
-
1598
-
1599 //radiation energy rate data buffers
-
1600 // - in - //
-
1601 addBuffer( "radiation_in", radiation_in_RTbuffer, radiation_in_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1602 // - out,top - //
-
1603 addBuffer( "radiation_out_top", radiation_out_top_RTbuffer, radiation_out_top_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1604 // - out,bottom - //
-
1605 addBuffer( "radiation_out_bottom", radiation_out_bottom_RTbuffer, radiation_out_bottom_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1606 // - camera - //
-
1607 addBuffer( "radiation_in_camera", radiation_in_camera_RTbuffer, radiation_in_camera_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1608 addBuffer( "camera_pixel_label", camera_pixel_label_RTbuffer, camera_pixel_label_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1609 addBuffer( "camera_pixel_depth", camera_pixel_depth_RTbuffer, camera_pixel_depth_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1610
-
1611 //primitive scattering buffers
-
1612 // - top - //
-
1613 addBuffer( "scatter_buff_top", scatter_buff_top_RTbuffer, scatter_buff_top_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1614 // - bottom - //
-
1615 addBuffer( "scatter_buff_bottom", scatter_buff_bottom_RTbuffer, scatter_buff_bottom_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1616
-
1617 //Energy absorbed by "sky"
-
1618 addBuffer( "Rsky", Rsky_RTbuffer, Rsky_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1619
-
1620 //number of external radiation sources
-
1621 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nsources", &Nsources_RTvariable ) );
-
1622 RT_CHECK_ERROR( rtVariableSet1ui( Nsources_RTvariable,0 ) );
-
1623
-
1624 //External radiation source positions
-
1625 addBuffer( "source_positions", source_positions_RTbuffer, source_positions_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1626
-
1627 //External radiation source widths
-
1628 addBuffer( "source_widths", source_widths_RTbuffer, source_widths_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 1 );
-
1629
-
1630 //External radiation source rotations
-
1631 addBuffer( "source_rotations", source_rotations_RTbuffer, source_rotations_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1632
-
1633 //External radiation source types
-
1634 addBuffer( "source_types", source_types_RTbuffer, source_types_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1635
-
1636 //External radiation source fluxes
-
1637 addBuffer( "source_fluxes", source_fluxes_RTbuffer, source_fluxes_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1638
-
1639 //number of radiation bands
-
1640 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nbands", &Nbands_RTvariable ) );
-
1641 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_RTvariable,0 ) );
-
1642
-
1643 //flag to disable launches for certain bands
-
1644 addBuffer( "band_launch_flag", band_launch_flag_RTbuffer, band_launch_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 );
-
1645
-
1646 //number of Context primitives
-
1647 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nprimitives", &Nprimitives_RTvariable ) );
-
1648 RT_CHECK_ERROR( rtVariableSet1ui( Nprimitives_RTvariable,0 ) );
+
1544 /* Declare Buffers and Variables */
+
1545
+
1546 //primitive reflectivity buffer
+
1547 addBuffer( "rho", rho_RTbuffer, rho_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1548 //primitive transmissivity buffer
+
1549 addBuffer( "tau", tau_RTbuffer, tau_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1550
+
1551 //primitive reflectivity buffer
+
1552 addBuffer( "rho_cam", rho_cam_RTbuffer, rho_cam_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1553 //primitive transmissivity buffer
+
1554 addBuffer( "tau_cam", tau_cam_RTbuffer, tau_cam_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1555
+
1556 //primitive transformation matrix buffer
+
1557 addBuffer( "transform_matrix", transform_matrix_RTbuffer, transform_matrix_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 2 );
+
1558
+
1559 //primitive type buffer
+
1560 addBuffer( "primitive_type", primitive_type_RTbuffer, primitive_type_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1561
+
1562 //primitive area buffer
+
1563 addBuffer( "primitive_area", primitive_area_RTbuffer, primitive_area_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1564
+
1565 //primitive UUID buffers
+
1566 addBuffer( "patch_UUID", patch_UUID_RTbuffer, patch_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1567 addBuffer( "triangle_UUID", triangle_UUID_RTbuffer, triangle_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1568 addBuffer( "disk_UUID", disk_UUID_RTbuffer, disk_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1569 addBuffer( "tile_UUID", tile_UUID_RTbuffer, tile_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1570 addBuffer( "voxel_UUID", voxel_UUID_RTbuffer, voxel_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1571
+
1572 //Object ID Buffer
+
1573 addBuffer( "objectID", objectID_RTbuffer, objectID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1574
+
1575 //Primitive ID Buffer
+
1576 addBuffer( "primitiveID", primitiveID_RTbuffer, primitiveID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1577
+
1578 //primitive two-sided flag buffer
+
1579 addBuffer( "twosided_flag", twosided_flag_RTbuffer, twosided_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 );
+
1580
+
1581 //patch buffers
+
1582 addBuffer( "patch_vertices", patch_vertices_RTbuffer, patch_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1583
+
1584 //triangle buffers
+
1585 addBuffer( "triangle_vertices", triangle_vertices_RTbuffer, triangle_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1586
+
1587 //disk buffers
+
1588 addBuffer( "disk_centers", disk_centers_RTbuffer, disk_centers_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1589 addBuffer( "disk_radii", disk_radii_RTbuffer, disk_radii_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1590 addBuffer( "disk_normals", disk_normals_RTbuffer, disk_normals_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1591
+
1592 //tile buffers
+
1593 addBuffer( "tile_vertices", tile_vertices_RTbuffer, tile_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1594
+
1595 //voxel buffers
+
1596 addBuffer( "voxel_vertices", voxel_vertices_RTbuffer, voxel_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1597
+
1598 //object buffers
+
1599 addBuffer( "object_subdivisions", object_subdivisions_RTbuffer, object_subdivisions_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT2, 1 );
+
1600
+
1601 //radiation energy rate data buffers
+
1602 // - in - //
+
1603 addBuffer( "radiation_in", radiation_in_RTbuffer, radiation_in_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1604 // - out,top - //
+
1605 addBuffer( "radiation_out_top", radiation_out_top_RTbuffer, radiation_out_top_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1606 // - out,bottom - //
+
1607 addBuffer( "radiation_out_bottom", radiation_out_bottom_RTbuffer, radiation_out_bottom_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1608 // - camera - //
+
1609 addBuffer( "radiation_in_camera", radiation_in_camera_RTbuffer, radiation_in_camera_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1610 addBuffer( "camera_pixel_label", camera_pixel_label_RTbuffer, camera_pixel_label_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1611 addBuffer( "camera_pixel_depth", camera_pixel_depth_RTbuffer, camera_pixel_depth_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1612
+
1613 //primitive scattering buffers
+
1614 // - top - //
+
1615 addBuffer( "scatter_buff_top", scatter_buff_top_RTbuffer, scatter_buff_top_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1616 // - bottom - //
+
1617 addBuffer( "scatter_buff_bottom", scatter_buff_bottom_RTbuffer, scatter_buff_bottom_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1618
+
1619 //Energy absorbed by "sky"
+
1620 addBuffer( "Rsky", Rsky_RTbuffer, Rsky_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1621
+
1622 //number of external radiation sources
+
1623 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nsources", &Nsources_RTvariable ) );
+
1624 RT_CHECK_ERROR( rtVariableSet1ui( Nsources_RTvariable,0 ) );
+
1625
+
1626 //External radiation source positions
+
1627 addBuffer( "source_positions", source_positions_RTbuffer, source_positions_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1628
+
1629 //External radiation source widths
+
1630 addBuffer( "source_widths", source_widths_RTbuffer, source_widths_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 1 );
+
1631
+
1632 //External radiation source rotations
+
1633 addBuffer( "source_rotations", source_rotations_RTbuffer, source_rotations_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1634
+
1635 //External radiation source types
+
1636 addBuffer( "source_types", source_types_RTbuffer, source_types_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1637
+
1638 //External radiation source fluxes
+
1639 addBuffer( "source_fluxes", source_fluxes_RTbuffer, source_fluxes_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1640
+
1641 //number of radiation bands
+
1642 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nbands_global", &Nbands_global_RTvariable ) );
+
1643 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_global_RTvariable,0 ) );
+
1644 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nbands_launch", &Nbands_launch_RTvariable ) );
+
1645 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_launch_RTvariable,0 ) );
+
1646
+
1647 //flag to disable launches for certain bands
+
1648 addBuffer( "band_launch_flag", band_launch_flag_RTbuffer, band_launch_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 );
1649
-
1650 //Flux of diffuse radiation
-
1651 addBuffer( "diffuse_flux", diffuse_flux_RTbuffer, diffuse_flux_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1652
-
1653 //Diffuse distribution extinction coefficient of ambient diffuse radiation
-
1654 addBuffer( "diffuse_extinction", diffuse_extinction_RTbuffer, diffuse_extinction_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1655
-
1656 //Direction of peak diffuse radiation
-
1657 addBuffer( "diffuse_peak_dir", diffuse_peak_dir_RTbuffer, diffuse_peak_dir_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
-
1658
-
1659 //Diffuse distribution normalization factor
-
1660 addBuffer( "diffuse_dist_norm", diffuse_dist_norm_RTbuffer, diffuse_dist_norm_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
-
1661
-
1662 //Bounding sphere radius and center
-
1663 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "bound_sphere_radius", &bound_sphere_radius_RTvariable ) );
-
1664 RT_CHECK_ERROR( rtVariableSet1f( bound_sphere_radius_RTvariable, 0.f ));
-
1665 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "bound_sphere_center", &bound_sphere_center_RTvariable ) );
-
1666 RT_CHECK_ERROR( rtVariableSet3f( bound_sphere_center_RTvariable, 0.f, 0.f, 0.f ));
-
1667
-
1668 //Bounding Box
-
1669 addBuffer( "bbox_UUID", bbox_UUID_RTbuffer, bbox_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
-
1670 addBuffer( "bbox_vertices", bbox_vertices_RTbuffer, bbox_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1650 //number of Context primitives
+
1651 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nprimitives", &Nprimitives_RTvariable ) );
+
1652 RT_CHECK_ERROR( rtVariableSet1ui( Nprimitives_RTvariable,0 ) );
+
1653
+
1654 //Flux of diffuse radiation
+
1655 addBuffer( "diffuse_flux", diffuse_flux_RTbuffer, diffuse_flux_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1656
+
1657 //Diffuse distribution extinction coefficient of ambient diffuse radiation
+
1658 addBuffer( "diffuse_extinction", diffuse_extinction_RTbuffer, diffuse_extinction_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1659
+
1660 //Direction of peak diffuse radiation
+
1661 addBuffer( "diffuse_peak_dir", diffuse_peak_dir_RTbuffer, diffuse_peak_dir_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 1 );
+
1662
+
1663 //Diffuse distribution normalization factor
+
1664 addBuffer( "diffuse_dist_norm", diffuse_dist_norm_RTbuffer, diffuse_dist_norm_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 );
+
1665
+
1666 //Bounding sphere radius and center
+
1667 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "bound_sphere_radius", &bound_sphere_radius_RTvariable ) );
+
1668 RT_CHECK_ERROR( rtVariableSet1f( bound_sphere_radius_RTvariable, 0.f ));
+
1669 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "bound_sphere_center", &bound_sphere_center_RTvariable ) );
+
1670 RT_CHECK_ERROR( rtVariableSet3f( bound_sphere_center_RTvariable, 0.f, 0.f, 0.f ));
1671
-
1672 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "periodic_flag", &periodic_flag_RTvariable ) );
-
1673 RT_CHECK_ERROR( rtVariableSet2f( periodic_flag_RTvariable, 0.f, 0.f ));
-
1674
-
1675 //Texture mask data
-
1676 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, RT_BUFFER_INPUT, &maskdata_RTbuffer ) );
-
1677 RT_CHECK_ERROR( rtBufferSetFormat( maskdata_RTbuffer, RT_FORMAT_BYTE ) );
-
1678 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "maskdata", &maskdata_RTvariable ) );
-
1679 RT_CHECK_ERROR( rtVariableSetObject( maskdata_RTvariable, maskdata_RTbuffer ) );
-
1680 std::vector<std::vector<std::vector<bool> > > dummydata;
-
1681 initializeBuffer3D( maskdata_RTbuffer, dummydata );
-
1682
-
1683 //Texture mask size
-
1684 addBuffer( "masksize", masksize_RTbuffer, masksize_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT2, 1 );
-
1685
-
1686 //Texture mask ID
-
1687 addBuffer( "maskID", maskID_RTbuffer, maskID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT, 1 );
-
1688
-
1689 //Texture u,v data
-
1690 addBuffer( "uvdata", uvdata_RTbuffer, uvdata_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 2 );
-
1691
-
1692 //Texture u,v ID
-
1693 addBuffer( "uvID", uvID_RTbuffer, uvID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT, 1 );
-
1694
-
1695 // Radiation Camera Variables
-
1696 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_position", &camera_position_RTvariable ) );
-
1697 RT_CHECK_ERROR( rtVariableSet3f( camera_position_RTvariable, 0.f, 0.f, 0.f ));
-
1698 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_direction", &camera_direction_RTvariable ) );
-
1699 RT_CHECK_ERROR( rtVariableSet2f( camera_direction_RTvariable, 0.f, 0.f ));
-
1700 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_lens_diameter", &camera_lens_diameter_RTvariable ) );
-
1701 RT_CHECK_ERROR( rtVariableSet1f( camera_lens_diameter_RTvariable, 0.f ));
-
1702 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "FOV_aspect_ratio", &FOV_aspect_RTvariable ) );
-
1703 RT_CHECK_ERROR( rtVariableSet1f( FOV_aspect_RTvariable, 1.f ));
-
1704 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_focal_length", &camera_focal_length_RTvariable ) );
-
1705 RT_CHECK_ERROR( rtVariableSet1f( camera_focal_length_RTvariable, 0.f ));
-
1706 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_viewplane_length", &camera_viewplane_length_RTvariable ) );
-
1707 RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 0.f ));
-
1708 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Ncameras", &Ncameras_RTvariable ) );
-
1709 RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, 0 ));
-
1710 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_ID", &camera_ID_RTvariable ) );
-
1711 RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, 0 ));
-
1712
-
1713 // primitive scattering buffers (cameras)
-
1714 addBuffer( "scatter_buff_top_cam", scatter_buff_top_cam_RTbuffer, scatter_buff_top_cam_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
-
1715 addBuffer( "scatter_buff_bottom_cam", scatter_buff_bottom_cam_RTbuffer, scatter_buff_bottom_cam_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1672 //Bounding Box
+
1673 addBuffer( "bbox_UUID", bbox_UUID_RTbuffer, bbox_UUID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_UNSIGNED_INT, 1 );
+
1674 addBuffer( "bbox_vertices", bbox_vertices_RTbuffer, bbox_vertices_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT3, 2 );
+
1675
+
1676 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "periodic_flag", &periodic_flag_RTvariable ) );
+
1677 RT_CHECK_ERROR( rtVariableSet2f( periodic_flag_RTvariable, 0.f, 0.f ));
+
1678
+
1679 //Texture mask data
+
1680 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, RT_BUFFER_INPUT, &maskdata_RTbuffer ) );
+
1681 RT_CHECK_ERROR( rtBufferSetFormat( maskdata_RTbuffer, RT_FORMAT_BYTE ) );
+
1682 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "maskdata", &maskdata_RTvariable ) );
+
1683 RT_CHECK_ERROR( rtVariableSetObject( maskdata_RTvariable, maskdata_RTbuffer ) );
+
1684 std::vector<std::vector<std::vector<bool> > > dummydata;
+
1685 initializeBuffer3D( maskdata_RTbuffer, dummydata );
+
1686
+
1687 //Texture mask size
+
1688 addBuffer( "masksize", masksize_RTbuffer, masksize_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT2, 1 );
+
1689
+
1690 //Texture mask ID
+
1691 addBuffer( "maskID", maskID_RTbuffer, maskID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT, 1 );
+
1692
+
1693 //Texture u,v data
+
1694 addBuffer( "uvdata", uvdata_RTbuffer, uvdata_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT2, 2 );
+
1695
+
1696 //Texture u,v ID
+
1697 addBuffer( "uvID", uvID_RTbuffer, uvID_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_INT, 1 );
+
1698
+
1699 // Radiation Camera Variables
+
1700 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_position", &camera_position_RTvariable ) );
+
1701 RT_CHECK_ERROR( rtVariableSet3f( camera_position_RTvariable, 0.f, 0.f, 0.f ));
+
1702 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_direction", &camera_direction_RTvariable ) );
+
1703 RT_CHECK_ERROR( rtVariableSet2f( camera_direction_RTvariable, 0.f, 0.f ));
+
1704 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_lens_diameter", &camera_lens_diameter_RTvariable ) );
+
1705 RT_CHECK_ERROR( rtVariableSet1f( camera_lens_diameter_RTvariable, 0.f ));
+
1706 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "FOV_aspect_ratio", &FOV_aspect_RTvariable ) );
+
1707 RT_CHECK_ERROR( rtVariableSet1f( FOV_aspect_RTvariable, 1.f ));
+
1708 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_focal_length", &camera_focal_length_RTvariable ) );
+
1709 RT_CHECK_ERROR( rtVariableSet1f( camera_focal_length_RTvariable, 0.f ));
+
1710 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_viewplane_length", &camera_viewplane_length_RTvariable ) );
+
1711 RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 0.f ));
+
1712 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Ncameras", &Ncameras_RTvariable ) );
+
1713 RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, 0 ));
+
1714 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "camera_ID", &camera_ID_RTvariable ) );
+
1715 RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, 0 ));
1716
-
1717 /* Hit Programs */
-
1718 RTprogram closest_hit_direct;
-
1719 RTprogram closest_hit_diffuse;
-
1720 RTprogram closest_hit_camera;
-
1721 RTprogram closest_hit_pixel_label;
-
1722 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_direct", &closest_hit_direct ) );
-
1723 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_diffuse", &closest_hit_diffuse ) );
-
1724 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_camera", &closest_hit_camera ) );
-
1725 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_pixel_label", &closest_hit_pixel_label ) );
-
1726
-
1727 /* Initialize Patch Geometry */
-
1728
-
1729 RTprogram patch_intersection_program;
-
1730 RTprogram patch_bounding_box_program;
-
1731
-
1732 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &patch ) );
-
1733
-
1734 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "rectangle_bounds", &patch_bounding_box_program ) );
-
1735 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( patch, patch_bounding_box_program ) );
-
1736 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "rectangle_intersect", &patch_intersection_program ) );
-
1737 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( patch, patch_intersection_program ) );
-
1738
-
1739 /* Create Patch Material */
-
1740
-
1741 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &patch_material ) );
+
1717 // primitive scattering buffers (cameras)
+
1718 addBuffer( "scatter_buff_top_cam", scatter_buff_top_cam_RTbuffer, scatter_buff_top_cam_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1719 addBuffer( "scatter_buff_bottom_cam", scatter_buff_bottom_cam_RTbuffer, scatter_buff_bottom_cam_RTvariable, RT_BUFFER_INPUT_OUTPUT, RT_FORMAT_FLOAT, 1 );
+
1720
+
1721 /* Hit Programs */
+
1722 RTprogram closest_hit_direct;
+
1723 RTprogram closest_hit_diffuse;
+
1724 RTprogram closest_hit_camera;
+
1725 RTprogram closest_hit_pixel_label;
+
1726 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_direct", &closest_hit_direct ) );
+
1727 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_diffuse", &closest_hit_diffuse ) );
+
1728 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_camera", &closest_hit_camera ) );
+
1729 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "closest_hit_pixel_label", &closest_hit_pixel_label ) );
+
1730
+
1731 /* Initialize Patch Geometry */
+
1732
+
1733 RTprogram patch_intersection_program;
+
1734 RTprogram patch_bounding_box_program;
+
1735
+
1736 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &patch ) );
+
1737
+
1738 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "rectangle_bounds", &patch_bounding_box_program ) );
+
1739 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( patch, patch_bounding_box_program ) );
+
1740 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "rectangle_intersect", &patch_intersection_program ) );
+
1741 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( patch, patch_intersection_program ) );
1742
-
1743 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1744 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1745 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1746 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1747
-
1748 /* Initialize Triangle Geometry */
-
1749
-
1750 RTprogram triangle_intersection_program;
-
1751 RTprogram triangle_bounding_box_program;
-
1752
-
1753 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &triangle ) );
-
1754
-
1755 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "triangle_bounds", &triangle_bounding_box_program ) );
-
1756 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( triangle, triangle_bounding_box_program ) );
-
1757 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "triangle_intersect", &triangle_intersection_program ) );
-
1758 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( triangle, triangle_intersection_program ) );
-
1759
-
1760 /* Create Triangle Material */
-
1761
-
1762 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &triangle_material ) );
+
1743 /* Create Patch Material */
+
1744
+
1745 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &patch_material ) );
+
1746
+
1747 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1748 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1749 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1750 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( patch_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1751
+
1752 /* Initialize Triangle Geometry */
+
1753
+
1754 RTprogram triangle_intersection_program;
+
1755 RTprogram triangle_bounding_box_program;
+
1756
+
1757 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &triangle ) );
+
1758
+
1759 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "triangle_bounds", &triangle_bounding_box_program ) );
+
1760 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( triangle, triangle_bounding_box_program ) );
+
1761 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "triangle_intersect", &triangle_intersection_program ) );
+
1762 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( triangle, triangle_intersection_program ) );
1763
-
1764 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1765 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1766 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1767 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1768
-
1769 /* Initialize Disk Geometry */
-
1770
-
1771 RTprogram disk_intersection_program;
-
1772 RTprogram disk_bounding_box_program;
-
1773
-
1774 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &disk ) );
-
1775
-
1776 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "disk_bounds", &disk_bounding_box_program ) );
-
1777 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( disk, disk_bounding_box_program ) );
-
1778 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "disk_intersect", &disk_intersection_program ) );
-
1779 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( disk, disk_intersection_program ) );
-
1780
-
1781 /* Create Disk Material */
-
1782
-
1783 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &disk_material ) );
+
1764 /* Create Triangle Material */
+
1765
+
1766 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &triangle_material ) );
+
1767
+
1768 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1769 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1770 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1771 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( triangle_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1772
+
1773 /* Initialize Disk Geometry */
+
1774
+
1775 RTprogram disk_intersection_program;
+
1776 RTprogram disk_bounding_box_program;
+
1777
+
1778 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &disk ) );
+
1779
+
1780 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "disk_bounds", &disk_bounding_box_program ) );
+
1781 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( disk, disk_bounding_box_program ) );
+
1782 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "disk_intersect", &disk_intersection_program ) );
+
1783 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( disk, disk_intersection_program ) );
1784
-
1785 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1786 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1787 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1788 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1789
-
1790 /* Initialize Tile Geometry */
-
1791
-
1792 RTprogram tile_intersection_program;
-
1793 RTprogram tile_bounding_box_program;
-
1794
-
1795 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &tile ) );
-
1796
-
1797 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "tile_bounds", &tile_bounding_box_program ) );
-
1798 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( tile, tile_bounding_box_program ) );
-
1799 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "tile_intersect", &tile_intersection_program ) );
-
1800 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( tile, tile_intersection_program ) );
-
1801
-
1802 /* Create Tile Material */
-
1803
-
1804 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &tile_material ) );
+
1785 /* Create Disk Material */
+
1786
+
1787 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &disk_material ) );
+
1788
+
1789 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1790 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1791 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1792 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( disk_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1793
+
1794 /* Initialize Tile Geometry */
+
1795
+
1796 RTprogram tile_intersection_program;
+
1797 RTprogram tile_bounding_box_program;
+
1798
+
1799 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &tile ) );
+
1800
+
1801 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "tile_bounds", &tile_bounding_box_program ) );
+
1802 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( tile, tile_bounding_box_program ) );
+
1803 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "tile_intersect", &tile_intersection_program ) );
+
1804 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( tile, tile_intersection_program ) );
1805
-
1806 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1807 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1808 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_CAMERA, closest_hit_camera) );
-
1809 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1810
-
1811 /* Initialize Voxel Geometry */
-
1812
-
1813 RTprogram voxel_intersection_program;
-
1814 RTprogram voxel_bounding_box_program;
-
1815
-
1816 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &voxel ) );
-
1817
-
1818 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "voxel_bounds", &voxel_bounding_box_program ) );
-
1819 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( voxel, voxel_bounding_box_program ) );
-
1820 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "voxel_intersect", &voxel_intersection_program ) );
-
1821 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( voxel, voxel_intersection_program ) );
-
1822
-
1823 /* Create Voxel Material */
-
1824
-
1825 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &voxel_material ) );
+
1806 /* Create Tile Material */
+
1807
+
1808 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &tile_material ) );
+
1809
+
1810 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1811 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1812 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_CAMERA, closest_hit_camera) );
+
1813 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( tile_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1814
+
1815 /* Initialize Voxel Geometry */
+
1816
+
1817 RTprogram voxel_intersection_program;
+
1818 RTprogram voxel_bounding_box_program;
+
1819
+
1820 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &voxel ) );
+
1821
+
1822 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "voxel_bounds", &voxel_bounding_box_program ) );
+
1823 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( voxel, voxel_bounding_box_program ) );
+
1824 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "voxel_intersect", &voxel_intersection_program ) );
+
1825 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( voxel, voxel_intersection_program ) );
1826
-
1827 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1828 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1829 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1830 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1831
-
1832 /* Initialize Bounding Box Geometry */
-
1833
-
1834 RTprogram bbox_intersection_program;
-
1835 RTprogram bbox_bounding_box_program;
-
1836
-
1837 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &bbox ) );
-
1838
-
1839 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "bbox_bounds", &bbox_bounding_box_program ) );
-
1840 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( bbox, bbox_bounding_box_program ) );
-
1841 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "bbox_intersect", &bbox_intersection_program ) );
-
1842 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( bbox, bbox_intersection_program ) );
-
1843
-
1844 /* Create Bounding Box Material */
-
1845
-
1846 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &bbox_material ) );
+
1827 /* Create Voxel Material */
+
1828
+
1829 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &voxel_material ) );
+
1830
+
1831 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1832 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1833 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1834 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( voxel_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1835
+
1836 /* Initialize Bounding Box Geometry */
+
1837
+
1838 RTprogram bbox_intersection_program;
+
1839 RTprogram bbox_bounding_box_program;
+
1840
+
1841 RT_CHECK_ERROR( rtGeometryCreate( OptiX_Context, &bbox ) );
+
1842
+
1843 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "bbox_bounds", &bbox_bounding_box_program ) );
+
1844 RT_CHECK_ERROR( rtGeometrySetBoundingBoxProgram( bbox, bbox_bounding_box_program ) );
+
1845 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_primitiveIntersection.cu.ptx", "bbox_intersect", &bbox_intersection_program ) );
+
1846 RT_CHECK_ERROR( rtGeometrySetIntersectionProgram( bbox, bbox_intersection_program ) );
1847
-
1848 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_DIRECT, closest_hit_direct ) );
-
1849 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
-
1850 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_CAMERA, closest_hit_camera ) );
-
1851 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
-
1852
-
1853 /* Miss Program */
-
1854 RTprogram miss_program_direct;
-
1855 RTprogram miss_program_diffuse;
-
1856 RTprogram miss_program_camera;
-
1857 RTprogram miss_program_pixel_label;
-
1858 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_direct", &miss_program_direct ) );
-
1859 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_DIRECT, miss_program_direct ) );
-
1860 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_diffuse", &miss_program_diffuse ) );
-
1861 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_DIFFUSE, miss_program_diffuse ) );
-
1862 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_camera", &miss_program_camera ) );
-
1863 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_CAMERA, miss_program_camera ) );
-
1864 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_pixel_label", &miss_program_pixel_label ) );
-
1865 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_PIXEL_LABEL, miss_program_pixel_label ) );
-
1866
-
1867 /* Create OptiX Geometry Structures */
-
1868
-
1869 RTtransform transform;
+
1848 /* Create Bounding Box Material */
+
1849
+
1850 RT_CHECK_ERROR( rtMaterialCreate( OptiX_Context, &bbox_material ) );
+
1851
+
1852 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_DIRECT, closest_hit_direct ) );
+
1853 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_DIFFUSE, closest_hit_diffuse ) );
+
1854 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_CAMERA, closest_hit_camera ) );
+
1855 RT_CHECK_ERROR( rtMaterialSetClosestHitProgram( bbox_material, RAYTYPE_PIXEL_LABEL, closest_hit_pixel_label ) );
+
1856
+
1857 /* Miss Program */
+
1858 RTprogram miss_program_direct;
+
1859 RTprogram miss_program_diffuse;
+
1860 RTprogram miss_program_camera;
+
1861 RTprogram miss_program_pixel_label;
+
1862 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_direct", &miss_program_direct ) );
+
1863 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_DIRECT, miss_program_direct ) );
+
1864 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_diffuse", &miss_program_diffuse ) );
+
1865 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_DIFFUSE, miss_program_diffuse ) );
+
1866 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_camera", &miss_program_camera ) );
+
1867 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_CAMERA, miss_program_camera ) );
+
1868 RT_CHECK_ERROR( rtProgramCreateFromPTXFile( OptiX_Context, "plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx", "miss_pixel_label", &miss_program_pixel_label ) );
+
1869 RT_CHECK_ERROR( rtContextSetMissProgram( OptiX_Context, RAYTYPE_PIXEL_LABEL, miss_program_pixel_label ) );
1870
-
1871 RTgeometrygroup geometry_group;
+
1871 /* Create OptiX Geometry Structures */
1872
-
1873 RTgeometryinstance patch_instance;
-
1874 RTgeometryinstance triangle_instance;
-
1875 RTgeometryinstance disk_instance;
-
1876 RTgeometryinstance tile_instance;
-
1877 RTgeometryinstance voxel_instance;
-
1878 RTgeometryinstance bbox_instance;
-
1879
-
1880 /* Create top level group and associated (dummy) acceleration */
-
1881 RT_CHECK_ERROR( rtGroupCreate( OptiX_Context, &top_level_group ) );
-
1882 RT_CHECK_ERROR( rtGroupSetChildCount( top_level_group, 1 ) );
+
1873 RTtransform transform;
+
1874
+
1875 RTgeometrygroup geometry_group;
+
1876
+
1877 RTgeometryinstance patch_instance;
+
1878 RTgeometryinstance triangle_instance;
+
1879 RTgeometryinstance disk_instance;
+
1880 RTgeometryinstance tile_instance;
+
1881 RTgeometryinstance voxel_instance;
+
1882 RTgeometryinstance bbox_instance;
1883
-
1884 RT_CHECK_ERROR( rtAccelerationCreate( OptiX_Context, &top_level_acceleration ) );
-
1885 RT_CHECK_ERROR( rtAccelerationSetBuilder(top_level_acceleration,"NoAccel") );
-
1886 RT_CHECK_ERROR( rtAccelerationSetTraverser(top_level_acceleration,"NoAccel") );
-
1887 RT_CHECK_ERROR( rtGroupSetAcceleration( top_level_group, top_level_acceleration) );
-
1888
-
1889 /* mark acceleration as dirty */
-
1890 RT_CHECK_ERROR( rtAccelerationMarkDirty( top_level_acceleration ) );
-
1891
-
1892 /* Create transform node */
-
1893 RT_CHECK_ERROR( rtTransformCreate( OptiX_Context, &transform ) );
-
1894 float m[16];
-
1895 m[0] = 1.f; m[1] = 0; m[2] = 0; m[3] = 0;
-
1896 m[4] = 0.f; m[5] = 1.f; m[6] = 0; m[7] = 0;
-
1897 m[8] = 0.f; m[9] = 0; m[10] = 1.f; m[11] = 0;
-
1898 m[12] = 0.f; m[13] = 0; m[14] = 0; m[15] = 1.f;
-
1899 RT_CHECK_ERROR( rtTransformSetMatrix( transform, 0, m, nullptr ) );
-
1900 RT_CHECK_ERROR( rtGroupSetChild( top_level_group, 0, transform ) );
-
1901
-
1902 /* Create geometry group and associated acceleration*/
-
1903 RT_CHECK_ERROR( rtGeometryGroupCreate( OptiX_Context, &geometry_group ) );
-
1904 RT_CHECK_ERROR( rtGeometryGroupSetChildCount( geometry_group, 6 ) );
-
1905 RT_CHECK_ERROR( rtTransformSetChild( transform, geometry_group ) );
-
1906
-
1907 //create acceleration object for group and specify some build hints
-
1908 RT_CHECK_ERROR( rtAccelerationCreate(OptiX_Context,&geometry_acceleration) );
-
1909 RT_CHECK_ERROR( rtAccelerationSetBuilder(geometry_acceleration,"Trbvh") );
-
1910 RT_CHECK_ERROR( rtAccelerationSetTraverser(geometry_acceleration,"Bvh") );
-
1911 RT_CHECK_ERROR( rtGeometryGroupSetAcceleration( geometry_group, geometry_acceleration) );
-
1912 RT_CHECK_ERROR( rtAccelerationMarkDirty( geometry_acceleration ) );
-
1913
-
1914 /* Create geometry instances */
-
1915 //patches
-
1916 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &patch_instance ) );
-
1917 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( patch_instance, patch ) );
-
1918 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( patch_instance, 1 ) );
-
1919 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( patch_instance, 0, patch_material ) );
-
1920 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 0, patch_instance ) );
-
1921 //triangles
-
1922 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &triangle_instance ) );
-
1923 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( triangle_instance, triangle ) );
-
1924 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( triangle_instance, 1 ) );
-
1925 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( triangle_instance, 0, triangle_material ) );
-
1926 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 1, triangle_instance ) );
-
1927 //disks
-
1928 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &disk_instance ) );
-
1929 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( disk_instance, disk ) );
-
1930 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( disk_instance, 1 ) );
-
1931 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( disk_instance, 0, disk_material ) );
-
1932 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 2, disk_instance ) );
-
1933 //tiles
-
1934 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &tile_instance ) );
-
1935 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( tile_instance, tile ) );
-
1936 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( tile_instance, 1 ) );
-
1937 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( tile_instance, 0, tile_material ) );
-
1938 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 3, tile_instance ) );
-
1939 //voxels
-
1940 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &voxel_instance ) );
-
1941 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( voxel_instance, voxel ) );
-
1942 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( voxel_instance, 1 ) );
-
1943 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( voxel_instance, 0, voxel_material ) );
-
1944 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 4, voxel_instance ) );
-
1945
-
1946 //voxels
-
1947 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &bbox_instance ) );
-
1948 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( bbox_instance, bbox ) );
-
1949 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( bbox_instance, 1 ) );
-
1950 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( bbox_instance, 0, bbox_material ) );
-
1951 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 5, bbox_instance ) );
-
1952
-
1953 /* Set the top_object variable */
-
1954 //NOTE: Not sure exactly where this has to be set
-
1955 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "top_object", &top_object ) );
-
1956 RT_CHECK_ERROR( rtVariableSetObject( top_object, top_level_group ) );
-
1957
-
1958 //random number seed
-
1959 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "random_seed", &random_seed_RTvariable ) );
-
1960 RT_CHECK_ERROR( rtVariableSet1ui( random_seed_RTvariable, std::chrono::system_clock::now().time_since_epoch().count() ) );
+
1884 /* Create top level group and associated (dummy) acceleration */
+
1885 RT_CHECK_ERROR( rtGroupCreate( OptiX_Context, &top_level_group ) );
+
1886 RT_CHECK_ERROR( rtGroupSetChildCount( top_level_group, 1 ) );
+
1887
+
1888 RT_CHECK_ERROR( rtAccelerationCreate( OptiX_Context, &top_level_acceleration ) );
+
1889 RT_CHECK_ERROR( rtAccelerationSetBuilder(top_level_acceleration,"NoAccel") );
+
1890 RT_CHECK_ERROR( rtAccelerationSetTraverser(top_level_acceleration,"NoAccel") );
+
1891 RT_CHECK_ERROR( rtGroupSetAcceleration( top_level_group, top_level_acceleration) );
+
1892
+
1893 /* mark acceleration as dirty */
+
1894 RT_CHECK_ERROR( rtAccelerationMarkDirty( top_level_acceleration ) );
+
1895
+
1896 /* Create transform node */
+
1897 RT_CHECK_ERROR( rtTransformCreate( OptiX_Context, &transform ) );
+
1898 float m[16];
+
1899 m[0] = 1.f; m[1] = 0; m[2] = 0; m[3] = 0;
+
1900 m[4] = 0.f; m[5] = 1.f; m[6] = 0; m[7] = 0;
+
1901 m[8] = 0.f; m[9] = 0; m[10] = 1.f; m[11] = 0;
+
1902 m[12] = 0.f; m[13] = 0; m[14] = 0; m[15] = 1.f;
+
1903 RT_CHECK_ERROR( rtTransformSetMatrix( transform, 0, m, nullptr ) );
+
1904 RT_CHECK_ERROR( rtGroupSetChild( top_level_group, 0, transform ) );
+
1905
+
1906 /* Create geometry group and associated acceleration*/
+
1907 RT_CHECK_ERROR( rtGeometryGroupCreate( OptiX_Context, &geometry_group ) );
+
1908 RT_CHECK_ERROR( rtGeometryGroupSetChildCount( geometry_group, 6 ) );
+
1909 RT_CHECK_ERROR( rtTransformSetChild( transform, geometry_group ) );
+
1910
+
1911 //create acceleration object for group and specify some build hints
+
1912 RT_CHECK_ERROR( rtAccelerationCreate(OptiX_Context,&geometry_acceleration) );
+
1913 RT_CHECK_ERROR( rtAccelerationSetBuilder(geometry_acceleration,"Trbvh") );
+
1914 RT_CHECK_ERROR( rtAccelerationSetTraverser(geometry_acceleration,"Bvh") );
+
1915 RT_CHECK_ERROR( rtGeometryGroupSetAcceleration( geometry_group, geometry_acceleration) );
+
1916 RT_CHECK_ERROR( rtAccelerationMarkDirty( geometry_acceleration ) );
+
1917
+
1918 /* Create geometry instances */
+
1919 //patches
+
1920 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &patch_instance ) );
+
1921 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( patch_instance, patch ) );
+
1922 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( patch_instance, 1 ) );
+
1923 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( patch_instance, 0, patch_material ) );
+
1924 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 0, patch_instance ) );
+
1925 //triangles
+
1926 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &triangle_instance ) );
+
1927 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( triangle_instance, triangle ) );
+
1928 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( triangle_instance, 1 ) );
+
1929 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( triangle_instance, 0, triangle_material ) );
+
1930 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 1, triangle_instance ) );
+
1931 //disks
+
1932 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &disk_instance ) );
+
1933 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( disk_instance, disk ) );
+
1934 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( disk_instance, 1 ) );
+
1935 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( disk_instance, 0, disk_material ) );
+
1936 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 2, disk_instance ) );
+
1937 //tiles
+
1938 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &tile_instance ) );
+
1939 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( tile_instance, tile ) );
+
1940 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( tile_instance, 1 ) );
+
1941 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( tile_instance, 0, tile_material ) );
+
1942 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 3, tile_instance ) );
+
1943 //voxels
+
1944 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &voxel_instance ) );
+
1945 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( voxel_instance, voxel ) );
+
1946 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( voxel_instance, 1 ) );
+
1947 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( voxel_instance, 0, voxel_material ) );
+
1948 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 4, voxel_instance ) );
+
1949
+
1950 //voxels
+
1951 RT_CHECK_ERROR( rtGeometryInstanceCreate( OptiX_Context, &bbox_instance ) );
+
1952 RT_CHECK_ERROR( rtGeometryInstanceSetGeometry( bbox_instance, bbox ) );
+
1953 RT_CHECK_ERROR( rtGeometryInstanceSetMaterialCount( bbox_instance, 1 ) );
+
1954 RT_CHECK_ERROR( rtGeometryInstanceSetMaterial( bbox_instance, 0, bbox_material ) );
+
1955 RT_CHECK_ERROR( rtGeometryGroupSetChild( geometry_group, 5, bbox_instance ) );
+
1956
+
1957 /* Set the top_object variable */
+
1958 //NOTE: Not sure exactly where this has to be set
+
1959 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "top_object", &top_object ) );
+
1960 RT_CHECK_ERROR( rtVariableSetObject( top_object, top_level_group ) );
1961
-
1962 //launch offset
-
1963 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "launch_offset", &launch_offset_RTvariable ) );
-
1964 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, 0 ) );
+
1962 //random number seed
+
1963 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "random_seed", &random_seed_RTvariable ) );
+
1964 RT_CHECK_ERROR( rtVariableSet1ui( random_seed_RTvariable, std::chrono::system_clock::now().time_since_epoch().count() ) );
1965
-
1966 //maximum scattering depth
-
1967 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, RT_BUFFER_INPUT, &max_scatters_RTbuffer ) );
-
1968 RT_CHECK_ERROR( rtBufferSetFormat( max_scatters_RTbuffer, RT_FORMAT_UNSIGNED_INT ) );
-
1969 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "max_scatters", &max_scatters_RTvariable ) );
-
1970 RT_CHECK_ERROR( rtVariableSetObject( max_scatters_RTvariable, max_scatters_RTbuffer ) );
-
1971 zeroBuffer1D( max_scatters_RTbuffer, 1 );
-
1972
-
1973 // RTsize device_memory;
-
1974 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
1975
-
1976 // device_memory *= 1e-6;
-
1977 // if( device_memory < 1000 ){
-
1978 // printf("available device memory at end of OptiX initialization: %6.3f MB\n",device_memory);
-
1979 // }else{
-
1980 // printf("available device memory at end of OptiX initialization: %6.3f GB\n",device_memory*1e-3);
-
1981 // }
-
1982
-
1983}
-
1984
-
- -
1986 updateGeometry( context->getAllUUIDs() );
+
1966 //launch offset
+
1967 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "launch_offset", &launch_offset_RTvariable ) );
+
1968 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, 0 ) );
+
1969
+
1970 //maximum scattering depth
+
1971 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, RT_BUFFER_INPUT, &max_scatters_RTbuffer ) );
+
1972 RT_CHECK_ERROR( rtBufferSetFormat( max_scatters_RTbuffer, RT_FORMAT_UNSIGNED_INT ) );
+
1973 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "max_scatters", &max_scatters_RTvariable ) );
+
1974 RT_CHECK_ERROR( rtVariableSetObject( max_scatters_RTvariable, max_scatters_RTbuffer ) );
+
1975 zeroBuffer1D( max_scatters_RTbuffer, 1 );
+
1976
+
1977 // RTsize device_memory;
+
1978 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
1979
+
1980 // device_memory *= 1e-6;
+
1981 // if( device_memory < 1000 ){
+
1982 // printf("available device memory at end of OptiX initialization: %6.3f MB\n",device_memory);
+
1983 // }else{
+
1984 // printf("available device memory at end of OptiX initialization: %6.3f GB\n",device_memory*1e-3);
+
1985 // }
+
1986
1987}
-
1988
-
1989void RadiationModel::updateGeometry( const std::vector<uint>& UUIDs ){
-
1990
-
1991 if( message_flag ){
-
1992 std::cout << "Updating geometry in radiation transport model..." << std::flush;
-
1993 }
+ +
1990 updateGeometry( context->getAllUUIDs() );
+
1991}
+
+
1992
+
+
1993void RadiationModel::updateGeometry( const std::vector<uint>& UUIDs ){
1994
-
1995 for ( auto &band : radiation_bands ) {
-
1996 band.second.radiativepropertiesinitialized = false;
+
1995 if( message_flag ){
+
1996 std::cout << "Updating geometry in radiation transport model..." << std::flush;
1997 }
1998
1999 context_UUIDs = UUIDs;
2000
-
2001 for( int u=context_UUIDs.size()-1; u>=0; u-- ){
-
2002 float area = context->getPrimitiveArea(context_UUIDs.at(u));
-
2003 if( !context->doesPrimitiveExist( context_UUIDs.at(u) ) ){
-
2004 context_UUIDs.erase( context_UUIDs.begin()+u );
-
2005 }else if( area==0 || area!=area ){
-
2006 context_UUIDs.erase( context_UUIDs.begin()+u );
-
2007 }
-
2008 }
-
2009
-
2010 //--- Make Bounding Patches ---//
-
2011
-
2012 //determine domain bounding sphere
-
2013 float sphere_radius;
-
2014 vec3 sphere_center;
-
2015 context->getDomainBoundingSphere( sphere_center, sphere_radius );
-
2016
-
2017 rtVariableSet1f( bound_sphere_radius_RTvariable, sphere_radius );
-
2018 rtVariableSet3f( bound_sphere_center_RTvariable, sphere_center.x, sphere_center.y, sphere_center.z );
-
2019
-
2020 //--- Populate Primitive Geometry Buffers ---//
-
2021
-
2022 size_t Nprimitives = context_UUIDs.size(); //Number of primitives
-
2023
-
2024 //transformation matrix buffer - size=Nobjects
-
2025 std::vector<std::vector<float> > m_global;
-
2026
-
2027 //primitive type buffer - size=Nobjects
-
2028 std::vector<uint> ptype_global;
-
2029
-
2030 //primitive area buffer - size=Nobjects
-
2031 std::vector<float> area_global;
-
2032
-
2033 //primitive UUID buffers - total size of all combined is Nobjects
-
2034 std::vector<uint> patch_UUID;
-
2035 std::vector<uint> triangle_UUID;
-
2036 std::vector<uint> disk_UUID;
-
2037 std::vector<uint> tile_UUID;
-
2038 std::vector<uint> voxel_UUID;
-
2039
-
2040 //twosided flag buffer - size=Nobjects
-
2041 std::vector<char> twosided_flag_global;
-
2042
-
2043 //primitive geometry specification buffers
-
2044 std::vector<std::vector<optix::float3> > patch_vertices;
-
2045 std::vector<std::vector<optix::float3> > triangle_vertices;
-
2046 std::vector<std::vector<optix::float3> > disk_vertices;
-
2047 std::vector<std::vector<optix::float3> > tile_vertices;
-
2048 std::vector<std::vector<optix::float3> > voxel_vertices;
-
2049
-
2050 //number of patch subdivisions for each tile - size is same as tile_vertices
-
2051 std::vector<optix::int2> object_subdivisions;
-
2052
-
2053 std::vector<uint> objID_all = context->getAllObjectIDs();
-
2054
-
2055 //ID of object corresponding to each primitive - size Nprimitives
-
2056 std::vector<uint> objectID;
-
2057 objectID.resize(Nprimitives);
-
2058
-
2059 std::size_t patch_count = 0;
-
2060 std::size_t triangle_count = 0;
-
2061 std::size_t disk_count = 0;
-
2062 std::size_t tile_count = 0;
-
2063 std::size_t voxel_count = 0;
-
2064
-
2065 area_global.resize(Nprimitives);
-
2066
-
2067 primitiveID.resize(0);
-
2068
-
2069 //Create a vector of primitive pointers 'primitives' (note: only add one pointer for compound objects)
-
2070 uint objID = 0;
-
2071 uint ID = 99999;
-
2072 for( std::size_t u=0; u<Nprimitives; u++ ){
-
2073
-
2074 uint p = context_UUIDs.at(u);
-
2075
-
2076 //primitve area
-
2077 area_global.at(u) = context->getPrimitiveArea(p);
-
2078
-
2079 uint parentID = context->getPrimitiveParentObjectID(p);
-
2080
-
2081 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
-
2082 primitiveID.push_back( u );
-
2083 ID = parentID;
-
2084 objID++;
-
2085 }else{
-
2086 ID = parentID;
-
2087 }
-
2088
-
2089 assert(objID>0);
-
2090
-
2091 objectID.at(u) = objID-1;
-
2092
-
2093 }
-
2094
-
2095 //Nobjects is the number of isolated primitives plus the number of compound objects (all primitives inside and object combined only counts as one element)
-
2096 size_t Nobjects = primitiveID.size();
-
2097
-
2098 m_global.resize(Nobjects);
-
2099 ptype_global.resize(Nobjects);
-
2100 twosided_flag_global.resize(Nobjects);//initialize to be two-sided
-
2101 for( size_t i=0; i<Nobjects; i++ ){
-
2102 twosided_flag_global.at(i) = 1;
-
2103 }
-
2104
-
2105 //Populate attributes for each primitive in the pointer vector 'primitives'
-
2106 for( std::size_t u=0; u<Nobjects; u++ ){
-
2107
-
2108 uint p = context_UUIDs.at(primitiveID.at(u));
-
2109
-
2110 //transformation matrix
-
2111 float m[16];
-
2112
-
2113 //primitive type
-
2114 helios::PrimitiveType type = context->getPrimitiveType(p);
-
2115 ptype_global.at(u) = type;
-
2116
-
2117 assert( ptype_global.at(u)>=0 && ptype_global.at(u)<=4 );
-
2118
-
2119 //primitive twosided flag
-
2120 if( context->doesPrimitiveDataExist( p,"twosided_flag") ){
-
2121 uint flag;
-
2122 context->getPrimitiveData( p,"twosided_flag",flag);
-
2123 twosided_flag_global.at(u) = char(flag);
-
2124 }
-
2125
-
2126 uint parentID = context->getPrimitiveParentObjectID(p);
-
2127
-
2128 if( parentID>0 && context->getObjectPointer(parentID)->getObjectType()==helios::OBJECT_TYPE_TILE ){//tile objects
-
2129
-
2130 ptype_global.at(u) = 3;
-
2131
-
2132 context->getObjectPointer(parentID)->getTransformationMatrix(m);
-
2133
-
2134 m_global.at(u).resize(16);
-
2135 for( uint i=0; i<16; i++ ){
-
2136 m_global.at(u).at(i) = m[i];
-
2137 }
-
2138
-
2139 std::vector<vec3> vertices = context->getTileObjectPointer(parentID)->getVertices();
-
2140 std::vector<optix::float3> v(4);
-
2141 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
-
2142 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
-
2143 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
-
2144 v.at(3) = optix::make_float3(vertices.at(3).x,vertices.at(3).y,vertices.at(3).z);
-
2145 tile_vertices.push_back(v);
-
2146
-
2147 helios::int2 subdiv = context->getTileObjectPointer(parentID)->getSubdivisionCount();
-
2148
-
2149 object_subdivisions.push_back( optix::make_int2(subdiv.x,subdiv.y) );
-
2150
-
2151 tile_UUID.push_back( primitiveID.at(u) );
-
2152 tile_count ++;
-
2153
-
2154 }else if( type == helios::PRIMITIVE_TYPE_PATCH ){ //patches
-
2155
-
2156 context->getPrimitiveTransformationMatrix( p,m);
-
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(4);
-
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 v.at(3) = optix::make_float3(vertices.at(3).x,vertices.at(3).y,vertices.at(3).z);
-
2169 patch_vertices.push_back(v);
-
2170 object_subdivisions.push_back( optix::make_int2(1,1) );
-
2171 patch_UUID.push_back( primitiveID.at(u) );
-
2172 patch_count ++;
-
2173 }else if( type == helios::PRIMITIVE_TYPE_TRIANGLE ){ //triangles
-
2174
- -
2176
-
2177 m_global.at(u).resize(16);
-
2178 for( uint i=0; i<16; i++ ){
-
2179 m_global.at(u).at(i) = m[i];
-
2180 }
-
2181
-
2182 std::vector<vec3> vertices = context->getPrimitiveVertices(p);
-
2183 std::vector<optix::float3> v(3);
-
2184 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
-
2185 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
-
2186 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
-
2187 triangle_vertices.push_back(v);
-
2188 object_subdivisions.push_back( optix::make_int2(1,1) );
-
2189 triangle_UUID.push_back( primitiveID.at(u) );
-
2190 triangle_count ++;
-
2191 }else if( type == helios::PRIMITIVE_TYPE_VOXEL ){ //voxels
-
2192
- -
2194
-
2195 m_global.at(u).resize(16);
-
2196 for( uint i=0; i<16; i++ ){
-
2197 m_global.at(u).at(i) = m[i];
-
2198 }
-
2199
-
2200 helios::vec3 center = context->getVoxelCenter(p);
-
2201 helios::vec3 size = context->getVoxelSize(p);
-
2202 std::vector<optix::float3> v;
-
2203 v.push_back( optix::make_float3(center.x-0.5f*size.x, center.y-0.5f*size.y, center.z-0.5f*size.z ) );
-
2204 v.push_back( optix::make_float3(center.x+0.5f*size.x, center.y+0.5f*size.y, center.z+0.5f*size.z ) );
-
2205 voxel_vertices.push_back(v);
-
2206 object_subdivisions.push_back( optix::make_int2(1,1) );
-
2207 voxel_UUID.push_back( primitiveID.at(u) );
-
2208 voxel_count ++;
-
2209 }
-
2210
-
2211 }
-
2212
-
2213 //Texture mask data
-
2214 std::vector<std::vector<std::vector<bool> > > maskdata;
-
2215 std::map<std::string,uint> maskname;
-
2216 std::vector<optix::int2> masksize;
-
2217 std::vector<int> maskID;
-
2218 std::vector<std::vector<optix::float2> > uvdata;
-
2219 std::vector<int> uvID;
-
2220 maskID.resize(Nobjects);
-
2221 uvID.resize(Nobjects);
-
2222
-
2223 for( size_t u=0; u<Nobjects; u++ ){
-
2224
-
2225 uint p = context_UUIDs.at(primitiveID.at(u));
-
2226
-
2227 std::string maskfile = context->getPrimitiveTextureFile(p);
-
2228
-
2229 uint parentID = context->getPrimitiveParentObjectID(p);
-
2230
-
2231 if( context->getPrimitiveType(p)==PRIMITIVE_TYPE_VOXEL || maskfile.size()==0 || !context->primitiveTextureHasTransparencyChannel(p) ){ //does not have texture transparency
-
2232
-
2233 maskID.at(u) = -1;
-
2234 uvID.at(u) = -1;
-
2235
-
2236 }else{
-
2237
-
2238 // texture mask data //
-
2239
-
2240 //Check if this mask has already been added
-
2241 if( maskname.find(maskfile) != maskname.end() ){ //has already been added
-
2242 uint ID = maskname.at(maskfile);
-
2243 maskID.at(u) = ID;
-
2244 }else{ //mask has not been added
-
2245
-
2246 uint ID = maskdata.size();
-
2247 maskID.at(u) = ID;
-
2248 maskname[maskfile] = maskdata.size();
-
2249 maskdata.push_back( *context->getPrimitiveTextureTransparencyData(p) );
-
2250 auto sy = maskdata.back().size();
-
2251 auto sx = maskdata.back().front().size();
-
2252 masksize.push_back( optix::make_int2(sx,sy) );
-
2253 }
-
2254
-
2255 // uv coordinates //
-
2256 std::vector<vec2> uv;
-
2257
-
2258 if( parentID==0 || context->getObjectPointer(parentID)->getObjectType()!=helios::OBJECT_TYPE_TILE ){ //primitives
-
2259 uv = context->getPrimitiveTextureUV(p);
-
2260 }
-
2261
-
2262 if( !uv.empty() ){ //has custom (u,v) coordinates
-
2263 std::vector<optix::float2> uvf2;
-
2264 uvf2.resize(4);
-
2265 //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.
-
2266
-
2267 for( int i=0; i<uv.size(); i++ ){
-
2268 uvf2.at(i) = optix::make_float2(uv.at(i).x, uv.at(i).y);
-
2269 }
-
2270 if( uv.size()==3 ){
-
2271 uvf2.at(3) = optix::make_float2(0,0);
-
2272 }
-
2273 uvdata.push_back( uvf2 );
-
2274 uvID.at(u) = uvdata.size()-1;
-
2275 }else{ //DOES NOT have custom (u,v) coordinates
-
2276 uvID.at(u) = -1;
-
2277 }
-
2278
-
2279 }
-
2280 }
-
2281
-
2282 int2 size_max(0,0);
-
2283 for( int t=0; t<maskdata.size(); t++ ){
-
2284 int2 sz( maskdata.at(t).front().size(), maskdata.at(t).size() );
-
2285 if( sz.x>size_max.x ){
-
2286 size_max.x = sz.x;
-
2287 }
-
2288 if( sz.y>size_max.y ){
-
2289 size_max.y = sz.y;
-
2290 }
-
2291 }
-
2292
-
2293 for( int t=0; t<maskdata.size(); t++ ){
-
2294 maskdata.at(t).resize(size_max.y);
-
2295 for( int j=0; j<size_max.y; j++ ){
-
2296 maskdata.at(t).at(j).resize(size_max.x);
-
2297 }
-
2298 }
-
2299
-
2300 initializeBuffer3D( maskdata_RTbuffer, maskdata );
-
2301 initializeBuffer1Dint2( masksize_RTbuffer, masksize );
-
2302 initializeBuffer1Di( maskID_RTbuffer, maskID );
-
2303
-
2304 initializeBuffer2Dfloat2( uvdata_RTbuffer, uvdata );
-
2305 initializeBuffer1Di( uvID_RTbuffer, uvID );
-
2306
-
2307 //Bounding box
-
2308 helios::vec2 xbounds, ybounds, zbounds;
-
2309 context->getDomainBoundingBox( xbounds, ybounds, zbounds );
-
2310
-
2311 if( periodic_flag.x==1 || periodic_flag.y ==1 ) {
-
2312 if (!cameras.empty()) {
-
2313 for (auto &camera: cameras) {
-
2314 vec3 camerapos = camera.second.position;
-
2315 if (camerapos.x < xbounds.x || camerapos.x > xbounds.y || camerapos.y < ybounds.x || camerapos.y > ybounds.y) {
-
2316 std::cout << "WARNING (RadiationModel::updateGeometry): camera position is outside of the domain bounding box. Disabling periodic boundary conditions." << std::endl;
-
2317 periodic_flag.x = 0;
-
2318 periodic_flag.y = 0;
-
2319 break;
-
2320 }
-
2321 if (camerapos.z < zbounds.x) {
-
2322 zbounds.x = camerapos.z;
-
2323 }
-
2324 if (camerapos.z > zbounds.y) {
-
2325 zbounds.y = camerapos.z;
-
2326 }
-
2327 }
-
2328 }
-
2329 }
-
2330
-
2331 xbounds.x -= 1e-5;
-
2332 xbounds.y += 1e-5;
-
2333 ybounds.x -= 1e-5;
-
2334 ybounds.y += 1e-5;
-
2335 zbounds.x -= 1e-5;
-
2336 zbounds.y += 1e-5;
-
2337
-
2338 std::vector<uint> bbox_UUID;
-
2339 int bbox_face_count = 0;
-
2340
-
2341 std::vector<std::vector<optix::float3> > bbox_vertices;
-
2342
-
2343 //primitive type
-
2344
-
2345 std::vector<optix::float3> v;
-
2346 v.resize(4);
-
2347
-
2348 if( periodic_flag.x==1 ){
-
2349
-
2350 // -x facing
-
2351 v.at(0) = optix::make_float3(xbounds.x,ybounds.x,zbounds.x);
-
2352 v.at(1) = optix::make_float3(xbounds.x,ybounds.y,zbounds.x);
-
2353 v.at(2) = optix::make_float3(xbounds.x,ybounds.y,zbounds.y);
-
2354 v.at(3) = optix::make_float3(xbounds.x,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 // +x facing
-
2362 v.at(0) = optix::make_float3(xbounds.y,ybounds.x,zbounds.x);
-
2363 v.at(1) = optix::make_float3(xbounds.y,ybounds.y,zbounds.x);
-
2364 v.at(2) = optix::make_float3(xbounds.y,ybounds.y,zbounds.y);
-
2365 v.at(3) = optix::make_float3(xbounds.y,ybounds.x,zbounds.y);
-
2366 bbox_vertices.push_back(v);
-
2367 bbox_UUID.push_back(Nprimitives+bbox_face_count);
-
2368 objectID.push_back( Nobjects+bbox_face_count );
-
2369 ptype_global.push_back(5);
-
2370 bbox_face_count++;
-
2371
-
2372 }
-
2373 if( periodic_flag.y==1 ){
-
2374
-
2375 // -y facing
-
2376 v.at(0) = optix::make_float3(xbounds.x,ybounds.x,zbounds.x);
-
2377 v.at(1) = optix::make_float3(xbounds.y,ybounds.x,zbounds.x);
-
2378 v.at(2) = optix::make_float3(xbounds.y,ybounds.x,zbounds.y);
-
2379 v.at(3) = optix::make_float3(xbounds.x,ybounds.x,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 // +y facing
-
2387 v.at(0) = optix::make_float3(xbounds.x,ybounds.y,zbounds.x);
-
2388 v.at(1) = optix::make_float3(xbounds.y,ybounds.y,zbounds.x);
-
2389 v.at(2) = optix::make_float3(xbounds.y,ybounds.y,zbounds.y);
-
2390 v.at(3) = optix::make_float3(xbounds.x,ybounds.y,zbounds.y);
-
2391 bbox_vertices.push_back(v);
-
2392 bbox_UUID.push_back(Nprimitives+bbox_face_count);
-
2393 objectID.push_back( Nobjects+bbox_face_count );
-
2394 ptype_global.push_back(5);
-
2395 bbox_face_count++;
-
2396
-
2397 }
-
2398
-
2399 initializeBuffer2Df( transform_matrix_RTbuffer, m_global );
-
2400 initializeBuffer1Dui( primitive_type_RTbuffer, ptype_global );
-
2401 initializeBuffer1Df( primitive_area_RTbuffer, area_global );
-
2402 initializeBuffer1Dchar( twosided_flag_RTbuffer, twosided_flag_global );
-
2403 initializeBuffer2Dfloat3( patch_vertices_RTbuffer, patch_vertices );
-
2404 initializeBuffer2Dfloat3( triangle_vertices_RTbuffer, triangle_vertices );
-
2405 initializeBuffer2Dfloat3( tile_vertices_RTbuffer, tile_vertices );
-
2406 initializeBuffer2Dfloat3( voxel_vertices_RTbuffer, voxel_vertices );
-
2407 initializeBuffer2Dfloat3( bbox_vertices_RTbuffer, bbox_vertices );
-
2408
-
2409 initializeBuffer1Dint2( object_subdivisions_RTbuffer, object_subdivisions );
-
2410
-
2411 initializeBuffer1Dui( patch_UUID_RTbuffer, patch_UUID );
-
2412 initializeBuffer1Dui( triangle_UUID_RTbuffer, triangle_UUID );
-
2413 initializeBuffer1Dui( disk_UUID_RTbuffer, disk_UUID );
-
2414 initializeBuffer1Dui( tile_UUID_RTbuffer, tile_UUID );
-
2415 initializeBuffer1Dui( voxel_UUID_RTbuffer, voxel_UUID );
-
2416 initializeBuffer1Dui( bbox_UUID_RTbuffer, bbox_UUID );
-
2417
-
2418 initializeBuffer1Dui( objectID_RTbuffer, objectID );
-
2419 initializeBuffer1Dui( primitiveID_RTbuffer, primitiveID );
-
2420
-
2421 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( patch, patch_count ) );
-
2422 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( triangle, triangle_count ) );
-
2423 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( disk, disk_count ) );
-
2424 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( tile, tile_count ) );
-
2425 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( voxel, voxel_count ) );
-
2426 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( bbox, bbox_face_count ) );
-
2427
-
2428 RT_CHECK_ERROR( rtAccelerationMarkDirty( geometry_acceleration ) );
-
2429
-
2430 /* Set the top_object variable */
-
2431 //NOTE: not sure if this has to be set again or not..
-
2432 RT_CHECK_ERROR( rtVariableSetObject( top_object, top_level_group ) );
-
2433
-
2434 RTsize device_memory;
-
2435 RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2436
-
2437 device_memory *= 1e-6;
-
2438
-
2439 if( device_memory<500 ){
-
2440 std::cout << "WARNING (RadiationModel): device memory is very low (" << device_memory << " MB)" << std::endl;
-
2441 }
-
2442
-
2443 /* Validate/Compile OptiX Context */
-
2444 RT_CHECK_ERROR( rtContextValidate( OptiX_Context ) );
-
2445 RT_CHECK_ERROR( rtContextCompile( OptiX_Context ) );
-
2446
-
2447 // device_memory;
-
2448 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2449
-
2450 // device_memory *= 1e-6;
-
2451 // if( device_memory < 1000 ){
-
2452 // printf("available device memory at end of OptiX context compile: %6.3f MB\n",device_memory);
-
2453 // }else{
-
2454 // printf("available device memory at end of OptiX context compile: %6.3f GB\n",device_memory*1e-3);
-
2455 // }
-
2456
-
2457 isgeometryinitialized = true;
-
2458
-
2459 // device_memory;
-
2460 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2461
-
2462 // device_memory *= 1e-6;
-
2463 // if( device_memory < 1000 ){
-
2464 // printf("available device memory before acceleration build: %6.3f MB\n",device_memory);
-
2465 // }else{
-
2466 // printf("available device memory before acceleration build: %6.3f GB\n",device_memory*1e-3);
-
2467 // }
-
2468
-
2469 optix::int3 launch_dim_dummy = optix::make_int3( 1, 1, 1 );
-
2470 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIRECT , launch_dim_dummy.x, launch_dim_dummy.y, launch_dim_dummy.z ) );
-
2471
-
2472 RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2473
-
2474 // device_memory;
-
2475 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
-
2476
-
2477 // device_memory *= 1e-6;
-
2478 // if( device_memory < 1000 ){
-
2479 // printf("available device memory at end of acceleration build: %6.3f MB\n",device_memory);
-
2480 // }else{
-
2481 // printf("available device memory at end of acceleration build: %6.3f GB\n",device_memory*1e-3);
-
2482 // }
-
2483
-
2484 if( message_flag ){
-
2485 std::cout << "done." << std::endl;
-
2486 }
-
2487
-
2488}
+
2001 //remove any primitive UUIDs that don't exist or have zero area
+
2002 for( int u=context_UUIDs.size()-1; u>=0; u-- ){
+
2003 float area = context->getPrimitiveArea(context_UUIDs.at(u));
+
2004 if( !context->doesPrimitiveExist( context_UUIDs.at(u) ) ){
+
2005 context_UUIDs.erase( context_UUIDs.begin()+u );
+
2006 }else if( area==0 || area!=area ){
+
2007 context_UUIDs.erase( context_UUIDs.begin()+u );
+
2008 }
+
2009 }
+
2010
+
2011 //--- Make Bounding Patches ---//
+
2012
+
2013 //determine domain bounding sphere
+
2014 float sphere_radius;
+
2015 vec3 sphere_center;
+
2016 context->getDomainBoundingSphere( sphere_center, sphere_radius );
+
2017
+
2018 rtVariableSet1f( bound_sphere_radius_RTvariable, sphere_radius );
+
2019 rtVariableSet3f( bound_sphere_center_RTvariable, sphere_center.x, sphere_center.y, sphere_center.z );
+
2020
+
2021 //--- Populate Primitive Geometry Buffers ---//
+
2022
+
2023 size_t Nprimitives = context_UUIDs.size(); //Number of primitives
+
2024
+
2025 //transformation matrix buffer - size=Nobjects
+
2026 std::vector<std::vector<float> > m_global;
+
2027
+
2028 //primitive type buffer - size=Nobjects
+
2029 std::vector<uint> ptype_global;
+
2030
+
2031 //primitive area buffer - size=Nobjects
+
2032 std::vector<float> area_global;
+
2033
+
2034 //primitive UUID buffers - total size of all combined is Nobjects
+
2035 std::vector<uint> patch_UUID;
+
2036 std::vector<uint> triangle_UUID;
+
2037 std::vector<uint> disk_UUID;
+
2038 std::vector<uint> tile_UUID;
+
2039 std::vector<uint> voxel_UUID;
+
2040
+
2041 //twosided flag buffer - size=Nobjects
+
2042 std::vector<char> twosided_flag_global;
+
2043
+
2044 //primitive geometry specification buffers
+
2045 std::vector<std::vector<optix::float3> > patch_vertices;
+
2046 std::vector<std::vector<optix::float3> > triangle_vertices;
+
2047 std::vector<std::vector<optix::float3> > disk_vertices;
+
2048 std::vector<std::vector<optix::float3> > tile_vertices;
+
2049 std::vector<std::vector<optix::float3> > voxel_vertices;
+
2050
+
2051 //number of patch subdivisions for each tile - size is same as tile_vertices
+
2052 std::vector<optix::int2> object_subdivisions;
+
2053
+
2054 std::vector<uint> objID_all = context->getAllObjectIDs();
+
2055
+
2056 //ID of object corresponding to each primitive - size Nprimitives
+
2057 std::vector<uint> objectID;
+
2058 objectID.resize(Nprimitives);
+
2059
+
2060 std::size_t patch_count = 0;
+
2061 std::size_t triangle_count = 0;
+
2062 std::size_t disk_count = 0;
+
2063 std::size_t tile_count = 0;
+
2064 std::size_t voxel_count = 0;
+
2065
+
2066 area_global.resize(Nprimitives);
+
2067
+
2068 primitiveID.resize(0);
+
2069
+
2070 //Create a vector of primitive pointers 'primitives' (note: only add one pointer for compound objects)
+
2071 uint objID = 0;
+
2072 uint ID = 99999;
+
2073 for( std::size_t u=0; u<Nprimitives; u++ ){
+
2074
+
2075 uint p = context_UUIDs.at(u);
+
2076
+
2077 //primitve area
+
2078 area_global.at(u) = context->getPrimitiveArea(p);
+
2079
+
2080 uint parentID = context->getPrimitiveParentObjectID(p);
+
2081
+
2082 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
+
2083 primitiveID.push_back( u );
+
2084 ID = parentID;
+
2085 objID++;
+
2086 }else{
+
2087 ID = parentID;
+
2088 }
+
2089
+
2090 assert(objID>0);
+
2091
+
2092 objectID.at(u) = objID-1;
+
2093
+
2094 }
+
2095
+
2096 //Nobjects is the number of isolated primitives plus the number of compound objects (all primitives inside and object combined only counts as one element)
+
2097 size_t Nobjects = primitiveID.size();
+
2098
+
2099 m_global.resize(Nobjects);
+
2100 ptype_global.resize(Nobjects);
+
2101 twosided_flag_global.resize(Nobjects);//initialize to be two-sided
+
2102 for( size_t i=0; i<Nobjects; i++ ){
+
2103 twosided_flag_global.at(i) = 1;
+
2104 }
+
2105
+
2106 //Populate attributes for each primitive in the pointer vector 'primitives'
+
2107 for( std::size_t u=0; u<Nobjects; u++ ){
+
2108
+
2109 uint p = context_UUIDs.at(primitiveID.at(u));
+
2110
+
2111 //transformation matrix
+
2112 float m[16];
+
2113
+
2114 //primitive type
+
2115 helios::PrimitiveType type = context->getPrimitiveType(p);
+
2116 ptype_global.at(u) = type;
+
2117
+
2118 assert( ptype_global.at(u)>=0 && ptype_global.at(u)<=4 );
+
2119
+
2120 //primitive twosided flag
+
2121 if( context->doesPrimitiveDataExist( p,"twosided_flag") ){
+
2122 uint flag;
+
2123 context->getPrimitiveData( p,"twosided_flag",flag);
+
2124 twosided_flag_global.at(u) = char(flag);
+
2125 }
+
2126
+
2127 uint parentID = context->getPrimitiveParentObjectID(p);
+
2128
+
2129 if( parentID>0 && context->getObjectPointer(parentID)->getObjectType()==helios::OBJECT_TYPE_TILE ){//tile objects
+
2130
+
2131 ptype_global.at(u) = 3;
+
2132
+
2133 context->getObjectPointer(parentID)->getTransformationMatrix(m);
+
2134
+
2135 m_global.at(u).resize(16);
+
2136 for( uint i=0; i<16; i++ ){
+
2137 m_global.at(u).at(i) = m[i];
+
2138 }
+
2139
+
2140 std::vector<vec3> vertices = context->getTileObjectPointer(parentID)->getVertices();
+
2141 std::vector<optix::float3> v(4);
+
2142 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
+
2143 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
+
2144 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
+
2145 v.at(3) = optix::make_float3(vertices.at(3).x,vertices.at(3).y,vertices.at(3).z);
+
2146 tile_vertices.push_back(v);
+
2147
+
2148 helios::int2 subdiv = context->getTileObjectPointer(parentID)->getSubdivisionCount();
+
2149
+
2150 object_subdivisions.push_back( optix::make_int2(subdiv.x,subdiv.y) );
+
2151
+
2152 tile_UUID.push_back( primitiveID.at(u) );
+
2153 tile_count ++;
+
2154
+
2155 }else if( type == helios::PRIMITIVE_TYPE_PATCH ){ //patches
+
2156
+
2157 context->getPrimitiveTransformationMatrix( p,m);
+
2158
+
2159 m_global.at(u).resize(16);
+
2160 for( uint i=0; i<16; i++ ){
+
2161 m_global.at(u).at(i) = m[i];
+
2162 }
+
2163
+
2164 std::vector<vec3> vertices = context->getPrimitiveVertices(p);
+
2165 std::vector<optix::float3> v(4);
+
2166 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
+
2167 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
+
2168 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
+
2169 v.at(3) = optix::make_float3(vertices.at(3).x,vertices.at(3).y,vertices.at(3).z);
+
2170 patch_vertices.push_back(v);
+
2171 object_subdivisions.push_back( optix::make_int2(1,1) );
+
2172 patch_UUID.push_back( primitiveID.at(u) );
+
2173 patch_count ++;
+
2174 }else if( type == helios::PRIMITIVE_TYPE_TRIANGLE ){ //triangles
+
2175
+
2176 context->getPrimitiveTransformationMatrix(p,m);
+
2177
+
2178 m_global.at(u).resize(16);
+
2179 for( uint i=0; i<16; i++ ){
+
2180 m_global.at(u).at(i) = m[i];
+
2181 }
+
2182
+
2183 std::vector<vec3> vertices = context->getPrimitiveVertices(p);
+
2184 std::vector<optix::float3> v(3);
+
2185 v.at(0) = optix::make_float3(vertices.at(0).x,vertices.at(0).y,vertices.at(0).z);
+
2186 v.at(1) = optix::make_float3(vertices.at(1).x,vertices.at(1).y,vertices.at(1).z);
+
2187 v.at(2) = optix::make_float3(vertices.at(2).x,vertices.at(2).y,vertices.at(2).z);
+
2188 triangle_vertices.push_back(v);
+
2189 object_subdivisions.push_back( optix::make_int2(1,1) );
+
2190 triangle_UUID.push_back( primitiveID.at(u) );
+
2191 triangle_count ++;
+
2192 }else if( type == helios::PRIMITIVE_TYPE_VOXEL ){ //voxels
+
2193
+
2194 context->getPrimitiveTransformationMatrix(p,m);
+
2195
+
2196 m_global.at(u).resize(16);
+
2197 for( uint i=0; i<16; i++ ){
+
2198 m_global.at(u).at(i) = m[i];
+
2199 }
+
2200
+
2201 helios::vec3 center = context->getVoxelCenter(p);
+
2202 helios::vec3 size = context->getVoxelSize(p);
+
2203 std::vector<optix::float3> v;
+
2204 v.push_back( optix::make_float3(center.x-0.5f*size.x, center.y-0.5f*size.y, center.z-0.5f*size.z ) );
+
2205 v.push_back( optix::make_float3(center.x+0.5f*size.x, center.y+0.5f*size.y, center.z+0.5f*size.z ) );
+
2206 voxel_vertices.push_back(v);
+
2207 object_subdivisions.push_back( optix::make_int2(1,1) );
+
2208 voxel_UUID.push_back( primitiveID.at(u) );
+
2209 voxel_count ++;
+
2210 }
+
2211
+
2212 }
+
2213
+
2214 //Texture mask data
+
2215 std::vector<std::vector<std::vector<bool> > > maskdata;
+
2216 std::map<std::string,uint> maskname;
+
2217 std::vector<optix::int2> masksize;
+
2218 std::vector<int> maskID;
+
2219 std::vector<std::vector<optix::float2> > uvdata;
+
2220 std::vector<int> uvID;
+
2221 maskID.resize(Nobjects);
+
2222 uvID.resize(Nobjects);
+
2223
+
2224 for( size_t u=0; u<Nobjects; u++ ){
+
2225
+
2226 uint p = context_UUIDs.at(primitiveID.at(u));
+
2227
+
2228 std::string maskfile = context->getPrimitiveTextureFile(p);
+
2229
+
2230 uint parentID = context->getPrimitiveParentObjectID(p);
+
2231
+
2232 if( context->getPrimitiveType(p)==PRIMITIVE_TYPE_VOXEL || maskfile.size()==0 || !context->primitiveTextureHasTransparencyChannel(p) ){ //does not have texture transparency
+
2233
+
2234 maskID.at(u) = -1;
+
2235 uvID.at(u) = -1;
+
2236
+
2237 }else{
+
2238
+
2239 // texture mask data //
+
2240
+
2241 //Check if this mask has already been added
+
2242 if( maskname.find(maskfile) != maskname.end() ){ //has already been added
+
2243 uint ID = maskname.at(maskfile);
+
2244 maskID.at(u) = ID;
+
2245 }else{ //mask has not been added
+
2246
+
2247 uint ID = maskdata.size();
+
2248 maskID.at(u) = ID;
+
2249 maskname[maskfile] = maskdata.size();
+
2250 maskdata.push_back( *context->getPrimitiveTextureTransparencyData(p) );
+
2251 auto sy = maskdata.back().size();
+
2252 auto sx = maskdata.back().front().size();
+
2253 masksize.push_back( optix::make_int2(sx,sy) );
+
2254 }
+
2255
+
2256 // uv coordinates //
+
2257 std::vector<vec2> uv;
+
2258
+
2259 if( parentID==0 || context->getObjectPointer(parentID)->getObjectType()!=helios::OBJECT_TYPE_TILE ){ //primitives
+
2260 uv = context->getPrimitiveTextureUV(p);
+
2261 }
+
2262
+
2263 if( !uv.empty() ){ //has custom (u,v) coordinates
+
2264 std::vector<optix::float2> uvf2;
+
2265 uvf2.resize(4);
+
2266 //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.
+
2267
+
2268 for( int i=0; i<uv.size(); i++ ){
+
2269 uvf2.at(i) = optix::make_float2(uv.at(i).x, uv.at(i).y);
+
2270 }
+
2271 if( uv.size()==3 ){
+
2272 uvf2.at(3) = optix::make_float2(0,0);
+
2273 }
+
2274 uvdata.push_back( uvf2 );
+
2275 uvID.at(u) = uvdata.size()-1;
+
2276 }else{ //DOES NOT have custom (u,v) coordinates
+
2277 uvID.at(u) = -1;
+
2278 }
+
2279
+
2280 }
+
2281 }
+
2282
+
2283 int2 size_max(0,0);
+
2284 for( int t=0; t<maskdata.size(); t++ ){
+
2285 int2 sz( maskdata.at(t).front().size(), maskdata.at(t).size() );
+
2286 if( sz.x>size_max.x ){
+
2287 size_max.x = sz.x;
+
2288 }
+
2289 if( sz.y>size_max.y ){
+
2290 size_max.y = sz.y;
+
2291 }
+
2292 }
+
2293
+
2294 for( int t=0; t<maskdata.size(); t++ ){
+
2295 maskdata.at(t).resize(size_max.y);
+
2296 for( int j=0; j<size_max.y; j++ ){
+
2297 maskdata.at(t).at(j).resize(size_max.x);
+
2298 }
+
2299 }
+
2300
+
2301 initializeBuffer3D( maskdata_RTbuffer, maskdata );
+
2302 initializeBuffer1Dint2( masksize_RTbuffer, masksize );
+
2303 initializeBuffer1Di( maskID_RTbuffer, maskID );
+
2304
+
2305 initializeBuffer2Dfloat2( uvdata_RTbuffer, uvdata );
+
2306 initializeBuffer1Di( uvID_RTbuffer, uvID );
+
2307
+
2308 //Bounding box
+
2309 helios::vec2 xbounds, ybounds, zbounds;
+
2310 context->getDomainBoundingBox( xbounds, ybounds, zbounds );
+
2311
+
2312 if( periodic_flag.x==1 || periodic_flag.y ==1 ) {
+
2313 if (!cameras.empty()) {
+
2314 for (auto &camera: cameras) {
+
2315 vec3 camerapos = camera.second.position;
+
2316 if (camerapos.x < xbounds.x || camerapos.x > xbounds.y || camerapos.y < ybounds.x || camerapos.y > ybounds.y) {
+
2317 std::cout << "WARNING (RadiationModel::updateGeometry): camera position is outside of the domain bounding box. Disabling periodic boundary conditions." << std::endl;
+
2318 periodic_flag.x = 0;
+
2319 periodic_flag.y = 0;
+
2320 break;
+
2321 }
+
2322 if (camerapos.z < zbounds.x) {
+
2323 zbounds.x = camerapos.z;
+
2324 }
+
2325 if (camerapos.z > zbounds.y) {
+
2326 zbounds.y = camerapos.z;
+
2327 }
+
2328 }
+
2329 }
+
2330 }
+
2331
+
2332 xbounds.x -= 1e-5;
+
2333 xbounds.y += 1e-5;
+
2334 ybounds.x -= 1e-5;
+
2335 ybounds.y += 1e-5;
+
2336 zbounds.x -= 1e-5;
+
2337 zbounds.y += 1e-5;
+
2338
+
2339 std::vector<uint> bbox_UUID;
+
2340 int bbox_face_count = 0;
+
2341
+
2342 std::vector<std::vector<optix::float3> > bbox_vertices;
+
2343
+
2344 //primitive type
+
2345
+
2346 std::vector<optix::float3> v;
+
2347 v.resize(4);
+
2348
+
2349 if( periodic_flag.x==1 ){
+
2350
+
2351 // -x facing
+
2352 v.at(0) = optix::make_float3(xbounds.x,ybounds.x,zbounds.x);
+
2353 v.at(1) = optix::make_float3(xbounds.x,ybounds.y,zbounds.x);
+
2354 v.at(2) = optix::make_float3(xbounds.x,ybounds.y,zbounds.y);
+
2355 v.at(3) = optix::make_float3(xbounds.x,ybounds.x,zbounds.y);
+
2356 bbox_vertices.push_back(v);
+
2357 bbox_UUID.push_back(Nprimitives+bbox_face_count);
+
2358 objectID.push_back( Nobjects+bbox_face_count );
+
2359 ptype_global.push_back(5);
+
2360 bbox_face_count++;
+
2361
+
2362 // +x facing
+
2363 v.at(0) = optix::make_float3(xbounds.y,ybounds.x,zbounds.x);
+
2364 v.at(1) = optix::make_float3(xbounds.y,ybounds.y,zbounds.x);
+
2365 v.at(2) = optix::make_float3(xbounds.y,ybounds.y,zbounds.y);
+
2366 v.at(3) = optix::make_float3(xbounds.y,ybounds.x,zbounds.y);
+
2367 bbox_vertices.push_back(v);
+
2368 bbox_UUID.push_back(Nprimitives+bbox_face_count);
+
2369 objectID.push_back( Nobjects+bbox_face_count );
+
2370 ptype_global.push_back(5);
+
2371 bbox_face_count++;
+
2372
+
2373 }
+
2374 if( periodic_flag.y==1 ){
+
2375
+
2376 // -y facing
+
2377 v.at(0) = optix::make_float3(xbounds.x,ybounds.x,zbounds.x);
+
2378 v.at(1) = optix::make_float3(xbounds.y,ybounds.x,zbounds.x);
+
2379 v.at(2) = optix::make_float3(xbounds.y,ybounds.x,zbounds.y);
+
2380 v.at(3) = optix::make_float3(xbounds.x,ybounds.x,zbounds.y);
+
2381 bbox_vertices.push_back(v);
+
2382 bbox_UUID.push_back(Nprimitives+bbox_face_count);
+
2383 objectID.push_back( Nobjects+bbox_face_count );
+
2384 ptype_global.push_back(5);
+
2385 bbox_face_count++;
+
2386
+
2387 // +y facing
+
2388 v.at(0) = optix::make_float3(xbounds.x,ybounds.y,zbounds.x);
+
2389 v.at(1) = optix::make_float3(xbounds.y,ybounds.y,zbounds.x);
+
2390 v.at(2) = optix::make_float3(xbounds.y,ybounds.y,zbounds.y);
+
2391 v.at(3) = optix::make_float3(xbounds.x,ybounds.y,zbounds.y);
+
2392 bbox_vertices.push_back(v);
+
2393 bbox_UUID.push_back(Nprimitives+bbox_face_count);
+
2394 objectID.push_back( Nobjects+bbox_face_count );
+
2395 ptype_global.push_back(5);
+
2396 bbox_face_count++;
+
2397
+
2398 }
+
2399
+
2400 initializeBuffer2Df( transform_matrix_RTbuffer, m_global );
+
2401 initializeBuffer1Dui( primitive_type_RTbuffer, ptype_global );
+
2402 initializeBuffer1Df( primitive_area_RTbuffer, area_global );
+
2403 initializeBuffer1Dchar( twosided_flag_RTbuffer, twosided_flag_global );
+
2404 initializeBuffer2Dfloat3( patch_vertices_RTbuffer, patch_vertices );
+
2405 initializeBuffer2Dfloat3( triangle_vertices_RTbuffer, triangle_vertices );
+
2406 initializeBuffer2Dfloat3( tile_vertices_RTbuffer, tile_vertices );
+
2407 initializeBuffer2Dfloat3( voxel_vertices_RTbuffer, voxel_vertices );
+
2408 initializeBuffer2Dfloat3( bbox_vertices_RTbuffer, bbox_vertices );
+
2409
+
2410 initializeBuffer1Dint2( object_subdivisions_RTbuffer, object_subdivisions );
+
2411
+
2412 initializeBuffer1Dui( patch_UUID_RTbuffer, patch_UUID );
+
2413 initializeBuffer1Dui( triangle_UUID_RTbuffer, triangle_UUID );
+
2414 initializeBuffer1Dui( disk_UUID_RTbuffer, disk_UUID );
+
2415 initializeBuffer1Dui( tile_UUID_RTbuffer, tile_UUID );
+
2416 initializeBuffer1Dui( voxel_UUID_RTbuffer, voxel_UUID );
+
2417 initializeBuffer1Dui( bbox_UUID_RTbuffer, bbox_UUID );
+
2418
+
2419 initializeBuffer1Dui( objectID_RTbuffer, objectID );
+
2420 initializeBuffer1Dui( primitiveID_RTbuffer, primitiveID );
+
2421
+
2422 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( patch, patch_count ) );
+
2423 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( triangle, triangle_count ) );
+
2424 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( disk, disk_count ) );
+
2425 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( tile, tile_count ) );
+
2426 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( voxel, voxel_count ) );
+
2427 RT_CHECK_ERROR( rtGeometrySetPrimitiveCount( bbox, bbox_face_count ) );
+
2428
+
2429 RT_CHECK_ERROR( rtAccelerationMarkDirty( geometry_acceleration ) );
+
2430
+
2431 /* Set the top_object variable */
+
2432 //NOTE: not sure if this has to be set again or not..
+
2433 RT_CHECK_ERROR( rtVariableSetObject( top_object, top_level_group ) );
+
2434
+
2435 RTsize device_memory;
+
2436 RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2437
+
2438 device_memory *= 1e-6;
+
2439
+
2440 if( device_memory<500 ){
+
2441 std::cout << "WARNING (RadiationModel): device memory is very low (" << device_memory << " MB)" << std::endl;
+
2442 }
+
2443
+
2444 /* Validate/Compile OptiX Context */
+
2445 RT_CHECK_ERROR( rtContextValidate( OptiX_Context ) );
+
2446 RT_CHECK_ERROR( rtContextCompile( OptiX_Context ) );
+
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 at end of OptiX context compile: %6.3f MB\n",device_memory);
+
2454 // }else{
+
2455 // printf("available device memory at end of OptiX context compile: %6.3f GB\n",device_memory*1e-3);
+
2456 // }
+
2457
+
2458 isgeometryinitialized = true;
+
2459
+
2460 // device_memory;
+
2461 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2462
+
2463 // device_memory *= 1e-6;
+
2464 // if( device_memory < 1000 ){
+
2465 // printf("available device memory before acceleration build: %6.3f MB\n",device_memory);
+
2466 // }else{
+
2467 // printf("available device memory before acceleration build: %6.3f GB\n",device_memory*1e-3);
+
2468 // }
+
2469
+
2470 optix::int3 launch_dim_dummy = optix::make_int3( 1, 1, 1 );
+
2471 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIRECT , launch_dim_dummy.x, launch_dim_dummy.y, launch_dim_dummy.z ) );
+
2472
+
2473 RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2474
+
2475 // device_memory;
+
2476 // RT_CHECK_ERROR( rtContextGetAttribute( OptiX_Context, RT_CONTEXT_ATTRIBUTE_AVAILABLE_DEVICE_MEMORY, sizeof(RTsize), &device_memory ) );
+
2477
+
2478 // device_memory *= 1e-6;
+
2479 // if( device_memory < 1000 ){
+
2480 // printf("available device memory at end of acceleration build: %6.3f MB\n",device_memory);
+
2481 // }else{
+
2482 // printf("available device memory at end of acceleration build: %6.3f GB\n",device_memory*1e-3);
+
2483 // }
+
2484
+
2485 radiativepropertiesneedupdate = true;
+
2486
+
2487 if( message_flag ){
+
2488 std::cout << "done." << std::endl;
+
2489 }
+
2490
+
2491}
-
2489
-
2490void RadiationModel::updateRadiativeProperties( const std::vector<std::string> &labels ) {
-
2491
-
2492 // Possible scenarios for specifying a primitive's radiative properties
-
2493 // 1. If primitive data of form reflectivity_band/transmissivity_band is given, this value is used and overrides any other option.
-
2494 // 2. If primitive data of form reflectivity_spectrum/transmissivity_spectrum is given that references global data containing spectral reflectivity/transmissivity:
-
2495 // 2a. If radiation source spectrum was not given, assume source spectral intensity is constant over band and calculate using primitive spectrum
-
2496 // 2b. If radiation source spectrum was given, calculate using both source and primitive spectrum.
-
2497
-
2498 if( message_flag ) {
-
2499 std::cout << "Updating radiative properties..." << std::flush;
-
2500 }
-
2501
-
2502 uint Nbands = labels.size();//number of radiative bands
-
2503 uint Nsources = radiation_sources.size();
-
2504 uint Ncameras = cameras.size();
-
2505 size_t Nobjects = primitiveID.size();
-
2506 size_t Nprimitives = context_UUIDs.size();
-
2507
-
2508 scattering_iterations_needed.resize(Nbands);
-
2509 for( int b=0; b<Nbands; b++ ){
-
2510 scattering_iterations_needed.at(b) = false;
-
2511 }
-
2512
-
2513 std::vector<std::vector<std::vector<float> > > rho, tau; //first index is the source, second index is the primitive, third index is the band
-
2514 std::vector<std::vector<std::vector<std::vector<float> > > > rho_cam, tau_cam; //Fourth index is the camera
-
2515 float eps;
-
2516
-
2517 std::string prop;
-
2518
-
2519 for( auto &label : radiation_bands){
-
2520 label.second.radiativepropertiesinitialized = false;
-
2521 }
-
2522 for ( const auto &label: labels) {
-
2523 radiation_bands.at(label).radiativepropertiesinitialized = true;
+
2492
+
2493void RadiationModel::updateRadiativeProperties() {
+
2494
+
2495 // Possible scenarios for specifying a primitive's radiative properties
+
2496 // 1. If primitive data of form reflectivity_band/transmissivity_band is given, this value is used and overrides any other option.
+
2497 // 2. If primitive data of form reflectivity_spectrum/transmissivity_spectrum is given that references global data containing spectral reflectivity/transmissivity:
+
2498 // 2a. If radiation source spectrum was not given, assume source spectral intensity is constant over band and calculate using primitive spectrum
+
2499 // 2b. If radiation source spectrum was given, calculate using both source and primitive spectrum.
+
2500
+
2501 if( message_flag ) {
+
2502 std::cout << "Updating radiative properties..." << std::flush;
+
2503 }
+
2504
+
2505 uint Nbands = radiation_bands.size();//number of radiative bands
+
2506 uint Nsources = radiation_sources.size();
+
2507 uint Ncameras = cameras.size();
+
2508 size_t Nobjects = primitiveID.size();
+
2509 size_t Nprimitives = context_UUIDs.size();
+
2510
+
2511 scattering_iterations_needed.clear();
+
2512 for( auto &band : radiation_bands ){
+
2513 scattering_iterations_needed[band.first] = false;
+
2514 }
+
2515
+
2516 std::vector<std::vector<std::vector<float> > > rho, tau; //first index is the source, second index is the primitive, third index is the band
+
2517 std::vector<std::vector<std::vector<std::vector<float> > > > rho_cam, tau_cam; //Fourth index is the camera
+
2518 float eps;
+
2519
+
2520 std::string prop;
+
2521 std::vector<std::string> band_labels;
+
2522 for ( auto &band : radiation_bands ) {
+
2523 band_labels.push_back(band.first);
2524 }
2525
2526 rho.resize(Nsources);
@@ -2813,25 +2820,25 @@
2561
2562 for (uint b = 0; b < Nbands; b++) {
2563
-
2564 if( camera.second.band_spectral_response.find(labels.at(b)) == camera.second.band_spectral_response.end() ){
+
2564 if( camera.second.band_spectral_response.find(band_labels.at(b)) == camera.second.band_spectral_response.end() ){
2565 continue;
2566 }
2567
-
2568 std::string camera_response = camera.second.band_spectral_response.at(labels.at(b));
+
2568 std::string camera_response = camera.second.band_spectral_response.at(band_labels.at(b));
2569
2570 if (!camera_response.empty()) {
2571
-
2572 if( !context->doesGlobalDataExist(camera_response.c_str()) ){
+
2572 if( !context->doesGlobalDataExist(camera_response.c_str()) ){
2573 if( camera_response!="uniform" ) {
2574 std::cerr << "WARNING (RadiationModel::updateRadiativeProperties): Camera spectral response \"" << camera_response << "\" does not exist. Assuming a uniform spectral response..." << std::flush;
2575 }
-
2576 }else if ( context->getGlobalDataType(camera_response.c_str()) == helios::HELIOS_TYPE_VEC2) {
+
2576 }else if ( context->getGlobalDataType(camera_response.c_str()) == helios::HELIOS_TYPE_VEC2) {
2577
2578 std::vector<helios::vec2> data = loadSpectralData(camera_response.c_str());
2579
2580 camera_response_unique.at(cam).at(b) = data;
2581
-
2582 }else if ( context->getGlobalDataType(camera_response.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(camera_response.c_str()) != helios::HELIOS_TYPE_STRING ) {
+
2582 }else if ( context->getGlobalDataType(camera_response.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(camera_response.c_str()) != helios::HELIOS_TYPE_STRING ) {
2583 camera_response.clear();
2584 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;
2585 }
@@ -2852,25 +2859,25 @@
2600
2601 uint UUID = context_UUIDs.at(u);
2602
-
2603 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum") ) {
-
2604 if (context->getPrimitiveDataType(UUID, "reflectivity_spectrum") == HELIOS_TYPE_STRING) {
+
2603 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum") ) {
+
2604 if (context->getPrimitiveDataType(UUID, "reflectivity_spectrum") == HELIOS_TYPE_STRING) {
2605 std::string spectrum_label;
-
2606 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectrum_label);
+
2606 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectrum_label);
2607
2608 //get the spectral reflectivity data and store it in surface_spectra to avoid having to load it again
2609 if (surface_spectra_rho.find(spectrum_label) == surface_spectra_rho.end() ){
-
2610 if( !context->doesGlobalDataExist(spectrum_label.c_str()) ){
+
2610 if( !context->doesGlobalDataExist(spectrum_label.c_str()) ){
2611 if (message_flag && !spectrum_label.empty() ) {
2612 std::cerr << "WARNING (RadiationModel::runBand): Primitive spectral reflectivity \"" << spectrum_label << "\" does not exist. Using default reflectivity of 0..." << std::flush;
2613 }
2614 std::vector<helios::vec2> data;
2615 surface_spectra_rho.emplace(spectrum_label, data);
-
2616 }else if( context->getGlobalDataType(spectrum_label.c_str() ) == HELIOS_TYPE_VEC2 ) {
+
2616 }else if( context->getGlobalDataType(spectrum_label.c_str() ) == HELIOS_TYPE_VEC2 ) {
2617
2618 std::vector<helios::vec2> data = loadSpectralData(spectrum_label.c_str());
2619 surface_spectra_rho.emplace(spectrum_label, data);
2620
-
2621 }else if ( context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_STRING ) {
+
2621 }else if ( context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_STRING ) {
2622 spectrum_label.clear();
2623 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;
2624 }
@@ -2880,25 +2887,25 @@
2628 }
2629 }
2630
-
2631 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum") ) {
-
2632 if (context->getPrimitiveDataType(UUID, "transmissivity_spectrum") == HELIOS_TYPE_STRING) {
+
2631 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum") ) {
+
2632 if (context->getPrimitiveDataType(UUID, "transmissivity_spectrum") == HELIOS_TYPE_STRING) {
2633 std::string spectrum_label;
-
2634 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectrum_label);
+
2634 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectrum_label);
2635
2636 //get the spectral transmissivity data and store it in surface_spectra to avoid having to load it again
2637 if (surface_spectra_tau.find(spectrum_label) == surface_spectra_tau.end() ){
-
2638 if( !context->doesGlobalDataExist(spectrum_label.c_str()) ) {
+
2638 if( !context->doesGlobalDataExist(spectrum_label.c_str()) ) {
2639 if (message_flag && !spectrum_label.empty() ){
2640 std::cerr << "WARNING (RadiationModel::runBand): Primitive spectral transmissivity \"" << spectrum_label << "\" does not exist. Using default transmissivity of 0..." << std::flush;
2641 }
2642 std::vector<helios::vec2> data;
2643 surface_spectra_tau.emplace(spectrum_label, data);
-
2644 }else if( context->getGlobalDataType(spectrum_label.c_str() ) == HELIOS_TYPE_VEC2 ) {
+
2644 }else if( context->getGlobalDataType(spectrum_label.c_str() ) == HELIOS_TYPE_VEC2 ) {
2645
2646 std::vector<helios::vec2> data = loadSpectralData(spectrum_label.c_str());
2647 surface_spectra_tau.emplace(spectrum_label, data);
2648
-
2649 }else if ( context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_STRING ) {
+
2649 }else if ( context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_VEC2 && context->getGlobalDataType(spectrum_label.c_str()) != helios::HELIOS_TYPE_STRING ) {
2650 spectrum_label.clear();
2651 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;
2652 }
@@ -2941,7 +2948,7 @@
2689 }
2690
2691 for (uint b = 0; b < Nbands; b++) {
-
2692 std::string band = labels.at(b);
+
2692 std::string band = band_labels.at(b);
2693
2694 for (uint s = 0; s < Nsources; s++) {
2695
@@ -2999,7 +3006,7 @@
2747 }
2748
2749 for( uint b=0; b<Nbands; b++ ) {
-
2750 std::string band = labels.at(b);
+
2750 std::string band = band_labels.at(b);
2751
2752 for (uint s = 0; s < Nsources; s++) {
2753
@@ -3052,7 +3059,7 @@
2800
2801 uint UUID = context_UUIDs.at(u);
2802
-
2803 helios::PrimitiveType type = context->getPrimitiveType(UUID);
+
2803 helios::PrimitiveType type = context->getPrimitiveType(UUID);
2804
2805 if (type == helios::PRIMITIVE_TYPE_VOXEL) {
2806
@@ -3118,25 +3125,25 @@
2866
2867 //check for primitive data of form "reflectivity_spectrum" that can be used to calculate reflectivity
2868 std::string spectrum_label;
-
2869 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum")) {
-
2870 if (context->getPrimitiveDataType(UUID, "reflectivity_spectrum") == HELIOS_TYPE_STRING) {
-
2871 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectrum_label);
+
2869 if (context->doesPrimitiveDataExist(UUID, "reflectivity_spectrum")) {
+
2870 if (context->getPrimitiveDataType(UUID, "reflectivity_spectrum") == HELIOS_TYPE_STRING) {
+
2871 context->getPrimitiveData(UUID, "reflectivity_spectrum", spectrum_label);
2872 }
2873 }
2874
2875 uint b = 0;
-
2876 for (const auto &band: labels) {
+
2876 for (const auto &band : band_labels) {
2877
2878 //check for primitive data of form "reflectivity_bandname"
2879 prop = "reflectivity_" + band;
2880
2881 float rho_s = rho_default;
-
2882 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
-
2883 context->getPrimitiveData(UUID, prop.c_str(), rho_s);
+
2882 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
+
2883 context->getPrimitiveData(UUID, prop.c_str(), rho_s);
2884 }
2885
2886 for (uint s = 0; s < Nsources; s++) {
-
2887 if (!spectrum_label.empty() && context->doesGlobalDataExist(spectrum_label.c_str())) {
+
2887 if (!spectrum_label.empty() && context->doesGlobalDataExist(spectrum_label.c_str())) {
2888
2889 rho.at(s).at(u).at(b) = rho_unique.at(spectrum_label).at(b).at(s);
2890
@@ -3168,11 +3175,11 @@
2916 }
2917 }
2918 if( rho.at(s).at(u).at(b)!=0 ){
-
2919 scattering_iterations_needed.at(b) = true;
+
2919 scattering_iterations_needed.at(band) = true;
2920 }
2921 for( auto &odata : output_prim_data ) {
2922 if ( odata == "reflectivity" ){
-
2923 context->setPrimitiveData( UUID, ("reflectivity_" + std::to_string(s) + "_" + band).c_str(), rho.at(s).at(u).at(b) );
+
2923 context->setPrimitiveData( UUID, ("reflectivity_" + std::to_string(s) + "_" + band).c_str(), rho.at(s).at(u).at(b) );
2924 }
2925 }
2926
@@ -3184,25 +3191,25 @@
2932
2933 //check for primitive data of form "transmissivity_spectrum" that can be used to calculate transmissivity
2934 spectrum_label.resize(0);
-
2935 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum")) {
-
2936 if (context->getPrimitiveDataType(UUID, "transmissivity_spectrum") == HELIOS_TYPE_STRING) {
-
2937 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectrum_label);
+
2935 if (context->doesPrimitiveDataExist(UUID, "transmissivity_spectrum")) {
+
2936 if (context->getPrimitiveDataType(UUID, "transmissivity_spectrum") == HELIOS_TYPE_STRING) {
+
2937 context->getPrimitiveData(UUID, "transmissivity_spectrum", spectrum_label);
2938 }
2939 }
2940
2941 b = 0;
-
2942 for ( const auto &band: labels ) {
+
2942 for ( const auto &band : band_labels ) {
2943
2944 //check for primitive data of form "transmissivity_bandname"
2945 prop = "transmissivity_" + band;
2946
2947 float tau_s = tau_default;
-
2948 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
-
2949 context->getPrimitiveData(UUID, prop.c_str(), tau_s);
+
2948 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
+
2949 context->getPrimitiveData(UUID, prop.c_str(), tau_s);
2950 }
2951
2952 for (uint s = 0; s < Nsources; s++) {
-
2953 if (!spectrum_label.empty() && context->doesGlobalDataExist(spectrum_label.c_str())) {
+
2953 if (!spectrum_label.empty() && context->doesGlobalDataExist(spectrum_label.c_str())) {
2954 tau.at(s).at(u).at(b) = tau_unique.at(spectrum_label).at(b).at(s);
2955
2956 //cameras
@@ -3233,11 +3240,11 @@
2981 }
2982 }
2983 if( tau.at(s).at(u).at(b)!=0 ){
-
2984 scattering_iterations_needed.at(b) = true;
+
2984 scattering_iterations_needed.at(band) = true;
2985 }
2986 for( auto &odata : output_prim_data ) {
2987 if (odata == "transmissivity" ){
-
2988 context->setPrimitiveData( UUID, ("transmissivity_" + std::to_string(s) + "_" + band).c_str(), tau.at(s).at(u).at(b) );
+
2988 context->setPrimitiveData( UUID, ("transmissivity_" + std::to_string(s) + "_" + band).c_str(), tau.at(s).at(u).at(b) );
2989 }
2990 }
2991 }
@@ -3247,12 +3254,12 @@
2995 // Emissivity (only for error checking)
2996
2997 b = 0;
-
2998 for (const auto &band: labels) {
+
2998 for (const auto &band : band_labels) {
2999
3000 prop = "emissivity_" + band;
3001
-
3002 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
-
3003 context->getPrimitiveData(UUID, prop.c_str(), eps);
+
3002 if (context->doesPrimitiveDataExist(UUID, prop.c_str())) {
+
3003 context->getPrimitiveData(UUID, prop.c_str(), eps);
3004 } else {
3005 eps = eps_default;
3006 }
@@ -3269,7 +3276,7 @@
3017 }
3018 }
3019 if( eps!=1 ){
-
3020 scattering_iterations_needed.at(b) = true;
+
3020 scattering_iterations_needed.at(band) = true;
3021 }
3022
3023 assert(doesBandExist(band));
@@ -3310,751 +3317,751 @@
3058 initializeBuffer1Df(rho_cam_RTbuffer, flatten(rho_cam));
3059 initializeBuffer1Df(tau_cam_RTbuffer, flatten(tau_cam));
3060
-
3061 if( message_flag ) {
-
3062 std::cout << "done\n";
-
3063 }
-
3064
-
3065}
+
3061 radiativepropertiesneedupdate = false;
+
3062
+
3063 if( message_flag ) {
+
3064 std::cout << "done\n";
+
3065 }
3066
-
3067std::vector<helios::vec2> RadiationModel::loadSpectralData( const std::string &global_data_label ) const{
+
3067}
3068
-
3069 std::vector<helios::vec2> spectrum;
+
3069std::vector<helios::vec2> RadiationModel::loadSpectralData( const std::string &global_data_label ) const{
3070
-
3071 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
+
3071 std::vector<helios::vec2> spectrum;
3072
-
3073 //check if spectral data exists in any of the library files
-
3074 bool data_found = false;
-
3075 for( const auto &file : spectral_library_files ){
-
3076 if( Context::scanXMLForTag( file, "globaldata_vec2", global_data_label ) ){
-
3077 context->loadXML( file.c_str(), true );
-
3078 data_found = true;
-
3079 break;
-
3080 }
-
3081 }
-
3082
-
3083 if( !data_found ) {
-
3084 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' could not be found.");
-
3085 }
-
3086 }
-
3087
-
3088 if( context->getGlobalDataType(global_data_label.c_str()) != HELIOS_TYPE_VEC2 ){
-
3089 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' is not of type HELIOS_TYPE_VEC2.");
-
3090 }
-
3091
-
3092 context->getGlobalData(global_data_label.c_str(), spectrum);
+
3073 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
+
3074
+
3075 //check if spectral data exists in any of the library files
+
3076 bool data_found = false;
+
3077 for( const auto &file : spectral_library_files ){
+
3078 if( Context::scanXMLForTag( file, "globaldata_vec2", global_data_label ) ){
+
3079 context->loadXML( file.c_str(), true );
+
3080 data_found = true;
+
3081 break;
+
3082 }
+
3083 }
+
3084
+
3085 if( !data_found ) {
+
3086 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' could not be found.");
+
3087 }
+
3088 }
+
3089
+
3090 if( context->getGlobalDataType(global_data_label.c_str()) != HELIOS_TYPE_VEC2 ){
+
3091 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' is not of type HELIOS_TYPE_VEC2.");
+
3092 }
3093
-
3094 //validate spectrum
-
3095 if( spectrum.empty() ){
-
3096 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' is empty.");
-
3097 }
-
3098 for( auto s=0; s<spectrum.size(); s++ ) {
-
3099 //check that wavelengths are monotonic
-
3100 if( s>0 && spectrum.at(s).x<=spectrum.at(s-1).x ) {
-
3101 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Source spectral data validation failed. Wavelengths must increase monotonically.");
-
3102 }
-
3103 //check that wavelength is within a reasonable range
-
3104 if( spectrum.at(s).x<0 || spectrum.at(s).x>100000 ) {
-
3105 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.");
-
3106 }
-
3107 //check that flux is non-negative
-
3108 if( spectrum.at(s).y<0 ) {
-
3109 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.");
-
3110 }
-
3111 }
-
3112
-
3113 return spectrum;
+
3094 context->getGlobalData(global_data_label.c_str(), spectrum);
+
3095
+
3096 //validate spectrum
+
3097 if( spectrum.empty() ){
+
3098 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Global data for spectrum '" + global_data_label + "' is empty.");
+
3099 }
+
3100 for( auto s=0; s<spectrum.size(); s++ ) {
+
3101 //check that wavelengths are monotonic
+
3102 if( s>0 && spectrum.at(s).x<=spectrum.at(s-1).x ) {
+
3103 helios_runtime_error("ERROR (RadiationModel::loadSpectralData): Source spectral data validation failed. Wavelengths must increase monotonically.");
+
3104 }
+
3105 //check that wavelength is within a reasonable range
+
3106 if( spectrum.at(s).x<0 || spectrum.at(s).x>100000 ) {
+
3107 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.");
+
3108 }
+
3109 //check that flux is non-negative
+
3110 if( spectrum.at(s).y<0 ) {
+
3111 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.");
+
3112 }
+
3113 }
3114
-
3115}
+
3115 return spectrum;
3116
-
-
3117void RadiationModel::runBand( const std::string &label ) {
-
3118 std::vector<std::string> labels{label};
-
3119 runBand(labels);
-
3120}
+
3117}
+
3118
+
+
3119void RadiationModel::runBand( const std::string &label ) {
+
3120 std::vector<std::string> labels{label};
+
3121 runBand(labels);
+
3122}
-
3121
-
-
3122void RadiationModel::runBand( const std::vector<std::string> &label ) {
3123
-
3124 //----- VERIFICATIONS -----//
+
+
3124void RadiationModel::runBand( const std::vector<std::string> &label ) {
3125
-
3126 //Check to make sure some geometry was added to the context
-
3127 if( context->getPrimitiveCount()==0 ){
-
3128 std::cerr << "WARNING (RadiationModel::runBand): No geometry was added to the context. There is nothing to simulate...exiting." << std::endl;
-
3129 return;
-
3130 }
-
3131
-
3132 //Check to make sure geometry was built in OptiX
-
3133 if( !isgeometryinitialized ){
- +
3126 //----- VERIFICATIONS -----//
+
3127
+
3128 //We need the band label strings to appear in the same order as in radiation_bands map.
+
3129 //this is because that was the order in which radiative properties were laid out when updateRadiativeProperties() was called
+
3130 std::vector<std::string> band_labels;
+
3131 for( auto &band : radiation_bands ){
+
3132 if( std::find( label.begin(), label.end(), band.first ) != label.end() ) {
+
3133 band_labels.push_back(band.first);
+
3134 }
3135 }
3136
-
3137 for( const std::string &band : label ){
-
3138 if( !doesBandExist(band) ){
-
3139 helios_runtime_error("ERROR (RadiationModel::runBand): Cannot run band " + band + " because it is not a valid band. Use addRadiationBand() function to add the band.");
-
3140 }
+
3137 //Check to make sure some geometry was added to the context
+
3138 if( context->getPrimitiveCount()==0 ){
+
3139 std::cerr << "WARNING (RadiationModel::runBand): No geometry was added to the context. There is nothing to simulate...exiting." << std::endl;
+
3140 return;
3141 }
3142
-
3143 //if there are no radiation sources in the simulation, add at least one but with zero fluxes
-
3144 if( radiation_sources.empty() ){
- +
3143 //Check to make sure geometry was built in OptiX
+
3144 if( !isgeometryinitialized ){
+
3146 }
3147
-
3148 for( const auto &band : label ) {
-
3149 if (!radiation_bands.at(band).radiativepropertiesinitialized) {
-
3150 updateRadiativeProperties(label);
-
3151 break;
+
3148 //Check that all the bands passed to the runBand() method exist
+
3149 for( const std::string &band : band_labels ){
+
3150 if( !doesBandExist(band) ){
+
3151 helios_runtime_error("ERROR (RadiationModel::runBand): Cannot run band " + band + " because it is not a valid band. Use addRadiationBand() function to add the band.");
3152 }
3153 }
3154
-
3155 //Set the number of radiative bands
-
3156 size_t Nbands = label.size();
-
3157
-
3158 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_RTvariable, Nbands ) );
+
3155 //if there are no radiation sources in the simulation, add at least one but with zero fluxes
+
3156 if( radiation_sources.empty() ){
+ +
3158 }
3159
-
3160 //Run all bands by default
-
3161 std::vector<char> band_launch_flag(Nbands);
-
3162 for( uint b=0; b<Nbands; b++ ){
-
3163 band_launch_flag.at(b) = 1;
-
3164 }
-
3165 initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag );
-
3166
-
3167 //Set the number of Context primitives
-
3168 size_t Nobjects = primitiveID.size();
-
3169 size_t Nprimitives = context_UUIDs.size();
-
3170 RT_CHECK_ERROR( rtVariableSet1ui( Nprimitives_RTvariable, Nprimitives ) );
+
3160 if( radiativepropertiesneedupdate ){
+
3161 updateRadiativeProperties();
+
3162 }
+
3163
+
3164 //Number of radiation bands in this launch
+
3165 size_t Nbands_launch = band_labels.size();
+
3166 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_launch_RTvariable, Nbands_launch ) );
+
3167
+
3168 //Number of total bands in the radiation model
+
3169 size_t Nbands_global = radiation_bands.size();
+
3170 RT_CHECK_ERROR( rtVariableSet1ui( Nbands_global_RTvariable, Nbands_global ) );
3171
-
3172 //Set the random number seed
-
3173 RT_CHECK_ERROR( rtVariableSet1ui( random_seed_RTvariable, std::chrono::system_clock::now().time_since_epoch().count() ) );
-
3174
-
3175 //Number of external radiation sources
-
3176 uint Nsources = radiation_sources.size();
-
3177 RT_CHECK_ERROR( rtVariableSet1ui( Nsources_RTvariable, Nsources ) );
-
3178
-
3179 //Set periodic boundary condition (if applicable)
-
3180 RT_CHECK_ERROR( rtVariableSet2f( periodic_flag_RTvariable, periodic_flag.x, periodic_flag.y ));
-
3181
-
3182 //Number of radiation cameras
-
3183 uint Ncameras = cameras.size();
-
3184 RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, Ncameras ) );
-
3185
-
3186 //Set scattering depth for each band
-
3187 std::vector<uint> scattering_depth(Nbands);
-
3188 bool scatteringenabled = false;
-
3189 for( auto b=0; b<Nbands; b++ ){
-
3190 scattering_depth.at(b) = radiation_bands.at(label.at(b)).scatteringDepth;
-
3191 if( scattering_depth.at(b)>0 ){
-
3192 scatteringenabled=true;
-
3193 }
-
3194 }
-
3195 initializeBuffer1Dui( max_scatters_RTbuffer, scattering_depth );
-
3196
-
3197 //Issue warning if rho>0, tau>0, or eps<1
-
3198 for( int b=0; b<Nbands; b++ ){
-
3199 if( scattering_depth.at(b)==0 && scattering_iterations_needed.at(b) ){
-
3200 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;
-
3201 }
-
3202 }
-
3203
-
3204 //Set diffuse flux for each band
-
3205 std::vector<float> diffuse_flux(Nbands);
-
3206 bool diffuseenabled = false;
-
3207 for( auto b=0; b<Nbands; b++ ){
-
3208 diffuse_flux.at(b) = getDiffuseFlux( label.at(b) );
-
3209 if( diffuse_flux.at(b)>0.f ){
-
3210 diffuseenabled=true;
-
3211 }
-
3212 }
-
3213 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
-
3214
-
3215 //Set diffuse extinction coefficient for each band
-
3216 std::vector<float> diffuse_extinction(Nbands,0);
-
3217 if( diffuseenabled ) {
-
3218 for (auto b = 0; b < Nbands; b++) {
-
3219 diffuse_extinction.at(b) = radiation_bands.at(label.at(b)).diffuseExtinction;
-
3220 }
-
3221 }
-
3222 initializeBuffer1Df(diffuse_extinction_RTbuffer, diffuse_extinction);
-
3223
-
3224 //Set diffuse distribution normalization factor for each band
-
3225 std::vector<float> diffuse_dist_norm(Nbands,0);
-
3226 if( diffuseenabled ) {
-
3227 for (auto b = 0; b < Nbands; b++) {
-
3228 diffuse_dist_norm.at(b) = radiation_bands.at(label.at(b)).diffuseDistNorm;
-
3229 }
-
3230 initializeBuffer1Df(diffuse_dist_norm_RTbuffer, diffuse_dist_norm);
-
3231 }
-
3232
-
3233 //Set diffuse distribution peak direction for each band
-
3234 std::vector<optix::float3> diffuse_peak_dir(Nbands);
-
3235 if( diffuseenabled ) {
-
3236 for (auto b = 0; b < Nbands; b++) {
-
3237 helios::vec3 peak_dir = radiation_bands.at(label.at(b)).diffusePeakDir;
-
3238 diffuse_peak_dir.at(b) = optix::make_float3(peak_dir.x,peak_dir.y,peak_dir.z);
-
3239 }
-
3240 initializeBuffer1Dfloat3(diffuse_peak_dir_RTbuffer, diffuse_peak_dir);
-
3241 }
-
3242
-
3243 //Determine whether emission is enabled for any band
-
3244 bool emissionenabled = false;
-
3245 for( auto b=0; b<Nbands; b++ ){
-
3246 if( radiation_bands.at(label.at(b)).emissionFlag ){
-
3247 emissionenabled=true;
-
3248 }
-
3249 }
-
3250
-
3251 //Figure out the maximum direct ray count for all bands in this run and use this as the launch size
-
3252 size_t directRayCount = 0;
-
3253 for( const auto &band : label ) {
-
3254 if( radiation_bands.at(band).directRayCount>directRayCount ) {
-
3255 directRayCount = radiation_bands.at(band).directRayCount;
-
3256 }
+
3172 //Run all bands by default
+
3173 std::vector<char> band_launch_flag(Nbands_global);
+
3174 uint bb=0;
+
3175 for( auto &band : radiation_bands ){
+
3176 if( std::find( band_labels.begin(), band_labels.end(), band.first ) != band_labels.end() ) {
+
3177 band_launch_flag.at(bb) = 1;
+
3178 }
+
3179 bb++;
+
3180 }
+
3181 initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag );
+
3182
+
3183 //Set the number of Context primitives
+
3184 size_t Nobjects = primitiveID.size();
+
3185 size_t Nprimitives = context_UUIDs.size();
+
3186 RT_CHECK_ERROR( rtVariableSet1ui( Nprimitives_RTvariable, Nprimitives ) );
+
3187
+
3188 //Set the random number seed
+
3189 RT_CHECK_ERROR( rtVariableSet1ui( random_seed_RTvariable, std::chrono::system_clock::now().time_since_epoch().count() ) );
+
3190
+
3191 //Number of external radiation sources
+
3192 uint Nsources = radiation_sources.size();
+
3193 RT_CHECK_ERROR( rtVariableSet1ui( Nsources_RTvariable, Nsources ) );
+
3194
+
3195 //Set periodic boundary condition (if applicable)
+
3196 RT_CHECK_ERROR( rtVariableSet2f( periodic_flag_RTvariable, periodic_flag.x, periodic_flag.y ));
+
3197
+
3198 //Number of radiation cameras
+
3199 uint Ncameras = cameras.size();
+
3200 RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, Ncameras ) );
+
3201
+
3202 //Set scattering depth for each band
+
3203 std::vector<uint> scattering_depth(Nbands_launch);
+
3204 bool scatteringenabled = false;
+
3205 for(auto b=0; b < Nbands_launch; b++ ){
+
3206 scattering_depth.at(b) = radiation_bands.at(band_labels.at(b)).scatteringDepth;
+
3207 if( scattering_depth.at(b)>0 ){
+
3208 scatteringenabled=true;
+
3209 }
+
3210 }
+
3211 initializeBuffer1Dui( max_scatters_RTbuffer, scattering_depth );
+
3212
+
3213 //Issue warning if rho>0, tau>0, or eps<1
+
3214 for(int b=0; b < Nbands_launch; b++ ){
+
3215 if( scattering_depth.at(b)==0 && scattering_iterations_needed.at(band_labels.at(b)) ){
+
3216 std::cout << "WARNING (RadiationModel::runBand): Surface radiative properties for band " << band_labels.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;
+
3217 }
+
3218 }
+
3219
+
3220 //Set diffuse flux for each band
+
3221 std::vector<float> diffuse_flux(Nbands_launch);
+
3222 bool diffuseenabled = false;
+
3223 for(auto b=0; b < Nbands_launch; b++ ){
+
3224 diffuse_flux.at(b) = getDiffuseFlux( band_labels.at(b) );
+
3225 if( diffuse_flux.at(b)>0.f ){
+
3226 diffuseenabled=true;
+
3227 }
+
3228 }
+
3229 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
+
3230
+
3231 //Set diffuse extinction coefficient for each band
+
3232 std::vector<float> diffuse_extinction(Nbands_launch, 0);
+
3233 if( diffuseenabled ) {
+
3234 for (auto b = 0; b < Nbands_launch; b++) {
+
3235 diffuse_extinction.at(b) = radiation_bands.at(band_labels.at(b)).diffuseExtinction;
+
3236 }
+
3237 }
+
3238 initializeBuffer1Df(diffuse_extinction_RTbuffer, diffuse_extinction);
+
3239
+
3240 //Set diffuse distribution normalization factor for each band
+
3241 std::vector<float> diffuse_dist_norm(Nbands_launch, 0);
+
3242 if( diffuseenabled ) {
+
3243 for (auto b = 0; b < Nbands_launch; b++) {
+
3244 diffuse_dist_norm.at(b) = radiation_bands.at(band_labels.at(b)).diffuseDistNorm;
+
3245 }
+
3246 initializeBuffer1Df(diffuse_dist_norm_RTbuffer, diffuse_dist_norm);
+
3247 }
+
3248
+
3249 //Set diffuse distribution peak direction for each band
+
3250 std::vector<optix::float3> diffuse_peak_dir(Nbands_launch);
+
3251 if( diffuseenabled ) {
+
3252 for (auto b = 0; b < Nbands_launch; b++) {
+
3253 helios::vec3 peak_dir = radiation_bands.at(band_labels.at(b)).diffusePeakDir;
+
3254 diffuse_peak_dir.at(b) = optix::make_float3(peak_dir.x,peak_dir.y,peak_dir.z);
+
3255 }
+
3256 initializeBuffer1Dfloat3(diffuse_peak_dir_RTbuffer, diffuse_peak_dir);
3257 }
3258
-
3259 //Figure out the maximum diffuse ray count for all bands in this run and use this as the launch size
-
3260 size_t diffuseRayCount = 0;
-
3261 for( const auto &band : label ) {
-
3262 if( radiation_bands.at(band).diffuseRayCount>diffuseRayCount ) {
-
3263 diffuseRayCount = radiation_bands.at(band).diffuseRayCount;
+
3259 //Determine whether emission is enabled for any band
+
3260 bool emissionenabled = false;
+
3261 for(auto b=0; b < Nbands_launch; b++ ){
+
3262 if( radiation_bands.at(band_labels.at(b)).emissionFlag ){
+
3263 emissionenabled=true;
3264 }
3265 }
3266
-
3267 //Figure out the maximum diffuse ray count for all bands in this run and use this as the launch size
-
3268 size_t scatteringDepth = 0;
+
3267 //Figure out the maximum direct ray count for all bands in this run and use this as the launch size
+
3268 size_t directRayCount = 0;
3269 for( const auto &band : label ) {
-
3270 if( radiation_bands.at(band).scatteringDepth>scatteringDepth ) {
-
3271 scatteringDepth = radiation_bands.at(band).scatteringDepth;
+
3270 if( radiation_bands.at(band).directRayCount>directRayCount ) {
+
3271 directRayCount = radiation_bands.at(band).directRayCount;
3272 }
3273 }
3274
-
3275 // Zero buffers
-
3276 zeroBuffer1D( radiation_in_RTbuffer, Nbands*Nprimitives );
-
3277 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
-
3278 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
-
3279 zeroBuffer1D( Rsky_RTbuffer, Nbands*Nprimitives );
-
3280
-
3281 if( Ncameras>0 ){
-
3282 zeroBuffer1D( scatter_buff_top_cam_RTbuffer, Nbands*Nprimitives );
-
3283 zeroBuffer1D( scatter_buff_bottom_cam_RTbuffer, Nbands*Nprimitives );
-
3284 }
-
3285
-
3286 std::vector<float> TBS_top, TBS_bottom;
-
3287 TBS_top.resize(Nbands*Nprimitives, 0);
-
3288 TBS_bottom = TBS_top;
-
3289
-
3290 std::map<std::string,std::vector<std::vector<float> > > radiation_in_camera;
-
3291
-
3292 size_t maxRays = 1024*1024*1024; //maximum number of total rays in a launch
-
3293
-
3294 // ***** DIRECT LAUNCH FROM ALL RADIATION SOURCES ***** //
-
3295
-
3296 optix::int3 launch_dim_dir;
-
3297
-
3298 bool rundirect = false;
-
3299 for( uint s=0; s<Nsources; s++ ){
-
3300 for( uint b=0; b<Nbands; b++ ){
-
3301 if( getSourceFlux( s, label.at(b))>0.f){
-
3302 rundirect = true;
-
3303 break;
-
3304 }
-
3305 }
-
3306 }
+
3275 //Figure out the maximum diffuse ray count for all bands in this run and use this as the launch size
+
3276 size_t diffuseRayCount = 0;
+
3277 for( const auto &band : label ) {
+
3278 if( radiation_bands.at(band).diffuseRayCount>diffuseRayCount ) {
+
3279 diffuseRayCount = radiation_bands.at(band).diffuseRayCount;
+
3280 }
+
3281 }
+
3282
+
3283 //Figure out the maximum diffuse ray count for all bands in this run and use this as the launch size
+
3284 size_t scatteringDepth = 0;
+
3285 for( const auto &band : label ) {
+
3286 if( radiation_bands.at(band).scatteringDepth>scatteringDepth ) {
+
3287 scatteringDepth = radiation_bands.at(band).scatteringDepth;
+
3288 }
+
3289 }
+
3290
+
3291 // Zero buffers
+
3292 zeroBuffer1D(radiation_in_RTbuffer, Nbands_launch * Nprimitives );
+
3293 zeroBuffer1D(scatter_buff_top_RTbuffer, Nbands_launch * Nprimitives );
+
3294 zeroBuffer1D(scatter_buff_bottom_RTbuffer, Nbands_launch * Nprimitives );
+
3295 zeroBuffer1D(Rsky_RTbuffer, Nbands_launch * Nprimitives );
+
3296
+
3297 if( Ncameras>0 ){
+
3298 zeroBuffer1D(scatter_buff_top_cam_RTbuffer, Nbands_launch * Nprimitives );
+
3299 zeroBuffer1D(scatter_buff_bottom_cam_RTbuffer, Nbands_launch * Nprimitives );
+
3300 }
+
3301
+
3302 std::vector<float> TBS_top, TBS_bottom;
+
3303 TBS_top.resize(Nbands_launch * Nprimitives, 0);
+
3304 TBS_bottom = TBS_top;
+
3305
+
3306 std::map<std::string,std::vector<std::vector<float> > > radiation_in_camera;
3307
-
3308 if( Nsources>0 && rundirect ){
+
3308 size_t maxRays = 1024*1024*1024; //maximum number of total rays in a launch
3309
-
3310 //update radiation source buffers
+
3310 // ***** DIRECT LAUNCH FROM ALL RADIATION SOURCES ***** //
3311
-
3312 std::vector<std::vector<float> > fluxes; //first index is the source, second index is the band (only those passed to runBand() function)
-
3313 fluxes.resize(Nsources);
-
3314 std::vector<optix::float3> positions(Nsources);
-
3315 std::vector<optix::float2> widths(Nsources);
-
3316 std::vector<optix::float3> rotations(Nsources);
-
3317 std::vector<uint> types(Nsources);
-
3318
-
3319 size_t s=0;
-
3320 for( const auto &source : radiation_sources ) {
-
3321
-
3322 fluxes.at(s).resize(Nbands);
+
3312 optix::int3 launch_dim_dir;
+
3313
+
3314 bool rundirect = false;
+
3315 for( uint s=0; s<Nsources; s++ ){
+
3316 for(uint b=0; b < Nbands_launch; b++ ){
+
3317 if( getSourceFlux( s, band_labels.at(b))>0.f){
+
3318 rundirect = true;
+
3319 break;
+
3320 }
+
3321 }
+
3322 }
3323
-
3324 for( auto b=0; b<label.size(); b++ ) {
-
3325 fluxes.at(s).at(b) = getSourceFlux( s, label.at(b));
-
3326 }
+
3324 if( Nsources>0 && rundirect ){
+
3325
+
3326 //update radiation source buffers
3327
-
3328 positions.at(s) = optix::make_float3( source.source_position.x, source.source_position.y, source.source_position.z );
-
3329 widths.at(s) = optix::make_float2(source.source_width.x, source.source_width.y);
-
3330 rotations.at(s) = optix::make_float3( source.source_rotation.x,source.source_rotation.y,source.source_rotation.z );
-
3331 types.at(s) = source.source_type;
-
3332
-
3333 s++;
-
3334 }
-
3335
-
3336 initializeBuffer1Df( source_fluxes_RTbuffer, flatten(fluxes) );
-
3337 initializeBuffer1Dfloat3( source_positions_RTbuffer, positions );
-
3338 initializeBuffer1Dfloat2( source_widths_RTbuffer, widths );
-
3339 initializeBuffer1Dfloat3( source_rotations_RTbuffer, rotations );
-
3340 initializeBuffer1Dui( source_types_RTbuffer, types );
-
3341
-
3342 // -- Ray Trace -- //
+
3328 std::vector<std::vector<float> > fluxes; //first index is the source, second index is the band (only those passed to runBand() function)
+
3329 fluxes.resize(Nsources);
+
3330 std::vector<optix::float3> positions(Nsources);
+
3331 std::vector<optix::float2> widths(Nsources);
+
3332 std::vector<optix::float3> rotations(Nsources);
+
3333 std::vector<uint> types(Nsources);
+
3334
+
3335 size_t s=0;
+
3336 for( const auto &source : radiation_sources ) {
+
3337
+
3338 fluxes.at(s).resize(Nbands_launch);
+
3339
+
3340 for( auto b=0; b<label.size(); b++ ) {
+
3341 fluxes.at(s).at(b) = getSourceFlux( s, band_labels.at(b));
+
3342 }
3343
-
3344 // Compute direct launch dimension
-
3345 size_t n = ceil(sqrt(double(directRayCount)));
-
3346
-
3347 size_t maxPrims = floor( float(maxRays)/float(n*n) );
+
3344 positions.at(s) = optix::make_float3( source.source_position.x, source.source_position.y, source.source_position.z );
+
3345 widths.at(s) = optix::make_float2(source.source_width.x, source.source_width.y);
+
3346 rotations.at(s) = optix::make_float3( source.source_rotation.x,source.source_rotation.y,source.source_rotation.z );
+
3347 types.at(s) = source.source_type;
3348
-
3349 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
-
3350
-
3351 size_t prims_per_launch = fmin( Nobjects, maxPrims );
-
3352
-
3353 for( uint launch=0; launch<Nlaunches; launch++ ){
-
3354
-
3355 size_t prims_this_launch;
-
3356 if( (launch+1)*prims_per_launch > Nobjects ){
-
3357 prims_this_launch = Nobjects-launch*prims_per_launch;
-
3358 }else{
-
3359 prims_this_launch = prims_per_launch;
-
3360 }
-
3361
-
3362 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
-
3363
-
3364 launch_dim_dir = optix::make_int3( round(n), round(n), prims_this_launch );
-
3365
-
3366 if( message_flag ){
-
3367 std::cout << "Performing primary direct radiation ray trace for bands ";
-
3368 for( const auto &band : label ) {
-
3369 std::cout << band << ", ";
-
3370 }
-
3371 std::cout << " (batch " << launch+1 << " of " << Nlaunches << ")..." << std::flush;
-
3372 }
-
3373 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIRECT , launch_dim_dir.x, launch_dim_dir.y, launch_dim_dir.z ) );
-
3374
-
3375 if( message_flag ){
-
3376 std::cout << "\r \r" << std::flush;
-
3377 }
-
3378
-
3379 }
-
3380
-
3381 if( message_flag ){
-
3382 std::cout << "Performing primary direct radiation ray trace for bands ";
-
3383 for( const auto &band : label ) {
-
3384 std::cout << band << ", ";
-
3385 }
-
3386 std::cout << "...done." << std::endl;
-
3387 }
-
3388
-
3389 }//end direct source launch
+
3349 s++;
+
3350 }
+
3351
+
3352 initializeBuffer1Df( source_fluxes_RTbuffer, flatten(fluxes) );
+
3353 initializeBuffer1Dfloat3( source_positions_RTbuffer, positions );
+
3354 initializeBuffer1Dfloat2( source_widths_RTbuffer, widths );
+
3355 initializeBuffer1Dfloat3( source_rotations_RTbuffer, rotations );
+
3356 initializeBuffer1Dui( source_types_RTbuffer, types );
+
3357
+
3358 // -- Ray Trace -- //
+
3359
+
3360 // Compute direct launch dimension
+
3361 size_t n = ceil(sqrt(double(directRayCount)));
+
3362
+
3363 size_t maxPrims = floor( float(maxRays)/float(n*n) );
+
3364
+
3365 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
+
3366
+
3367 size_t prims_per_launch = fmin( Nobjects, maxPrims );
+
3368
+
3369 for( uint launch=0; launch<Nlaunches; launch++ ){
+
3370
+
3371 size_t prims_this_launch;
+
3372 if( (launch+1)*prims_per_launch > Nobjects ){
+
3373 prims_this_launch = Nobjects-launch*prims_per_launch;
+
3374 }else{
+
3375 prims_this_launch = prims_per_launch;
+
3376 }
+
3377
+
3378 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
+
3379
+
3380 launch_dim_dir = optix::make_int3( round(n), round(n), prims_this_launch );
+
3381
+
3382 if( message_flag ){
+
3383 std::cout << "Performing primary direct radiation ray trace for bands ";
+
3384 for( const auto &band : label ) {
+
3385 std::cout << band << ", ";
+
3386 }
+
3387 std::cout << " (batch " << launch+1 << " of " << Nlaunches << ")..." << std::flush;
+
3388 }
+
3389 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIRECT , launch_dim_dir.x, launch_dim_dir.y, launch_dim_dir.z ) );
3390
-
3391 // --- Diffuse/Emission launch ---- //
-
3392
-
3393 if( emissionenabled || diffuseenabled ){
+
3391 if( message_flag ){
+
3392 std::cout << "\r \r" << std::flush;
+
3393 }
3394
-
3395 std::vector<float> flux_top, flux_bottom;
-
3396 flux_top.resize(Nbands*Nprimitives,0);
-
3397 flux_bottom = flux_top;
-
3398
-
3399 //If we are doing a diffuse/emission ray trace anyway and we have direct scattered energy, we get a "free" scattering trace here
-
3400 if( scatteringenabled && rundirect ){
-
3401 flux_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
-
3402 flux_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
-
3403 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
-
3404 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
-
3405 }
+
3395 }
+
3396
+
3397 if( message_flag ){
+
3398 std::cout << "Performing primary direct radiation ray trace for bands ";
+
3399 for( const auto &band : label ) {
+
3400 std::cout << band << ", ";
+
3401 }
+
3402 std::cout << "...done." << std::endl;
+
3403 }
+
3404
+
3405 }//end direct source launch
3406
-
3407 //add any emitted energy to the outgoing energy buffer
-
3408 if( emissionenabled ) {
-
3409 // Update primitive outgoing emission
-
3410 float eps, temperature;
-
3411
-
3412 void *ptr;
-
3413 float *scatter_buff_top_cam_data, *scatter_buff_bottom_cam_data;
-
3414 if( Ncameras>0 ){
-
3415 //add emitted flux to camera scattered energy buffer
-
3416 RT_CHECK_ERROR( rtBufferMap( scatter_buff_top_cam_RTbuffer, &ptr ) );
-
3417 scatter_buff_top_cam_data = (float*)ptr;
-
3418 RT_CHECK_ERROR( rtBufferMap( scatter_buff_bottom_cam_RTbuffer, &ptr ) );
-
3419 scatter_buff_bottom_cam_data = (float*)ptr;
-
3420 }
-
3421
-
3422 for (auto b = 0; b < Nbands; b++) {
-
3423 if (radiation_bands.at(label.at(b)).emissionFlag) {
-
3424 std::string prop = "emissivity_" + label.at(b);
-
3425 for (size_t u = 0; u < Nprimitives; u++) {
-
3426 size_t ind = u * Nbands + b;
-
3427 uint p = context_UUIDs.at(u);
-
3428 if (context->doesPrimitiveDataExist(p, prop.c_str())) {
-
3429 context->getPrimitiveData(p, prop.c_str(), eps);
-
3430 } else {
-
3431 eps = eps_default;
-
3432 }
-
3433 if (scattering_depth.at(b) == 0 && eps != 1.f) {
-
3434 eps = 1.f;
-
3435 }
-
3436 if (context->doesPrimitiveDataExist(p, "temperature")) {
-
3437 context->getPrimitiveData(p, "temperature", temperature);
-
3438 if (temperature < 0) {
-
3439 temperature = temperature_default;
-
3440 }
-
3441 } else {
-
3442 temperature = temperature_default;
-
3443 }
-
3444 float out_top = sigma * eps * pow(temperature, 4);
-
3445 flux_top.at(ind) += out_top;
-
3446 if( Ncameras>0 ) {
-
3447 scatter_buff_top_cam_data[ind] += out_top;
+
3407 // --- Diffuse/Emission launch ---- //
+
3408
+
3409 if( emissionenabled || diffuseenabled ){
+
3410
+
3411 std::vector<float> flux_top, flux_bottom;
+
3412 flux_top.resize(Nbands_launch * Nprimitives, 0);
+
3413 flux_bottom = flux_top;
+
3414
+
3415 //If we are doing a diffuse/emission ray trace anyway and we have direct scattered energy, we get a "free" scattering trace here
+
3416 if( scatteringenabled && rundirect ){
+
3417 flux_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
+
3418 flux_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
+
3419 zeroBuffer1D(scatter_buff_top_RTbuffer, Nbands_launch * Nprimitives );
+
3420 zeroBuffer1D(scatter_buff_bottom_RTbuffer, Nbands_launch * Nprimitives );
+
3421 }
+
3422
+
3423 //add any emitted energy to the outgoing energy buffer
+
3424 if( emissionenabled ) {
+
3425 // Update primitive outgoing emission
+
3426 float eps, temperature;
+
3427
+
3428 void *ptr;
+
3429 float *scatter_buff_top_cam_data, *scatter_buff_bottom_cam_data;
+
3430 if( Ncameras>0 ){
+
3431 //add emitted flux to camera scattered energy buffer
+
3432 RT_CHECK_ERROR( rtBufferMap( scatter_buff_top_cam_RTbuffer, &ptr ) );
+
3433 scatter_buff_top_cam_data = (float*)ptr;
+
3434 RT_CHECK_ERROR( rtBufferMap( scatter_buff_bottom_cam_RTbuffer, &ptr ) );
+
3435 scatter_buff_bottom_cam_data = (float*)ptr;
+
3436 }
+
3437
+
3438 for (auto b = 0; b < Nbands_launch; b++) {
+
3439 if (radiation_bands.at(band_labels.at(b)).emissionFlag) {
+
3440 std::string prop = "emissivity_" + band_labels.at(b);
+
3441 for (size_t u = 0; u < Nprimitives; u++) {
+
3442 size_t ind = u * Nbands_launch + b;
+
3443 uint p = context_UUIDs.at(u);
+
3444 if (context->doesPrimitiveDataExist(p, prop.c_str())) {
+
3445 context->getPrimitiveData(p, prop.c_str(), eps);
+
3446 } else {
+
3447 eps = eps_default;
3448 }
-
3449 if (!context->doesPrimitiveDataExist(p, "twosided_flag")) { //if does not exist, assume two-sided
-
3450 flux_bottom.at(ind) += flux_top.at(ind);
-
3451 if( Ncameras>0 ) {
-
3452 scatter_buff_bottom_cam_data[ind] += out_top;
-
3453 }
-
3454 } else {
-
3455 uint flag;
-
3456 context->getPrimitiveData(p, "twosided_flag", flag);
-
3457 if (flag) {
-
3458 flux_bottom.at(ind) += flux_top.at(ind);
-
3459 if( Ncameras>0 ) {
-
3460 scatter_buff_bottom_cam_data[ind] += out_top;
-
3461 }
-
3462 }
-
3463 }
-
3464 }
-
3465 }
-
3466 }
-
3467 if( Ncameras>0 ){
-
3468 RT_CHECK_ERROR( rtBufferUnmap( scatter_buff_top_cam_RTbuffer ) );
-
3469 RT_CHECK_ERROR( rtBufferUnmap( scatter_buff_bottom_cam_RTbuffer ) );
-
3470 }
-
3471 }
-
3472
-
3473 initializeBuffer1Df( radiation_out_top_RTbuffer, flux_top );
-
3474 initializeBuffer1Df( radiation_out_bottom_RTbuffer, flux_bottom );
-
3475
-
3476 // Compute diffuse launch dimension
-
3477 size_t n = ceil(sqrt(double(diffuseRayCount)));
-
3478
-
3479 size_t maxPrims = floor( float(maxRays)/float(n*n) );
-
3480
-
3481 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
-
3482
-
3483 size_t prims_per_launch = fmin( Nobjects, maxPrims );
-
3484
-
3485 for( uint launch=0; launch<Nlaunches; launch++ ){
-
3486
-
3487 size_t prims_this_launch;
-
3488 if( (launch+1)*prims_per_launch > Nobjects ){
-
3489 prims_this_launch = Nobjects-launch*prims_per_launch;
-
3490 }else{
-
3491 prims_this_launch = prims_per_launch;
-
3492 }
-
3493
-
3494 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
-
3495
-
3496 optix::int3 launch_dim_diff = optix::make_int3( round(n), round(n), prims_this_launch );
-
3497 assert( launch_dim_diff.x>0 && launch_dim_diff.y>0 );
+
3449 if (scattering_depth.at(b) == 0 && eps != 1.f) {
+
3450 eps = 1.f;
+
3451 }
+
3452 if (context->doesPrimitiveDataExist(p, "temperature")) {
+
3453 context->getPrimitiveData(p, "temperature", temperature);
+
3454 if (temperature < 0) {
+
3455 temperature = temperature_default;
+
3456 }
+
3457 } else {
+
3458 temperature = temperature_default;
+
3459 }
+
3460 float out_top = sigma * eps * pow(temperature, 4);
+
3461 flux_top.at(ind) += out_top;
+
3462 if( Ncameras>0 ) {
+
3463 scatter_buff_top_cam_data[ind] += out_top;
+
3464 }
+
3465 if (!context->doesPrimitiveDataExist(p, "twosided_flag")) { //if does not exist, assume two-sided
+
3466 flux_bottom.at(ind) += flux_top.at(ind);
+
3467 if( Ncameras>0 ) {
+
3468 scatter_buff_bottom_cam_data[ind] += out_top;
+
3469 }
+
3470 } else {
+
3471 uint flag;
+
3472 context->getPrimitiveData(p, "twosided_flag", flag);
+
3473 if (flag) {
+
3474 flux_bottom.at(ind) += flux_top.at(ind);
+
3475 if( Ncameras>0 ) {
+
3476 scatter_buff_bottom_cam_data[ind] += out_top;
+
3477 }
+
3478 }
+
3479 }
+
3480 }
+
3481 }
+
3482 }
+
3483 if( Ncameras>0 ){
+
3484 RT_CHECK_ERROR( rtBufferUnmap( scatter_buff_top_cam_RTbuffer ) );
+
3485 RT_CHECK_ERROR( rtBufferUnmap( scatter_buff_bottom_cam_RTbuffer ) );
+
3486 }
+
3487 }
+
3488
+
3489 initializeBuffer1Df( radiation_out_top_RTbuffer, flux_top );
+
3490 initializeBuffer1Df( radiation_out_bottom_RTbuffer, flux_bottom );
+
3491
+
3492 // Compute diffuse launch dimension
+
3493 size_t n = ceil(sqrt(double(diffuseRayCount)));
+
3494
+
3495 size_t maxPrims = floor( float(maxRays)/float(n*n) );
+
3496
+
3497 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
3498
-
3499 if( message_flag ){
-
3500 std::cout << "Performing primary diffuse radiation ray trace for bands ";
-
3501 for( const auto &band : label ) {
-
3502 std::cout << band << " ";
-
3503 }
-
3504 std::cout << " (batch " << launch+1 << " of " << Nlaunches << ")..." << std::flush;
-
3505 }
-
3506 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIFFUSE , launch_dim_diff.x, launch_dim_diff.y, launch_dim_diff.z ) );
-
3507 if( message_flag ){
-
3508 std::cout << "\r \r" << std::flush;
-
3509 }
-
3510 }
+
3499 size_t prims_per_launch = fmin( Nobjects, maxPrims );
+
3500
+
3501 for( uint launch=0; launch<Nlaunches; launch++ ){
+
3502
+
3503 size_t prims_this_launch;
+
3504 if( (launch+1)*prims_per_launch > Nobjects ){
+
3505 prims_this_launch = Nobjects-launch*prims_per_launch;
+
3506 }else{
+
3507 prims_this_launch = prims_per_launch;
+
3508 }
+
3509
+
3510 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
3511
-
3512 if( message_flag ){
-
3513 std::cout << "Performing primary diffuse radiation ray trace for bands ";
-
3514 for( const auto &band : label ) {
-
3515 std::cout << band << ", ";
-
3516 }
-
3517 std::cout << "...done." << std::endl;
-
3518 }
-
3519
-
3520 }
-
3521
-
3522 if( scatteringenabled ){
-
3523
-
3524 for( auto b=0; b<Nbands; b++ ) {
-
3525 diffuse_flux.at(b) = 0.f;
+
3512 optix::int3 launch_dim_diff = optix::make_int3( round(n), round(n), prims_this_launch );
+
3513 assert( launch_dim_diff.x>0 && launch_dim_diff.y>0 );
+
3514
+
3515 if( message_flag ){
+
3516 std::cout << "Performing primary diffuse radiation ray trace for bands ";
+
3517 for( const auto &band : label ) {
+
3518 std::cout << band << " ";
+
3519 }
+
3520 std::cout << " (batch " << launch+1 << " of " << Nlaunches << ")..." << std::flush;
+
3521 }
+
3522 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIFFUSE , launch_dim_diff.x, launch_dim_diff.y, launch_dim_diff.z ) );
+
3523 if( message_flag ){
+
3524 std::cout << "\r \r" << std::flush;
+
3525 }
3526 }
-
3527 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
-
3528
-
3529 size_t n = ceil(sqrt(double(diffuseRayCount)));
-
3530
-
3531 size_t maxPrims = floor( float(maxRays)/float(n*n) );
-
3532
-
3533 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
-
3534
-
3535 size_t prims_per_launch = fmin( Nobjects, maxPrims );
-
3536
-
3537 uint s;
-
3538 for( s=0; s<scatteringDepth; s++ ){
-
3539 if( message_flag ){
-
3540 std::cout << "Performing scattering ray trace (iteration " << s+1 << " of " << scatteringDepth << ")..." << std::flush;
-
3541 }
-
3542
-
3543 for( uint b=0; b<Nbands; b++ ){
-
3544 uint depth = radiation_bands.at(label.at(b)).scatteringDepth;
-
3545 if( s+1>depth ) {
-
3546 if( message_flag ) {
-
3547 std::cout << "Skipping band " << label.at(b) << " for scattering launch " << s + 1 << std::flush;
-
3548 }
-
3549 band_launch_flag.at(b) = 0;
-
3550 }else{
-
3551 band_launch_flag.at(b) = 1;
-
3552 }
-
3553 }
-
3554 initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag );
-
3555
-
3556// TBS_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
-
3557// TBS_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
-
3558// float TBS_max = 0;
-
3559// for( size_t u=0; u<Nprimitives*Nbands; u++ ){
-
3560// if( TBS_top.at(u)+TBS_bottom.at(u)>TBS_max ){
-
3561// TBS_max = TBS_top.at(u)+TBS_bottom.at(u);
-
3562// }
-
3563// }
-
3564
-
3565 copyBuffer1D( scatter_buff_top_RTbuffer, radiation_out_top_RTbuffer );
-
3566 zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives );
-
3567 copyBuffer1D( scatter_buff_bottom_RTbuffer, radiation_out_bottom_RTbuffer );
-
3568 zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives );
-
3569
-
3570 for( uint launch=0; launch<Nlaunches; launch++ ){
-
3571
-
3572 size_t prims_this_launch;
-
3573 if( (launch+1)*prims_per_launch > Nobjects ){
-
3574 prims_this_launch = Nobjects-launch*prims_per_launch;
-
3575 }else{
-
3576 prims_this_launch = prims_per_launch;
-
3577 }
-
3578 optix::int3 launch_dim_diff = optix::make_int3( round(n), round(n), prims_this_launch );
-
3579
-
3580 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
-
3581
-
3582 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIFFUSE , launch_dim_diff.x, launch_dim_diff.y, launch_dim_diff.z ) );
-
3583
-
3584 }
-
3585 if( message_flag ){
-
3586 std::cout << "\r \r" << std::flush;
-
3587 }
-
3588
-
3589 }
+
3527
+
3528 if( message_flag ){
+
3529 std::cout << "Performing primary diffuse radiation ray trace for bands ";
+
3530 for( const auto &band : label ) {
+
3531 std::cout << band << ", ";
+
3532 }
+
3533 std::cout << "...done." << std::endl;
+
3534 }
+
3535
+
3536 }
+
3537
+
3538 if( scatteringenabled ){
+
3539
+
3540 for(auto b=0; b < Nbands_launch; b++ ) {
+
3541 diffuse_flux.at(b) = 0.f;
+
3542 }
+
3543 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
+
3544
+
3545 size_t n = ceil(sqrt(double(diffuseRayCount)));
+
3546
+
3547 size_t maxPrims = floor( float(maxRays)/float(n*n) );
+
3548
+
3549 int Nlaunches = ceil( n*n*Nobjects/float(maxRays) );
+
3550
+
3551 size_t prims_per_launch = fmin( Nobjects, maxPrims );
+
3552
+
3553 uint s;
+
3554 for( s=0; s<scatteringDepth; s++ ){
+
3555 if( message_flag ){
+
3556 std::cout << "Performing scattering ray trace (iteration " << s+1 << " of " << scatteringDepth << ")..." << std::flush;
+
3557 }
+
3558
+
3559 int b = -1;
+
3560 for(uint b_global=0; b_global < Nbands_global; b_global++ ){
+
3561
+
3562 if( band_launch_flag.at(b_global)==0 ){
+
3563 continue;
+
3564 }
+
3565 b++;
+
3566
+
3567 uint depth = radiation_bands.at(band_labels.at(b)).scatteringDepth;
+
3568 if( s+1>depth ) {
+
3569 if( message_flag ) {
+
3570 std::cout << "Skipping band " << band_labels.at(b) << " for scattering launch " << s + 1 << std::flush;
+
3571 }
+
3572 band_launch_flag.at(b_global) = 0;
+
3573 }
+
3574 }
+
3575 initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag );
+
3576
+
3577// TBS_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
+
3578// TBS_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
+
3579// float TBS_max = 0;
+
3580// for( size_t u=0; u<Nprimitives*Nbands; u++ ){
+
3581// if( TBS_top.at(u)+TBS_bottom.at(u)>TBS_max ){
+
3582// TBS_max = TBS_top.at(u)+TBS_bottom.at(u);
+
3583// }
+
3584// }
+
3585
+
3586 copyBuffer1D( scatter_buff_top_RTbuffer, radiation_out_top_RTbuffer );
+
3587 zeroBuffer1D(scatter_buff_top_RTbuffer, Nbands_launch * Nprimitives );
+
3588 copyBuffer1D( scatter_buff_bottom_RTbuffer, radiation_out_bottom_RTbuffer );
+
3589 zeroBuffer1D(scatter_buff_bottom_RTbuffer, Nbands_launch * Nprimitives );
3590
-
3591 if( message_flag ){
-
3592 std::cout << "Performing scattering ray trace...done." << std::endl;
-
3593 }
-
3594
-
3595 }
-
3596
-
3597 // **** CAMERA RAY TRACE **** //
-
3598 if( Ncameras>0 ){
-
3599
-
3600 //re-set outgoing radiation buffers
-
3601 copyBuffer1D( scatter_buff_top_cam_RTbuffer, radiation_out_top_RTbuffer );
-
3602 copyBuffer1D( scatter_buff_bottom_cam_RTbuffer, radiation_out_bottom_RTbuffer );
-
3603
-
3604 //re-set diffuse radiation fluxes
-
3605 if( diffuseenabled ){
-
3606 for( auto b=0; b<Nbands; b++ ){
-
3607 diffuse_flux.at(b) = getDiffuseFlux(label.at(b));
+
3591 for( uint launch=0; launch<Nlaunches; launch++ ){
+
3592
+
3593 size_t prims_this_launch;
+
3594 if( (launch+1)*prims_per_launch > Nobjects ){
+
3595 prims_this_launch = Nobjects-launch*prims_per_launch;
+
3596 }else{
+
3597 prims_this_launch = prims_per_launch;
+
3598 }
+
3599 optix::int3 launch_dim_diff = optix::make_int3( round(n), round(n), prims_this_launch );
+
3600
+
3601 RT_CHECK_ERROR( rtVariableSet1ui( launch_offset_RTvariable, launch*prims_per_launch ) );
+
3602
+
3603 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_DIFFUSE , launch_dim_diff.x, launch_dim_diff.y, launch_dim_diff.z ) );
+
3604
+
3605 }
+
3606 if( message_flag ){
+
3607 std::cout << "\r \r" << std::flush;
3608 }
-
3609 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
+
3609
3610 }
3611
-
3612
-
3613 size_t n = ceil(sqrt(double(diffuseRayCount)));
-
3614
-
3615 uint cam=0;
-
3616 for( auto & camera : cameras ){
+
3612 if( message_flag ){
+
3613 std::cout << "Performing scattering ray trace...done." << std::endl;
+
3614 }
+
3615
+
3616 }
3617
-
3618 //set variable values
-
3619 RT_CHECK_ERROR( rtVariableSet3f( camera_position_RTvariable, camera.second.position.x, camera.second.position.y, camera.second.position.z ) );
-
3620 helios::SphericalCoord dir = cart2sphere( camera.second.lookat - camera.second.position );
-
3621 RT_CHECK_ERROR( rtVariableSet2f( camera_direction_RTvariable, dir.zenith, dir.azimuth ) );
-
3622 RT_CHECK_ERROR( rtVariableSet1f( camera_lens_diameter_RTvariable, camera.second.lens_diameter ) );
-
3623 RT_CHECK_ERROR( rtVariableSet1f( FOV_aspect_RTvariable, camera.second.FOV_aspect_ratio ) );
-
3624 RT_CHECK_ERROR( rtVariableSet1f( camera_focal_length_RTvariable, camera.second.focal_length ) );
-
3625 RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 0.5f/tanf(0.5f*camera.second.HFOV_degrees*M_PI/180.f) ) );
-
3626 RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, cam ));
-
3627
-
3628 zeroBuffer1D( radiation_in_camera_RTbuffer, camera.second.resolution.x*camera.second.resolution.y*Nbands );
-
3629
-
3630 optix::int3 launch_dim_camera = optix::make_int3( camera.second.antialiasing_samples, camera.second.resolution.x, camera.second.resolution.y );
-
3631
-
3632 if( message_flag ){
-
3633 std::cout << "Performing scattering radiation camera ray trace for camera " << camera.second.label << "..." << std::flush;
-
3634 }
-
3635 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_CAMERA , launch_dim_camera.x, launch_dim_camera.y, launch_dim_camera.z ) );
-
3636 if( message_flag ){
-
3637 std::cout << "done." << std::endl;
-
3638 }
-
3639
-
3640 std::vector<float> radiation_camera = getOptiXbufferData(radiation_in_camera_RTbuffer);
-
3641
-
3642 std::string camera_label = camera.second.label;
-
3643
-
3644 for( auto b=0; b<Nbands; b++ ) {
-
3645
-
3646 camera.second.pixel_data[label.at(b)].resize(camera.second.resolution.x*camera.second.resolution.y);
-
3647
-
3648 std::string data_label = "camera_" + camera_label + "_" + label.at(b);
-
3649
-
3650 for( auto p=0; p<camera.second.resolution.x*camera.second.resolution.y; p++ ){
-
3651 camera.second.pixel_data.at(label.at(b)).at(p) = radiation_camera.at(p*Nbands+b);
-
3652 }
-
3653
-
3654 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]);
-
3655
-
3656 }
-
3657
-
3658 //--- Pixel Labeling Trace ---//
-
3659
-
3660 zeroBuffer1D(camera_pixel_label_RTbuffer,camera.second.resolution.x*camera.second.resolution.y);
-
3661 zeroBuffer1D(camera_pixel_depth_RTbuffer,camera.second.resolution.x*camera.second.resolution.y);
+
3618 // **** CAMERA RAY TRACE **** //
+
3619 if( Ncameras>0 ){
+
3620
+
3621 //re-set outgoing radiation buffers
+
3622 copyBuffer1D( scatter_buff_top_cam_RTbuffer, radiation_out_top_RTbuffer );
+
3623 copyBuffer1D( scatter_buff_bottom_cam_RTbuffer, radiation_out_bottom_RTbuffer );
+
3624
+
3625 //re-set diffuse radiation fluxes
+
3626 if( diffuseenabled ){
+
3627 for(auto b=0; b < Nbands_launch; b++ ){
+
3628 diffuse_flux.at(b) = getDiffuseFlux(band_labels.at(b));
+
3629 }
+
3630 initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux );
+
3631 }
+
3632
+
3633
+
3634 size_t n = ceil(sqrt(double(diffuseRayCount)));
+
3635
+
3636 uint cam=0;
+
3637 for( auto & camera : cameras ){
+
3638
+
3639 //set variable values
+
3640 RT_CHECK_ERROR( rtVariableSet3f( camera_position_RTvariable, camera.second.position.x, camera.second.position.y, camera.second.position.z ) );
+
3641 helios::SphericalCoord dir = cart2sphere( camera.second.lookat - camera.second.position );
+
3642 RT_CHECK_ERROR( rtVariableSet2f( camera_direction_RTvariable, dir.zenith, dir.azimuth ) );
+
3643 RT_CHECK_ERROR( rtVariableSet1f( camera_lens_diameter_RTvariable, camera.second.lens_diameter ) );
+
3644 RT_CHECK_ERROR( rtVariableSet1f( FOV_aspect_RTvariable, camera.second.FOV_aspect_ratio ) );
+
3645 RT_CHECK_ERROR( rtVariableSet1f( camera_focal_length_RTvariable, camera.second.focal_length ) );
+
3646 RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 0.5f/tanf(0.5f*camera.second.HFOV_degrees*M_PI/180.f) ) );
+
3647 RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, cam ));
+
3648
+
3649 zeroBuffer1D( radiation_in_camera_RTbuffer, camera.second.resolution.x * camera.second.resolution.y * Nbands_launch );
+
3650
+
3651 optix::int3 launch_dim_camera = optix::make_int3( camera.second.antialiasing_samples, camera.second.resolution.x, camera.second.resolution.y );
+
3652
+
3653 if( message_flag ){
+
3654 std::cout << "Performing scattering radiation camera ray trace for camera " << camera.second.label << "..." << std::flush;
+
3655 }
+
3656 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_CAMERA , launch_dim_camera.x, launch_dim_camera.y, launch_dim_camera.z ) );
+
3657 if( message_flag ){
+
3658 std::cout << "done." << std::endl;
+
3659 }
+
3660
+
3661 std::vector<float> radiation_camera = getOptiXbufferData(radiation_in_camera_RTbuffer);
3662
-
3663 if( message_flag ){
-
3664 std::cout << "Performing camera pixel labeling ray trace for camera " << camera.second.label << "..." << std::flush;
-
3665 }
-
3666 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_PIXEL_LABEL , 1, launch_dim_camera.y, launch_dim_camera.z ) );
-
3667 if( message_flag ){
-
3668 std::cout << "done." << std::endl;
-
3669 }
+
3663 std::string camera_label = camera.second.label;
+
3664
+
3665 for(auto b=0; b < Nbands_launch; b++ ) {
+
3666
+
3667 camera.second.pixel_data[band_labels.at(b)].resize(camera.second.resolution.x*camera.second.resolution.y);
+
3668
+
3669 std::string data_label = "camera_" + camera_label + "_" + band_labels.at(b);
3670
-
3671 camera.second.pixel_label_UUID = getOptiXbufferData_ui(camera_pixel_label_RTbuffer);
-
3672 camera.second.pixel_depth = getOptiXbufferData(camera_pixel_depth_RTbuffer);
-
3673
-
3674 //the IDs from the ray trace do not necessarily correspond to the actual primitive UUIDs, so look them up.
-
3675 for( uint ID=0; ID<camera.second.pixel_label_UUID.size(); ID++ ){
-
3676 if( camera.second.pixel_label_UUID.at(ID)>0 ){
-
3677 camera.second.pixel_label_UUID.at(ID) = context_UUIDs.at(camera.second.pixel_label_UUID.at(ID) - 1) + 1;
-
3678 }
-
3679 }
+
3671 for( auto p=0; p<camera.second.resolution.x*camera.second.resolution.y; p++ ){
+
3672 camera.second.pixel_data.at(band_labels.at(b)).at(p) = radiation_camera.at(p * Nbands_launch + b);
+
3673 }
+
3674
+
3675 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_data.at(band_labels.at(b))[0]);
+
3676
+
3677 }
+
3678
+
3679 //--- Pixel Labeling Trace ---//
3680
-
3681 std::string data_label = "camera_" + camera_label + "_pixel_UUID";
-
3682
-
3683 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_UINT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_label_UUID[0]);
-
3684
-
3685 data_label = "camera_" + camera_label + "_pixel_depth";
-
3686
-
3687 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_depth[0]);
-
3688
-
3689 cam++;
-
3690 }
-
3691 }
-
3692
-
3693 //deposit any energy that is left to make sure we satisfy conservation of energy
-
3694 TBS_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
-
3695 TBS_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
-
3696
-
3697 // Set variables in geometric objects
-
3698
-
3699 std::vector<float> radiation_flux_data;
-
3700 radiation_flux_data=getOptiXbufferData( radiation_in_RTbuffer );
+
3681 zeroBuffer1D(camera_pixel_label_RTbuffer,camera.second.resolution.x*camera.second.resolution.y);
+
3682 zeroBuffer1D(camera_pixel_depth_RTbuffer,camera.second.resolution.x*camera.second.resolution.y);
+
3683
+
3684 if( message_flag ){
+
3685 std::cout << "Performing camera pixel labeling ray trace for camera " << camera.second.label << "..." << std::flush;
+
3686 }
+
3687 RT_CHECK_ERROR( rtContextLaunch3D( OptiX_Context, RAYTYPE_PIXEL_LABEL , 1, launch_dim_camera.y, launch_dim_camera.z ) );
+
3688 if( message_flag ){
+
3689 std::cout << "done." << std::endl;
+
3690 }
+
3691
+
3692 camera.second.pixel_label_UUID = getOptiXbufferData_ui(camera_pixel_label_RTbuffer);
+
3693 camera.second.pixel_depth = getOptiXbufferData(camera_pixel_depth_RTbuffer);
+
3694
+
3695 //the IDs from the ray trace do not necessarily correspond to the actual primitive UUIDs, so look them up.
+
3696 for( uint ID=0; ID<camera.second.pixel_label_UUID.size(); ID++ ){
+
3697 if( camera.second.pixel_label_UUID.at(ID)>0 ){
+
3698 camera.second.pixel_label_UUID.at(ID) = context_UUIDs.at(camera.second.pixel_label_UUID.at(ID) - 1) + 1;
+
3699 }
+
3700 }
3701
-
3702 std::vector<uint> UUIDs_context_all = context->getAllUUIDs();
+
3702 std::string data_label = "camera_" + camera_label + "_pixel_UUID";
3703
-
3704 for( auto b=0; b<Nbands; b++ ) {
+
3704 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_UINT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_label_UUID[0]);
3705
-
3706 std::string prop = "radiation_flux_" + label.at(b);
-
3707 for (size_t u = 0; u < Nprimitives; u++) {
-
3708 size_t ind = u * Nbands + b;
-
3709 float R = radiation_flux_data.at(ind) + TBS_top.at(ind) + TBS_bottom.at(ind);
-
3710 context->setPrimitiveData(context_UUIDs.at(u), prop.c_str(), R);
-
3711 if (radiation_flux_data.at(ind) != radiation_flux_data.at(ind)) {
-
3712 std::cout << "NaN here " << ind << std::endl;
-
3713 }
-
3714 }
-
3715
-
3716 if( UUIDs_context_all.size()!=Nprimitives ){
-
3717 for( uint UUID : UUIDs_context_all ){
-
3718 if( context->doesPrimitiveExist(UUID) && !context->doesPrimitiveDataExist(UUID,prop.c_str()) ){
-
3719 context->setPrimitiveData(UUID,prop.c_str(),0.f);
-
3720 }
-
3721 }
-
3722 }
-
3723
-
3724 }
-
3725
-
3726}
-
-
3727
-
- -
3729
-
3730 std::vector<float> Rsky_SW;
-
3731 Rsky_SW=getOptiXbufferData( Rsky_RTbuffer );
-
3732 float Rsky=0.f;
-
3733 for( size_t i=0; i<Rsky_SW.size(); i++ ){
-
3734 Rsky += Rsky_SW.at(i);
-
3735 }
-
3736 return Rsky;
-
3737
-
3738}
-
-
3739
-
- -
3741
-
3742 std::vector<float> total_flux;
-
3743 total_flux.resize(context->getPrimitiveCount(),0.f);
+
3706 data_label = "camera_" + camera_label + "_pixel_depth";
+
3707
+
3708 context->setGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_depth[0]);
+
3709
+
3710 cam++;
+
3711 }
+
3712 }
+
3713
+
3714 //deposit any energy that is left to make sure we satisfy conservation of energy
+
3715 TBS_top=getOptiXbufferData( scatter_buff_top_RTbuffer );
+
3716 TBS_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer );
+
3717
+
3718 // Set variables in geometric objects
+
3719
+
3720 std::vector<float> radiation_flux_data;
+
3721 radiation_flux_data=getOptiXbufferData( radiation_in_RTbuffer );
+
3722
+
3723 std::vector<uint> UUIDs_context_all = context->getAllUUIDs();
+
3724
+
3725 for(auto b=0; b < Nbands_launch; b++ ) {
+
3726
+
3727 std::string prop = "radiation_flux_" + band_labels.at(b);
+
3728 for (size_t u = 0; u < Nprimitives; u++) {
+
3729 size_t ind = u * Nbands_launch + b;
+
3730 float R = radiation_flux_data.at(ind) + TBS_top.at(ind) + TBS_bottom.at(ind);
+
3731 context->setPrimitiveData(context_UUIDs.at(u), prop.c_str(), R);
+
3732 if (radiation_flux_data.at(ind) != radiation_flux_data.at(ind)) {
+
3733 std::cout << "NaN here " << ind << std::endl;
+
3734 }
+
3735 }
+
3736
+
3737 if( UUIDs_context_all.size()!=Nprimitives ){
+
3738 for( uint UUID : UUIDs_context_all ){
+
3739 if( context->doesPrimitiveExist(UUID) && !context->doesPrimitiveDataExist(UUID,prop.c_str()) ){
+
3740 context->setPrimitiveData(UUID,prop.c_str(),0.f);
+
3741 }
+
3742 }
+
3743 }
3744
-
3745 for( const auto &band : radiation_bands ){
+
3745 }
3746
-
3747 std::string label = band.first;
+
3747}
+
3748
-
3749 for( size_t u=0; u<context_UUIDs.size(); u++ ){
+
+
3750
-
3751 uint p = context_UUIDs.at(u);
-
3752
-
3753 std::string str = "radiation_flux_" + label;
-
3754
-
3755 float R;
-
3756 context->getPrimitiveData( p, str.c_str(), R );
-
3757 total_flux.at(u) += R;
+
3751 std::vector<float> Rsky_SW;
+
3752 Rsky_SW=getOptiXbufferData( Rsky_RTbuffer );
+
3753 float Rsky=0.f;
+
3754 for( size_t i=0; i<Rsky_SW.size(); i++ ){
+
3755 Rsky += Rsky_SW.at(i);
+
3756 }
+
3757 return Rsky;
3758
-
3759 }
+
3759}
+
3760
-
3761 }
+
+
3762
-
3763 return total_flux;
-
3764
-
3765}
-
-
3766
-
3767std::vector<float> RadiationModel::getOptiXbufferData( RTbuffer buffer ){
-
3768
-
3769 void* _data_;
-
3770 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
-
3771 float* data_ptr = (float*)_data_;
-
3772
-
3773 RTsize size;
-
3774 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
+
3763 std::vector<float> total_flux;
+
3764 total_flux.resize(context->getPrimitiveCount(),0.f);
+
3765
+
3766 for( const auto &band : radiation_bands ){
+
3767
+
3768 std::string label = band.first;
+
3769
+
3770 for( size_t u=0; u<context_UUIDs.size(); u++ ){
+
3771
+
3772 uint p = context_UUIDs.at(u);
+
3773
+
3774 std::string str = "radiation_flux_" + label;
3775
-
3776 std::vector<float> data_vec;
-
3777 data_vec.resize(size);
-
3778 for( int i=0; i<size; i++ ){
-
3779 data_vec.at(i)=data_ptr[i];
-
3780 }
+
3776 float R;
+
3777 context->getPrimitiveData( p, str.c_str(), R );
+
3778 total_flux.at(u) += R;
+
3779
+
3780 }
3781
-
3782 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3782 }
3783
-
3784 return data_vec;
+
3784 return total_flux;
3785
3786}
+
3787
-
3788std::vector<double> RadiationModel::getOptiXbufferData_d( RTbuffer buffer ){
+
3788std::vector<float> RadiationModel::getOptiXbufferData( RTbuffer buffer ){
3789
3790 void* _data_;
3791 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
-
3792 double* data_ptr = (double*)_data_;
+
3792 float* data_ptr = (float*)_data_;
3793
3794 RTsize size;
3795 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
3796
-
3797 std::vector<double> data_vec;
+
3797 std::vector<float> data_vec;
3798 data_vec.resize(size);
3799 for( int i=0; i<size; i++ ){
3800 data_vec.at(i)=data_ptr[i];
@@ -4066,16 +4073,16 @@
3806
3807}
3808
-
3809std::vector<uint> RadiationModel::getOptiXbufferData_ui( RTbuffer buffer ){
+
3809std::vector<double> RadiationModel::getOptiXbufferData_d( RTbuffer buffer ){
3810
3811 void* _data_;
3812 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
-
3813 uint* data_ptr = (uint*)_data_;
+
3813 double* data_ptr = (double*)_data_;
3814
3815 RTsize size;
3816 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
3817
-
3818 std::vector<uint> data_vec;
+
3818 std::vector<double> data_vec;
3819 data_vec.resize(size);
3820 for( int i=0; i<size; i++ ){
3821 data_vec.at(i)=data_ptr[i];
@@ -4087,1995 +4094,2020 @@
3827
3828}
3829
-
3830void RadiationModel::addBuffer( const char* name, RTbuffer& buffer, RTvariable& variable, RTbuffertype type, RTformat format, size_t dimension ){
+
3830std::vector<uint> RadiationModel::getOptiXbufferData_ui( RTbuffer buffer ){
3831
-
3832 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, type, &buffer ) );
-
3833 RT_CHECK_ERROR( rtBufferSetFormat( buffer, format ) );
-
3834 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, name, &variable ) );
-
3835 RT_CHECK_ERROR( rtVariableSetObject( variable, buffer ) );
-
3836 if( dimension==1 ){
-
3837 zeroBuffer1D( buffer, 1 );
-
3838 }else if( dimension==2 ){
-
3839 zeroBuffer2D( buffer, optix::make_int2(1,1) );
-
3840 }else{
-
3841 helios_runtime_error("ERROR (RadiationModel::addBuffer): invalid buffer dimension of " + std::to_string(dimension) + ", must be 1 or 2.");
-
3842 }
-
3843
-
3844}
-
3845
-
3846void RadiationModel::zeroBuffer1D(RTbuffer &buffer, size_t bsize ){
-
3847
-
3848 //get buffer format
-
3849 RTformat format;
-
3850 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
3851
-
3852 if( format==RT_FORMAT_USER ){//Note: for now, assume user format means it's a double
-
3853
-
3854 std::vector<double> array;
-
3855 array.resize(bsize);
-
3856 for( int i=0; i<bsize; i++ ){
-
3857 array.at(i)=0.f;
-
3858 }
-
3859
-
3860 initializeBuffer1Dd( buffer, array );
-
3861
-
3862 }else if( format==RT_FORMAT_FLOAT ){
-
3863
-
3864 std::vector<float> array;
-
3865 array.resize(bsize);
-
3866 for( int i=0; i<bsize; i++ ){
-
3867 array.at(i)=0.f;
-
3868 }
-
3869
-
3870 initializeBuffer1Df( buffer, array );
-
3871
-
3872 }else if( format==RT_FORMAT_FLOAT2 ){
-
3873
-
3874 std::vector<optix::float2> array;
-
3875 array.resize(bsize);
-
3876 for( int i=0; i<bsize; i++ ){
-
3877 array.at(i)=optix::make_float2(0,0);
-
3878 }
-
3879
-
3880 initializeBuffer1Dfloat2( buffer, array );
-
3881
-
3882 }else if( format==RT_FORMAT_FLOAT3 ){
-
3883
-
3884 std::vector<optix::float3> array;
-
3885 array.resize(bsize);
-
3886 for( int i=0; i<bsize; i++ ){
-
3887 array.at(i)=optix::make_float3(0,0,0);
-
3888 }
-
3889
-
3890 initializeBuffer1Dfloat3( buffer, array );
-
3891
-
3892 }else if( format==RT_FORMAT_INT ){
-
3893
-
3894 std::vector<int> array;
-
3895 array.resize(bsize);
-
3896 for( int i=0; i<bsize; i++ ){
-
3897 array.at(i)=0;
-
3898 }
-
3899
-
3900 initializeBuffer1Di( buffer, array );
-
3901
-
3902 }else if( format==RT_FORMAT_INT2 ){
-
3903
-
3904 std::vector<optix::int2> array;
-
3905 array.resize(bsize);
-
3906 for( int i=0; i<bsize; i++ ){
-
3907 array.at(i)=optix::make_int2(0,0);
-
3908 }
-
3909
-
3910 initializeBuffer1Dint2( buffer, array );
-
3911
-
3912 }else if( format==RT_FORMAT_INT3 ){
-
3913
-
3914 std::vector<optix::int3> array;
-
3915 array.resize(bsize);
-
3916 for( int i=0; i<bsize; i++ ){
-
3917 array.at(i)=optix::make_int3(0,0,0);
-
3918 }
-
3919
-
3920 initializeBuffer1Dint3( buffer, array );
-
3921
-
3922 }else if( format==RT_FORMAT_UNSIGNED_INT ){
-
3923
-
3924 std::vector<uint> array;
-
3925 array.resize(bsize);
-
3926 for( int i=0; i<bsize; i++ ){
-
3927 array.at(i)=0;
-
3928 }
-
3929
-
3930 initializeBuffer1Dui( buffer, array );
-
3931
-
3932 }else if( format==RT_FORMAT_BYTE ){
-
3933
-
3934 std::vector<char> array;
-
3935 array.resize(bsize);
-
3936 for( int i=0; i<bsize; i++ ){
-
3937 array.at(i)=0;
-
3938 }
-
3939
-
3940 initializeBuffer1Dchar( buffer, array );
-
3941 }else{
-
3942 helios_runtime_error("ERROR (RadiationModel::zeroBuffer1D): Buffer type not supported.");
-
3943 }
+
3832 void* _data_;
+
3833 RT_CHECK_ERROR( rtBufferMap( buffer, &_data_ ) );
+
3834 uint* data_ptr = (uint*)_data_;
+
3835
+
3836 RTsize size;
+
3837 RT_CHECK_ERROR( rtBufferGetSize1D( buffer, &size ) );
+
3838
+
3839 std::vector<uint> data_vec;
+
3840 data_vec.resize(size);
+
3841 for( int i=0; i<size; i++ ){
+
3842 data_vec.at(i)=data_ptr[i];
+
3843 }
+
3844
+
3845 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
3846
+
3847 return data_vec;
+
3848
+
3849}
+
3850
+
3851void RadiationModel::addBuffer( const char* name, RTbuffer& buffer, RTvariable& variable, RTbuffertype type, RTformat format, size_t dimension ){
+
3852
+
3853 RT_CHECK_ERROR( rtBufferCreate( OptiX_Context, type, &buffer ) );
+
3854 RT_CHECK_ERROR( rtBufferSetFormat( buffer, format ) );
+
3855 RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, name, &variable ) );
+
3856 RT_CHECK_ERROR( rtVariableSetObject( variable, buffer ) );
+
3857 if( dimension==1 ){
+
3858 zeroBuffer1D( buffer, 1 );
+
3859 }else if( dimension==2 ){
+
3860 zeroBuffer2D( buffer, optix::make_int2(1,1) );
+
3861 }else{
+
3862 helios_runtime_error("ERROR (RadiationModel::addBuffer): invalid buffer dimension of " + std::to_string(dimension) + ", must be 1 or 2.");
+
3863 }
+
3864
+
3865}
+
3866
+
3867void RadiationModel::zeroBuffer1D(RTbuffer &buffer, size_t bsize ){
+
3868
+
3869 //get buffer format
+
3870 RTformat format;
+
3871 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
3872
+
3873 if( format==RT_FORMAT_USER ){//Note: for now, assume user format means it's a double
+
3874
+
3875 std::vector<double> array;
+
3876 array.resize(bsize);
+
3877 for( int i=0; i<bsize; i++ ){
+
3878 array.at(i)=0.f;
+
3879 }
+
3880
+
3881 initializeBuffer1Dd( buffer, array );
+
3882
+
3883 }else if( format==RT_FORMAT_FLOAT ){
+
3884
+
3885 std::vector<float> array;
+
3886 array.resize(bsize);
+
3887 for( int i=0; i<bsize; i++ ){
+
3888 array.at(i)=0.f;
+
3889 }
+
3890
+
3891 initializeBuffer1Df( buffer, array );
+
3892
+
3893 }else if( format==RT_FORMAT_FLOAT2 ){
+
3894
+
3895 std::vector<optix::float2> array;
+
3896 array.resize(bsize);
+
3897 for( int i=0; i<bsize; i++ ){
+
3898 array.at(i)=optix::make_float2(0,0);
+
3899 }
+
3900
+
3901 initializeBuffer1Dfloat2( buffer, array );
+
3902
+
3903 }else if( format==RT_FORMAT_FLOAT3 ){
+
3904
+
3905 std::vector<optix::float3> array;
+
3906 array.resize(bsize);
+
3907 for( int i=0; i<bsize; i++ ){
+
3908 array.at(i)=optix::make_float3(0,0,0);
+
3909 }
+
3910
+
3911 initializeBuffer1Dfloat3( buffer, array );
+
3912
+
3913 }else if( format==RT_FORMAT_INT ){
+
3914
+
3915 std::vector<int> array;
+
3916 array.resize(bsize);
+
3917 for( int i=0; i<bsize; i++ ){
+
3918 array.at(i)=0;
+
3919 }
+
3920
+
3921 initializeBuffer1Di( buffer, array );
+
3922
+
3923 }else if( format==RT_FORMAT_INT2 ){
+
3924
+
3925 std::vector<optix::int2> array;
+
3926 array.resize(bsize);
+
3927 for( int i=0; i<bsize; i++ ){
+
3928 array.at(i)=optix::make_int2(0,0);
+
3929 }
+
3930
+
3931 initializeBuffer1Dint2( buffer, array );
+
3932
+
3933 }else if( format==RT_FORMAT_INT3 ){
+
3934
+
3935 std::vector<optix::int3> array;
+
3936 array.resize(bsize);
+
3937 for( int i=0; i<bsize; i++ ){
+
3938 array.at(i)=optix::make_int3(0,0,0);
+
3939 }
+
3940
+
3941 initializeBuffer1Dint3( buffer, array );
+
3942
+
3943 }else if( format==RT_FORMAT_UNSIGNED_INT ){
3944
-
3945}
-
3946
-
3947void RadiationModel::copyBuffer1D( RTbuffer &buffer, RTbuffer &buffer_copy ){
-
3948
-
3949 /* \todo Add support for all data types (currently only works for float and float3)*/
+
3945 std::vector<uint> array;
+
3946 array.resize(bsize);
+
3947 for( int i=0; i<bsize; i++ ){
+
3948 array.at(i)=0;
+
3949 }
3950
-
3951 //get buffer format
-
3952 RTformat format;
-
3953 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
3951 initializeBuffer1Dui( buffer, array );
+
3952
+
3953 }else if( format==RT_FORMAT_BYTE ){
3954
-
3955 //get buffer size
-
3956 RTsize bsize;
-
3957 rtBufferGetSize1D( buffer, &bsize );
-
3958
-
3959 rtBufferSetSize1D( buffer_copy, bsize );
+
3955 std::vector<char> array;
+
3956 array.resize(bsize);
+
3957 for( int i=0; i<bsize; i++ ){
+
3958 array.at(i)=0;
+
3959 }
3960
-
3961 if( format==RT_FORMAT_FLOAT ){
-
3962
-
3963 void* ptr;
-
3964 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
3965 float* data = (float*)ptr;
-
3966
-
3967 void* ptr_copy;
-
3968 RT_CHECK_ERROR( rtBufferMap( buffer_copy, &ptr_copy ) );
-
3969 float* data_copy = (float*)ptr_copy;
-
3970
-
3971 for( size_t i = 0; i <bsize; i++ ) {
-
3972 data_copy[i] = data[i];
-
3973 }
-
3974
-
3975 }else if( format==RT_FORMAT_FLOAT3 ){
-
3976
-
3977 void* ptr;
-
3978 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
3979 optix::float3* data = (optix::float3*)ptr;
-
3980
-
3981 void* ptr_copy;
-
3982 RT_CHECK_ERROR( rtBufferMap( buffer_copy, &ptr_copy ) );
-
3983 optix::float3* data_copy = (optix::float3*)ptr_copy;
-
3984
-
3985 for( size_t i = 0; i <bsize; i++ ) {
-
3986 data_copy[i] = data[i];
-
3987 }
-
3988
-
3989 }
-
3990
-
3991 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
3992 RT_CHECK_ERROR( rtBufferUnmap( buffer_copy ) );
-
3993
-
3994}
+
3961 initializeBuffer1Dchar( buffer, array );
+
3962 }else{
+
3963 helios_runtime_error("ERROR (RadiationModel::zeroBuffer1D): Buffer type not supported.");
+
3964 }
+
3965
+
3966}
+
3967
+
3968void RadiationModel::copyBuffer1D( RTbuffer &buffer, RTbuffer &buffer_copy ){
+
3969
+
3970 /* \todo Add support for all data types (currently only works for float and float3)*/
+
3971
+
3972 //get buffer format
+
3973 RTformat format;
+
3974 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
3975
+
3976 //get buffer size
+
3977 RTsize bsize;
+
3978 rtBufferGetSize1D( buffer, &bsize );
+
3979
+
3980 rtBufferSetSize1D( buffer_copy, bsize );
+
3981
+
3982 if( format==RT_FORMAT_FLOAT ){
+
3983
+
3984 void* ptr;
+
3985 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
3986 float* data = (float*)ptr;
+
3987
+
3988 void* ptr_copy;
+
3989 RT_CHECK_ERROR( rtBufferMap( buffer_copy, &ptr_copy ) );
+
3990 float* data_copy = (float*)ptr_copy;
+
3991
+
3992 for( size_t i = 0; i <bsize; i++ ) {
+
3993 data_copy[i] = data[i];
+
3994 }
3995
-
3996void RadiationModel::initializeBuffer1Dd(RTbuffer &buffer, const std::vector<double> &array ){
+
3996 }else if( format==RT_FORMAT_FLOAT3 ){
3997
-
3998 size_t bsize = array.size();
-
3999
-
4000 //set buffer size
-
4001 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4002
-
4003 //get buffer format
-
4004 RTformat format;
-
4005 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4006
-
4007 if( format!=RT_FORMAT_USER ){
-
4008 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dd): Buffer must have type double.");
-
4009 }
-
4010
-
4011 void* ptr;
-
4012 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4013
-
4014 double* data = (double*)ptr;
-
4015
-
4016 for( size_t i = 0; i <bsize; i++ ) {
-
4017 data[i] = array[i];
-
4018 }
-
4019
-
4020 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4021
-
4022}
+
3998 void* ptr;
+
3999 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4000 optix::float3* data = (optix::float3*)ptr;
+
4001
+
4002 void* ptr_copy;
+
4003 RT_CHECK_ERROR( rtBufferMap( buffer_copy, &ptr_copy ) );
+
4004 optix::float3* data_copy = (optix::float3*)ptr_copy;
+
4005
+
4006 for( size_t i = 0; i <bsize; i++ ) {
+
4007 data_copy[i] = data[i];
+
4008 }
+
4009
+
4010 }
+
4011
+
4012 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4013 RT_CHECK_ERROR( rtBufferUnmap( buffer_copy ) );
+
4014
+
4015}
+
4016
+
4017void RadiationModel::initializeBuffer1Dd(RTbuffer &buffer, const std::vector<double> &array ){
+
4018
+
4019 size_t bsize = array.size();
+
4020
+
4021 //set buffer size
+
4022 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4023
-
4024void RadiationModel::initializeBuffer1Df(RTbuffer &buffer, const std::vector<float> &array ){
-
4025
-
4026 size_t bsize = array.size();
+
4024 //get buffer format
+
4025 RTformat format;
+
4026 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4027
-
4028 //set buffer size
-
4029 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4030
-
4031 //get buffer format
-
4032 RTformat format;
-
4033 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4028 if( format!=RT_FORMAT_USER ){
+
4029 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dd): Buffer must have type double.");
+
4030 }
+
4031
+
4032 void* ptr;
+
4033 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4034
-
4035 if( format!=RT_FORMAT_FLOAT ){
-
4036 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Df): Buffer must have type float.");
-
4037 }
-
4038
-
4039 void* ptr;
-
4040 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4041
-
4042 float* data = (float*)ptr;
-
4043
-
4044 for( size_t i = 0; i <bsize; i++ ) {
-
4045 data[i] = array[i];
-
4046 }
-
4047
-
4048 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4049
-
4050}
+
4035 double* data = (double*)ptr;
+
4036
+
4037 for( size_t i = 0; i <bsize; i++ ) {
+
4038 data[i] = array[i];
+
4039 }
+
4040
+
4041 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4042
+
4043}
+
4044
+
4045void RadiationModel::initializeBuffer1Df(RTbuffer &buffer, const std::vector<float> &array ){
+
4046
+
4047 size_t bsize = array.size();
+
4048
+
4049 //set buffer size
+
4050 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4051
-
4052void RadiationModel::initializeBuffer1Dfloat2(RTbuffer &buffer, const std::vector<optix::float2> &array ){
-
4053
-
4054 size_t bsize = array.size();
+
4052 //get buffer format
+
4053 RTformat format;
+
4054 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4055
-
4056 //set buffer size
-
4057 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4058
-
4059 //get buffer format
-
4060 RTformat format;
-
4061 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4056 if( format!=RT_FORMAT_FLOAT ){
+
4057 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Df): Buffer must have type float.");
+
4058 }
+
4059
+
4060 void* ptr;
+
4061 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4062
-
4063 if( format!=RT_FORMAT_FLOAT2 ){
-
4064 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat2): Buffer must have type float2.");
-
4065 }
-
4066
-
4067 void* ptr;
-
4068 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4069
-
4070 optix::float2* data = (optix::float2*)ptr;
-
4071
-
4072 for( size_t i = 0; i <bsize; i++ ) {
-
4073 data[i].x = array[i].x;
-
4074 data[i].y = array[i].y;
-
4075 }
+
4063 float* data = (float*)ptr;
+
4064
+
4065 for( size_t i = 0; i <bsize; i++ ) {
+
4066 data[i] = array[i];
+
4067 }
+
4068
+
4069 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4070
+
4071}
+
4072
+
4073void RadiationModel::initializeBuffer1Dfloat2(RTbuffer &buffer, const std::vector<optix::float2> &array ){
+
4074
+
4075 size_t bsize = array.size();
4076
-
4077 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4078
-
4079}
-
4080
-
4081void RadiationModel::initializeBuffer1Dfloat3(RTbuffer &buffer, const std::vector<optix::float3> &array ){
-
4082
-
4083 size_t bsize = array.size();
-
4084
-
4085 //set buffer size
-
4086 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
+
4077 //set buffer size
+
4078 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
+
4079
+
4080 //get buffer format
+
4081 RTformat format;
+
4082 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4083
+
4084 if( format!=RT_FORMAT_FLOAT2 ){
+
4085 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat2): Buffer must have type float2.");
+
4086 }
4087
-
4088 //get buffer format
-
4089 RTformat format;
-
4090 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4091
-
4092 if( format!=RT_FORMAT_FLOAT3 ){
-
4093 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat3): Buffer must have type float3.");
-
4094 }
-
4095
-
4096 void* ptr;
-
4097 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4098
-
4099 optix::float3* data = (optix::float3*)ptr;
-
4100
-
4101 for( size_t i = 0; i <bsize; i++ ) {
-
4102 data[i].x = array[i].x;
-
4103 data[i].y = array[i].y;
-
4104 data[i].z = array[i].z;
-
4105 }
-
4106
-
4107 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4088 void* ptr;
+
4089 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4090
+
4091 optix::float2* data = (optix::float2*)ptr;
+
4092
+
4093 for( size_t i = 0; i <bsize; i++ ) {
+
4094 data[i].x = array[i].x;
+
4095 data[i].y = array[i].y;
+
4096 }
+
4097
+
4098 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4099
+
4100}
+
4101
+
4102void RadiationModel::initializeBuffer1Dfloat3(RTbuffer &buffer, const std::vector<optix::float3> &array ){
+
4103
+
4104 size_t bsize = array.size();
+
4105
+
4106 //set buffer size
+
4107 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4108
-
4109}
-
4110
-
4111void RadiationModel::initializeBuffer1Dfloat4(RTbuffer &buffer, const std::vector<optix::float4> &array ){
+
4109 //get buffer format
+
4110 RTformat format;
+
4111 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4112
-
4113 size_t bsize = array.size();
-
4114
-
4115 //set buffer size
-
4116 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4117
-
4118 //get buffer format
-
4119 RTformat format;
-
4120 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4113 if( format!=RT_FORMAT_FLOAT3 ){
+
4114 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat3): Buffer must have type float3.");
+
4115 }
+
4116
+
4117 void* ptr;
+
4118 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4119
+
4120 optix::float3* data = (optix::float3*)ptr;
4121
-
4122 if( format!=RT_FORMAT_FLOAT4 ){
-
4123 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat4): Buffer must have type float4.");
-
4124 }
-
4125
-
4126 void* ptr;
-
4127 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4128
-
4129 optix::float4* data = (optix::float4*)ptr;
-
4130
-
4131 for( size_t i = 0; i <bsize; i++ ) {
-
4132 data[i].x = array[i].x;
-
4133 data[i].y = array[i].y;
-
4134 data[i].z = array[i].z;
-
4135 data[i].w = array[i].w;
-
4136 }
-
4137
-
4138 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4139
-
4140}
-
4141
-
4142void RadiationModel::initializeBuffer1Di(RTbuffer &buffer, const std::vector<int> &array ){
-
4143
-
4144 size_t bsize = array.size();
-
4145
-
4146 //set buffer size
-
4147 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4148
-
4149 //get buffer format
-
4150 RTformat format;
-
4151 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4152
-
4153 if( format!=RT_FORMAT_INT ){
-
4154 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Di): Buffer must have type int.");
-
4155 }
-
4156
-
4157 void* ptr;
-
4158 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4159
-
4160 int* data = (int*)ptr;
-
4161
-
4162 for( size_t i = 0; i <bsize; i++ ) {
-
4163 data[i] = array[i];
-
4164 }
-
4165
-
4166 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4167
-
4168}
+
4122 for( size_t i = 0; i <bsize; i++ ) {
+
4123 data[i].x = array[i].x;
+
4124 data[i].y = array[i].y;
+
4125 data[i].z = array[i].z;
+
4126 }
+
4127
+
4128 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4129
+
4130}
+
4131
+
4132void RadiationModel::initializeBuffer1Dfloat4(RTbuffer &buffer, const std::vector<optix::float4> &array ){
+
4133
+
4134 size_t bsize = array.size();
+
4135
+
4136 //set buffer size
+
4137 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
+
4138
+
4139 //get buffer format
+
4140 RTformat format;
+
4141 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4142
+
4143 if( format!=RT_FORMAT_FLOAT4 ){
+
4144 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dfloat4): Buffer must have type float4.");
+
4145 }
+
4146
+
4147 void* ptr;
+
4148 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4149
+
4150 optix::float4* data = (optix::float4*)ptr;
+
4151
+
4152 for( size_t i = 0; i <bsize; i++ ) {
+
4153 data[i].x = array[i].x;
+
4154 data[i].y = array[i].y;
+
4155 data[i].z = array[i].z;
+
4156 data[i].w = array[i].w;
+
4157 }
+
4158
+
4159 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4160
+
4161}
+
4162
+
4163void RadiationModel::initializeBuffer1Di(RTbuffer &buffer, const std::vector<int> &array ){
+
4164
+
4165 size_t bsize = array.size();
+
4166
+
4167 //set buffer size
+
4168 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4169
-
4170void RadiationModel::initializeBuffer1Dui(RTbuffer &buffer, const std::vector<uint> &array ){
-
4171
-
4172 size_t bsize = array.size();
+
4170 //get buffer format
+
4171 RTformat format;
+
4172 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4173
-
4174 //set buffer size
-
4175 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4176
-
4177 //get buffer format
-
4178 RTformat format;
-
4179 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4174 if( format!=RT_FORMAT_INT ){
+
4175 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Di): Buffer must have type int.");
+
4176 }
+
4177
+
4178 void* ptr;
+
4179 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4180
-
4181 if( format!=RT_FORMAT_UNSIGNED_INT ){
-
4182 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dui): Buffer must have type unsigned int.");
-
4183 }
-
4184
-
4185 void* ptr;
-
4186 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4187
-
4188 uint* data = (uint*)ptr;
-
4189
-
4190 for( size_t i = 0; i <bsize; i++ ) {
-
4191 data[i] = array[i];
-
4192 }
-
4193
-
4194 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4195
-
4196}
+
4181 int* data = (int*)ptr;
+
4182
+
4183 for( size_t i = 0; i <bsize; i++ ) {
+
4184 data[i] = array[i];
+
4185 }
+
4186
+
4187 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4188
+
4189}
+
4190
+
4191void RadiationModel::initializeBuffer1Dui(RTbuffer &buffer, const std::vector<uint> &array ){
+
4192
+
4193 size_t bsize = array.size();
+
4194
+
4195 //set buffer size
+
4196 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4197
-
4198void RadiationModel::initializeBuffer1Dint2(RTbuffer &buffer, const std::vector<optix::int2> &array ){
-
4199
-
4200 size_t bsize = array.size();
+
4198 //get buffer format
+
4199 RTformat format;
+
4200 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4201
-
4202 //set buffer size
-
4203 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4204
-
4205 //get buffer format
-
4206 RTformat format;
-
4207 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4202 if( format!=RT_FORMAT_UNSIGNED_INT ){
+
4203 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dui): Buffer must have type unsigned int.");
+
4204 }
+
4205
+
4206 void* ptr;
+
4207 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4208
-
4209 if( format!=RT_FORMAT_INT2 ){
-
4210 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dint2): Buffer must have type int2.");
-
4211 }
-
4212
-
4213 void* ptr;
-
4214 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4215
-
4216 optix::int2* data = (optix::int2*)ptr;
-
4217
-
4218 for( size_t i = 0; i <bsize; i++ ) {
-
4219 data[i] = array[i];
-
4220 }
-
4221
-
4222 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4223
-
4224}
+
4209 uint* data = (uint*)ptr;
+
4210
+
4211 for( size_t i = 0; i <bsize; i++ ) {
+
4212 data[i] = array[i];
+
4213 }
+
4214
+
4215 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4216
+
4217}
+
4218
+
4219void RadiationModel::initializeBuffer1Dint2(RTbuffer &buffer, const std::vector<optix::int2> &array ){
+
4220
+
4221 size_t bsize = array.size();
+
4222
+
4223 //set buffer size
+
4224 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4225
-
4226void RadiationModel::initializeBuffer1Dint3(RTbuffer &buffer, const std::vector<optix::int3> &array ){
-
4227
-
4228 size_t bsize = array.size();
+
4226 //get buffer format
+
4227 RTformat format;
+
4228 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4229
-
4230 //set buffer size
-
4231 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4232
-
4233 //get buffer format
-
4234 RTformat format;
-
4235 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4230 if( format!=RT_FORMAT_INT2 ){
+
4231 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dint2): Buffer must have type int2.");
+
4232 }
+
4233
+
4234 void* ptr;
+
4235 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4236
-
4237 if( format!=RT_FORMAT_INT3 ){
-
4238 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dint3): Buffer must have type int3.");
-
4239 }
-
4240
-
4241 void* ptr;
-
4242 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4243
-
4244 optix::int3* data = (optix::int3*)ptr;
-
4245
-
4246 for( size_t i = 0; i <bsize; i++ ) {
-
4247 data[i] = array[i];
-
4248 }
-
4249
-
4250 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4251
-
4252}
+
4237 optix::int2* data = (optix::int2*)ptr;
+
4238
+
4239 for( size_t i = 0; i <bsize; i++ ) {
+
4240 data[i] = array[i];
+
4241 }
+
4242
+
4243 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4244
+
4245}
+
4246
+
4247void RadiationModel::initializeBuffer1Dint3(RTbuffer &buffer, const std::vector<optix::int3> &array ){
+
4248
+
4249 size_t bsize = array.size();
+
4250
+
4251 //set buffer size
+
4252 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4253
-
4254void RadiationModel::initializeBuffer1Dchar(RTbuffer &buffer, const std::vector<char> &array ){
-
4255
-
4256 size_t bsize = array.size();
+
4254 //get buffer format
+
4255 RTformat format;
+
4256 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4257
-
4258 //set buffer size
-
4259 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
-
4260
-
4261 //get buffer format
-
4262 RTformat format;
-
4263 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4258 if( format!=RT_FORMAT_INT3 ){
+
4259 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dint3): Buffer must have type int3.");
+
4260 }
+
4261
+
4262 void* ptr;
+
4263 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
4264
-
4265 if( format!=RT_FORMAT_BYTE ){
-
4266 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dchar): Buffer must have type char.");
-
4267 }
-
4268
-
4269 void* ptr;
-
4270 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4271
-
4272 char* data = (char*)ptr;
-
4273
-
4274 for( size_t i = 0; i <bsize; i++ ) {
-
4275 data[i] = array[i];
-
4276 }
-
4277
-
4278 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4279
-
4280}
+
4265 optix::int3* data = (optix::int3*)ptr;
+
4266
+
4267 for( size_t i = 0; i <bsize; i++ ) {
+
4268 data[i] = array[i];
+
4269 }
+
4270
+
4271 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4272
+
4273}
+
4274
+
4275void RadiationModel::initializeBuffer1Dchar(RTbuffer &buffer, const std::vector<char> &array ){
+
4276
+
4277 size_t bsize = array.size();
+
4278
+
4279 //set buffer size
+
4280 RT_CHECK_ERROR( rtBufferSetSize1D( buffer, bsize ) );
4281
-
4282void RadiationModel::zeroBuffer2D(RTbuffer &buffer, optix::int2 bsize ){
-
4283
-
4284 //set buffer size
-
4285 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4286
-
4287 //get buffer format
-
4288 RTformat format;
-
4289 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4290
-
4291 if( format==RT_FORMAT_USER ){//Note: for now we'll assume this means it's a double
-
4292 std::vector<std::vector<double> > array;
-
4293 array.resize(bsize.y);
-
4294 for( int j=0; j<bsize.y; j++ ){
-
4295 array.at(j).resize(bsize.x);
-
4296 for( int i=0; i<bsize.x; i++ ){
-
4297 array.at(j).at(i)=0.f;
-
4298 }
-
4299 }
-
4300 initializeBuffer2Dd( buffer, array );
-
4301 }else if( format==RT_FORMAT_FLOAT ){
-
4302 std::vector<std::vector<float> > array;
-
4303 array.resize(bsize.y);
-
4304 for( int j=0; j<bsize.y; j++ ){
-
4305 array.at(j).resize(bsize.x);
-
4306 for( int i=0; i<bsize.x; i++ ){
-
4307 array.at(j).at(i)=0.f;
-
4308 }
-
4309 }
-
4310 initializeBuffer2Df( buffer, array );
-
4311 }else if( format==RT_FORMAT_FLOAT2 ){
-
4312 std::vector<std::vector<optix::float2> > 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;
+
4282 //get buffer format
+
4283 RTformat format;
+
4284 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4285
+
4286 if( format!=RT_FORMAT_BYTE ){
+
4287 helios_runtime_error("ERROR (RadiationModel::initializeBuffer1Dchar): Buffer must have type char.");
+
4288 }
+
4289
+
4290 void* ptr;
+
4291 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4292
+
4293 char* data = (char*)ptr;
+
4294
+
4295 for( size_t i = 0; i <bsize; i++ ) {
+
4296 data[i] = array[i];
+
4297 }
+
4298
+
4299 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4300
+
4301}
+
4302
+
4303void RadiationModel::zeroBuffer2D(RTbuffer &buffer, optix::int2 bsize ){
+
4304
+
4305 //set buffer size
+
4306 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4307
+
4308 //get buffer format
+
4309 RTformat format;
+
4310 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4311
+
4312 if( format==RT_FORMAT_USER ){//Note: for now we'll assume this means it's a double
+
4313 std::vector<std::vector<double> > array;
+
4314 array.resize(bsize.y);
+
4315 for( int j=0; j<bsize.y; j++ ){
+
4316 array.at(j).resize(bsize.x);
+
4317 for( int i=0; i<bsize.x; i++ ){
+
4318 array.at(j).at(i)=0.f;
4319 }
4320 }
-
4321 initializeBuffer2Dfloat2( buffer, array );
-
4322 }else if( format==RT_FORMAT_FLOAT3 ){
-
4323 std::vector<std::vector<optix::float3> > array;
+
4321 initializeBuffer2Dd( buffer, array );
+
4322 }else if( format==RT_FORMAT_FLOAT ){
+
4323 std::vector<std::vector<float> > array;
4324 array.resize(bsize.y);
4325 for( int j=0; j<bsize.y; j++ ){
4326 array.at(j).resize(bsize.x);
4327 for( int i=0; i<bsize.x; i++ ){
-
4328 array.at(j).at(i).x=0.f;
-
4329 array.at(j).at(i).y=0.f;
-
4330 array.at(j).at(i).z=0.f;
-
4331 }
-
4332 }
-
4333 initializeBuffer2Dfloat3( buffer, array );
-
4334 }else if( format==RT_FORMAT_FLOAT4 ){
-
4335 std::vector<std::vector<optix::float4> > array;
-
4336 array.resize(bsize.y);
-
4337 for( int j=0; j<bsize.y; j++ ){
-
4338 array.at(j).resize(bsize.x);
-
4339 for( int i=0; i<bsize.x; i++ ){
-
4340 array.at(j).at(i).x=0.f;
-
4341 array.at(j).at(i).y=0.f;
-
4342 array.at(j).at(i).z=0.f;
-
4343 array.at(j).at(i).w=0.f;
-
4344 }
-
4345 }
-
4346 initializeBuffer2Dfloat4( buffer, array );
-
4347 }else if( format==RT_FORMAT_INT ){
-
4348 std::vector<std::vector<int> > array;
-
4349 array.resize(bsize.y);
-
4350 for( int j=0; j<bsize.y; j++ ){
-
4351 array.at(j).resize(bsize.x);
-
4352 for( int i=0; i<bsize.x; i++ ){
-
4353 array.at(j).at(i)=0;
-
4354 }
-
4355 }
-
4356 initializeBuffer2Di( buffer, array );
-
4357 }else if( format==RT_FORMAT_UNSIGNED_INT ){
-
4358 std::vector<std::vector<uint> > array;
-
4359 array.resize(bsize.y);
-
4360 for( int j=0; j<bsize.y; j++ ){
-
4361 array.at(j).resize(bsize.x);
-
4362 for( int i=0; i<bsize.x; i++ ){
-
4363 array.at(j).at(i)=0;
-
4364 }
-
4365 }
-
4366 initializeBuffer2Dui( buffer, array );
-
4367 }else if( format==RT_FORMAT_INT2 ){
-
4368 std::vector<std::vector<optix::int2> > 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;
+
4328 array.at(j).at(i)=0.f;
+
4329 }
+
4330 }
+
4331 initializeBuffer2Df( buffer, array );
+
4332 }else if( format==RT_FORMAT_FLOAT2 ){
+
4333 std::vector<std::vector<optix::float2> > array;
+
4334 array.resize(bsize.y);
+
4335 for( int j=0; j<bsize.y; j++ ){
+
4336 array.at(j).resize(bsize.x);
+
4337 for( int i=0; i<bsize.x; i++ ){
+
4338 array.at(j).at(i).x=0.f;
+
4339 array.at(j).at(i).y=0.f;
+
4340 }
+
4341 }
+
4342 initializeBuffer2Dfloat2( buffer, array );
+
4343 }else if( format==RT_FORMAT_FLOAT3 ){
+
4344 std::vector<std::vector<optix::float3> > array;
+
4345 array.resize(bsize.y);
+
4346 for( int j=0; j<bsize.y; j++ ){
+
4347 array.at(j).resize(bsize.x);
+
4348 for( int i=0; i<bsize.x; i++ ){
+
4349 array.at(j).at(i).x=0.f;
+
4350 array.at(j).at(i).y=0.f;
+
4351 array.at(j).at(i).z=0.f;
+
4352 }
+
4353 }
+
4354 initializeBuffer2Dfloat3( buffer, array );
+
4355 }else if( format==RT_FORMAT_FLOAT4 ){
+
4356 std::vector<std::vector<optix::float4> > array;
+
4357 array.resize(bsize.y);
+
4358 for( int j=0; j<bsize.y; j++ ){
+
4359 array.at(j).resize(bsize.x);
+
4360 for( int i=0; i<bsize.x; i++ ){
+
4361 array.at(j).at(i).x=0.f;
+
4362 array.at(j).at(i).y=0.f;
+
4363 array.at(j).at(i).z=0.f;
+
4364 array.at(j).at(i).w=0.f;
+
4365 }
+
4366 }
+
4367 initializeBuffer2Dfloat4( buffer, array );
+
4368 }else if( format==RT_FORMAT_INT ){
+
4369 std::vector<std::vector<int> > array;
+
4370 array.resize(bsize.y);
+
4371 for( int j=0; j<bsize.y; j++ ){
+
4372 array.at(j).resize(bsize.x);
+
4373 for( int i=0; i<bsize.x; i++ ){
+
4374 array.at(j).at(i)=0;
4375 }
4376 }
-
4377 initializeBuffer2Dint2( buffer, array );
-
4378 }else if( format==RT_FORMAT_INT3 ){
-
4379 std::vector<std::vector<optix::int3> > array;
+
4377 initializeBuffer2Di( buffer, array );
+
4378 }else if( format==RT_FORMAT_UNSIGNED_INT ){
+
4379 std::vector<std::vector<uint> > array;
4380 array.resize(bsize.y);
4381 for( int j=0; j<bsize.y; j++ ){
4382 array.at(j).resize(bsize.x);
4383 for( int i=0; i<bsize.x; i++ ){
-
4384 array.at(j).at(i).x=0;
-
4385 array.at(j).at(i).y=0;
-
4386 array.at(j).at(i).z=0;
-
4387 }
-
4388 }
-
4389 initializeBuffer2Dint3( buffer, array );
-
4390 }else if( format==RT_FORMAT_BYTE ){
-
4391 std::vector<std::vector<bool> > array;
-
4392 array.resize(bsize.y);
-
4393 for( int j=0; j<bsize.y; j++ ){
-
4394 array.at(j).resize(bsize.x);
-
4395 for( int i=0; i<bsize.x; i++ ){
-
4396 array.at(j).at(i)=false;
-
4397 }
-
4398 }
-
4399 initializeBuffer2Dbool( buffer, array );
-
4400 }else{
-
4401 helios_runtime_error("ERROR (RadiationModel::zeroBuffer2D): unknown buffer format.");
-
4402 }
-
4403
-
4404}
-
4405
-
4406void RadiationModel::initializeBuffer2Dd(RTbuffer &buffer, const std::vector<std::vector<double>> &array ){
-
4407
-
4408 optix::int2 bsize;
-
4409 bsize.y = array.size();
-
4410 if( bsize.y==0 ){
-
4411 bsize.x = 0;
-
4412 }else{
-
4413 bsize.x = array.front().size();
-
4414 }
-
4415
-
4416 //set buffer size
-
4417 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4418
-
4419 //get buffer formatsyn
-
4420 RTformat format;
-
4421 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
-
4422
-
4423 void* ptr;
-
4424 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4425
-
4426 if( format==RT_FORMAT_USER ){
-
4427 double* data = (double*)ptr;
-
4428 for( size_t j = 0; j<bsize.y; j++ ) {
-
4429 for( size_t i = 0; i<bsize.x; i++ ) {
-
4430 data[i+j*bsize.x] = array[j][i];
-
4431 }
-
4432 }
+
4384 array.at(j).at(i)=0;
+
4385 }
+
4386 }
+
4387 initializeBuffer2Dui( buffer, array );
+
4388 }else if( format==RT_FORMAT_INT2 ){
+
4389 std::vector<std::vector<optix::int2> > array;
+
4390 array.resize(bsize.y);
+
4391 for( int j=0; j<bsize.y; j++ ){
+
4392 array.at(j).resize(bsize.x);
+
4393 for( int i=0; i<bsize.x; i++ ){
+
4394 array.at(j).at(i).x=0;
+
4395 array.at(j).at(i).y=0;
+
4396 }
+
4397 }
+
4398 initializeBuffer2Dint2( buffer, array );
+
4399 }else if( format==RT_FORMAT_INT3 ){
+
4400 std::vector<std::vector<optix::int3> > array;
+
4401 array.resize(bsize.y);
+
4402 for( int j=0; j<bsize.y; j++ ){
+
4403 array.at(j).resize(bsize.x);
+
4404 for( int i=0; i<bsize.x; i++ ){
+
4405 array.at(j).at(i).x=0;
+
4406 array.at(j).at(i).y=0;
+
4407 array.at(j).at(i).z=0;
+
4408 }
+
4409 }
+
4410 initializeBuffer2Dint3( buffer, array );
+
4411 }else if( format==RT_FORMAT_BYTE ){
+
4412 std::vector<std::vector<bool> > array;
+
4413 array.resize(bsize.y);
+
4414 for( int j=0; j<bsize.y; j++ ){
+
4415 array.at(j).resize(bsize.x);
+
4416 for( int i=0; i<bsize.x; i++ ){
+
4417 array.at(j).at(i)=false;
+
4418 }
+
4419 }
+
4420 initializeBuffer2Dbool( buffer, array );
+
4421 }else{
+
4422 helios_runtime_error("ERROR (RadiationModel::zeroBuffer2D): unknown buffer format.");
+
4423 }
+
4424
+
4425}
+
4426
+
4427void RadiationModel::initializeBuffer2Dd(RTbuffer &buffer, const std::vector<std::vector<double>> &array ){
+
4428
+
4429 optix::int2 bsize;
+
4430 bsize.y = array.size();
+
4431 if( bsize.y==0 ){
+
4432 bsize.x = 0;
4433 }else{
-
4434 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dd): Buffer does not have format 'RT_FORMAT_USER'.");
+
4434 bsize.x = array.front().size();
4435 }
4436
-
4437 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4438
-
4439}
-
4440
-
4441void RadiationModel::initializeBuffer2Df(RTbuffer &buffer, const std::vector<std::vector<float>> &array ){
-
4442
-
4443 optix::int2 bsize;
-
4444 bsize.y = array.size();
-
4445 if( bsize.y==0 ){
-
4446 bsize.x = 0;
-
4447 }else{
-
4448 bsize.x = array.front().size();
-
4449 }
-
4450
-
4451 //set buffer size
-
4452 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4453
-
4454 //get buffer format
-
4455 RTformat format;
-
4456 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4437 //set buffer size
+
4438 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4439
+
4440 //get buffer formatsyn
+
4441 RTformat format;
+
4442 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4443
+
4444 void* ptr;
+
4445 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4446
+
4447 if( format==RT_FORMAT_USER ){
+
4448 double* data = (double*)ptr;
+
4449 for( size_t j = 0; j<bsize.y; j++ ) {
+
4450 for( size_t i = 0; i<bsize.x; i++ ) {
+
4451 data[i+j*bsize.x] = array[j][i];
+
4452 }
+
4453 }
+
4454 }else{
+
4455 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dd): Buffer does not have format 'RT_FORMAT_USER'.");
+
4456 }
4457
-
4458 void* ptr;
-
4459 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4460
-
4461 if( format==RT_FORMAT_FLOAT ){
-
4462 float* data = (float*)ptr;
-
4463 for( size_t j = 0; j<bsize.y; j++ ) {
-
4464 for( size_t i = 0; i<bsize.x; i++ ) {
-
4465 data[i+j*bsize.x] = array[j][i];
-
4466 }
-
4467 }
+
4458 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4459
+
4460}
+
4461
+
4462void RadiationModel::initializeBuffer2Df(RTbuffer &buffer, const std::vector<std::vector<float>> &array ){
+
4463
+
4464 optix::int2 bsize;
+
4465 bsize.y = array.size();
+
4466 if( bsize.y==0 ){
+
4467 bsize.x = 0;
4468 }else{
-
4469 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Df): Buffer does not have format 'RT_FORMAT_FLOAT'.");
+
4469 bsize.x = array.front().size();
4470 }
4471
-
4472 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4473
-
4474}
-
4475
-
4476void RadiationModel::initializeBuffer2Dfloat2(RTbuffer &buffer, const std::vector<std::vector<optix::float2>> &array ){
-
4477
-
4478 optix::int2 bsize;
-
4479 bsize.y = array.size();
-
4480 if( bsize.y==0 ){
-
4481 bsize.x = 0;
-
4482 }else{
-
4483 bsize.x = array.front().size();
-
4484 }
-
4485
-
4486 //set buffer size
-
4487 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4488
-
4489 //get buffer format
-
4490 RTformat format;
-
4491 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4472 //set buffer size
+
4473 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4474
+
4475 //get buffer format
+
4476 RTformat format;
+
4477 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4478
+
4479 void* ptr;
+
4480 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4481
+
4482 if( format==RT_FORMAT_FLOAT ){
+
4483 float* data = (float*)ptr;
+
4484 for( size_t j = 0; j<bsize.y; j++ ) {
+
4485 for( size_t i = 0; i<bsize.x; i++ ) {
+
4486 data[i+j*bsize.x] = array[j][i];
+
4487 }
+
4488 }
+
4489 }else{
+
4490 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Df): Buffer does not have format 'RT_FORMAT_FLOAT'.");
+
4491 }
4492
-
4493 void* ptr;
-
4494 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4495
-
4496 if( format==RT_FORMAT_FLOAT2 ){
-
4497 optix::float2* data = (optix::float2*)ptr;
-
4498 for( size_t j = 0; j<bsize.y; j++ ) {
-
4499 for( size_t i = 0; i<bsize.x; i++ ) {
-
4500 data[i+j*bsize.x].x = array[j][i].x;
-
4501 data[i+j*bsize.x].y = array[j][i].y;
-
4502 }
-
4503 }
-
4504 }else{
-
4505 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat2): Buffer does not have format 'RT_FORMAT_FLOAT2'.");
-
4506 }
-
4507
-
4508 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4493 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4494
+
4495}
+
4496
+
4497void RadiationModel::initializeBuffer2Dfloat2(RTbuffer &buffer, const std::vector<std::vector<optix::float2>> &array ){
+
4498
+
4499 optix::int2 bsize;
+
4500 bsize.y = array.size();
+
4501 if( bsize.y==0 ){
+
4502 bsize.x = 0;
+
4503 }else{
+
4504 bsize.x = array.front().size();
+
4505 }
+
4506
+
4507 //set buffer size
+
4508 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
4509
-
4510}
-
4511
-
4512void RadiationModel::initializeBuffer2Dfloat3(RTbuffer &buffer, const std::vector<std::vector<optix::float3>> &array ){
+
4510 //get buffer format
+
4511 RTformat format;
+
4512 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4513
-
4514 optix::int2 bsize;
-
4515 bsize.y = array.size();
-
4516 if( bsize.y==0 ){
-
4517 bsize.x = 0;
-
4518 }else{
-
4519 bsize.x = array.front().size();
-
4520 }
-
4521
-
4522 //set buffer size
-
4523 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4524
-
4525 //get buffer format
-
4526 RTformat format;
-
4527 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4514 void* ptr;
+
4515 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4516
+
4517 if( format==RT_FORMAT_FLOAT2 ){
+
4518 optix::float2* data = (optix::float2*)ptr;
+
4519 for( size_t j = 0; j<bsize.y; j++ ) {
+
4520 for( size_t i = 0; i<bsize.x; i++ ) {
+
4521 data[i+j*bsize.x].x = array[j][i].x;
+
4522 data[i+j*bsize.x].y = array[j][i].y;
+
4523 }
+
4524 }
+
4525 }else{
+
4526 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat2): Buffer does not have format 'RT_FORMAT_FLOAT2'.");
+
4527 }
4528
-
4529 void* ptr;
-
4530 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4531
-
4532 if( format==RT_FORMAT_FLOAT3 ){
-
4533 optix::float3* data = (optix::float3*)ptr;
-
4534 for( size_t j = 0; j<bsize.y; j++ ) {
-
4535 for( size_t i = 0; i<bsize.x; i++ ) {
-
4536 data[i+j*bsize.x].x = array.at(j).at(i).x;
-
4537 data[i+j*bsize.x].y = array.at(j).at(i).y;
-
4538 data[i+j*bsize.x].z = array.at(j).at(i).z;
-
4539 }
-
4540 }
-
4541 }else{
-
4542 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat3): Buffer does not have format 'RT_FORMAT_FLOAT3'.");
-
4543 }
-
4544
-
4545 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4546
-
4547}
-
4548
-
4549void RadiationModel::initializeBuffer2Dfloat4(RTbuffer &buffer, const std::vector<std::vector<optix::float4>> &array ){
-
4550
-
4551 optix::int2 bsize;
-
4552 bsize.y = array.size();
-
4553 if( bsize.y==0 ){
-
4554 bsize.x = 0;
-
4555 }else{
-
4556 bsize.x = array.front().size();
-
4557 }
-
4558
-
4559 //set buffer size
-
4560 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4561
-
4562 //get buffer format
-
4563 RTformat format;
-
4564 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4529 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4530
+
4531}
+
4532
+
4533void RadiationModel::initializeBuffer2Dfloat3(RTbuffer &buffer, const std::vector<std::vector<optix::float3>> &array ){
+
4534
+
4535 optix::int2 bsize;
+
4536 bsize.y = array.size();
+
4537 if( bsize.y==0 ){
+
4538 bsize.x = 0;
+
4539 }else{
+
4540 bsize.x = array.front().size();
+
4541 }
+
4542
+
4543 //set buffer size
+
4544 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4545
+
4546 //get buffer format
+
4547 RTformat format;
+
4548 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4549
+
4550 void* ptr;
+
4551 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4552
+
4553 if( format==RT_FORMAT_FLOAT3 ){
+
4554 optix::float3* data = (optix::float3*)ptr;
+
4555 for( size_t j = 0; j<bsize.y; j++ ) {
+
4556 for( size_t i = 0; i<bsize.x; i++ ) {
+
4557 data[i+j*bsize.x].x = array.at(j).at(i).x;
+
4558 data[i+j*bsize.x].y = array.at(j).at(i).y;
+
4559 data[i+j*bsize.x].z = array.at(j).at(i).z;
+
4560 }
+
4561 }
+
4562 }else{
+
4563 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat3): Buffer does not have format 'RT_FORMAT_FLOAT3'.");
+
4564 }
4565
-
4566 void* ptr;
-
4567 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4568
-
4569 if( format==RT_FORMAT_FLOAT4 ){
-
4570 optix::float4* data = (optix::float4*)ptr;
-
4571 for( size_t j = 0; j<bsize.y; j++ ) {
-
4572 for( size_t i = 0; i<bsize.x; i++ ) {
-
4573 data[i+j*bsize.x].x = array[j][i].x;
-
4574 data[i+j*bsize.x].y = array[j][i].y;
-
4575 data[i+j*bsize.x].z = array[j][i].z;
-
4576 data[i+j*bsize.x].w = array[j][i].w;
-
4577 }
-
4578 }
-
4579 }else{
-
4580 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat4): Buffer does not have format 'RT_FORMAT_FLOAT4'.");
-
4581 }
+
4566 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4567
+
4568}
+
4569
+
4570void RadiationModel::initializeBuffer2Dfloat4(RTbuffer &buffer, const std::vector<std::vector<optix::float4>> &array ){
+
4571
+
4572 optix::int2 bsize;
+
4573 bsize.y = array.size();
+
4574 if( bsize.y==0 ){
+
4575 bsize.x = 0;
+
4576 }else{
+
4577 bsize.x = array.front().size();
+
4578 }
+
4579
+
4580 //set buffer size
+
4581 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
4582
-
4583 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4584
-
4585}
+
4583 //get buffer format
+
4584 RTformat format;
+
4585 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4586
-
4587void RadiationModel::initializeBuffer2Di(RTbuffer &buffer, const std::vector<std::vector<int>> &array ){
-
4588
-
4589 optix::int2 bsize;
-
4590 bsize.y = array.size();
-
4591 if( bsize.y==0 ){
-
4592 bsize.x = 0;
-
4593 }else{
-
4594 bsize.x = array.front().size();
-
4595 }
-
4596
-
4597 //set buffer size
-
4598 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4599
-
4600 //get buffer format
-
4601 RTformat format;
-
4602 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4587 void* ptr;
+
4588 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4589
+
4590 if( format==RT_FORMAT_FLOAT4 ){
+
4591 optix::float4* data = (optix::float4*)ptr;
+
4592 for( size_t j = 0; j<bsize.y; j++ ) {
+
4593 for( size_t i = 0; i<bsize.x; i++ ) {
+
4594 data[i+j*bsize.x].x = array[j][i].x;
+
4595 data[i+j*bsize.x].y = array[j][i].y;
+
4596 data[i+j*bsize.x].z = array[j][i].z;
+
4597 data[i+j*bsize.x].w = array[j][i].w;
+
4598 }
+
4599 }
+
4600 }else{
+
4601 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dfloat4): Buffer does not have format 'RT_FORMAT_FLOAT4'.");
+
4602 }
4603
-
4604 void* ptr;
-
4605 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4606
-
4607 if( format==RT_FORMAT_INT ){
-
4608 int* data = (int*)ptr;
-
4609 for( size_t j = 0; j<bsize.y; j++ ) {
-
4610 for( size_t i = 0; i<bsize.x; i++ ) {
-
4611 data[i+j*bsize.x] = array[j][i];
-
4612 }
-
4613 }
+
4604 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4605
+
4606}
+
4607
+
4608void RadiationModel::initializeBuffer2Di(RTbuffer &buffer, const std::vector<std::vector<int>> &array ){
+
4609
+
4610 optix::int2 bsize;
+
4611 bsize.y = array.size();
+
4612 if( bsize.y==0 ){
+
4613 bsize.x = 0;
4614 }else{
-
4615 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Di): Buffer does not have format 'RT_FORMAT_INT'.");
+
4615 bsize.x = array.front().size();
4616 }
4617
-
4618 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4619
-
4620}
-
4621
-
4622void RadiationModel::initializeBuffer2Dui(RTbuffer &buffer, const std::vector<std::vector<uint>> &array ){
-
4623
-
4624 optix::int2 bsize;
-
4625 bsize.y = array.size();
-
4626 if( bsize.y==0 ){
-
4627 bsize.x = 0;
-
4628 }else{
-
4629 bsize.x = array.front().size();
-
4630 }
-
4631
-
4632 //set buffer size
-
4633 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4634
-
4635 //get buffer format
-
4636 RTformat format;
-
4637 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4618 //set buffer size
+
4619 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4620
+
4621 //get buffer format
+
4622 RTformat format;
+
4623 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4624
+
4625 void* ptr;
+
4626 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4627
+
4628 if( format==RT_FORMAT_INT ){
+
4629 int* data = (int*)ptr;
+
4630 for( size_t j = 0; j<bsize.y; j++ ) {
+
4631 for( size_t i = 0; i<bsize.x; i++ ) {
+
4632 data[i+j*bsize.x] = array[j][i];
+
4633 }
+
4634 }
+
4635 }else{
+
4636 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Di): Buffer does not have format 'RT_FORMAT_INT'.");
+
4637 }
4638
-
4639 void* ptr;
-
4640 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4641
-
4642 if( format==RT_FORMAT_UNSIGNED_INT ){
-
4643 uint* data = (uint*)ptr;
-
4644 for( size_t j = 0; j<bsize.y; j++ ) {
-
4645 for( size_t i = 0; i<bsize.x; i++ ) {
-
4646 data[i+j*bsize.x] = array[j][i];
-
4647 }
-
4648 }
+
4639 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4640
+
4641}
+
4642
+
4643void RadiationModel::initializeBuffer2Dui(RTbuffer &buffer, const std::vector<std::vector<uint>> &array ){
+
4644
+
4645 optix::int2 bsize;
+
4646 bsize.y = array.size();
+
4647 if( bsize.y==0 ){
+
4648 bsize.x = 0;
4649 }else{
-
4650 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dui): Buffer does not have format 'RT_FORMAT_UNSIGNED_INT'.");
+
4650 bsize.x = array.front().size();
4651 }
4652
-
4653 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4654
-
4655}
-
4656
-
4657void RadiationModel::initializeBuffer2Dint2(RTbuffer &buffer, const std::vector<std::vector<optix::int2>> &array ){
-
4658
-
4659 optix::int2 bsize;
-
4660 bsize.y = array.size();
-
4661 if( bsize.y==0 ){
-
4662 bsize.x = 0;
-
4663 }else{
-
4664 bsize.x = array.front().size();
-
4665 }
-
4666
-
4667 //set buffer size
-
4668 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4669
-
4670 //get buffer format
-
4671 RTformat format;
-
4672 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4653 //set buffer size
+
4654 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4655
+
4656 //get buffer format
+
4657 RTformat format;
+
4658 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4659
+
4660 void* ptr;
+
4661 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4662
+
4663 if( format==RT_FORMAT_UNSIGNED_INT ){
+
4664 uint* data = (uint*)ptr;
+
4665 for( size_t j = 0; j<bsize.y; j++ ) {
+
4666 for( size_t i = 0; i<bsize.x; i++ ) {
+
4667 data[i+j*bsize.x] = array[j][i];
+
4668 }
+
4669 }
+
4670 }else{
+
4671 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dui): Buffer does not have format 'RT_FORMAT_UNSIGNED_INT'.");
+
4672 }
4673
-
4674 void* ptr;
-
4675 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4676
-
4677 if( format==RT_FORMAT_INT2 ){
-
4678 optix::int2* data = (optix::int2*)ptr;
-
4679 for( size_t j = 0; j<bsize.y; j++ ) {
-
4680 for( size_t i = 0; i<bsize.x; i++ ) {
-
4681 data[i+j*bsize.x].x = array[j][i].x;
-
4682 data[i+j*bsize.x].y = array[j][i].y;
-
4683 }
-
4684 }
-
4685 }else{
-
4686 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dint2): Buffer does not have format 'RT_FORMAT_INT2'.");
-
4687 }
-
4688
-
4689 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4674 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4675
+
4676}
+
4677
+
4678void RadiationModel::initializeBuffer2Dint2(RTbuffer &buffer, const std::vector<std::vector<optix::int2>> &array ){
+
4679
+
4680 optix::int2 bsize;
+
4681 bsize.y = array.size();
+
4682 if( bsize.y==0 ){
+
4683 bsize.x = 0;
+
4684 }else{
+
4685 bsize.x = array.front().size();
+
4686 }
+
4687
+
4688 //set buffer size
+
4689 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
4690
-
4691}
-
4692
-
4693void RadiationModel::initializeBuffer2Dint3(RTbuffer &buffer, const std::vector<std::vector<optix::int3>> &array ){
+
4691 //get buffer format
+
4692 RTformat format;
+
4693 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4694
-
4695 optix::int2 bsize;
-
4696 bsize.y = array.size();
-
4697 if( bsize.y==0 ){
-
4698 bsize.x = 0;
-
4699 }else{
-
4700 bsize.x = array.front().size();
-
4701 }
-
4702
-
4703 //set buffer size
-
4704 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4705
-
4706 //get buffer format
-
4707 RTformat format;
-
4708 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4695 void* ptr;
+
4696 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4697
+
4698 if( format==RT_FORMAT_INT2 ){
+
4699 optix::int2* data = (optix::int2*)ptr;
+
4700 for( size_t j = 0; j<bsize.y; j++ ) {
+
4701 for( size_t i = 0; i<bsize.x; i++ ) {
+
4702 data[i+j*bsize.x].x = array[j][i].x;
+
4703 data[i+j*bsize.x].y = array[j][i].y;
+
4704 }
+
4705 }
+
4706 }else{
+
4707 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dint2): Buffer does not have format 'RT_FORMAT_INT2'.");
+
4708 }
4709
-
4710 void* ptr;
-
4711 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4712
-
4713 if( format==RT_FORMAT_INT3 ){
-
4714 optix::int3* data = (optix::int3*)ptr;
-
4715 for( size_t j = 0; j<bsize.y; j++ ) {
-
4716 for( size_t i = 0; i<bsize.x; i++ ) {
-
4717 data[i+j*bsize.x].x = array[j][i].x;
-
4718 data[i+j*bsize.x].y = array[j][i].y;
-
4719 data[i+j*bsize.x].z = array[j][i].z;
-
4720 }
-
4721 }
-
4722 }else{
-
4723 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dint3): Buffer does not have format 'RT_FORMAT_INT3'.");
-
4724 }
-
4725
-
4726 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4727
-
4728}
-
4729
-
4730void RadiationModel::initializeBuffer2Dbool(RTbuffer &buffer, const std::vector<std::vector<bool>> &array ){
-
4731
-
4732 optix::int2 bsize;
-
4733 bsize.y = array.size();
-
4734 if( bsize.y==0 ){
-
4735 bsize.x = 0;
-
4736 }else{
-
4737 bsize.x = array.front().size();
-
4738 }
-
4739
-
4740 //set buffer size
-
4741 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
-
4742
-
4743 //get buffer format
-
4744 RTformat format;
-
4745 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4710 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4711
+
4712}
+
4713
+
4714void RadiationModel::initializeBuffer2Dint3(RTbuffer &buffer, const std::vector<std::vector<optix::int3>> &array ){
+
4715
+
4716 optix::int2 bsize;
+
4717 bsize.y = array.size();
+
4718 if( bsize.y==0 ){
+
4719 bsize.x = 0;
+
4720 }else{
+
4721 bsize.x = array.front().size();
+
4722 }
+
4723
+
4724 //set buffer size
+
4725 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4726
+
4727 //get buffer format
+
4728 RTformat format;
+
4729 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4730
+
4731 void* ptr;
+
4732 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4733
+
4734 if( format==RT_FORMAT_INT3 ){
+
4735 optix::int3* data = (optix::int3*)ptr;
+
4736 for( size_t j = 0; j<bsize.y; j++ ) {
+
4737 for( size_t i = 0; i<bsize.x; i++ ) {
+
4738 data[i+j*bsize.x].x = array[j][i].x;
+
4739 data[i+j*bsize.x].y = array[j][i].y;
+
4740 data[i+j*bsize.x].z = array[j][i].z;
+
4741 }
+
4742 }
+
4743 }else{
+
4744 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dint3): Buffer does not have format 'RT_FORMAT_INT3'.");
+
4745 }
4746
-
4747 void* ptr;
-
4748 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4749
-
4750 if( format==RT_FORMAT_BYTE ){
-
4751 bool* data = (bool*)ptr;
-
4752 for( size_t j = 0; j<bsize.y; j++ ) {
-
4753 for( size_t i = 0; i<bsize.x; i++ ) {
-
4754 data[i+j*bsize.x] = array[j][i];
-
4755 }
-
4756 }
+
4747 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4748
+
4749}
+
4750
+
4751void RadiationModel::initializeBuffer2Dbool(RTbuffer &buffer, const std::vector<std::vector<bool>> &array ){
+
4752
+
4753 optix::int2 bsize;
+
4754 bsize.y = array.size();
+
4755 if( bsize.y==0 ){
+
4756 bsize.x = 0;
4757 }else{
-
4758 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dbool): Buffer does not have format 'RT_FORMAT_BYTE'.");
+
4758 bsize.x = array.front().size();
4759 }
4760
-
4761 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4762
-
4763}
-
4764
-
4765template <typename anytype>
-
4766void RadiationModel::initializeBuffer3D(RTbuffer &buffer, const std::vector<std::vector<std::vector<anytype>>> &array ){
+
4761 //set buffer size
+
4762 RT_CHECK_ERROR( rtBufferSetSize2D( buffer, bsize.x, bsize.y ) );
+
4763
+
4764 //get buffer format
+
4765 RTformat format;
+
4766 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
4767
-
4768 optix::int3 bsize;
-
4769 bsize.z = array.size();
-
4770 if( bsize.z==0 ){
-
4771 bsize.y=0;
-
4772 bsize.x=0;
-
4773 }else{
-
4774 bsize.y=array.front().size();
-
4775 if( bsize.y==0 ){
-
4776 bsize.x=0;
-
4777 }else{
-
4778 bsize.x = array.front().front().size();
-
4779 }
+
4768 void* ptr;
+
4769 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4770
+
4771 if( format==RT_FORMAT_BYTE ){
+
4772 bool* data = (bool*)ptr;
+
4773 for( size_t j = 0; j<bsize.y; j++ ) {
+
4774 for( size_t i = 0; i<bsize.x; i++ ) {
+
4775 data[i+j*bsize.x] = array[j][i];
+
4776 }
+
4777 }
+
4778 }else{
+
4779 helios_runtime_error("ERROR (RadiationModel::initializeBuffer2Dbool): Buffer does not have format 'RT_FORMAT_BYTE'.");
4780 }
4781
-
4782 //set buffer size
-
4783 RT_CHECK_ERROR( rtBufferSetSize3D( buffer, bsize.x, bsize.y, bsize.z ) );
-
4784
-
4785 //get buffer format
-
4786 RTformat format;
-
4787 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4782 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
+
4783
+
4784}
+
4785
+
4786template <typename anytype>
+
4787void RadiationModel::initializeBuffer3D(RTbuffer &buffer, const std::vector<std::vector<std::vector<anytype>>> &array ){
4788
-
4789 //zero out buffer
-
4790 void* ptr;
-
4791 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
-
4792
-
4793 if( format==RT_FORMAT_FLOAT ){
-
4794 float* data = (float*)ptr;
-
4795 for( size_t k = 0; k<bsize.z; k++ ) {
-
4796 for( size_t j = 0; j<bsize.y; j++ ) {
-
4797 for( size_t i = 0; i<bsize.x; i++ ) {
-
4798 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
-
4799 }
-
4800 }
-
4801 }
-
4802 }else if( format==RT_FORMAT_INT ){
-
4803 int* data = (int*)ptr;
-
4804 for( size_t k = 0; k<bsize.z; k++ ) {
-
4805 for( size_t j = 0; j<bsize.y; j++ ) {
-
4806 for( size_t i = 0; i<bsize.x; i++ ) {
-
4807 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
-
4808 }
-
4809 }
-
4810 }
-
4811 }else if( format==RT_FORMAT_UNSIGNED_INT ){
-
4812 uint* data = (uint*)ptr;
-
4813 for( size_t k = 0; k<bsize.z; k++ ) {
-
4814 for( size_t j = 0; j<bsize.y; j++ ) {
-
4815 for( size_t i = 0; i<bsize.x; i++ ) {
-
4816 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
-
4817 }
-
4818 }
-
4819 }
-
4820 }else if( format==RT_FORMAT_BYTE ){
-
4821 bool* data = (bool*)ptr;
-
4822 for( size_t k = 0; k<bsize.z; k++ ) {
-
4823 for( size_t j = 0; j<bsize.y; j++ ) {
-
4824 for( size_t i = 0; i<bsize.x; i++ ) {
-
4825 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
-
4826 }
-
4827 }
-
4828 }
-
4829 }else{
-
4830 std::cerr<< "ERROR (RadiationModel::initializeBuffer3D): unsupported buffer format." << std::endl;
-
4831
-
4832 }
-
4833
-
4834 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
-
4835
-
4836
-
4837}
-
4838
-
- -
4840
-
4841 vec3 dir = view_direction;
-
4842 dir.normalize();
-
4843
-
4844 float Gtheta = 0;
-
4845 float total_area = 0;
-
4846 for( std::size_t u=0; u<primitiveID.size(); u++ ){
-
4847
-
4848 uint UUID = context_UUIDs.at(primitiveID.at(u));
-
4849
-
4850 vec3 normal = context->getPrimitiveNormal(UUID);
-
4851 float area = context->getPrimitiveArea(UUID);
+
4789 optix::int3 bsize;
+
4790 bsize.z = array.size();
+
4791 if( bsize.z==0 ){
+
4792 bsize.y=0;
+
4793 bsize.x=0;
+
4794 }else{
+
4795 bsize.y=array.front().size();
+
4796 if( bsize.y==0 ){
+
4797 bsize.x=0;
+
4798 }else{
+
4799 bsize.x = array.front().front().size();
+
4800 }
+
4801 }
+
4802
+
4803 //set buffer size
+
4804 RT_CHECK_ERROR( rtBufferSetSize3D( buffer, bsize.x, bsize.y, bsize.z ) );
+
4805
+
4806 //get buffer format
+
4807 RTformat format;
+
4808 RT_CHECK_ERROR( rtBufferGetFormat( buffer, &format ) );
+
4809
+
4810 //zero out buffer
+
4811 void* ptr;
+
4812 RT_CHECK_ERROR( rtBufferMap( buffer, &ptr ) );
+
4813
+
4814 if( format==RT_FORMAT_FLOAT ){
+
4815 float* data = (float*)ptr;
+
4816 for( size_t k = 0; k<bsize.z; k++ ) {
+
4817 for( size_t j = 0; j<bsize.y; j++ ) {
+
4818 for( size_t i = 0; i<bsize.x; i++ ) {
+
4819 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
+
4820 }
+
4821 }
+
4822 }
+
4823 }else if( format==RT_FORMAT_INT ){
+
4824 int* data = (int*)ptr;
+
4825 for( size_t k = 0; k<bsize.z; k++ ) {
+
4826 for( size_t j = 0; j<bsize.y; j++ ) {
+
4827 for( size_t i = 0; i<bsize.x; i++ ) {
+
4828 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
+
4829 }
+
4830 }
+
4831 }
+
4832 }else if( format==RT_FORMAT_UNSIGNED_INT ){
+
4833 uint* data = (uint*)ptr;
+
4834 for( size_t k = 0; k<bsize.z; k++ ) {
+
4835 for( size_t j = 0; j<bsize.y; j++ ) {
+
4836 for( size_t i = 0; i<bsize.x; i++ ) {
+
4837 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
+
4838 }
+
4839 }
+
4840 }
+
4841 }else if( format==RT_FORMAT_BYTE ){
+
4842 bool* data = (bool*)ptr;
+
4843 for( size_t k = 0; k<bsize.z; k++ ) {
+
4844 for( size_t j = 0; j<bsize.y; j++ ) {
+
4845 for( size_t i = 0; i<bsize.x; i++ ) {
+
4846 data[i+j*bsize.x+k*bsize.y*bsize.x] = array[k][j][i];
+
4847 }
+
4848 }
+
4849 }
+
4850 }else{
+
4851 std::cerr<< "ERROR (RadiationModel::initializeBuffer3D): unsupported buffer format." << std::endl;
4852
-
4853 Gtheta += fabsf(normal*dir)*area;
+
4853 }
4854
-
4855 total_area += area;
+
4855 RT_CHECK_ERROR( rtBufferUnmap( buffer ) );
4856
-
4857 }
-
4858
-
4859 return Gtheta/total_area;
-
4860
-
4861}
-
-
4862
-
4863void RadiationModel::setCameraCalibration(CameraCalibration *CameraCalibration){
-
4864 cameracalibration = CameraCalibration;
-
4865 calibration_flag = true;
-
4866}
-
4867
-
-
4868void RadiationModel::updateCameraResponse(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels_raw,
-
4869 const std::vector<std::string>& cameraresponselabels, vec2 &wavelengthrange,
-
4870 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark) {
-
4871
-
4872 std::vector<std::string> objectlabels;
-
4873 vec2 wavelengthrange_c = wavelengthrange;
-
4874 cameracalibration->preprocessSpectra(sourcelabels_raw, cameraresponselabels, objectlabels, wavelengthrange_c);
+
4857
+
4858}
+
4859
+
+ +
4861
+
4862 vec3 dir = view_direction;
+
4863 dir.normalize();
+
4864
+
4865 float Gtheta = 0;
+
4866 float total_area = 0;
+
4867 for( std::size_t u=0; u<primitiveID.size(); u++ ){
+
4868
+
4869 uint UUID = context_UUIDs.at(primitiveID.at(u));
+
4870
+
4871 vec3 normal = context->getPrimitiveNormal(UUID);
+
4872 float area = context->getPrimitiveArea(UUID);
+
4873
+
4874 Gtheta += fabsf(normal*dir)*area;
4875
-
4876 RadiationCamera calibratecamera = cameras.at(orginalcameralabel);
-
4877 CameraProperties cameraproperties;
-
4878 cameraproperties.HFOV = calibratecamera.HFOV_degrees;
-
4879 cameraproperties.camera_resolution = calibratecamera.resolution;
-
4880 cameraproperties.focal_plane_distance = calibratecamera.focal_length;
-
4881 cameraproperties.lens_diameter = calibratecamera.lens_diameter;
-
4882 cameraproperties.FOV_aspect_ratio = calibratecamera.FOV_aspect_ratio;
+
4876 total_area += area;
+
4877
+
4878 }
+
4879
+
4880 return Gtheta/total_area;
+
4881
+
4882}
+
4883
-
4884 std::vector<uint> UUIDs_target = cameracalibration->getColorBoardUUIDs();
-
4885 std::string cameralabel = "calibration";
-
4886 std::map<uint,std::vector<vec2>> simulatedcolorboardspectra;
-
4887 for (uint UUID:UUIDs_target){
-
4888 simulatedcolorboardspectra.emplace(UUID, NULL);
-
4889 }
-
4890
-
4891 for (uint ID = 0; ID<radiation_sources.size();ID++) {
- -
4893 }
-
4894
-
4895 std::vector<float> wavelengths;
-
4896 context->getGlobalData("wavelengths", wavelengths);
-
4897 int numberwavelengths= wavelengths.size();
-
4898
-
4899 for (int iw=0; iw < numberwavelengths; iw++) {
-
4900 std::string wavelengthlabel = std::to_string(wavelengths.at(iw));
-
4901
-
4902 std::vector<std::string> sourcelabels;
-
4903 for (std::string sourcelabel_raw:sourcelabels_raw){
-
4904 std::vector<vec2> icalsource;
-
4905 icalsource.push_back(cameracalibration->processedspectra.at("source").at(sourcelabel_raw).at(iw));
-
4906 icalsource.push_back(cameracalibration->processedspectra.at("source").at(sourcelabel_raw).at(iw));
-
4907 icalsource.at(1).x+=1;
-
4908 std::string sourcelable = "Cal_source_"+sourcelabel_raw;
-
4909 sourcelabels.push_back(sourcelable);
-
4910 context->setGlobalData(sourcelable.c_str(),HELIOS_TYPE_VEC2,2,&icalsource[0]);
-
4911 }
-
4912
-
4913 std::vector<vec2> icalcamera(2);
-
4914 icalcamera.at(0).y=1;
-
4915 icalcamera.at(1).y=1;
-
4916 icalcamera.at(0).x=wavelengths.at(iw);
-
4917 icalcamera.at(1).x=wavelengths.at(iw)+1;
-
4918 std::string camlable = "Cal_cameraresponse";
-
4919 context->setGlobalData(camlable.c_str(),HELIOS_TYPE_VEC2,2,&icalcamera[0]);
-
4920
-
4921 for (auto objectpair : cameracalibration->processedspectra.at("object")){
-
4922 std::vector<vec2> spectrum_obj;
-
4923 spectrum_obj.push_back(objectpair.second.at(iw));
-
4924 spectrum_obj.push_back(objectpair.second.at(iw));
-
4925 spectrum_obj.at(1).x += 1;
-
4926 context->setGlobalData(objectpair.first.c_str(), HELIOS_TYPE_VEC2, 2, &spectrum_obj[0]);
-
4927 }
-
4928
-
4929 RadiationModel::addRadiationBand(wavelengthlabel, std::stof(wavelengthlabel), std::stof(wavelengthlabel) + 1);
-
4930 RadiationModel::disableEmission(wavelengthlabel);
-
4931
-
4932 uint ID = 0;
-
4933 for (std::string sourcelabel_raw:sourcelabels_raw) {
-
4934 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
-
4935 RadiationModel::setSourceFlux(ID, wavelengthlabel, 1);
-
4936 ID ++;
-
4937 }
-
4938 RadiationModel::setScatteringDepth(wavelengthlabel, 1);
-
4939 RadiationModel::setDiffuseRadiationFlux(wavelengthlabel, 0);
-
4940 RadiationModel::setDiffuseRadiationExtinctionCoeff(wavelengthlabel, 0.f, make_vec3(-0.5, 0.5, 1));
+
4884void RadiationModel::setCameraCalibration(CameraCalibration *CameraCalibration){
+
4885 cameracalibration = CameraCalibration;
+
4886 calibration_flag = true;
+
4887}
+
4888
+
+
4889void RadiationModel::updateCameraResponse(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels_raw,
+
4890 const std::vector<std::string>& cameraresponselabels, vec2 &wavelengthrange,
+
4891 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark) {
+
4892
+
4893 std::vector<std::string> objectlabels;
+
4894 vec2 wavelengthrange_c = wavelengthrange;
+
4895 cameracalibration->preprocessSpectra(sourcelabels_raw, cameraresponselabels, objectlabels, wavelengthrange_c);
+
4896
+
4897 RadiationCamera calibratecamera = cameras.at(orginalcameralabel);
+
4898 CameraProperties cameraproperties;
+
4899 cameraproperties.HFOV = calibratecamera.HFOV_degrees;
+
4900 cameraproperties.camera_resolution = calibratecamera.resolution;
+
4901 cameraproperties.focal_plane_distance = calibratecamera.focal_length;
+
4902 cameraproperties.lens_diameter = calibratecamera.lens_diameter;
+
4903 cameraproperties.FOV_aspect_ratio = calibratecamera.FOV_aspect_ratio;
+
4904
+
4905 std::vector<uint> UUIDs_target = cameracalibration->getColorBoardUUIDs();
+
4906 std::string cameralabel = "calibration";
+
4907 std::map<uint,std::vector<vec2>> simulatedcolorboardspectra;
+
4908 for (uint UUID:UUIDs_target){
+
4909 simulatedcolorboardspectra.emplace(UUID, NULL);
+
4910 }
+
4911
+
4912 for (uint ID = 0; ID<radiation_sources.size();ID++) {
+ +
4914 }
+
4915
+
4916 std::vector<float> wavelengths;
+
4917 context->getGlobalData("wavelengths", wavelengths);
+
4918 int numberwavelengths= wavelengths.size();
+
4919
+
4920 for (int iw=0; iw < numberwavelengths; iw++) {
+
4921 std::string wavelengthlabel = std::to_string(wavelengths.at(iw));
+
4922
+
4923 std::vector<std::string> sourcelabels;
+
4924 for (std::string sourcelabel_raw:sourcelabels_raw){
+
4925 std::vector<vec2> icalsource;
+
4926 icalsource.push_back(cameracalibration->processedspectra.at("source").at(sourcelabel_raw).at(iw));
+
4927 icalsource.push_back(cameracalibration->processedspectra.at("source").at(sourcelabel_raw).at(iw));
+
4928 icalsource.at(1).x+=1;
+
4929 std::string sourcelable = "Cal_source_"+sourcelabel_raw;
+
4930 sourcelabels.push_back(sourcelable);
+
4931 context->setGlobalData(sourcelable.c_str(),HELIOS_TYPE_VEC2,2,&icalsource[0]);
+
4932 }
+
4933
+
4934 std::vector<vec2> icalcamera(2);
+
4935 icalcamera.at(0).y=1;
+
4936 icalcamera.at(1).y=1;
+
4937 icalcamera.at(0).x=wavelengths.at(iw);
+
4938 icalcamera.at(1).x=wavelengths.at(iw)+1;
+
4939 std::string camlable = "Cal_cameraresponse";
+
4940 context->setGlobalData(camlable.c_str(),HELIOS_TYPE_VEC2,2,&icalcamera[0]);
4941
-
4942 RadiationModel::addRadiationCamera(cameralabel, {wavelengthlabel}, calibratecamera.position, calibratecamera.lookat, cameraproperties, 10);
-
4943 RadiationModel::setCameraSpectralResponse(cameralabel, wavelengthlabel, camlable);
- -
4945 RadiationModel::runBand({wavelengthlabel});
-
4946
-
4947 std::vector<float> camera_data;
-
4948 std::string global_data_label = "camera_" + cameralabel + "_" + wavelengthlabel;
-
4949 context->getGlobalData(global_data_label.c_str(), camera_data);
-
4950
-
4951 std::vector<uint> pixel_labels;
-
4952 std::string global_data_label_UUID = "camera_" + cameralabel + "_pixel_UUID";
-
4953 context->getGlobalData(global_data_label_UUID.c_str(), pixel_labels);
-
4954
-
4955 for (uint j = 0; j < calibratecamera.resolution.y; j++) {
-
4956 for (uint i = 0; i < calibratecamera.resolution.x; i++) {
-
4957 float icdata = camera_data.at(j * calibratecamera.resolution.x + i);
-
4958
-
4959 uint UUID = pixel_labels.at(j * calibratecamera.resolution.x + i)-1;
-
4960 if (find(UUIDs_target.begin(), UUIDs_target.end(), UUID) != UUIDs_target.end()){
-
4961 if ( simulatedcolorboardspectra.at(UUID).empty()){
-
4962 simulatedcolorboardspectra.at(UUID).push_back(make_vec2(wavelengths.at(iw), icdata / float(numberwavelengths)));
-
4963 }
-
4964 else if (simulatedcolorboardspectra.at(UUID).back().x == wavelengths.at(iw)){
-
4965 simulatedcolorboardspectra.at(UUID).back().y += icdata / float(numberwavelengths);
-
4966 }
-
4967 else if(simulatedcolorboardspectra.at(UUID).back().x !=wavelengths.at(iw)){
-
4968 simulatedcolorboardspectra.at(UUID).push_back(make_vec2(wavelengths.at(iw), icdata / float(numberwavelengths)));
-
4969 }
-
4970 }
-
4971 }
-
4972 }
-
4973 }
-
4974 // Update camera response spectra
-
4975 cameracalibration->updateCameraResponseSpectra(cameraresponselabels, calibratedmark ,simulatedcolorboardspectra, truevalues);
-
4976 // Reset color board spectra
-
4977 std::vector<uint> UUIDs_colorbd = cameracalibration->getColorBoardUUIDs();
-
4978 for (uint UUID:UUIDs_colorbd){
-
4979 std::string colorboardspectra;
-
4980 context->getPrimitiveData(UUID, "reflectivity_spectrum", colorboardspectra);
-
4981 context->setPrimitiveData(UUID, "reflectivity_spectrum", colorboardspectra+"_raw");
-
4982 }
-
4983}
-
-
4984
-
-
4985void RadiationModel::runRadiationImaging(const std::string& cameralabel, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
-
4986 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
-
4987 float fluxscale, float diffusefactor, uint scatteringdepth){
-
4988
-
4989 float sources_fluxsum = 0;
-
4990 std::vector<float> sources_fluxes;
-
4991 for (uint ID = 0; ID < sourcelabels.size(); ID++){
-
4992 std::vector<vec2> Source_spectrum = loadSpectralData(sourcelabels.at(ID).c_str());
-
4993 sources_fluxes.push_back(RadiationModel::integrateSpectrum(Source_spectrum, wavelengthrange.x, wavelengthrange.y));
-
4994 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
-
4995 RadiationModel::setSourceSpectrumIntegral(ID, sources_fluxes.at(ID));
-
4996 sources_fluxsum += sources_fluxes.at(ID);
-
4997 }
-
4998
-
4999 RadiationModel::addRadiationBand(bandlabels.at(0), wavelengthrange.x, wavelengthrange.y);
-
5000 RadiationModel::disableEmission(bandlabels.at(0));
-
5001 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
-
5002 RadiationModel::setSourceFlux(ID, bandlabels.at(0), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
4942 for (auto objectpair : cameracalibration->processedspectra.at("object")){
+
4943 std::vector<vec2> spectrum_obj;
+
4944 spectrum_obj.push_back(objectpair.second.at(iw));
+
4945 spectrum_obj.push_back(objectpair.second.at(iw));
+
4946 spectrum_obj.at(1).x += 1;
+
4947 context->setGlobalData(objectpair.first.c_str(), HELIOS_TYPE_VEC2, 2, &spectrum_obj[0]);
+
4948 }
+
4949
+
4950 RadiationModel::addRadiationBand(wavelengthlabel, std::stof(wavelengthlabel), std::stof(wavelengthlabel) + 1);
+
4951 RadiationModel::disableEmission(wavelengthlabel);
+
4952
+
4953 uint ID = 0;
+
4954 for (std::string sourcelabel_raw:sourcelabels_raw) {
+
4955 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
+
4956 RadiationModel::setSourceFlux(ID, wavelengthlabel, 1);
+
4957 ID ++;
+
4958 }
+
4959 RadiationModel::setScatteringDepth(wavelengthlabel, 1);
+
4960 RadiationModel::setDiffuseRadiationFlux(wavelengthlabel, 0);
+
4961 RadiationModel::setDiffuseRadiationExtinctionCoeff(wavelengthlabel, 0.f, make_vec3(-0.5, 0.5, 1));
+
4962
+
4963 RadiationModel::addRadiationCamera(cameralabel, {wavelengthlabel}, calibratecamera.position, calibratecamera.lookat, cameraproperties, 10);
+
4964 RadiationModel::setCameraSpectralResponse(cameralabel, wavelengthlabel, camlable);
+ +
4966 RadiationModel::runBand({wavelengthlabel});
+
4967
+
4968 std::vector<float> camera_data;
+
4969 std::string global_data_label = "camera_" + cameralabel + "_" + wavelengthlabel;
+
4970 context->getGlobalData(global_data_label.c_str(), camera_data);
+
4971
+
4972 std::vector<uint> pixel_labels;
+
4973 std::string global_data_label_UUID = "camera_" + cameralabel + "_pixel_UUID";
+
4974 context->getGlobalData(global_data_label_UUID.c_str(), pixel_labels);
+
4975
+
4976 for (uint j = 0; j < calibratecamera.resolution.y; j++) {
+
4977 for (uint i = 0; i < calibratecamera.resolution.x; i++) {
+
4978 float icdata = camera_data.at(j * calibratecamera.resolution.x + i);
+
4979
+
4980 uint UUID = pixel_labels.at(j * calibratecamera.resolution.x + i)-1;
+
4981 if (find(UUIDs_target.begin(), UUIDs_target.end(), UUID) != UUIDs_target.end()){
+
4982 if ( simulatedcolorboardspectra.at(UUID).empty()){
+
4983 simulatedcolorboardspectra.at(UUID).push_back(make_vec2(wavelengths.at(iw), icdata / float(numberwavelengths)));
+
4984 }
+
4985 else if (simulatedcolorboardspectra.at(UUID).back().x == wavelengths.at(iw)){
+
4986 simulatedcolorboardspectra.at(UUID).back().y += icdata / float(numberwavelengths);
+
4987 }
+
4988 else if(simulatedcolorboardspectra.at(UUID).back().x !=wavelengths.at(iw)){
+
4989 simulatedcolorboardspectra.at(UUID).push_back(make_vec2(wavelengths.at(iw), icdata / float(numberwavelengths)));
+
4990 }
+
4991 }
+
4992 }
+
4993 }
+
4994 }
+
4995 // Update camera response spectra
+
4996 cameracalibration->updateCameraResponseSpectra(cameraresponselabels, calibratedmark ,simulatedcolorboardspectra, truevalues);
+
4997 // Reset color board spectra
+
4998 std::vector<uint> UUIDs_colorbd = cameracalibration->getColorBoardUUIDs();
+
4999 for (uint UUID:UUIDs_colorbd){
+
5000 std::string colorboardspectra;
+
5001 context->getPrimitiveData(UUID, "reflectivity_spectrum", colorboardspectra);
+
5002 context->setPrimitiveData(UUID, "reflectivity_spectrum", colorboardspectra+"_raw");
5003 }
-
5004 RadiationModel::setScatteringDepth(bandlabels.at(0), scatteringdepth);
-
5005 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(0), diffusefactor * sources_fluxsum );
-
5006 RadiationModel::setDiffuseRadiationExtinctionCoeff(bandlabels.at(0), 1.f, make_vec3(-0.5, 0.5, 1) );
-
5007
-
5008 if (bandlabels.size()>1){
-
5009 for (int iband=1;iband<bandlabels.size();iband++){
-
5010 RadiationModel::copyRadiationBand(bandlabels.at(iband-1), bandlabels.at(iband), wavelengthrange.x, wavelengthrange.y);
-
5011 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
-
5012 RadiationModel::setSourceFlux(ID, bandlabels.at(iband), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
-
5013 }
-
5014 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(iband), diffusefactor * sources_fluxsum );
-
5015 }
-
5016 }
-
5017
-
5018 for (int iband=0;iband<bandlabels.size();iband++){
-
5019 RadiationModel::setCameraSpectralResponse(cameralabel, bandlabels.at(iband), cameraresponselabels.at(iband));
-
5020 }
-
5021
- -
5023 RadiationModel::runBand(bandlabels);
-
5024}
+
5004}
-
5025
-
-
5026void RadiationModel::runRadiationImaging(const std::vector<std::string>& cameralabels, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
-
5027 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
-
5028 float fluxscale, float diffusefactor, uint scatteringdepth){
-
5029
-
5030 float sources_fluxsum = 0;
-
5031 std::vector<float> sources_fluxes;
-
5032 for (uint ID = 0; ID < sourcelabels.size(); ID++){
-
5033 std::vector<vec2> Source_spectrum = loadSpectralData(sourcelabels.at(ID).c_str());
-
5034 sources_fluxes.push_back(RadiationModel::integrateSpectrum(Source_spectrum, wavelengthrange.x, wavelengthrange.y));
-
5035 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
-
5036 RadiationModel::setSourceSpectrumIntegral(ID, sources_fluxes.at(ID));
-
5037 sources_fluxsum += sources_fluxes.at(ID);
-
5038 }
-
5039
-
5040 RadiationModel::addRadiationBand(bandlabels.at(0), wavelengthrange.x, wavelengthrange.y);
-
5041 RadiationModel::disableEmission(bandlabels.at(0));
-
5042 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
-
5043 RadiationModel::setSourceFlux(ID, bandlabels.at(0), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
-
5044 }
-
5045 RadiationModel::setScatteringDepth(bandlabels.at(0), scatteringdepth);
-
5046 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(0), diffusefactor * sources_fluxsum );
-
5047 RadiationModel::setDiffuseRadiationExtinctionCoeff(bandlabels.at(0), 1.f, make_vec3(-0.5, 0.5, 1) );
-
5048
-
5049 if (bandlabels.size()>1){
-
5050 for (int iband=1;iband<bandlabels.size();iband++){
-
5051 RadiationModel::copyRadiationBand(bandlabels.at(iband-1), bandlabels.at(iband), wavelengthrange.x, wavelengthrange.y);
-
5052 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
-
5053 RadiationModel::setSourceFlux(ID, bandlabels.at(iband), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
-
5054 }
-
5055 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(iband), diffusefactor * sources_fluxsum );
-
5056 }
-
5057 }
-
5058
-
5059 for (int ic=0;ic<cameralabels.size();ic++){
-
5060 for (int iband=0;iband<bandlabels.size();iband++){
-
5061 RadiationModel::setCameraSpectralResponse(cameralabels.at(ic), bandlabels.at(iband), cameraresponselabels.at(iband));
-
5062 }
-
5063 }
-
5064
-
5065
- -
5067 RadiationModel::runBand(bandlabels);
-
5068}
+
5005
+
+
5006void RadiationModel::runRadiationImaging(const std::string& cameralabel, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
+
5007 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
+
5008 float fluxscale, float diffusefactor, uint scatteringdepth){
+
5009
+
5010 float sources_fluxsum = 0;
+
5011 std::vector<float> sources_fluxes;
+
5012 for (uint ID = 0; ID < sourcelabels.size(); ID++){
+
5013 std::vector<vec2> Source_spectrum = loadSpectralData(sourcelabels.at(ID).c_str());
+
5014 sources_fluxes.push_back(RadiationModel::integrateSpectrum(Source_spectrum, wavelengthrange.x, wavelengthrange.y));
+
5015 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
+
5016 RadiationModel::setSourceSpectrumIntegral(ID, sources_fluxes.at(ID));
+
5017 sources_fluxsum += sources_fluxes.at(ID);
+
5018 }
+
5019
+
5020 RadiationModel::addRadiationBand(bandlabels.at(0), wavelengthrange.x, wavelengthrange.y);
+
5021 RadiationModel::disableEmission(bandlabels.at(0));
+
5022 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
+
5023 RadiationModel::setSourceFlux(ID, bandlabels.at(0), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
5024 }
+
5025 RadiationModel::setScatteringDepth(bandlabels.at(0), scatteringdepth);
+
5026 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(0), diffusefactor * sources_fluxsum );
+
5027 RadiationModel::setDiffuseRadiationExtinctionCoeff(bandlabels.at(0), 1.f, make_vec3(-0.5, 0.5, 1) );
+
5028
+
5029 if (bandlabels.size()>1){
+
5030 for (int iband=1;iband<bandlabels.size();iband++){
+
5031 RadiationModel::copyRadiationBand(bandlabels.at(iband-1), bandlabels.at(iband), wavelengthrange.x, wavelengthrange.y);
+
5032 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
+
5033 RadiationModel::setSourceFlux(ID, bandlabels.at(iband), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
5034 }
+
5035 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(iband), diffusefactor * sources_fluxsum );
+
5036 }
+
5037 }
+
5038
+
5039 for (int iband=0;iband<bandlabels.size();iband++){
+
5040 RadiationModel::setCameraSpectralResponse(cameralabel, bandlabels.at(iband), cameraresponselabels.at(iband));
+
5041 }
+
5042
+ +
5044 RadiationModel::runBand(bandlabels);
+
5045}
+
5046
+
+
5047void RadiationModel::runRadiationImaging(const std::vector<std::string>& cameralabels, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
+
5048 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
+
5049 float fluxscale, float diffusefactor, uint scatteringdepth){
+
5050
+
5051 float sources_fluxsum = 0;
+
5052 std::vector<float> sources_fluxes;
+
5053 for (uint ID = 0; ID < sourcelabels.size(); ID++){
+
5054 std::vector<vec2> Source_spectrum = loadSpectralData(sourcelabels.at(ID).c_str());
+
5055 sources_fluxes.push_back(RadiationModel::integrateSpectrum(Source_spectrum, wavelengthrange.x, wavelengthrange.y));
+
5056 RadiationModel::setSourceSpectrum(ID, sourcelabels.at(ID).c_str());
+
5057 RadiationModel::setSourceSpectrumIntegral(ID, sources_fluxes.at(ID));
+
5058 sources_fluxsum += sources_fluxes.at(ID);
+
5059 }
+
5060
+
5061 RadiationModel::addRadiationBand(bandlabels.at(0), wavelengthrange.x, wavelengthrange.y);
+
5062 RadiationModel::disableEmission(bandlabels.at(0));
+
5063 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
+
5064 RadiationModel::setSourceFlux(ID, bandlabels.at(0), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
5065 }
+
5066 RadiationModel::setScatteringDepth(bandlabels.at(0), scatteringdepth);
+
5067 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(0), diffusefactor * sources_fluxsum );
+
5068 RadiationModel::setDiffuseRadiationExtinctionCoeff(bandlabels.at(0), 1.f, make_vec3(-0.5, 0.5, 1) );
5069
-
-
5070float RadiationModel::getCameraResponseScale(const std::string &orginalcameralabel, const std::vector<std::string>& cameraresponselabels,
-
5071 const std::vector<std::string>& bandlabels, const std::vector<std::string> &sourcelabels,
-
5072 vec2 &wavelengthrange, const std::vector<std::vector<float>> &truevalues){
-
5073
-
5074
-
5075 RadiationCamera calibratecamera = cameras.at(orginalcameralabel);
-
5076 CameraProperties cameraproperties;
-
5077 cameraproperties.HFOV = calibratecamera.HFOV_degrees;
-
5078 cameraproperties.camera_resolution = calibratecamera.resolution;
-
5079 cameraproperties.focal_plane_distance = calibratecamera.focal_length;
-
5080 cameraproperties.lens_diameter = calibratecamera.lens_diameter;
-
5081 cameraproperties.FOV_aspect_ratio = calibratecamera.FOV_aspect_ratio;
-
5082
-
5083 std::string cameralabel = orginalcameralabel+"Scale";
-
5084 RadiationModel::addRadiationCamera(cameralabel, bandlabels, calibratecamera.position, calibratecamera.lookat, cameraproperties,20);
-
5085 RadiationModel::runRadiationImaging(cameralabel, sourcelabels, bandlabels, cameraresponselabels, wavelengthrange, 1, 0);
+
5070 if (bandlabels.size()>1){
+
5071 for (int iband=1;iband<bandlabels.size();iband++){
+
5072 RadiationModel::copyRadiationBand(bandlabels.at(iband-1), bandlabels.at(iband), wavelengthrange.x, wavelengthrange.y);
+
5073 for( uint ID =0; ID<radiation_sources.size();ID++ ) {
+
5074 RadiationModel::setSourceFlux(ID, bandlabels.at(iband), (1 - diffusefactor) * sources_fluxes.at(ID) * fluxscale);
+
5075 }
+
5076 RadiationModel::setDiffuseRadiationFlux(bandlabels.at(iband), diffusefactor * sources_fluxsum );
+
5077 }
+
5078 }
+
5079
+
5080 for (int ic=0;ic<cameralabels.size();ic++){
+
5081 for (int iband=0;iband<bandlabels.size();iband++){
+
5082 RadiationModel::setCameraSpectralResponse(cameralabels.at(ic), bandlabels.at(iband), cameraresponselabels.at(iband));
+
5083 }
+
5084 }
+
5085
5086
-
5087 // Get camera spectral response scale based on comparing true values and calibrated image
-
5088 float camerascale = cameracalibration->getCameraResponseScale(cameralabel, cameraproperties.camera_resolution, bandlabels, truevalues);
-
5089 return camerascale;
-
5090}
+ +
5088 RadiationModel::runBand(bandlabels);
+
5089}
-
5091
-
5092
-
-
5093void 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){
+
5090
+
+
5091float RadiationModel::getCameraResponseScale(const std::string &orginalcameralabel, const std::vector<std::string>& cameraresponselabels,
+
5092 const std::vector<std::string>& bandlabels, const std::vector<std::string> &sourcelabels,
+
5093 vec2 &wavelengthrange, const std::vector<std::vector<float>> &truevalues){
5094
-
5095 if( cameras.find(cameralabel)==cameras.end() ){
-
5096 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Camera '" + cameralabel + "' does not exist." );
-
5097 }
-
5098
-
5099 //Get image UUID labels
-
5100 std::vector<uint> camera_UUIDs;
-
5101 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
-
5102 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
-
5103 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
-
5104 }
-
5105 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
-
5106 std::vector<uint> pixel_UUIDs = camera_UUIDs;
-
5107 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5108
-
5109 std::string frame_str;
-
5110 if( frame>=0 ) {
-
5111 frame_str = std::to_string(frame);
-
5112 }
+
5095
+
5096 RadiationCamera calibratecamera = cameras.at(orginalcameralabel);
+
5097 CameraProperties cameraproperties;
+
5098 cameraproperties.HFOV = calibratecamera.HFOV_degrees;
+
5099 cameraproperties.camera_resolution = calibratecamera.resolution;
+
5100 cameraproperties.focal_plane_distance = calibratecamera.focal_length;
+
5101 cameraproperties.lens_diameter = calibratecamera.lens_diameter;
+
5102 cameraproperties.FOV_aspect_ratio = calibratecamera.FOV_aspect_ratio;
+
5103
+
5104 std::string cameralabel = orginalcameralabel+"Scale";
+
5105 RadiationModel::addRadiationCamera(cameralabel, bandlabels, calibratecamera.position, calibratecamera.lookat, cameraproperties,20);
+
5106 RadiationModel::runRadiationImaging(cameralabel, sourcelabels, bandlabels, cameraresponselabels, wavelengthrange, 1, 0);
+
5107
+
5108 // Get camera spectral response scale based on comparing true values and calibrated image
+
5109 float camerascale = cameracalibration->getCameraResponseScale(cameralabel, cameraproperties.camera_resolution, bandlabels, truevalues);
+
5110 return camerascale;
+
5111}
+
+
5112
5113
-
5114 std::string output_path = image_path;
-
5115 if( !image_path.empty() && !validateOutputPath(output_path) ){
-
5116 helios_runtime_error("ERROR (RadiationModel::writePrimitiveDataLabelMap): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
-
5117 }else if( !getFileName(output_path).empty() ){
-
5118 helios_runtime_error("ERROR(RadiationModel::writePrimitiveDataLabelMap): Image output directory contains a filename. This argument should be the path to a directory not a file.");
-
5119 }
-
5120
-
5121 std::ostringstream outfile;
-
5122 outfile << output_path;
-
5123
-
5124 if( frame>=0 ) {
-
5125 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5126 }else{
-
5127 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5128 }
+
+
5114void 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){
+
5115
+
5116 if( cameras.find(cameralabel)==cameras.end() ){
+
5117 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Camera '" + cameralabel + "' does not exist." );
+
5118 }
+
5119
+
5120 //Get image UUID labels
+
5121 std::vector<uint> camera_UUIDs;
+
5122 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
+
5123 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
+
5124 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
+
5125 }
+
5126 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
+
5127 std::vector<uint> pixel_UUIDs = camera_UUIDs;
+
5128 int2 camera_resolution = cameras.at(cameralabel).resolution;
5129
-
5130 //Output label image in ".txt" format
-
5131 std::ofstream pixel_data(outfile.str());
-
5132
-
5133 if( !pixel_data.is_open() ){
-
5134 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Could not open file '" + outfile.str() + "' for writing." );
-
5135 }
-
5136
-
5137 bool empty_flag = true;
-
5138 for (uint j = 0; j < camera_resolution.y; j++) {
-
5139 for (uint i = 0; i < camera_resolution.x; i++) {
-
5140 uint ii = camera_resolution.x - i -1;
-
5141 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
-
5142 if (context->doesPrimitiveExist(UUID) && context->doesPrimitiveDataExist(UUID,primitive_data_label.c_str())){
-
5143 HeliosDataType datatype = context->getPrimitiveDataType(UUID,primitive_data_label.c_str());
-
5144 if( datatype == HELIOS_TYPE_FLOAT ){
-
5145 float labeldata;
-
5146 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
-
5147 pixel_data << labeldata << " ";
-
5148 empty_flag = false;
-
5149 }
-
5150 else if (datatype == HELIOS_TYPE_UINT){
-
5151 uint labeldata;
-
5152 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
-
5153 pixel_data << labeldata << " ";
-
5154 empty_flag = false;
-
5155 }
-
5156 else if (datatype == HELIOS_TYPE_INT){
-
5157 int labeldata;
-
5158 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
-
5159 pixel_data << labeldata << " ";
-
5160 empty_flag = false;
-
5161 }
-
5162 else if (datatype == HELIOS_TYPE_DOUBLE){
-
5163 double labeldata;
-
5164 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
-
5165 pixel_data << labeldata << " ";
-
5166 empty_flag = false;
-
5167 }else{
-
5168 pixel_data << padvalue << " ";
-
5169 }
-
5170 }else{
-
5171 pixel_data << padvalue << " ";
-
5172 }
-
5173 }
-
5174 pixel_data << "\n";
-
5175 }
-
5176 pixel_data.close();
-
5177
-
5178 if( empty_flag ){
-
5179 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;
-
5180 }
-
5181
-
5182}
+
5130 std::string frame_str;
+
5131 if( frame>=0 ) {
+
5132 frame_str = std::to_string(frame);
+
5133 }
+
5134
+
5135 std::string output_path = image_path;
+
5136 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5137 helios_runtime_error("ERROR (RadiationModel::writePrimitiveDataLabelMap): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5138 }else if( !getFileName(output_path).empty() ){
+
5139 helios_runtime_error("ERROR(RadiationModel::writePrimitiveDataLabelMap): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5140 }
+
5141
+
5142 std::ostringstream outfile;
+
5143 outfile << output_path;
+
5144
+
5145 if( frame>=0 ) {
+
5146 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5147 }else{
+
5148 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5149 }
+
5150
+
5151 //Output label image in ".txt" format
+
5152 std::ofstream pixel_data(outfile.str());
+
5153
+
5154 if( !pixel_data.is_open() ){
+
5155 helios_runtime_error( "ERROR (RadiationModel::writePrimitiveDataLabelMap): Could not open file '" + outfile.str() + "' for writing." );
+
5156 }
+
5157
+
5158 bool empty_flag = true;
+
5159 for (uint j = 0; j < camera_resolution.y; j++) {
+
5160 for (uint i = 0; i < camera_resolution.x; i++) {
+
5161 uint ii = camera_resolution.x - i -1;
+
5162 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5163 if (context->doesPrimitiveExist(UUID) && context->doesPrimitiveDataExist(UUID,primitive_data_label.c_str())){
+
5164 HeliosDataType datatype = context->getPrimitiveDataType(UUID,primitive_data_label.c_str());
+
5165 if( datatype == HELIOS_TYPE_FLOAT ){
+
5166 float labeldata;
+
5167 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
+
5168 pixel_data << labeldata << " ";
+
5169 empty_flag = false;
+
5170 }
+
5171 else if (datatype == HELIOS_TYPE_UINT){
+
5172 uint labeldata;
+
5173 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
+
5174 pixel_data << labeldata << " ";
+
5175 empty_flag = false;
+
5176 }
+
5177 else if (datatype == HELIOS_TYPE_INT){
+
5178 int labeldata;
+
5179 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
+
5180 pixel_data << labeldata << " ";
+
5181 empty_flag = false;
+
5182 }
+
5183 else if (datatype == HELIOS_TYPE_DOUBLE){
+
5184 double labeldata;
+
5185 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata);
+
5186 pixel_data << labeldata << " ";
+
5187 empty_flag = false;
+
5188 }else{
+
5189 pixel_data << padvalue << " ";
+
5190 }
+
5191 }else{
+
5192 pixel_data << padvalue << " ";
+
5193 }
+
5194 }
+
5195 pixel_data << "\n";
+
5196 }
+
5197 pixel_data.close();
+
5198
+
5199 if( empty_flag ){
+
5200 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;
+
5201 }
+
5202
+
5203}
-
5183
-
-
5184void 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){
-
5185
-
5186 if( cameras.find(cameralabel)==cameras.end() ){
-
5187 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Camera '" + cameralabel + "' does not exist." );
-
5188 }
-
5189
-
5190 //Get image UUID labels
-
5191 std::vector<uint> camera_UUIDs;
-
5192 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
-
5193 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
-
5194 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
-
5195 }
-
5196 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
-
5197 std::vector<uint> pixel_UUIDs = camera_UUIDs;
-
5198 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5199
-
5200 std::string frame_str;
-
5201 if( frame>=0 ) {
-
5202 frame_str = std::to_string(frame);
-
5203 }
5204
-
5205 std::string output_path = image_path;
-
5206 if( !image_path.empty() && !validateOutputPath(output_path) ){
-
5207 helios_runtime_error("ERROR (RadiationModel::writeObjectDataLabelMap): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
-
5208 }else if( !getFileName(output_path).empty() ){
-
5209 helios_runtime_error("ERROR(RadiationModel::writeObjectDataLabelMap): Image output directory contains a filename. This argument should be the path to a directory not a file.");
-
5210 }
-
5211
-
5212 std::ostringstream outfile;
-
5213 outfile << output_path;
-
5214
-
5215 if( frame>=0 ) {
-
5216 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5217 }else{
-
5218 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5219 }
+
+
5205void 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){
+
5206
+
5207 if( cameras.find(cameralabel)==cameras.end() ){
+
5208 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Camera '" + cameralabel + "' does not exist." );
+
5209 }
+
5210
+
5211 //Get image UUID labels
+
5212 std::vector<uint> camera_UUIDs;
+
5213 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
+
5214 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
+
5215 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
+
5216 }
+
5217 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
+
5218 std::vector<uint> pixel_UUIDs = camera_UUIDs;
+
5219 int2 camera_resolution = cameras.at(cameralabel).resolution;
5220
-
5221 //Output label image in ".txt" format
-
5222 std::ofstream pixel_data(outfile.str());
-
5223
-
5224 if( !pixel_data.is_open() ){
-
5225 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Could not open file '" + outfile.str() + "' for writing." );
-
5226 }
-
5227
-
5228 bool empty_flag = true;
-
5229 for (uint j = 0; j < camera_resolution.y; j++) {
-
5230 for (uint i = 0; i < camera_resolution.x; i++) {
-
5231 uint ii = camera_resolution.x - i -1;
-
5232 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
-
5233 uint objID = context->getPrimitiveParentObjectID(UUID);
-
5234 if (context->doesObjectExist(objID) && context->doesObjectDataExist(objID,object_data_label.c_str())){
-
5235 HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str());
-
5236 if( datatype == HELIOS_TYPE_FLOAT ){
-
5237 float labeldata;
-
5238 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
-
5239 pixel_data << labeldata << " ";
-
5240 empty_flag = false;
-
5241 }
-
5242 else if (datatype == HELIOS_TYPE_UINT){
-
5243 uint labeldata;
-
5244 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
-
5245 pixel_data << labeldata << " ";
-
5246 empty_flag = false;
-
5247 }
-
5248 else if (datatype == HELIOS_TYPE_INT){
-
5249 int labeldata;
-
5250 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
-
5251 pixel_data << labeldata << " ";
-
5252 empty_flag = false;
-
5253 }
-
5254 else if (datatype == HELIOS_TYPE_DOUBLE){
-
5255 double labeldata;
-
5256 context->getObjectData(UUID,object_data_label.c_str(),labeldata);
-
5257 pixel_data << labeldata << " ";
-
5258 empty_flag = false;
-
5259 }else{
-
5260 pixel_data << padvalue << " ";
-
5261 }
-
5262 }else{
-
5263 pixel_data << padvalue << " ";
-
5264 }
-
5265 }
-
5266 pixel_data << "\n";
-
5267 }
-
5268 pixel_data.close();
-
5269
-
5270 if( empty_flag ){
-
5271 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;
-
5272 }
-
5273
-
5274}
+
5221 std::string frame_str;
+
5222 if( frame>=0 ) {
+
5223 frame_str = std::to_string(frame);
+
5224 }
+
5225
+
5226 std::string output_path = image_path;
+
5227 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5228 helios_runtime_error("ERROR (RadiationModel::writeObjectDataLabelMap): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5229 }else if( !getFileName(output_path).empty() ){
+
5230 helios_runtime_error("ERROR(RadiationModel::writeObjectDataLabelMap): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5231 }
+
5232
+
5233 std::ostringstream outfile;
+
5234 outfile << output_path;
+
5235
+
5236 if( frame>=0 ) {
+
5237 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5238 }else{
+
5239 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5240 }
+
5241
+
5242 //Output label image in ".txt" format
+
5243 std::ofstream pixel_data(outfile.str());
+
5244
+
5245 if( !pixel_data.is_open() ){
+
5246 helios_runtime_error( "ERROR (RadiationModel::writeObjectDataLabelMap): Could not open file '" + outfile.str() + "' for writing." );
+
5247 }
+
5248
+
5249 bool empty_flag = true;
+
5250 for (uint j = 0; j < camera_resolution.y; j++) {
+
5251 for (uint i = 0; i < camera_resolution.x; i++) {
+
5252 uint ii = camera_resolution.x - i -1;
+
5253 uint UUID = pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5254 if( !context->doesPrimitiveExist(UUID) ){
+
5255 pixel_data << padvalue << " ";
+
5256 continue;
+
5257 }
+
5258 uint objID = context->getPrimitiveParentObjectID(UUID);
+
5259 if (context->doesObjectExist(objID) && context->doesObjectDataExist(objID,object_data_label.c_str())){
+
5260 HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str());
+
5261 if( datatype == HELIOS_TYPE_FLOAT ){
+
5262 float labeldata;
+
5263 context->getObjectData(objID,object_data_label.c_str(),labeldata);
+
5264 pixel_data << labeldata << " ";
+
5265 empty_flag = false;
+
5266 }
+
5267 else if (datatype == HELIOS_TYPE_UINT){
+
5268 uint labeldata;
+
5269 context->getObjectData(objID,object_data_label.c_str(),labeldata);
+
5270 pixel_data << labeldata << " ";
+
5271 empty_flag = false;
+
5272 }
+
5273 else if (datatype == HELIOS_TYPE_INT){
+
5274 int labeldata;
+
5275 context->getObjectData(objID,object_data_label.c_str(),labeldata);
+
5276 pixel_data << labeldata << " ";
+
5277 empty_flag = false;
+
5278 }
+
5279 else if (datatype == HELIOS_TYPE_DOUBLE){
+
5280 double labeldata;
+
5281 context->getObjectData(objID,object_data_label.c_str(),labeldata);
+
5282 pixel_data << labeldata << " ";
+
5283 empty_flag = false;
+
5284 }else{
+
5285 pixel_data << padvalue << " ";
+
5286 }
+
5287 }else{
+
5288 pixel_data << padvalue << " ";
+
5289 }
+
5290 }
+
5291 pixel_data << "\n";
+
5292 }
+
5293 pixel_data.close();
+
5294
+
5295 if( empty_flag ){
+
5296 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;
+
5297 }
+
5298
+
5299}
-
5275
-
-
5276void RadiationModel::writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path, int frame) {
-
5277
-
5278 if( cameras.find(cameralabel)==cameras.end() ){
-
5279 helios_runtime_error( "ERROR (RadiationModel::writeDepthImageData): Camera '" + cameralabel + "' does not exist." );
-
5280 }
-
5281
-
5282 std::string global_data_label = "camera_" + cameralabel + "_pixel_depth";
-
5283 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
-
5284 helios_runtime_error("ERROR (RadiationModel::writeDepthImageData): Depth data for camera '" + cameralabel + "' does not exist. Was the radiation model run for the camera?" );
-
5285 }
-
5286 std::vector<float> camera_depth;
-
5287 context->getGlobalData(global_data_label.c_str(), camera_depth);
-
5288 helios::vec3 camera_position = cameras.at(cameralabel).position;
-
5289 helios::vec3 camera_lookat = cameras.at(cameralabel).lookat;
-
5290
-
5291 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5292
-
5293 std::string frame_str;
-
5294 if( frame>=0 ) {
-
5295 frame_str = std::to_string(frame);
-
5296 }
-
5297
-
5298 std::string output_path = image_path;
-
5299 if( !image_path.empty() && !validateOutputPath(output_path) ){
-
5300 helios_runtime_error("ERROR (RadiationModel::writeDepthImageData): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
-
5301 }else if( !getFileName(output_path).empty() ){
-
5302 helios_runtime_error("ERROR(RadiationModel::writeDepthImageData): Image output directory contains a filename. This argument should be the path to a directory not a file.");
-
5303 }
-
5304
-
5305 std::ostringstream outfile;
-
5306 outfile << output_path;
-
5307
-
5308 if( frame>=0 ) {
-
5309 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5310 }else{
-
5311 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5312 }
-
5313
-
5314 //Output label image in ".txt" format
-
5315 std::ofstream pixel_data(outfile.str());
-
5316
-
5317 if( !pixel_data.is_open() ){
-
5318 helios_runtime_error( "ERROR (RadiationModel::writeDepthImageData): Could not open file '" + outfile.str() + "' for writing." );
-
5319 }
-
5320
-
5321 for ( int j = 0; j<camera_resolution.y; j++ ) {
-
5322 for ( int i = camera_resolution.x-1; i >= 0; i--) {
-
5323 pixel_data << camera_depth.at(j*camera_resolution.x + i) << " ";
-
5324 }
-
5325 pixel_data << "\n";
-
5326 }
-
5327
-
5328 pixel_data.close();
+
5300
+
+
5301void RadiationModel::writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path, int frame) {
+
5302
+
5303 if( cameras.find(cameralabel)==cameras.end() ){
+
5304 helios_runtime_error( "ERROR (RadiationModel::writeDepthImageData): 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::writeDepthImageData): 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 }
+
5322
+
5323 std::string output_path = image_path;
+
5324 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5325 helios_runtime_error("ERROR (RadiationModel::writeDepthImageData): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5326 }else if( !getFileName(output_path).empty() ){
+
5327 helios_runtime_error("ERROR(RadiationModel::writeDepthImageData): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5328 }
5329
-
5330}
+
5330 std::ostringstream outfile;
+
5331 outfile << output_path;
+
5332
+
5333 if( frame>=0 ) {
+
5334 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5335 }else{
+
5336 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5337 }
+
5338
+
5339 //Output label image in ".txt" format
+
5340 std::ofstream pixel_data(outfile.str());
+
5341
+
5342 if( !pixel_data.is_open() ){
+
5343 helios_runtime_error( "ERROR (RadiationModel::writeDepthImageData): Could not open file '" + outfile.str() + "' for writing." );
+
5344 }
+
5345
+
5346 for ( int j = 0; j<camera_resolution.y; j++ ) {
+
5347 for ( int i = camera_resolution.x-1; i >= 0; i--) {
+
5348 pixel_data << camera_depth.at(j*camera_resolution.x + i) << " ";
+
5349 }
+
5350 pixel_data << "\n";
+
5351 }
+
5352
+
5353 pixel_data.close();
+
5354
+
5355}
-
5331
-
-
5332void RadiationModel::writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path, int frame){
-
5333
-
5334 if( cameras.find(cameralabel)==cameras.end() ){
-
5335 helios_runtime_error( "ERROR (RadiationModel::writeNormDepthImage): Camera '" + cameralabel + "' does not exist." );
-
5336 }
-
5337
-
5338 std::string global_data_label = "camera_" + cameralabel + "_pixel_depth";
-
5339 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
-
5340 helios_runtime_error("ERROR (RadiationModel::writeNormDepthImage): Depth data for camera '" + cameralabel + "' does not exist. Was the radiation model run for the camera?" );
-
5341 }
-
5342 std::vector<float> camera_depth;
-
5343 context->getGlobalData(global_data_label.c_str(), camera_depth);
-
5344 helios::vec3 camera_position = cameras.at(cameralabel).position;
-
5345 helios::vec3 camera_lookat = cameras.at(cameralabel).lookat;
-
5346
-
5347 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5348
-
5349 std::string frame_str;
-
5350 if( frame>=0 ) {
-
5351 frame_str = std::to_string(frame);
-
5352 }
-
5353
-
5354 std::string output_path = image_path;
-
5355 if( !image_path.empty() && !validateOutputPath(output_path) ){
-
5356 helios_runtime_error("ERROR (RadiationModel::writeNormDepthImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
-
5357 }else if( !getFileName(output_path).empty() ){
-
5358 helios_runtime_error("ERROR(RadiationModel::writeNormDepthImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
-
5359 }
-
5360
-
5361 std::ostringstream outfile;
-
5362 outfile << output_path;
-
5363
-
5364 if( frame>=0 ) {
-
5365 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg";
-
5366 }else{
-
5367 outfile << cameralabel << "_" << imagefile_base << ".jpeg";
-
5368 }
-
5369
-
5370 float min_depth = 99999;
-
5371 for( int i=0; i<camera_depth.size(); i++ ){
-
5372 if( camera_depth.at(i)<0 || camera_depth.at(i)>max_depth ){
-
5373 camera_depth.at(i) = max_depth;
-
5374 }
-
5375 if( camera_depth.at(i)<min_depth ){
-
5376 min_depth = camera_depth.at(i);
-
5377 }
-
5378 }
-
5379 for( int i=0; i<camera_depth.size(); i++ ){
-
5380 camera_depth.at(i) = 1.f-(camera_depth.at(i)-min_depth)/(max_depth-min_depth);
-
5381 }
-
5382
-
5383 std::vector<RGBcolor> pixel_data(camera_resolution.x*camera_resolution.y);
-
5384
-
5385 RGBcolor pixel_color;
-
5386 for (uint j = 0; j < camera_resolution.y; j++) {
-
5387 for (uint i=0; i < camera_resolution.x; i++) {
+
5356
+
+
5357void RadiationModel::writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path, int frame){
+
5358
+
5359 if( cameras.find(cameralabel)==cameras.end() ){
+
5360 helios_runtime_error( "ERROR (RadiationModel::writeNormDepthImage): Camera '" + cameralabel + "' does not exist." );
+
5361 }
+
5362
+
5363 std::string global_data_label = "camera_" + cameralabel + "_pixel_depth";
+
5364 if( !context->doesGlobalDataExist(global_data_label.c_str()) ){
+
5365 helios_runtime_error("ERROR (RadiationModel::writeNormDepthImage): Depth data for camera '" + cameralabel + "' does not exist. Was the radiation model run for the camera?" );
+
5366 }
+
5367 std::vector<float> camera_depth;
+
5368 context->getGlobalData(global_data_label.c_str(), camera_depth);
+
5369 helios::vec3 camera_position = cameras.at(cameralabel).position;
+
5370 helios::vec3 camera_lookat = cameras.at(cameralabel).lookat;
+
5371
+
5372 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5373
+
5374 std::string frame_str;
+
5375 if( frame>=0 ) {
+
5376 frame_str = std::to_string(frame);
+
5377 }
+
5378
+
5379 std::string output_path = image_path;
+
5380 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5381 helios_runtime_error("ERROR (RadiationModel::writeNormDepthImage): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5382 }else if( !getFileName(output_path).empty() ){
+
5383 helios_runtime_error("ERROR(RadiationModel::writeNormDepthImage): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5384 }
+
5385
+
5386 std::ostringstream outfile;
+
5387 outfile << output_path;
5388
-
5389 float c = camera_depth.at(j * camera_resolution.x + i);
-
5390 pixel_color = make_RGBcolor(c,c,c);
-
5391
-
5392 uint ii = camera_resolution.x - i -1;
-
5393 uint jj = camera_resolution.y - j - 1;
-
5394 pixel_data.at(jj * camera_resolution.x + ii) = pixel_color;
-
5395 }
-
5396 }
-
5397
-
5398 writeJPEG( outfile.str(), camera_resolution.x, camera_resolution.y, pixel_data );
-
5399
-
5400}
+
5389 if( frame>=0 ) {
+
5390 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".jpeg";
+
5391 }else{
+
5392 outfile << cameralabel << "_" << imagefile_base << ".jpeg";
+
5393 }
+
5394
+
5395 float min_depth = 99999;
+
5396 for( int i=0; i<camera_depth.size(); i++ ){
+
5397 if( camera_depth.at(i)<0 || camera_depth.at(i)>max_depth ){
+
5398 camera_depth.at(i) = max_depth;
+
5399 }
+
5400 if( camera_depth.at(i)<min_depth ){
+
5401 min_depth = camera_depth.at(i);
+
5402 }
+
5403 }
+
5404 for( int i=0; i<camera_depth.size(); i++ ){
+
5405 camera_depth.at(i) = 1.f-(camera_depth.at(i)-min_depth)/(max_depth-min_depth);
+
5406 }
+
5407
+
5408 std::vector<RGBcolor> pixel_data(camera_resolution.x*camera_resolution.y);
+
5409
+
5410 RGBcolor pixel_color;
+
5411 for (uint j = 0; j < camera_resolution.y; j++) {
+
5412 for (uint i=0; i < camera_resolution.x; i++) {
+
5413
+
5414 float c = camera_depth.at(j * camera_resolution.x + i);
+
5415 pixel_color = make_RGBcolor(c,c,c);
+
5416
+
5417 uint ii = camera_resolution.x - i -1;
+
5418 uint jj = camera_resolution.y - j - 1;
+
5419 pixel_data.at(jj * camera_resolution.x + ii) = pixel_color;
+
5420 }
+
5421 }
+
5422
+
5423 writeJPEG( outfile.str(), camera_resolution.x, camera_resolution.y, pixel_data );
+
5424
+
5425}
-
5401
-
5402
-
-
5403void 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){
-
5404
-
5405 if( cameras.find(cameralabel)==cameras.end() ){
-
5406 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Camera '" + cameralabel + "' does not exist." );
-
5407 }
-
5408
-
5409 //Get image UUID labels
-
5410 std::vector<uint> camera_UUIDs;
-
5411 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
-
5412 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
-
5413 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
-
5414 }
-
5415 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
-
5416 std::vector<uint> pixel_UUIDs = camera_UUIDs;
-
5417 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5418
-
5419 std::string frame_str;
-
5420 if( frame>=0 ) {
-
5421 frame_str = std::to_string(frame);
-
5422 }
-
5423
-
5424 std::string output_path = image_path;
-
5425 if( !image_path.empty() && !validateOutputPath(output_path) ){
-
5426 helios_runtime_error("ERROR (RadiationModel::writeImageBoundingBoxes): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
-
5427 }else if( !getFileName(output_path).empty() ){
-
5428 helios_runtime_error("ERROR(RadiationModel::writeImageBoundingBoxes): Image output directory contains a filename. This argument should be the path to a directory not a file.");
-
5429 }
-
5430
-
5431 std::ostringstream outfile;
-
5432 outfile << output_path;
+
5426
+
5427
+
+
5428void 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){
+
5429
+
5430 if( cameras.find(cameralabel)==cameras.end() ){
+
5431 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Camera '" + cameralabel + "' does not exist." );
+
5432 }
5433
-
5434 if( frame>=0 ) {
-
5435 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5436 }else{
-
5437 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5438 }
-
5439
-
5440 //Output label image in ".txt" format
-
5441 std::ofstream label_file;
-
5442 if( append_label_file ){
-
5443 label_file.open(outfile.str(), std::ios::out | std::ios::app);
-
5444 }else{
-
5445 label_file.open(outfile.str());
-
5446 }
-
5447
-
5448 if( !label_file.is_open() ){
-
5449 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Could not open file '" + outfile.str() + "'." );
-
5450 }
-
5451
-
5452 std::map<int, vec4> pdata_bounds;
-
5453
-
5454 for (int j = 0; j < camera_resolution.y; j++) {
-
5455 for (int i = 0; i < camera_resolution.x; i++) {
-
5456 uint ii = camera_resolution.x - i -1;
-
5457 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
-
5458 if (context->doesPrimitiveExist(UUID) && context->doesPrimitiveDataExist(UUID,primitive_data_label.c_str())){
-
5459
-
5460 uint labeldata;
-
5461
-
5462 HeliosDataType datatype = context->getPrimitiveDataType(UUID,primitive_data_label.c_str());
-
5463 if (datatype == HELIOS_TYPE_UINT){
-
5464 uint labeldata_ui;
-
5465 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata_ui);
-
5466 labeldata = labeldata_ui;
-
5467 }
-
5468 else if (datatype == HELIOS_TYPE_INT){
-
5469 int labeldata_i;
-
5470 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata_i);
-
5471 labeldata = (uint)labeldata_i;
-
5472 }else{
-
5473 continue;
-
5474 }
-
5475
-
5476 if( pdata_bounds.find(labeldata) == pdata_bounds.end() ) {
-
5477 pdata_bounds[labeldata] = make_vec4(1e6, -1, 1e6, -1);
-
5478 }
-
5479
-
5480 if( i<pdata_bounds[labeldata].x ){
-
5481 pdata_bounds[labeldata].x = i;
-
5482 }
-
5483 if( i>pdata_bounds[labeldata].y ){
-
5484 pdata_bounds[labeldata].y = i;
-
5485 }
-
5486 if( j<pdata_bounds[labeldata].z ){
-
5487 pdata_bounds[labeldata].z = j;
-
5488 }
-
5489 if( j>pdata_bounds[labeldata].w ){
-
5490 pdata_bounds[labeldata].w = j;
-
5491 }
-
5492
-
5493 }
-
5494 }
-
5495 }
-
5496
-
5497 for( auto box : pdata_bounds ){
-
5498 vec4 bbox = box.second;
-
5499 if( bbox.x==bbox.y || bbox.z==bbox.w ){ //filter boxes of zeros size
-
5500 continue;
-
5501 }
-
5502 label_file << object_class_ID << " " << (bbox.x + 0.5 * (bbox.y - bbox.x)) / float(camera_resolution.x) << " "
-
5503 << (bbox.z + 0.5 * (bbox.w - bbox.z)) / float(camera_resolution.y) << " " << std::setprecision(6)
-
5504 << std::fixed << (bbox.y - bbox.x) / float(camera_resolution.x) << " "
-
5505 << (bbox.w - bbox.z) / float(camera_resolution.y) << std::endl;
-
5506 }
-
5507
-
5508 label_file.close();
-
5509
-
5510}
-
-
5511
-
-
5512void 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){
-
5513
-
5514 if( cameras.find(cameralabel)==cameras.end() ){
-
5515 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Camera '" + cameralabel + "' does not exist." );
-
5516 }
+
5434 //Get image UUID labels
+
5435 std::vector<uint> camera_UUIDs;
+
5436 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
+
5437 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
+
5438 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
+
5439 }
+
5440 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
+
5441 std::vector<uint> pixel_UUIDs = camera_UUIDs;
+
5442 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5443
+
5444 std::string frame_str;
+
5445 if( frame>=0 ) {
+
5446 frame_str = std::to_string(frame);
+
5447 }
+
5448
+
5449 std::string output_path = image_path;
+
5450 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5451 helios_runtime_error("ERROR (RadiationModel::writeImageBoundingBoxes): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5452 }else if( !getFileName(output_path).empty() ){
+
5453 helios_runtime_error("ERROR(RadiationModel::writeImageBoundingBoxes): Image output directory contains a filename. This argument should be the path to a directory not a file.");
+
5454 }
+
5455
+
5456 std::ostringstream outfile;
+
5457 outfile << output_path;
+
5458
+
5459 if( frame>=0 ) {
+
5460 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5461 }else{
+
5462 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5463 }
+
5464
+
5465 //Output label image in ".txt" format
+
5466 std::ofstream label_file;
+
5467 if( append_label_file ){
+
5468 label_file.open(outfile.str(), std::ios::out | std::ios::app);
+
5469 }else{
+
5470 label_file.open(outfile.str());
+
5471 }
+
5472
+
5473 if( !label_file.is_open() ){
+
5474 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes): Could not open file '" + outfile.str() + "'." );
+
5475 }
+
5476
+
5477 std::map<int, vec4> pdata_bounds;
+
5478
+
5479 for (int j = 0; j < camera_resolution.y; j++) {
+
5480 for (int i = 0; i < camera_resolution.x; i++) {
+
5481 uint ii = camera_resolution.x - i -1;
+
5482 uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5483 if (context->doesPrimitiveExist(UUID) && context->doesPrimitiveDataExist(UUID,primitive_data_label.c_str())){
+
5484
+
5485 uint labeldata;
+
5486
+
5487 HeliosDataType datatype = context->getPrimitiveDataType(UUID,primitive_data_label.c_str());
+
5488 if (datatype == HELIOS_TYPE_UINT){
+
5489 uint labeldata_ui;
+
5490 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata_ui);
+
5491 labeldata = labeldata_ui;
+
5492 }
+
5493 else if (datatype == HELIOS_TYPE_INT){
+
5494 int labeldata_i;
+
5495 context->getPrimitiveData(UUID,primitive_data_label.c_str(),labeldata_i);
+
5496 labeldata = (uint)labeldata_i;
+
5497 }else{
+
5498 continue;
+
5499 }
+
5500
+
5501 if( pdata_bounds.find(labeldata) == pdata_bounds.end() ) {
+
5502 pdata_bounds[labeldata] = make_vec4(1e6, -1, 1e6, -1);
+
5503 }
+
5504
+
5505 if( i<pdata_bounds[labeldata].x ){
+
5506 pdata_bounds[labeldata].x = i;
+
5507 }
+
5508 if( i>pdata_bounds[labeldata].y ){
+
5509 pdata_bounds[labeldata].y = i;
+
5510 }
+
5511 if( j<pdata_bounds[labeldata].z ){
+
5512 pdata_bounds[labeldata].z = j;
+
5513 }
+
5514 if( j>pdata_bounds[labeldata].w ){
+
5515 pdata_bounds[labeldata].w = j;
+
5516 }
5517
-
5518 //Get image UUID labels
-
5519 std::vector<uint> camera_UUIDs;
-
5520 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
-
5521 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
-
5522 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
-
5523 }
-
5524 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
-
5525 std::vector<uint> pixel_UUIDs = camera_UUIDs;
-
5526 int2 camera_resolution = cameras.at(cameralabel).resolution;
-
5527
-
5528 std::string frame_str;
-
5529 if( frame>=0 ) {
-
5530 frame_str = std::to_string(frame);
+
5518 }
+
5519 }
+
5520 }
+
5521
+
5522 for( auto box : pdata_bounds ){
+
5523 vec4 bbox = box.second;
+
5524 if( bbox.x==bbox.y || bbox.z==bbox.w ){ //filter boxes of zeros size
+
5525 continue;
+
5526 }
+
5527 label_file << object_class_ID << " " << (bbox.x + 0.5 * (bbox.y - bbox.x)) / float(camera_resolution.x) << " "
+
5528 << (bbox.z + 0.5 * (bbox.w - bbox.z)) / float(camera_resolution.y) << " " << std::setprecision(6)
+
5529 << std::fixed << (bbox.y - bbox.x) / float(camera_resolution.x) << " "
+
5530 << (bbox.w - bbox.z) / float(camera_resolution.y) << std::endl;
5531 }
5532
-
5533 std::string output_path = image_path;
-
5534 if( !image_path.empty() && !validateOutputPath(output_path) ){
-
5535 helios_runtime_error("ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
-
5536 }else if( !getFileName(output_path).empty() ){
-
5537 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.");
-
5538 }
-
5539
-
5540 std::ostringstream outfile;
-
5541 outfile << output_path;
+
5533 label_file.close();
+
5534
+
5535}
+
+
5536
+
+
5537void 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){
+
5538
+
5539 if( cameras.find(cameralabel)==cameras.end() ){
+
5540 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Camera '" + cameralabel + "' does not exist." );
+
5541 }
5542
-
5543 if( frame>=0 ) {
-
5544 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
-
5545 }else{
-
5546 outfile << cameralabel << "_" << imagefile_base << ".txt";
-
5547 }
-
5548
-
5549 //Output label image in ".txt" format
-
5550 std::ofstream label_file;
-
5551 if( append_label_file ){
-
5552 label_file.open(outfile.str(), std::ios::out | std::ios::app);
-
5553 }else{
-
5554 label_file.open(outfile.str());
-
5555 }
-
5556
-
5557 if( !label_file.is_open() ){
-
5558 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Could not open file '" + outfile.str() + "'." );
-
5559 }
-
5560
-
5561 std::map<int, vec4> pdata_bounds;
-
5562
-
5563 for (int j = 0; j < camera_resolution.y; j++) {
-
5564 for (int i = 0; i < camera_resolution.x; i++) {
-
5565 uint ii = camera_resolution.x - i -1;
-
5566 uint UUID = pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5543 //Get image UUID labels
+
5544 std::vector<uint> camera_UUIDs;
+
5545 std::string global_data_label = "camera_" + cameralabel + "_pixel_UUID";
+
5546 if( !context->doesGlobalDataExist(global_data_label.c_str() ) ){
+
5547 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Pixel labels for camera '" + cameralabel + "' do not exist. Was the radiation model run to generate labels?" );
+
5548 }
+
5549 context->getGlobalData(global_data_label.c_str(), camera_UUIDs);
+
5550 std::vector<uint> pixel_UUIDs = camera_UUIDs;
+
5551 int2 camera_resolution = cameras.at(cameralabel).resolution;
+
5552
+
5553 std::string frame_str;
+
5554 if( frame>=0 ) {
+
5555 frame_str = std::to_string(frame);
+
5556 }
+
5557
+
5558 std::string output_path = image_path;
+
5559 if( !image_path.empty() && !validateOutputPath(output_path) ){
+
5560 helios_runtime_error("ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Invalid image output directory '" + image_path + "'. Check that the path exists and that you have write permission.");
+
5561 }else if( !getFileName(output_path).empty() ){
+
5562 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.");
+
5563 }
+
5564
+
5565 std::ostringstream outfile;
+
5566 outfile << output_path;
5567
-
5568 if ( !context->doesPrimitiveExist(UUID) ){
-
5569 continue;
-
5570 }
-
5571
-
5572 uint objID = context->getPrimitiveParentObjectID(UUID);
+
5568 if( frame>=0 ) {
+
5569 outfile << cameralabel << "_" << imagefile_base << "_" << std::setw(5) << std::setfill('0') << frame_str << ".txt";
+
5570 }else{
+
5571 outfile << cameralabel << "_" << imagefile_base << ".txt";
+
5572 }
5573
-
5574 if ( !context->doesObjectExist(objID) || !context->doesObjectDataExist(objID,object_data_label.c_str())) {
-
5575 continue;
-
5576 }
-
5577
-
5578 uint labeldata;
-
5579
-
5580 HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str());
-
5581 if (datatype == HELIOS_TYPE_UINT){
-
5582 uint labeldata_ui;
-
5583 context->getObjectData(objID,object_data_label.c_str(),labeldata_ui);
-
5584 labeldata = labeldata_ui;
-
5585 }
-
5586 else if (datatype == HELIOS_TYPE_INT){
-
5587 int labeldata_i;
-
5588 context->getObjectData(objID,object_data_label.c_str(),labeldata_i);
-
5589 labeldata = (uint)labeldata_i;
-
5590 }else{
-
5591 continue;
-
5592 }
-
5593
-
5594 if( pdata_bounds.find(labeldata) == pdata_bounds.end() ) {
-
5595 pdata_bounds[labeldata] = make_vec4(1e6, -1, 1e6, -1);
-
5596 }
-
5597
-
5598 if( i<pdata_bounds[labeldata].x ){
-
5599 pdata_bounds[labeldata].x = i;
-
5600 }
-
5601 if( i>pdata_bounds[labeldata].y ){
-
5602 pdata_bounds[labeldata].y = i;
-
5603 }
-
5604 if( j<pdata_bounds[labeldata].z ){
-
5605 pdata_bounds[labeldata].z = j;
-
5606 }
-
5607 if( j>pdata_bounds[labeldata].w ){
-
5608 pdata_bounds[labeldata].w = j;
-
5609 }
-
5610
-
5611 }
-
5612 }
-
5613
-
5614 for( auto box : pdata_bounds ){
-
5615 vec4 bbox = box.second;
-
5616 if( bbox.x==bbox.y || bbox.z==bbox.w ){ //filter boxes of zeros size
-
5617 continue;
-
5618 }
-
5619 label_file << object_class_ID << " " << (bbox.x + 0.5 * (bbox.y - bbox.x)) / float(camera_resolution.x) << " "
-
5620 << (bbox.z + 0.5 * (bbox.w - bbox.z)) / float(camera_resolution.y) << " " << std::setprecision(6)
-
5621 << std::fixed << (bbox.y - bbox.x) / float(camera_resolution.x) << " "
-
5622 << (bbox.w - bbox.z) / float(camera_resolution.y) << std::endl;
-
5623 }
-
5624
-
5625 label_file.close();
-
5626
-
5627}
-
-
5628
-
5629
-
-
5630void RadiationModel::setPadValue(const std::string &cameralabel, const std::vector<std::string> &bandlabels, const std::vector<float> &padvalues) {
-
5631 for (uint b = 0; b < bandlabels.size(); b++) {
-
5632 std::string bandlabel = bandlabels.at(b);
-
5633
-
5634 std::string image_value_label = "camera_" + cameralabel + "_" + bandlabel;
-
5635 std::vector<float> cameradata;
-
5636 context->getGlobalData(image_value_label.c_str(), cameradata);
-
5637
-
5638 std::vector<uint> camera_UUIDs;
-
5639 std::string image_UUID_label = "camera_" + cameralabel + "_pixel_UUID";
-
5640 context->getGlobalData(image_UUID_label.c_str(), camera_UUIDs);
-
5641
-
5642 for (uint i = 0; i < cameradata.size(); i++) {
-
5643 uint UUID = camera_UUIDs.at(i)-1;
-
5644 if (!context->doesPrimitiveExist(UUID)) {
-
5645 cameradata.at(i) = padvalues.at(b);
-
5646 }
-
5647 }
-
5648 context->setGlobalData(image_value_label.c_str(), HELIOS_TYPE_FLOAT, cameradata.size(), &cameradata[0]);
-
5649 }
-
5650}
-
+
5574 //Output label image in ".txt" format
+
5575 std::ofstream label_file;
+
5576 if( append_label_file ){
+
5577 label_file.open(outfile.str(), std::ios::out | std::ios::app);
+
5578 }else{
+
5579 label_file.open(outfile.str());
+
5580 }
+
5581
+
5582 if( !label_file.is_open() ){
+
5583 helios_runtime_error( "ERROR (RadiationModel::writeImageBoundingBoxes_ObjectData): Could not open file '" + outfile.str() + "'." );
+
5584 }
+
5585
+
5586 std::map<int, vec4> pdata_bounds;
+
5587
+
5588 for (int j = 0; j < camera_resolution.y; j++) {
+
5589 for (int i = 0; i < camera_resolution.x; i++) {
+
5590 uint ii = camera_resolution.x - i -1;
+
5591 uint UUID = pixel_UUIDs.at(j * camera_resolution.x + ii)-1;
+
5592
+
5593 if ( !context->doesPrimitiveExist(UUID) ){
+
5594 continue;
+
5595 }
+
5596
+
5597 uint objID = context->getPrimitiveParentObjectID(UUID);
+
5598
+
5599 if ( !context->doesObjectExist(objID) || !context->doesObjectDataExist(objID,object_data_label.c_str())) {
+
5600 continue;
+
5601 }
+
5602
+
5603 uint labeldata;
+
5604
+
5605 HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str());
+
5606 if (datatype == HELIOS_TYPE_UINT){
+
5607 uint labeldata_ui;
+
5608 context->getObjectData(objID,object_data_label.c_str(),labeldata_ui);
+
5609 labeldata = labeldata_ui;
+
5610 }
+
5611 else if (datatype == HELIOS_TYPE_INT){
+
5612 int labeldata_i;
+
5613 context->getObjectData(objID,object_data_label.c_str(),labeldata_i);
+
5614 labeldata = (uint)labeldata_i;
+
5615 }else{
+
5616 continue;
+
5617 }
+
5618
+
5619 if( pdata_bounds.find(labeldata) == pdata_bounds.end() ) {
+
5620 pdata_bounds[labeldata] = make_vec4(1e6, -1, 1e6, -1);
+
5621 }
+
5622
+
5623 if( i<pdata_bounds[labeldata].x ){
+
5624 pdata_bounds[labeldata].x = i;
+
5625 }
+
5626 if( i>pdata_bounds[labeldata].y ){
+
5627 pdata_bounds[labeldata].y = i;
+
5628 }
+
5629 if( j<pdata_bounds[labeldata].z ){
+
5630 pdata_bounds[labeldata].z = j;
+
5631 }
+
5632 if( j>pdata_bounds[labeldata].w ){
+
5633 pdata_bounds[labeldata].w = j;
+
5634 }
+
5635
+
5636 }
+
5637 }
+
5638
+
5639 for( auto box : pdata_bounds ){
+
5640 vec4 bbox = box.second;
+
5641 if( bbox.x==bbox.y || bbox.z==bbox.w ){ //filter boxes of zeros size
+
5642 continue;
+
5643 }
+
5644 label_file << object_class_ID << " " << (bbox.x + 0.5 * (bbox.y - bbox.x)) / float(camera_resolution.x) << " "
+
5645 << (bbox.z + 0.5 * (bbox.w - bbox.z)) / float(camera_resolution.y) << " " << std::setprecision(6)
+
5646 << std::fixed << (bbox.y - bbox.x) / float(camera_resolution.x) << " "
+
5647 << (bbox.w - bbox.z) / float(camera_resolution.y) << std::endl;
+
5648 }
+
5649
+
5650 label_file.close();
5651
-
-
5652void RadiationModel::calibrateCamera(const std::string &originalcameralabel, const std::vector<std::string> &sourcelabels,
-
5653 const std::vector<std::string>& cameraresplabels_raw, const std::vector<std::string> &bandlabels, const float scalefactor,
-
5654 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark) {
-
5655
-
5656 if( cameras.find(originalcameralabel) == cameras.end() ){
-
5657 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): Camera " + originalcameralabel + " does not exist.");
-
5658 }else if( radiation_sources.empty() ){
-
5659 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): No radiation sources were added to the radiation model. Cannot perform calibration.");
-
5660 }
-
5661
-
5662 CameraCalibration cameracalibration_(context);
-
5663 if (!calibration_flag){
-
5664 std::cout<< "No color board added, use default color calibration." <<std::endl;
-
5665 cameracalibration = &cameracalibration_;
-
5666 vec3 centrelocation =make_vec3(0,0,0.2); // Location of color board
-
5667 vec3 rotationrad =make_vec3(0,0,1.5705); // Rotation angle of color board
-
5668 cameracalibration->addDefaultColorboard(centrelocation, 0.1, rotationrad);
-
5669 }
-
5670 vec2 wavelengthrange = make_vec2(-10000,10000);
-
5671
-
5672 // Calibrated camera response labels
-
5673 std::vector<std::string> cameraresplabels_cal(cameraresplabels_raw.size());
-
5674
-
5675 for (int iband=0;iband<bandlabels.size();iband++){
-
5676 cameraresplabels_cal.at(iband) = calibratedmark + "_" + cameraresplabels_raw.at(iband);
-
5677 }
-
5678
-
5679 RadiationModel::runRadiationImaging(originalcameralabel, sourcelabels, bandlabels, cameraresplabels_raw, wavelengthrange, 1, 0);
-
5680 // Update camera responses
-
5681 RadiationModel::updateCameraResponse(originalcameralabel, sourcelabels, cameraresplabels_raw, wavelengthrange, truevalues, calibratedmark);
-
5682
-
5683 float camerascale = RadiationModel::getCameraResponseScale(originalcameralabel, cameraresplabels_cal, bandlabels,sourcelabels, wavelengthrange, truevalues);
-
5684
-
5685 std::cout << "Camera response scale: " << camerascale << std::endl;
-
5686 // Scale and write calibrated camera responses
-
5687 cameracalibration->writeCalibratedCameraResponses(cameraresplabels_raw, calibratedmark, camerascale*scalefactor);
-
5688
-
5689}
+
5652}
+
+
5653
+
5654
+
+
5655void RadiationModel::setPadValue(const std::string &cameralabel, const std::vector<std::string> &bandlabels, const std::vector<float> &padvalues) {
+
5656 for (uint b = 0; b < bandlabels.size(); b++) {
+
5657 std::string bandlabel = bandlabels.at(b);
+
5658
+
5659 std::string image_value_label = "camera_" + cameralabel + "_" + bandlabel;
+
5660 std::vector<float> cameradata;
+
5661 context->getGlobalData(image_value_label.c_str(), cameradata);
+
5662
+
5663 std::vector<uint> camera_UUIDs;
+
5664 std::string image_UUID_label = "camera_" + cameralabel + "_pixel_UUID";
+
5665 context->getGlobalData(image_UUID_label.c_str(), camera_UUIDs);
+
5666
+
5667 for (uint i = 0; i < cameradata.size(); i++) {
+
5668 uint UUID = camera_UUIDs.at(i)-1;
+
5669 if (!context->doesPrimitiveExist(UUID)) {
+
5670 cameradata.at(i) = padvalues.at(b);
+
5671 }
+
5672 }
+
5673 context->setGlobalData(image_value_label.c_str(), HELIOS_TYPE_FLOAT, cameradata.size(), &cameradata[0]);
+
5674 }
+
5675}
-
5690
-
-
5691void RadiationModel::calibrateCamera(const std::string &originalcameralabel, const float scalefactor, const std::vector<std::vector<float>> &truevalues,
-
5692 const std::string &calibratedmark) {
-
5693
-
5694 if( cameras.find(originalcameralabel) == cameras.end() ){
-
5695 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): Camera " + originalcameralabel + " does not exist.");
-
5696 }else if( radiation_sources.empty() ){
-
5697 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): No radiation sources were added to the radiation model. Cannot perform calibration.");
-
5698 }
+
5676
+
+
5677void RadiationModel::calibrateCamera(const std::string &originalcameralabel, const std::vector<std::string> &sourcelabels,
+
5678 const std::vector<std::string>& cameraresplabels_raw, const std::vector<std::string> &bandlabels, const float scalefactor,
+
5679 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark) {
+
5680
+
5681 if( cameras.find(originalcameralabel) == cameras.end() ){
+
5682 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): Camera " + originalcameralabel + " does not exist.");
+
5683 }else if( radiation_sources.empty() ){
+
5684 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): No radiation sources were added to the radiation model. Cannot perform calibration.");
+
5685 }
+
5686
+
5687 CameraCalibration cameracalibration_(context);
+
5688 if (!calibration_flag){
+
5689 std::cout<< "No color board added, use default color calibration." <<std::endl;
+
5690 cameracalibration = &cameracalibration_;
+
5691 vec3 centrelocation =make_vec3(0,0,0.2); // Location of color board
+
5692 vec3 rotationrad =make_vec3(0,0,1.5705); // Rotation angle of color board
+
5693 cameracalibration->addDefaultColorboard(centrelocation, 0.1, rotationrad);
+
5694 }
+
5695 vec2 wavelengthrange = make_vec2(-10000,10000);
+
5696
+
5697 // Calibrated camera response labels
+
5698 std::vector<std::string> cameraresplabels_cal(cameraresplabels_raw.size());
5699
-
5700 CameraCalibration cameracalibration_(context);
-
5701 if (!calibration_flag){
-
5702 std::cout<< "No color board added, use default color calibration." <<std::endl;
-
5703 vec3 centrelocation =make_vec3(0,0,0.2); // Location of color board
-
5704 vec3 rotationrad =make_vec3(0,0,1.5705); // Rotation angle of color board
-
5705 cameracalibration_.addDefaultColorboard(centrelocation, 0.1, rotationrad);
-
5706 RadiationModel::setCameraCalibration(&cameracalibration_);
-
5707 }
-
5708
-
5709 vec2 wavelengthrange = make_vec2(-10000,10000);
-
5710
-
5711 std::vector<std::string> bandlabels = cameras.at(originalcameralabel).band_labels;
-
5712
-
5713 // Get camera response spectra labels from camera
-
5714 std::vector<std::string> cameraresplabels_cal(cameras.at(originalcameralabel).band_spectral_response.size() );
-
5715 std::vector<std::string> cameraresplabels_raw = cameraresplabels_cal;
-
5716
-
5717 int iband = 0;
-
5718 for( auto &band : cameras.at(originalcameralabel).band_spectral_response ){
-
5719 cameraresplabels_raw.at(iband) = band.second;
-
5720 cameraresplabels_cal.at(iband) = calibratedmark + "_" + band.second;
-
5721 iband++;
-
5722 }
-
5723
-
5724 // Get labels of radiation sources from camera
-
5725 std::vector<std::string> sourcelabels(radiation_sources.size());
-
5726 int isource = 0;
-
5727 for( auto &source : radiation_sources ){
-
5728 if( source.source_spectrum.empty() ){
-
5729 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): A spectral distribution was not specified for source " + source.source_spectrum_label + ". Cannot perform camera calibration.");
-
5730 }
-
5731 sourcelabels.at(isource) = source.source_spectrum_label;
-
5732 isource++;
-
5733 }
-
5734
- -
5736 RadiationModel::runBand(bandlabels);
-
5737 // Update camera responses
-
5738 RadiationModel::updateCameraResponse(originalcameralabel, sourcelabels, cameraresplabels_raw, wavelengthrange, truevalues, calibratedmark);
-
5739
-
5740 float camerascale = RadiationModel::getCameraResponseScale(originalcameralabel, cameraresplabels_cal, bandlabels,sourcelabels, wavelengthrange, truevalues);
-
5741
-
5742 std::cout << "Camera response scale: " << camerascale << std::endl;
-
5743 // Scale and write calibrated camera responses
-
5744 cameracalibration->writeCalibratedCameraResponses(cameraresplabels_raw, calibratedmark, camerascale*scalefactor);
-
5745
-
5746}
+
5700 for (int iband=0;iband<bandlabels.size();iband++){
+
5701 cameraresplabels_cal.at(iband) = calibratedmark + "_" + cameraresplabels_raw.at(iband);
+
5702 }
+
5703
+
5704 RadiationModel::runRadiationImaging(originalcameralabel, sourcelabels, bandlabels, cameraresplabels_raw, wavelengthrange, 1, 0);
+
5705 // Update camera responses
+
5706 RadiationModel::updateCameraResponse(originalcameralabel, sourcelabels, cameraresplabels_raw, wavelengthrange, truevalues, calibratedmark);
+
5707
+
5708 float camerascale = RadiationModel::getCameraResponseScale(originalcameralabel, cameraresplabels_cal, bandlabels,sourcelabels, wavelengthrange, truevalues);
+
5709
+
5710 std::cout << "Camera response scale: " << camerascale << std::endl;
+
5711 // Scale and write calibrated camera responses
+
5712 cameracalibration->writeCalibratedCameraResponses(cameraresplabels_raw, calibratedmark, camerascale*scalefactor);
+
5713
+
5714}
-
5747
-
5748std::vector<helios::vec2> RadiationModel::generateGaussianCameraResponse(float FWHM, float mu, float centrawavelength, const helios::int2 &wavebanrange){
-
5749
-
5750 // Convert FWHM to sigma
-
5751 float sigma = FWHM / (2 * std::sqrt(2 * std::log(2)));
-
5752
-
5753 size_t lenspectra = wavebanrange.y - wavebanrange.x;
-
5754 std::vector<helios::vec2> cameraresponse(lenspectra);
-
5755
-
5756
-
5757 for (int i = 0; i < lenspectra; ++i) {
-
5758 cameraresponse.at(i).x = float(wavebanrange.x + i);
-
5759 }
-
5760
-
5761 // Gaussian function
-
5762 for (size_t i = 0; i < lenspectra; ++i) {
-
5763 cameraresponse.at(i).y = centrawavelength * std::exp(-std::pow((cameraresponse.at(i).x - mu), 2) / (2 * std::pow(sigma, 2)));
-
5764 }
-
5765
+
5715
+
+
5716void RadiationModel::calibrateCamera(const std::string &originalcameralabel, const float scalefactor, const std::vector<std::vector<float>> &truevalues,
+
5717 const std::string &calibratedmark) {
+
5718
+
5719 if( cameras.find(originalcameralabel) == cameras.end() ){
+
5720 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): Camera " + originalcameralabel + " does not exist.");
+
5721 }else if( radiation_sources.empty() ){
+
5722 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): No radiation sources were added to the radiation model. Cannot perform calibration.");
+
5723 }
+
5724
+
5725 CameraCalibration cameracalibration_(context);
+
5726 if (!calibration_flag){
+
5727 std::cout<< "No color board added, use default color calibration." <<std::endl;
+
5728 vec3 centrelocation =make_vec3(0,0,0.2); // Location of color board
+
5729 vec3 rotationrad =make_vec3(0,0,1.5705); // Rotation angle of color board
+
5730 cameracalibration_.addDefaultColorboard(centrelocation, 0.1, rotationrad);
+
5731 RadiationModel::setCameraCalibration(&cameracalibration_);
+
5732 }
+
5733
+
5734 vec2 wavelengthrange = make_vec2(-10000,10000);
+
5735
+
5736 std::vector<std::string> bandlabels = cameras.at(originalcameralabel).band_labels;
+
5737
+
5738 // Get camera response spectra labels from camera
+
5739 std::vector<std::string> cameraresplabels_cal(cameras.at(originalcameralabel).band_spectral_response.size() );
+
5740 std::vector<std::string> cameraresplabels_raw = cameraresplabels_cal;
+
5741
+
5742 int iband = 0;
+
5743 for( auto &band : cameras.at(originalcameralabel).band_spectral_response ){
+
5744 cameraresplabels_raw.at(iband) = band.second;
+
5745 cameraresplabels_cal.at(iband) = calibratedmark + "_" + band.second;
+
5746 iband++;
+
5747 }
+
5748
+
5749 // Get labels of radiation sources from camera
+
5750 std::vector<std::string> sourcelabels(radiation_sources.size());
+
5751 int isource = 0;
+
5752 for( auto &source : radiation_sources ){
+
5753 if( source.source_spectrum.empty() ){
+
5754 helios_runtime_error("ERROR (RadiationModel::calibrateCamera): A spectral distribution was not specified for source " + source.source_spectrum_label + ". Cannot perform camera calibration.");
+
5755 }
+
5756 sourcelabels.at(isource) = source.source_spectrum_label;
+
5757 isource++;
+
5758 }
+
5759
+ +
5761 RadiationModel::runBand(bandlabels);
+
5762 // Update camera responses
+
5763 RadiationModel::updateCameraResponse(originalcameralabel, sourcelabels, cameraresplabels_raw, wavelengthrange, truevalues, calibratedmark);
+
5764
+
5765 float camerascale = RadiationModel::getCameraResponseScale(originalcameralabel, cameraresplabels_cal, bandlabels,sourcelabels, wavelengthrange, truevalues);
5766
-
5767 return cameraresponse;
-
5768}
-
5769
-
5770void sutilHandleError(RTcontext context, RTresult code, const char* file, int line)
-
5771{
-
5772 const char* message;
-
5773 char s[2048];
-
5774 rtContextGetErrorString(context, code, &message);
-
5775 sprintf(s, "%s\n(%s:%d)", message, file, line);
-
5776 sutilReportError( s );
-
5777 exit(1);
-
5778}
-
5779
-
5780void sutilReportError(const char* message)
-
5781{
-
5782 fprintf( stderr, "OptiX Error: %s\n", message );
-
5783#if defined(_WIN32) && defined(RELEASE_PUBLIC)
-
5784 {
-
5785 char s[2048];
-
5786 sprintf( s, "OptiX Error: %s", message );
-
5787 MessageBox( 0, s, "OptiX Error", MB_OK|MB_ICONWARNING|MB_SYSTEMMODAL );
-
5788 }
-
5789#endif
-
5790}
+
5767 std::cout << "Camera response scale: " << camerascale << std::endl;
+
5768 // Scale and write calibrated camera responses
+
5769 cameracalibration->writeCalibratedCameraResponses(cameraresplabels_raw, calibratedmark, camerascale*scalefactor);
+
5770
+
5771}
+
+
5772
+
5773std::vector<helios::vec2> RadiationModel::generateGaussianCameraResponse(float FWHM, float mu, float centrawavelength, const helios::int2 &wavebanrange){
+
5774
+
5775 // Convert FWHM to sigma
+
5776 float sigma = FWHM / (2 * std::sqrt(2 * std::log(2)));
+
5777
+
5778 size_t lenspectra = wavebanrange.y - wavebanrange.x;
+
5779 std::vector<helios::vec2> cameraresponse(lenspectra);
+
5780
+
5781
+
5782 for (int i = 0; i < lenspectra; ++i) {
+
5783 cameraresponse.at(i).x = float(wavebanrange.x + i);
+
5784 }
+
5785
+
5786 // Gaussian function
+
5787 for (size_t i = 0; i < lenspectra; ++i) {
+
5788 cameraresponse.at(i).y = centrawavelength * std::exp(-std::pow((cameraresponse.at(i).x - mu), 2) / (2 * std::pow(sigma, 2)));
+
5789 }
+
5790
+
5791
+
5792 return cameraresponse;
+
5793}
+
5794
+
5795void sutilHandleError(RTcontext context, RTresult code, const char* file, int line)
+
5796{
+
5797 const char* message;
+
5798 char s[2048];
+
5799 rtContextGetErrorString(context, code, &message);
+
5800 sprintf(s, "%s\n(%s:%d)", message, file, line);
+
5801 sutilReportError( s );
+
5802 exit(1);
+
5803}
+
5804
+
5805void sutilReportError(const char* message)
+
5806{
+
5807 fprintf( stderr, "OptiX Error: %s\n", message );
+
5808#if defined(_WIN32) && defined(RELEASE_PUBLIC)
+
5809 {
+
5810 char s[2048];
+
5811 sprintf( s, "OptiX Error: %s", message );
+
5812 MessageBox( 0, s, "OptiX Error", MB_OK|MB_ICONWARNING|MB_SYSTEMMODAL );
+
5813 }
+
5814#endif
+
5815}
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
@@ -6084,57 +6116,57 @@
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
PrimitiveType
Type of primitive element.
Definition Context.h:31
@ PRIMITIVE_TYPE_PATCH
< Rectangular primitive
Definition Context.h:33
-
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
+
@ 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
-
helios::SphericalCoord getCameraOrientation(const std::string &camera_label) const
Get the orientation of the radiation camera based on a spherical coordinate.
+
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 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.
-
void setCameraOrientation(const std::string &camera_label, const helios::vec3 &direction)
Set the orientation of the radiation camera based on a Cartesian vector.
+
void setCameraOrientation(const std::string &camera_label, const helios::vec3 &direction)
Set the orientation of the radiation camera based on a Cartesian vector.
void scaleSpectrum(const std::string &existing_global_data_label, const std::string &new_global_data_label, float scale_factor) const
Scale an entire spectrum by a constant factor. Creates new global data for scaled spectrum.
void blendSpectraRandomly(const std::string &new_spectrum_label, const std::vector< std::string > &spectrum_labels) const
Blend one or more spectra together into a new spectrum, with random weights assigned to each input sp...
void blendSpectra(const std::string &new_spectrum_label, const std::vector< std::string > &spectrum_labels, const std::vector< float > &weights) const
Blend one or more spectra together into a new spectrum.
uint addSphereRadiationSource(const helios::vec3 &position, float radius)
Add an external source of radiation that emits from the surface of a sphere.
void enforcePeriodicBoundary(const std::string &boundary)
Use a periodic boundary condition in one or more lateral directions.
-
std::vector< std::string > getAllCameraLabels()
Get the labels for all radiation cameras that have been added to the radiation model.
+
std::vector< std::string > getAllCameraLabels()
Get the labels for all radiation cameras that have been added to the radiation model.
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.
-
helios::vec3 getCameraPosition(const std::string &camera_label) const
Get the position of the radiation camera.
+
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)
+
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 setCameraLookat(const std::string &camera_label, const helios::vec3 &lookat)
Set the position the radiation camera is pointed toward (used to calculate camera orientation)
+
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 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 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.
@@ -6142,66 +6174,25 @@
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',...
-
helios::ObjectType getObjectType() const
Get an enumeration specifying the type of the object.
Definition Context.cpp:2247
-
void getTransformationMatrix(float(&T)[16]) const
Method to return the Affine transformation matrix of a Compound Object.
Definition Context.cpp:2503
-
Stores the state associated with simulation.
Definition Context.h:1882
-
void getPrimitiveTransformationMatrix(uint UUID, float(&T)[16]) const
Method to return the Affine transformation matrix of a Primitive.
Definition Context.cpp:7108
-
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:1406
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
-
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:1536
-
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
-
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7017
-
std::vector< uint > getAllObjectIDs() const
Get the IDs for all Compound Objects in the Context.
Definition Context.cpp:2589
-
void getObjectData(uint objID, const char *label, int &data) const
Get data associated with a compound object.
-
void getDomainBoundingSphere(helios::vec3 &center, float &radius) const
Get the center and radius of a sphere that bounds all primitives in the domain.
Definition Context.cpp:2116
-
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
-
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7159
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7175
-
bool primitiveTextureHasTransparencyChannel(uint UUID) const
Check if primitive texture map has a transparency channel.
Definition Context.cpp:7179
-
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
-
helios::vec3 getVoxelSize(uint UUID) const
Get the size of a voxel element.
Definition Context.cpp:1741
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
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:1888
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:2046
-
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)
-
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
const std::vector< std::vector< bool > > * getPrimitiveTextureTransparencyData(uint UUID) const
Get the transparency channel pixel data from primitive texture map. If transparency channel does not ...
Definition Context.cpp:7187
-
bool doesObjectExist(uint ObjID) const
Check whether Compound Object exists in the Context.
Definition Context.cpp:2585
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
-
void setGlobalData(const char *label, const int &data)
Add global data value (int)
-
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1491
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7104
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
-
helios::vec3 getVoxelCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a voxel element.
Definition Context.cpp:1750
-
bool doesPrimitiveExist(uint UUID) const
Check if primitive exists for a given UUID.
Definition Context.cpp:1659
-
Tile * getTileObjectPointer(uint ObjID) const
Get a pointer to a Tile Compound Object.
Definition Context.cpp:3312
static bool scanXMLForTag(const std::string &filename, const std::string &tag, const std::string &label="")
Scan a Helios XML file to check if a tag exists.
-
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:7122
-
HeliosDataType getObjectDataType(uint objID, const char *label) const
Get the Helios data type of primitive data.
-
helios::int2 getSubdivisionCount() const
Get the number of sub-patch divisions of the tile.
Definition Context.cpp:3343
-
std::vector< helios::vec3 > getVertices() const
Get the Cartesian coordinates of each of the four corners of the tile object.
Definition Context.cpp:3352
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:3022
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:3102
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3085
@@ -6212,24 +6203,19 @@
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
float sum(const std::vector< float > &vect)
Sum of a vector of floats.
Definition global.cpp:1069
-
uint getPrimitiveCount() const
Get the total number of Primitives in the Context.
Definition Context.cpp:1759
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor vector.
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
vec4 make_vec4(float x, float y, float z, float w)
Make a vec4 from three floats.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
Camera calibration structure used for camera calibration tasks.
-
void writeCalibratedCameraResponses(const std::vector< std::string > &camerareponselabels, const std::string &calibratemark, float scale)
Write calibrated camera response spectra.
-
float getCameraResponseScale(const std::string &cameralabel, const helios::int2 cameraresolution, const std::vector< std::string > &bandlabels, const std::vector< std::vector< float > > &truevalues)
Get camera spectral response scale.
std::vector< uint > addDefaultColorboard(const helios::vec3 &centrelocation, float patchsize=0.5, const helios::vec3 &rotationrad=helios::make_vec3(0, 0, 0))
Set reflectivity for a specific UUID.
-
void preprocessSpectra(const std::vector< std::string > &sourcelabels, const std::vector< std::string > &cameralabels, std::vector< std::string > &objectlabels, helios::vec2 &wavelengthrange, const std::string &targetlabel="")
Preprocess all spectra for modelling.
-
std::vector< float > updateCameraResponseSpectra(const std::vector< std::string > &camerareponselabels, const std::string &label, const std::map< uint, std::vector< helios::vec2 > > &simulatedinputspectra, const std::vector< std::vector< float > > &truevalues)
Update camera response spectra.
Properties defining a radiation camera.
helios::int2 camera_resolution
Camera sensor resolution (number of pixels) in the horizontal (.x) and vertical (....
float focal_plane_distance
Distance from the viewing plane to the focal plane.
float HFOV
Camera horizontal field of view in degrees.
-
float lens_diameter
Diameter of the camera lens (lens_diameter = 0 gives a 'pinhole' camera with everything in focus)
-
float FOV_aspect_ratio
Physical dimensions of the pixel array sensor in the horizontal (.x) and vertical (....
+
float lens_diameter
Diameter of the camera lens (lens_diameter = 0 gives a 'pinhole' camera with everything in focus)
+
float FOV_aspect_ratio
Ratio of horizontal to vertical camera field of view.
Properties defining a radiation band.
helios::vec2 wavebandBounds
Waveband range of band.
std::string label
Label for band.
@@ -6248,28 +6234,27 @@
const float & zenith
Zenithal angle (radians)
const float & elevation
Elevation angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
float magnitude() const
Compute the vector magnitude.
-
Vector of four elements of type 'float'.
-
float y
Second element in vector.
-
float w
Fourth element in vector.
-
float z
Third element in vector.
-
float x
First element in vector.
+
Vector of four elements of type 'float'.
- -
+ + diff --git a/doc/html/_radiation_model_8h.html b/doc/html/_radiation_model_8h.html index f2b38e873..8b200ef93 100644 --- a/doc/html/_radiation_model_8h.html +++ b/doc/html/_radiation_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Data Structures | @@ -244,7 +250,7 @@

-

Definition at line 5770 of file RadiationModel.cpp.

+

Definition at line 5795 of file RadiationModel.cpp.

@@ -263,15 +269,18 @@

-

Definition at line 5780 of file RadiationModel.cpp.

+

Definition at line 5805 of file RadiationModel.cpp.

- -
+ + diff --git a/doc/html/_radiation_model_8h.js b/doc/html/_radiation_model_8h.js new file mode 100644 index 000000000..f8de5101d --- /dev/null +++ b/doc/html/_radiation_model_8h.js @@ -0,0 +1,15 @@ +var _radiation_model_8h = +[ + [ "CameraProperties", "struct_camera_properties.html", "struct_camera_properties" ], + [ "RadiationCamera", "struct_radiation_camera.html", null ], + [ "RadiationBand", "struct_radiation_band.html", "struct_radiation_band" ], + [ "RadiationSource", "struct_radiation_source.html", "struct_radiation_source" ], + [ "RadiationModel", "class_radiation_model.html", "class_radiation_model" ], + [ "RadiationSourceType", "_radiation_model_8h.html#a87dc3655cd959da2cde2b3b72e844579", [ + [ "RADIATION_SOURCE_TYPE_COLLIMATED", "_radiation_model_8h.html#a87dc3655cd959da2cde2b3b72e844579acb49c6eb942625f5216fbba09fa8bfd7", null ], + [ "RADIATION_SOURCE_TYPE_SPHERE", "_radiation_model_8h.html#a87dc3655cd959da2cde2b3b72e844579a22e609f833c8acc7af767a68552f0300", null ], + [ "RADIATION_SOURCE_TYPE_SUN_SPHERE", "_radiation_model_8h.html#a87dc3655cd959da2cde2b3b72e844579a106569b07f26cbc989524fad65353c5c", null ], + [ "RADIATION_SOURCE_TYPE_RECTANGLE", "_radiation_model_8h.html#a87dc3655cd959da2cde2b3b72e844579a262afa7dceb5df6354a6edc0ed7bf955", null ], + [ "RADIATION_SOURCE_TYPE_DISK", "_radiation_model_8h.html#a87dc3655cd959da2cde2b3b72e844579a4e9b23fa5163fc4bccabd95abcc2c9d2", null ] + ] ] +]; \ No newline at end of file diff --git a/doc/html/_radiation_model_8h_source.html b/doc/html/_radiation_model_8h_source.html index d62207581..8d43b5e25 100644 --- a/doc/html/_radiation_model_8h_source.html +++ b/doc/html/_radiation_model_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
RadiationModel.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef RADIATION_MODEL
17#define RADIATION_MODEL
18
@@ -118,25 +125,25 @@
26#include <optixu/optixpp_namespace.h>
27
28#include <utility>
-
29
+
29
- +
31struct CameraProperties{
32
-
33 bool operator!=(const CameraProperties &rhs) const {
+
33 bool operator!=(const CameraProperties &rhs) const {
34 return !(rhs == *this);
35 }
-
36
+
36
-
39
+
39
-
42
+
42
44 float lens_diameter = 0.05;
-
45
+
45
47 float HFOV = 20.f;
-
48
+
48
50 float FOV_aspect_ratio = 1.f;
51
- +
52 CameraProperties(){
55 lens_diameter = 0.05;
@@ -153,12 +160,12 @@
66
67};
-
68
+
68
- +
70struct RadiationCamera{
71
72 //Constructor
-
73 RadiationCamera(std::string initlabel, const std::vector<std::string> &band_label, const helios::vec3 &initposition, const helios::vec3 &initlookat, const helios::int2 &initresolution, float initlens_diameter, float initfocal_length, float intitHFOV_degrees, float initFOV_aspect_ratio,
+
73 RadiationCamera(std::string initlabel, const std::vector<std::string> &band_label, const helios::vec3 &initposition, const helios::vec3 &initlookat, const helios::int2 &initresolution, float initlens_diameter, float initfocal_length, float intitHFOV_degrees, float initFOV_aspect_ratio,
74 uint initantialiasing_samples)
75 : label(std::move(initlabel)), band_labels(band_label), position(initposition), lookat(initlookat), lens_diameter(initlens_diameter), FOV_aspect_ratio(initFOV_aspect_ratio), resolution(initresolution), focal_length(initfocal_length), HFOV_degrees(intitHFOV_degrees), antialiasing_samples(initantialiasing_samples)
76 {
@@ -197,11 +204,11 @@
109
110};
-
111
+
111
- +
114public:
-
115
+
115
117 explicit RadiationBand( std::string a_label, size_t directRayCount_default, size_t diffuseRayCount_default, float diffuseFlux_default, uint scatteringDepth_default, float minScatterEnergy_default ) : label(std::move(a_label)) {
118 directRayCount = directRayCount_default;
@@ -216,31 +223,31 @@
128 }
-
129
+
129
131 std::string label;
-
132
+
132
-
135
+
135
-
138
+
138
-
141
+
141
-
144
+
144
-
147
+
147
-
150
+
150
152 std::vector<helios::vec2> diffuse_spectrum;
-
153
+
153
-
156
+
156
-
159
+
159
-
162
+
162
-
165
+
165
168
169private:
@@ -248,7 +255,7 @@
171
172};
-
173
+
173
176 RADIATION_SOURCE_TYPE_COLLIMATED = 0,
@@ -258,11 +265,11 @@
180 RADIATION_SOURCE_TYPE_DISK = 4
181};
-
182
+
182
- +
185public:
-
186
+
186
188 explicit RadiationSource( const helios::vec3 &position) : source_position(position){
189 source_type = RADIATION_SOURCE_TYPE_COLLIMATED;
@@ -272,7 +279,7 @@
194 };
-
195
+
195
197 RadiationSource( const helios::vec3 &position, float width ) : source_position(position){
198 source_type = RADIATION_SOURCE_TYPE_SPHERE;
@@ -284,7 +291,7 @@
205 };
-
206
+
206
208 RadiationSource( const helios::vec3 &position, float position_scaling_factor, float width, float flux_scaling_factor ) : source_position(position), source_position_scaling_factor(position_scaling_factor), source_flux_scaling_factor(flux_scaling_factor){
209 source_type = RADIATION_SOURCE_TYPE_SUN_SPHERE;
@@ -292,7 +299,7 @@
211 };
212
-
213
+
213
215 RadiationSource( const helios::vec3 &position, const helios::vec2 &size, const helios::vec3 &rotation ) : source_position(position), source_width(size), source_rotation(rotation){
216 source_type = RADIATION_SOURCE_TYPE_RECTANGLE;
@@ -302,7 +309,7 @@
221 };
-
222
+
222
224 RadiationSource( const helios::vec3 &position, float width, const helios::vec3 &rotation ) : source_position(position), source_rotation(rotation){
225 source_type = RADIATION_SOURCE_TYPE_DISK;
@@ -314,347 +321,347 @@
232 };
-
233
+
233
-
236
+
236
-
239
+
239
241 std::vector<helios::vec2> source_spectrum;
242
243 std::string source_spectrum_label = "none";
-
244
+
244
-
247
+
247
-
250
+
250
-
253
+
253
-
256
+
256
258 std::map<std::string,float> source_fluxes;
259
260};
-
261
+
261
- +
264public:
-
265
+
265
267 explicit RadiationModel( helios::Context* context );
-
268
+
268
-
271
-
273
+
271
+
273
274 int selfTest();
-
275
-
277
+
275
+
277
278 void disableMessages();
-
279
+
279
281 void enableMessages();
-
282
-
284
+
282
+
284
287 void optionalOutputPrimitiveData( const char* label );
-
288
-
290
+
288
+
290
294 void setDirectRayCount(const std::string &label, size_t N );
-
295
-
297
+
295
+
297
301 void setDiffuseRayCount(const std::string &label, size_t N );
-
302
-
304
+
302
+
304
308 void setDiffuseRadiationFlux(const std::string &label, float flux );
-
309
-
311
+
309
+
311
316 void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::vec3 &peak_dir );
-
317
-
319
+
317
+
319
324 void setDiffuseRadiationExtinctionCoeff(const std::string &label, float K, const helios::SphericalCoord &peak_dir );
-
325
-
327
+
325
+
327
331 void setDiffuseSpectrumIntegral( float spectrum_integral);
-
332
-
334
+
332
+
334
338 void setDiffuseSpectrumIntegral( float spectrum_integral, float wavelength1, float wavelength2);
-
339
-
341
+
339
+
341
346 void setDiffuseSpectrumIntegral( const std::string &band_label, float spectrum_integral);
-
347
-
349
+
347
+
349
354 void setDiffuseSpectrumIntegral( const std::string &band_label, float spectrum_integral, float wavelength1, float wavelength2);
-
355
-
357
+
355
+
357
361 void addRadiationBand(const std::string &label );
-
362
-
364
+
362
+
364
369 void addRadiationBand( const std::string &label, float wavelength_min, float wavelength_max );
-
370
-
372
+
370
+
372
376 void copyRadiationBand(const std::string &old_label, const std::string &new_label );
-
377
-
379
+
377
+
379
385 void copyRadiationBand(const std::string &old_label, const std::string &new_label, float wavelength_min, float wavelength_max );
-
386
-
388
+
386
+
388
391 bool doesBandExist(const std::string &label ) const;
-
392
-
394
+
392
+
394
397 void disableEmission(const std::string &label );
-
398
-
400
+
398
+
400
403 void enableEmission(const std::string &label );
-
404
-
406
+
404
+
406
-
410
-
412
+
410
+
412
-
417
-
419
+
417
+
419
423 uint addCollimatedRadiationSource(const helios::vec3 &direction );
-
424
-
426
+
424
+
426
432 uint addSphereRadiationSource(const helios::vec3 &position, float radius );
-
433
-
435
+
433
+
435
-
439
-
441
+
439
+
441
445 uint addSunSphereRadiationSource(const helios::SphericalCoord &sun_direction );
-
446
-
448
+
446
+
448
452 uint addSunSphereRadiationSource(const helios::vec3 &sun_direction );
-
453
-
455
+
453
+
455
461 uint addRectangleRadiationSource( const helios::vec3 &position, const helios::vec2 &size, const helios::vec3& rotation );
-
462
-
464
+
462
+
464
470 uint addDiskRadiationSource( const helios::vec3 &position, float radius, const helios::vec3& rotation );
-
471
-
473
+
471
+
473
476 void deleteRadiationSource(uint sourceID);
-
477
-
479
+
477
+
479
484 void setSourceSpectrumIntegral(uint source_ID, float source_integral);
-
485
-
487
+
485
+
487
492 void setSourceSpectrumIntegral(uint source_ID, float source_integral, float wavelength1, float wavelength2);
-
493
-
495
+
493
+
495
500 void setSourceFlux(uint source_ID, const std::string &band_label, float flux );
-
501
-
503
+
501
+
503
508 void setSourceFlux(const std::vector<uint> &source_ID, const std::string &band_label, float flux );
-
509
-
511
+
509
+
511
516 float getSourceFlux(uint source_ID, const std::string &band_label )const;
-
517
-
519
+
517
+
519
523 void setSourcePosition(uint source_ID, const helios::vec3 &position );
-
524
-
526
+
524
+
526
530 void setSourcePosition(uint source_ID, const helios::SphericalCoord &position );
-
531
-
533
+
531
+
533
537 helios::vec3 getSourcePosition(uint source_ID )const;
-
538
-
540
+
538
+
540
544 void setSourceSpectrum(uint source_ID, const std::vector<helios::vec2> &spectrum );
-
545
-
547
+
545
+
547
551 void setSourceSpectrum(const std::vector<uint> &source_ID, const std::vector<helios::vec2> &spectrum );
-
552
-
554
+
552
+
554
558 void setSourceSpectrum(uint source_ID, const std::string &spectrum_label );
-
559
-
561
+
559
+
561
565 void setSourceSpectrum(const std::vector<uint> &source_ID, const std::string &spectrum_label );
-
566
-
568
+
566
+
568
571 void setDiffuseSpectrum( const std::string &spectrum_label );
-
572
-
574
+
572
+
574
578 void setDiffuseSpectrum( const std::string &band_label, const std::string &spectrum_label );
-
579
-
581
+
579
+
581
585 float getDiffuseFlux( const std::string &band_label ) const;
-
586
+
586
-
589
+
589
-
592
+
592
-
595
+
595
-
598
-
600
+
598
+
600
606 float integrateSpectrum( const std::vector<helios::vec2> &object_spectrum, float wavelength1, float wavelength2 ) const;
-
607
-
609
+
607
+
609
613 float integrateSpectrum( const std::vector<helios::vec2> &object_spectrum) const;
-
614
-
616
+
614
+
616
623 float integrateSpectrum(uint source_ID, const std::vector<helios::vec2> &object_spectrum, float wavelength1, float wavelength2 ) const;
-
624
-
626
+
624
+
626
632 float integrateSpectrum(uint source_ID, const std::vector<helios::vec2> &object_spectrum, const std::vector<helios::vec2> &camera_spectrum ) const;
-
633
-
635
+
633
+
635
640 float integrateSpectrum( const std::vector<helios::vec2> &object_spectrum, const std::vector<helios::vec2> &camera_spectrum ) const;
-
641
-
643
+
641
+
643
649 float integrateSourceSpectrum( uint source_ID, float wavelength1, float wavelength2 ) const;
-
650
-
652
+
650
+
652
657 void scaleSpectrum( const std::string &existing_global_data_label, const std::string &new_global_data_label, float scale_factor ) const;
-
658
-
660
+
658
+
660
664 void scaleSpectrum( const std::string &global_data_label, float scale_factor ) const;
-
665
-
667
+
665
+
667
673 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;
-
674
-
676
+
674
+
676
682 void blendSpectra( const std::string &new_spectrum_label, const std::vector<std::string> &spectrum_labels, const std::vector<float> &weights ) const;
-
683
-
685
+
683
+
685
690 void blendSpectraRandomly( const std::string &new_spectrum_label, const std::vector<std::string> &spectrum_labels ) const;
-
691
-
693
+
691
+
693
697 void setScatteringDepth(const std::string &label, uint depth );
-
698
-
700
+
698
+
700
704 void setMinScatterEnergy(const std::string &label, uint energy );
-
705
-
707
+
705
+
707
711 void enforcePeriodicBoundary(const std::string &boundary );
-
712
-
714
+
712
+
714
722 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);
-
723
-
725
+
723
+
725
733 void addRadiationCamera(const std::string &camera_label, const std::vector<std::string> &band_label, const helios::vec3 &position, const helios::SphericalCoord &viewing_direction, const CameraProperties &camera_properties, uint antialiasing_samples);
734
-
735
-
737
+
735
+
737
743 void setCameraSpectralResponse( const std::string &camera_label, const std::string &band_label, const std::string &global_data );
-
744
-
746
+
744
+
746
750 void setCameraPosition( const std::string &camera_label, const helios::vec3& position );
-
751
-
753
+
751
+
753
757 helios::vec3 getCameraPosition(const std::string &camera_label) const;
-
758
-
760
+
758
+
760
764 void setCameraLookat( const std::string &camera_label, const helios::vec3& lookat );
-
765
-
767
+
765
+
767
771 helios::vec3 getCameraLookat(const std::string &camera_label) const;
-
772
-
774
+
772
+
774
778 void setCameraOrientation( const std::string &camera_label, const helios::vec3& direction );
-
779
-
781
+
779
+
781
785 void setCameraOrientation( const std::string &camera_label, const helios::SphericalCoord& direction );
-
786
-
788
+
786
+
788
792 helios::SphericalCoord getCameraOrientation(const std::string &camera_label) const;
-
793
-
795
+
793
+
795
798 std::vector<std::string> getAllCameraLabels();
-
799
-
801
+
799
+
801
805 void updateGeometry();
-
806
-
808
+
806
+
808
813 void updateGeometry( const std::vector<uint>& UUIDs );
-
814
-
816
+
814
+
816
820 void runBand( const std::string &label );
-
821
-
823
+
821
+
823
827 void runBand( const std::vector<std::string> &labels );
-
828
+
828
830 std::vector<float> getTotalAbsorbedFlux();
-
831
+
831
833 float getSkyEnergy();
-
834
-
836
+
834
+
836
841 float calculateGtheta(helios::Context* context, helios::vec3 view_direction );
842
843 void setCameraCalibration(CameraCalibration *CameraCalibration);
-
844
-
846
+
844
+
846
854 void updateCameraResponse(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels_raw,
855 const std::vector<std::string>& cameraresponselabels, helios::vec2 &wavelengthrange,
856 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
-
857
-
859
+
857
+
859
868 float getCameraResponseScale(const std::string &orginalcameralabel, const std::vector<std::string>& cameraresponselabels,
869 const std::vector<std::string>& bandlabels, const std::vector<std::string> &sourcelabels,
870 helios::vec2 &wavelengthrange, const std::vector<std::vector<float>> &truevalues);
-
871
-
873
+
871
+
873
883 void runRadiationImaging(const std::string& cameralabel, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
884 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
885 float fluxscale = 1, float diffusefactor = 0.0005, uint scatteringdepth = 4);
-
886
-
888
+
886
+
888
898 void runRadiationImaging(const std::vector<std::string>& cameralabels, const std::vector<std::string>& sourcelabels, const std::vector<std::string>& bandlabels,
899 const std::vector<std::string>& cameraresponselabels, helios::vec2 wavelengthrange,
900 float fluxscale = 1, float diffusefactor = 0.0005, uint scatteringdepth = 4);
-
901
-
903
+
901
+
903
911 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);
-
912
-
914
+
912
+
914
921 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);
-
922
-
924
+
922
+
924
931 void writeCameraImageData(const std::string &camera, const std::string &band, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
-
932
-
934
+
932
+
934
942 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);
-
943
-
945
+
943
+
945
953 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);
-
954
-
956
+
954
+
956
962 void writeDepthImageData(const std::string &cameralabel, const std::string &imagefile_base, const std::string &image_path = "./", int frame = -1);
-
963
-
965
+
963
+
965
972 void writeNormDepthImage(const std::string &cameralabel, const std::string &imagefile_base, float max_depth, const std::string &image_path = "./", int frame = -1);
-
973
-
975
+
973
+
975
983 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);
-
984
-
986
+
984
+
986
994 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);
-
995
-
997
+
995
+
997
1002 void setPadValue(const std::string &cameralabel, const std::vector<std::string> &bandlabels, const std::vector<float> &padvalues);
-
1003
-
1005
+
1003
+
1005
1015 void calibrateCamera(const std::string &orginalcameralabel, const std::vector<std::string> &sourcelabels,
1016 const std::vector<std::string>& cameraresponselabels, const std::vector<std::string> &bandlabels, const float scalefactor,
1017 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
-
1018
-
1020
+
1018
+
1020
1027 void calibrateCamera(const std::string &originalcameralabel, const float scalefactor,
1028 const std::vector<std::vector<float>> &truevalues, const std::string &calibratedmark);
1029
1030
1031
1032protected:
-
1033
+
1033
1035 bool message_flag;
-
1036
+
1036
1038 helios::Context* context;
1039
1040 CameraCalibration *cameracalibration;
1041 bool calibration_flag = false;
-
1042
+
1042
1044 std::vector<uint> primitiveID;
-
1045
+
1045
1047 std::vector<uint> context_UUIDs;
1048
1049 // --- Radiation Band Variables --- //
@@ -666,151 +673,151 @@
1055 // --- radiation source variables --- //
1056
1057 std::vector<RadiationSource> radiation_sources;
-
1058
+
1058
1060 RTvariable Nsources_RTvariable;
-
1061
+
1061
1063 RTbuffer source_positions_RTbuffer;
1065 RTvariable source_positions_RTvariable;
-
1066
+
1066
1068 RTbuffer source_types_RTbuffer;
1070 RTvariable source_types_RTvariable;
-
1071
+
1071
1073 RTbuffer source_fluxes_RTbuffer;
1075 RTvariable source_fluxes_RTvariable;
-
1076
+
1076
1078 RTbuffer source_widths_RTbuffer;
1080 RTvariable source_widths_RTvariable;
1081
-
1082
+
1082
1084 RTbuffer source_rotations_RTbuffer;
1086 RTvariable source_rotations_RTvariable;
1087
1088 // --- Camera Variables --- //
-
1089
+
1089
1091 std::map<std::string,RadiationCamera> cameras;
-
1092
+
1092
1094 RTvariable camera_position_RTvariable;
-
1095
+
1095
1097 RTvariable camera_direction_RTvariable;
-
1098
+
1098
1100 RTvariable camera_lens_diameter_RTvariable;
-
1101
+
1101
1103 RTvariable FOV_aspect_RTvariable;
-
1104
+
1104
1106 RTvariable camera_focal_length_RTvariable;
-
1107
+
1107
1109 RTvariable camera_viewplane_length_RTvariable;
-
1110
+
1110
1112 RTvariable Ncameras_RTvariable;
-
1113
+
1113
1115 RTvariable camera_ID_RTvariable;
-
1116
+
1116
1118 std::map<std::string,std::vector<uint>> spectral_reflectivity_data;
-
1119
+
1119
1121 std::map<std::string,std::vector<uint>> spectral_transmissivity_data;
1122
1123 std::vector<helios::vec2> generateGaussianCameraResponse(float FWHM, float mu, float centrawavelength, const helios::int2 &wavebanrange);
1124
1125 // --- Constants and Defaults --- //
-
1126
+
1126
1128 float sigma = 5.6703744E-8;
-
1129
+
1129
1131 float scene_radius;
-
1132
+
1132
1134 float rho_default;
-
1135
+
1135
1137 float tau_default;
-
1138
+
1138
1140 float eps_default;
-
1141
+
1141
1143 float kappa_default;
-
1144
+
1144
1146 float sigmas_default;
-
1147
+
1147
1149 float temperature_default;
-
1150
+
1150
1152 size_t directRayCount_default;
-
1153
+
1153
1155 size_t diffuseRayCount_default;
-
1156
+
1156
1158 float diffuseFlux_default;
-
1159
+
1159
1161 float minScatterEnergy_default;
-
1162
+
1162
1164 uint scatteringDepth_default;
1165
1166 // --- Functions --- //
-
1167
+
1167
1169 void initializeOptiX();
-
1170
-
1172
+
1170
+
1172
1175 void updateRadiativeProperties( const std::vector<std::string> &labels );
-
1176
-
1178
+
1176
+
1178
1182 std::vector<helios::vec2> loadSpectralData( const std::string &global_data_label )const;
-
1183
-
1185
-
1187
+
1183
+
1185
+
1187
1190 std::vector<float> getOptiXbufferData( RTbuffer buffer );
-
1191
-
1193
+
1191
+
1193
1196 std::vector<double> getOptiXbufferData_d( RTbuffer buffer );
-
1197
-
1199
+
1197
+
1199
1202 std::vector<uint> getOptiXbufferData_ui( RTbuffer buffer );
1203
1204 void addBuffer( const char* name, RTbuffer& buffer, RTvariable& variable, RTbuffertype type, RTformat format, size_t dimension );
-
1205
-
1207
+
1205
+
1207
1211 void zeroBuffer1D(RTbuffer &buffer, size_t bsize );
-
1212
-
1214
+
1212
+
1214
1218 void copyBuffer1D( RTbuffer &buffer, RTbuffer &buffer_copy );
-
1219
-
1221
+
1219
+
1221
1225 void initializeBuffer1Dd(RTbuffer &buffer, const std::vector<double> &array );
-
1227
+
1227
1231 void initializeBuffer1Df(RTbuffer &buffer, const std::vector<float> &array );
-
1233
+
1233
1237 void initializeBuffer1Dfloat2(RTbuffer &buffer, const std::vector<optix::float2> &array );
-
1239
+
1239
1243 void initializeBuffer1Dfloat3(RTbuffer &buffer, const std::vector<optix::float3> &array );
-
1245
+
1245
1249 void initializeBuffer1Dfloat4(RTbuffer &buffer, const std::vector<optix::float4> &array );
-
1251
+
1251
1255 void initializeBuffer1Di(RTbuffer &buffer, const std::vector<int> &array );
-
1257
+
1257
1261 void initializeBuffer1Dui(RTbuffer &buffer, const std::vector<uint> &array );
-
1263
+
1263
1267 void initializeBuffer1Dint2(RTbuffer &buffer, const std::vector<optix::int2> &array );
-
1269
+
1269
1273 void initializeBuffer1Dint3(RTbuffer &buffer, const std::vector<optix::int3> &array );
-
1275
+
1275
1279 void initializeBuffer1Dchar(RTbuffer &buffer, const std::vector<char> &array );
-
1281
+
1281
1285 void zeroBuffer2D(RTbuffer &buffer, optix::int2 bsize );
-
1287
+
1287
1291 void initializeBuffer2Dd(RTbuffer &buffer, const std::vector<std::vector<double>> &array );
-
1293
+
1293
1297 void initializeBuffer2Df(RTbuffer &buffer, const std::vector<std::vector<float>> &array );
-
1299
+
1299
1303 void initializeBuffer2Dfloat2(RTbuffer &buffer, const std::vector<std::vector<optix::float2>> &array );
-
1305
+
1305
1309 void initializeBuffer2Dfloat3(RTbuffer &buffer, const std::vector<std::vector<optix::float3>> &array );
-
1311
+
1311
1315 void initializeBuffer2Dfloat4(RTbuffer &buffer, const std::vector<std::vector<optix::float4>> &array );
-
1317
+
1317
1321 void initializeBuffer2Di(RTbuffer &buffer, const std::vector<std::vector<int>> &array );
-
1323
+
1323
1327 void initializeBuffer2Dui(RTbuffer &buffer, const std::vector<std::vector<uint>> &array );
-
1329
+
1329
1333 void initializeBuffer2Dint2(RTbuffer &buffer, const std::vector<std::vector<optix::int2>> &array );
-
1335
+
1335
1339 void initializeBuffer2Dint3(RTbuffer &buffer, const std::vector<std::vector<optix::int3>> &array );
-
1341
+
1341
1345 void initializeBuffer2Dbool(RTbuffer &buffer, const std::vector<std::vector<bool>> &array );
-
1346
-
1348
+
1346
+
1348
1352 template <typename anytype>
1353 void initializeBuffer3D(RTbuffer &buffer, const std::vector<std::vector<std::vector<anytype>>> &array );
1354
@@ -826,69 +833,69 @@
1364 std::map<std::string,std::vector<uint>> camera_model_UUIDs;
1365
1366 /* Primary RT API objects */
-
1367
+
1367
1369 RTcontext OptiX_Context;
1371 RTprogram direct_raygen;
1373 RTprogram diffuse_raygen;
-
1374
+
1374
1376 RTprogram camera_raygen;
1378 RTprogram pixel_label_raygen;
1379
1380 /* Variables */
-
1381
+
1381
1383 RTvariable random_seed_RTvariable;
-
1384
+
1384
1386 RTvariable launch_offset_RTvariable;
-
1387
+
1387
1389 RTvariable max_scatters_RTvariable;
1390 RTbuffer max_scatters_RTbuffer;
-
1391
+
1391
1393 RTvariable Nbands_RTvariable;
-
1394
+
1394
1396 RTvariable band_launch_flag_RTvariable;
1397 RTbuffer band_launch_flag_RTbuffer;
-
1398
+
1398
1400 RTvariable Nprimitives_RTvariable;
-
1401
+
1401
1403 RTvariable diffuse_flux_RTvariable;
1404 RTbuffer diffuse_flux_RTbuffer;
-
1405
+
1405
1407 RTvariable diffuse_extinction_RTvariable;
1408 RTbuffer diffuse_extinction_RTbuffer;
-
1409
+
1409
1411 RTvariable diffuse_peak_dir_RTvariable;
1412 RTbuffer diffuse_peak_dir_RTbuffer;
-
1413
+
1413
1415 RTvariable diffuse_dist_norm_RTvariable;
1416 RTbuffer diffuse_dist_norm_RTbuffer;
-
1417
+
1417
1419 RTvariable emission_flag_RTvariable;
1420 RTbuffer emission_flag_RTbuffer;
-
1421
+
1421
1423 RTvariable bound_sphere_radius_RTvariable;
1425 RTvariable bound_sphere_center_RTvariable;
-
1426
+
1426
1428 helios::vec2 periodic_flag;
1429 RTvariable periodic_flag_RTvariable;
-
1430
+
1430
1432 RTvariable Rsky_RTvariable;
-
1433
+
1433
1435 RTbuffer rho_RTbuffer;
1437 RTvariable rho_RTvariable;
1439 RTbuffer tau_RTbuffer;
1441 RTvariable tau_RTvariable;
-
1442
+
1442
1444 RTbuffer rho_cam_RTbuffer;
1446 RTvariable rho_cam_RTvariable;
1448 RTbuffer tau_cam_RTbuffer;
1450 RTvariable tau_cam_RTvariable;
-
1451
+
1451
1453 RTbuffer primitive_type_RTbuffer;
1455 RTvariable primitive_type_RTvariable;
-
1456
+
1456
1458 RTbuffer primitive_area_RTbuffer;
1460 RTvariable primitive_area_RTvariable;
-
1461
+
1461
1463 RTbuffer patch_UUID_RTbuffer;
1464 RTbuffer triangle_UUID_RTbuffer;
1465 RTbuffer disk_UUID_RTbuffer;
@@ -901,16 +908,16 @@
1473 RTvariable tile_UUID_RTvariable;
1474 RTvariable voxel_UUID_RTvariable;
1475 RTvariable bbox_UUID_RTvariable;
-
1476
+
1476
1478 RTbuffer objectID_RTbuffer;
1480 RTvariable objectID_RTvariable;
-
1481
+
1481
1483 RTbuffer primitiveID_RTbuffer;
1485 RTvariable primitiveID_RTvariable;
-
1486
+
1486
1488 RTbuffer twosided_flag_RTbuffer;
1490 RTvariable twosided_flag_RTvariable;
-
1491
+
1491
1493 RTbuffer Rsky_RTbuffer;
1494
1495 //-- Patch Buffers --//
@@ -946,12 +953,12 @@
1525 RTvariable object_subdivisions_RTvariable;
1526
1527 /* Output Buffers */
-
1528
+
1528
1530 RTbuffer transform_matrix_RTbuffer;
1532 RTvariable transform_matrix_RTvariable;
1534 RTbuffer primitive_emission_RTbuffer;
1536 RTvariable primitive_emission_RTvariable;
-
1537
+
1537
1539 RTbuffer radiation_in_RTbuffer;
1541 RTvariable radiation_in_RTvariable;
1543 RTbuffer radiation_out_top_RTbuffer;
@@ -962,21 +969,21 @@
1553 RTvariable scatter_buff_top_RTvariable;
1555 RTbuffer scatter_buff_bottom_RTbuffer;
1557 RTvariable scatter_buff_bottom_RTvariable;
-
1558
+
1558
1560 RTbuffer radiation_in_camera_RTbuffer;
1562 RTvariable radiation_in_camera_RTvariable;
-
1563
+
1563
1565 RTbuffer scatter_buff_top_cam_RTbuffer;
1567 RTvariable scatter_buff_top_cam_RTvariable;
1569 RTbuffer scatter_buff_bottom_cam_RTbuffer;
1571 RTvariable scatter_buff_bottom_cam_RTvariable;
-
1572
+
1572
1574 RTbuffer camera_pixel_label_RTbuffer;
1576 RTvariable camera_pixel_label_RTvariable;
-
1577
+
1577
1579 RTbuffer camera_pixel_depth_RTbuffer;
1581 RTvariable camera_pixel_depth_RTvariable;
-
1582
+
1582
1584 RTbuffer maskdata_RTbuffer;
1586 RTvariable maskdata_RTvariable;
1588 RTbuffer masksize_RTbuffer;
@@ -990,7 +997,7 @@
1603
1604
1605 /* Ray Types */
-
1606
+
1606
1608 RTvariable direct_ray_type_RTvariable;
1610 RTvariable diffuse_ray_type_RTvariable;
1611
@@ -998,7 +1005,7 @@
1613 RTvariable camera_ray_type_RTvariable;
1614 //Handle to OptiX ray type for camera pixel labeling rays
1615 RTvariable pixel_label_ray_type_RTvariable;
-
1616
+
1616
1618 enum RayType { RAYTYPE_DIRECT=0, RAYTYPE_DIFFUSE=1, RAYTYPE_CAMERA=2, RAYTYPE_PIXEL_LABEL=3 };
1619
1620 /* OptiX Geometry Structures */
@@ -1020,15 +1027,15 @@
1636 RTvariable top_object;
1637 RTacceleration geometry_acceleration;
1638
-
1639
-
1641
+
1639
+
1641
1644 bool isgeometryinitialized;
1645
1646 std::vector<bool> isbandpropertyinitialized;
1647
1648 bool islightvisualizationenabled = false;
1649 bool iscameravisualizationenabled = false;
-
1650
+
1650
1652 std::vector<std::string> output_prim_data;
1653
1654 std::vector<std::string> spectral_library_files;
@@ -1052,55 +1059,54 @@
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.
+
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 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.
-
void setCameraOrientation(const std::string &camera_label, const helios::vec3 &direction)
Set the orientation of the radiation camera based on a Cartesian vector.
+
void setCameraOrientation(const std::string &camera_label, const helios::vec3 &direction)
Set the orientation of the radiation camera based on a Cartesian vector.
void scaleSpectrum(const std::string &existing_global_data_label, const std::string &new_global_data_label, float scale_factor) const
Scale an entire spectrum by a constant factor. Creates new global data for scaled spectrum.
void blendSpectraRandomly(const std::string &new_spectrum_label, const std::vector< std::string > &spectrum_labels) const
Blend one or more spectra together into a new spectrum, with random weights assigned to each input sp...
void blendSpectra(const std::string &new_spectrum_label, const std::vector< std::string > &spectrum_labels, const std::vector< float > &weights) const
Blend one or more spectra together into a new spectrum.
uint addSphereRadiationSource(const helios::vec3 &position, float radius)
Add an external source of radiation that emits from the surface of a sphere.
void enforcePeriodicBoundary(const std::string &boundary)
Use a periodic boundary condition in one or more lateral directions.
-
std::vector< std::string > getAllCameraLabels()
Get the labels for all radiation cameras that have been added to the radiation model.
+
std::vector< std::string > getAllCameraLabels()
Get the labels for all radiation cameras that have been added to the radiation model.
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.
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.
-
helios::vec3 getCameraPosition(const std::string &camera_label) const
Get the position of the radiation camera.
+
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)
+
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 setCameraLookat(const std::string &camera_label, const helios::vec3 &lookat)
Set the position the radiation camera is pointed toward (used to calculate camera orientation)
+
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 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 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.
@@ -1108,23 +1114,23 @@
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',...
-
Stores the state associated with simulation.
Definition Context.h:1882
+
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:1888
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.
Camera calibration structure used for camera calibration tasks.
@@ -1132,9 +1138,8 @@
helios::int2 camera_resolution
Camera sensor resolution (number of pixels) in the horizontal (.x) and vertical (....
float focal_plane_distance
Distance from the viewing plane to the focal plane.
float HFOV
Camera horizontal field of view in degrees.
-
float lens_diameter
Diameter of the camera lens (lens_diameter = 0 gives a 'pinhole' camera with everything in focus)
-
float FOV_aspect_ratio
Physical dimensions of the pixel array sensor in the horizontal (.x) and vertical (....
-
Properties defining a radiation band.
+
float lens_diameter
Diameter of the camera lens (lens_diameter = 0 gives a 'pinhole' camera with everything in focus)
+
float FOV_aspect_ratio
Ratio of horizontal to vertical camera field of view.
helios::vec2 wavebandBounds
Waveband range of band.
uint scatteringDepth
Scattering depth for wave band.
std::vector< helios::vec2 > diffuse_spectrum
Spectral distribution of diffuse radiation flux for wave band.
@@ -1149,8 +1154,6 @@
bool emissionFlag
Flag that determines if emission calculations are performed for wave band.
size_t diffuseRayCount
Number of diffuse rays launched per element.
size_t directRayCount
Number of direct rays launched per element.
-
Data object for a radiation camera.
-
Radiation source data object.
RadiationSource(const helios::vec3 &position, float position_scaling_factor, float width, float flux_scaling_factor)
Constructor for sun sphere radiation source.
float source_position_scaling_factor
Source position factors used to scale position in case of a sun sphere source.
RadiationSource(const helios::vec3 &position)
Constructor for collimated radiation source.
@@ -1165,14 +1168,17 @@
RadiationSource(const helios::vec3 &position, float width, const helios::vec3 &rotation)
Constructor for disk radiation source.
std::map< std::string, float > source_fluxes
Fluxes of radiation source for all bands.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of two elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_ray_tracing_8cu_8h.html b/doc/html/_ray_tracing_8cu_8h.html index ef4346373..b73ed9aa4 100644 --- a/doc/html/_ray_tracing_8cu_8h.html +++ b/doc/html/_ray_tracing_8cu_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Data Structures | @@ -482,10 +488,13 @@

+ + diff --git a/doc/html/_ray_tracing_8cu_8h.js b/doc/html/_ray_tracing_8cu_8h.js new file mode 100644 index 000000000..f09c0e174 --- /dev/null +++ b/doc/html/_ray_tracing_8cu_8h.js @@ -0,0 +1,8 @@ +var _ray_tracing_8cu_8h = +[ + [ "PerRayData", "struct_per_ray_data.html", "struct_per_ray_data" ], + [ "d_calculatePrimitiveArea", "_ray_tracing_8cu_8h.html#a216a63a21845766a5ad1fe4b8002e983", null ], + [ "d_magnitude", "_ray_tracing_8cu_8h.html#a59b52bcf03b8801f444e081e943f7138", null ], + [ "d_rotatePoint", "_ray_tracing_8cu_8h.html#af48d117e18e1319cd61b4af9ef999b01", null ], + [ "d_transformPoint", "_ray_tracing_8cu_8h.html#a515aa9bdd11a5648143611f9c9d76500", null ] +]; \ No newline at end of file diff --git a/doc/html/_ray_tracing_8cu_8h_source.html b/doc/html/_ray_tracing_8cu_8h_source.html index c15727dbe..f6d4ba17e 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
RayTracing.cu.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef M_PI
17#define M_PI 3.14159265358979323846
18#endif
@@ -112,18 +119,18 @@
20typedef unsigned int uint;
21
22void queryGPUMemory( void );
-
23
+
23
26{
-
27
+
27
29 double strength;
33 bool face;
35 float area;
37 uint seed;
39 unsigned char periodic_depth;
-
41
+
41
44 unsigned char source_ID;
45
46};
@@ -185,10 +192,11 @@
101{
102 return ((float) lcg(prev) / (float) 0x01000000);
103}
-
104
+
104
106__device__ float3 d_rotatePoint(const float3 &position, const float &theta, const float &phi) {
-
107
+
107
+
111
112 float Ry[3][3], Rz[3][3];
113
114 float st = sinf(theta);
@@ -392,7 +400,7 @@
311
312}
313
-
314
+
314
316__device__ void d_transformPoint( const float (&transform_matrix)[16], float3 &v ){
317
@@ -406,13 +414,13 @@
325
326}
-
327
+
327
329__device__ float d_magnitude( const float3 v ){
330 return sqrtf( v.x*v.x+v.y*v.y+v.z*v.z );
331}
-
332
+
332
334__device__ float d_calculatePrimitiveArea( const uint primitive_type, const float (&transform_matrix)[16] ){
335
@@ -550,14 +558,14 @@
466
467}
468
-
469static __host__ __device__ __inline__ float acos_safe( float x )
+
469static __host__ __device__ __inline__ float acos_safe( float x )
470{
471 if (x < -1.0) x = -1.0 ;
472 else if (x > 1.0) x = 1.0 ;
473 return acos(x) ;
474}
475
-
476static __host__ __device__ __inline__ float asin_safe( float x )
+
476static __host__ __device__ __inline__ float asin_safe( float x )
477{
478 if (x < -1.0) x = -1.0 ;
479 else if (x > 1.0) x = 1.0 ;
@@ -567,8 +575,6 @@
__device__ void d_transformPoint(const float(&transform_matrix)[16], float3 &v)
Function to transform a 3D point based on current affine transformation matrix on the GPU.
__device__ float d_magnitude(const float3 v)
Function to calculate the magnitude of float3 vector on the GPU.
__device__ float3 d_rotatePoint(const float3 &position, const float &theta, const float &phi)
-
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
-
float asin_safe(float x)
arcsine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:247
unsigned char source_ID
Numerical identifier for radiation source corresponding to each ray.
double strength
"strength" or amount of energy associated with the ray.
@@ -578,10 +584,13 @@
unsigned char periodic_depth
Number of periodic boundary intersections for ray.
bool face
Face of primitive from which ray was launched (true=top, false=bottom)
- -
+ + diff --git a/doc/html/_solar_position_8cpp.html b/doc/html/_solar_position_8cpp.html index 89586830c..0415ea1bd 100644 --- a/doc/html/_solar_position_8cpp.html +++ b/doc/html/_solar_position_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
SolarPosition.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file SolarPosition.cpp.

- -
+ + diff --git a/doc/html/_solar_position_8cpp_source.html b/doc/html/_solar_position_8cpp_source.html index 342580aee..7d103676d 100644 --- a/doc/html/_solar_position_8cpp_source.html +++ b/doc/html/_solar_position_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
SolarPosition.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "SolarPosition.h"
17
18using namespace std;
@@ -114,8 +121,8 @@
22 context = context_ptr;
23 UTC = context->getLocation().UTC_offset;
-
24 latitude = context->getLocation().latitude_deg;
-
25 longitude = context->getLocation().longitude_deg;
+
24 latitude = context->getLocation().latitude_deg;
+
25 longitude = context->getLocation().longitude_deg;
26}
27
@@ -199,7 +206,7 @@
102 SphericalCoord sun_dir;
103 for( uint h=1; h<=23; h++ ){
104 for( uint m=1; m<=59; m++ ){
-
105 SphericalCoord sun_dir = calculateSunDirection(make_Time(h,m,0),context->getDate());
+
105 SphericalCoord sun_dir = calculateSunDirection(make_Time(h,m,0),context->getDate());
106 if( sun_dir.elevation>0 ){
107 return make_Time(h,m);
108 }
@@ -217,7 +224,7 @@
118 // SphericalCoord sun_dir;
119 for( uint h=23; h>=1; h-- ){
120 for( uint m=59; m>=1; m-- ){
-
121 SphericalCoord sun_dir = calculateSunDirection(make_Time(h,m,0),context->getDate());
+
121 SphericalCoord sun_dir = calculateSunDirection(make_Time(h,m,0),context->getDate());
122 if( sun_dir.elevation>0 ){
123 return make_Time(h,m);
124 }
@@ -233,9 +240,9 @@
133 float elevation;
134 if( issolarpositionoverridden ){
-
135 elevation = sun_direction.elevation;
+
135 elevation = sun_direction.elevation;
136 }else{
-
137 elevation = calculateSunDirection(context->getTime(),context->getDate()).elevation;
+
137 elevation = calculateSunDirection(context->getTime(),context->getDate()).elevation;
138 }
139 return elevation;
140}
@@ -245,9 +252,9 @@
143 float zenith;
144 if( issolarpositionoverridden ){
-
145 zenith = sun_direction.zenith;
+
145 zenith = sun_direction.zenith;
146 }else{
-
147 zenith = calculateSunDirection(context->getTime(),context->getDate()).zenith;
+
147 zenith = calculateSunDirection(context->getTime(),context->getDate()).zenith;
148 }
149 return zenith;
150}
@@ -257,9 +264,9 @@
153 float azimuth;
154 if( issolarpositionoverridden ){
-
155 azimuth = sun_direction.azimuth;
+
155 azimuth = sun_direction.azimuth;
156 }else{
-
157 azimuth = calculateSunDirection(context->getTime(),context->getDate()).azimuth;
+
157 azimuth = calculateSunDirection(context->getTime(),context->getDate()).azimuth;
158 }
159 return azimuth;
160}
@@ -271,7 +278,7 @@
164 if( issolarpositionoverridden ) {
165 sundirection = sun_direction;
166 }else{
-
167 sundirection = calculateSunDirection(context->getTime(),context->getDate());
+
167 sundirection = calculateSunDirection(context->getTime(),context->getDate());
168 }
169 return sphere2cart(sundirection);
170}
@@ -283,7 +290,7 @@
174 if( issolarpositionoverridden ) {
175 sundirection = sun_direction;
176 }else{
-
177 sundirection = calculateSunDirection(context->getTime(),context->getDate());
+
177 sundirection = calculateSunDirection(context->getTime(),context->getDate());
178 }
179 return sundirection;
180}
@@ -361,7 +368,7 @@
241 float E0_PAR=635.4;
242 float E0_NIR=709.7;
243
-
244 vec2 alpha(1.3,1.3);
+
244 vec2 alpha(1.3,1.3);
245
246 //---- Rayleigh ----//
247 //NOTE: Rayleigh scattering dominates the atmospheric attenuation, and thus variations in the model predictions are almost entirely due to pressure (and theta)
@@ -516,17 +523,17 @@
394float SolarPosition::calibrateTurbidityFromTimeseries( const std::string &timeseries_shortwave_flux_label_Wm2 ) const{
395
-
396 if( !context->doesTimeseriesVariableExist(timeseries_shortwave_flux_label_Wm2.c_str()) ){
+
396 if( !context->doesTimeseriesVariableExist(timeseries_shortwave_flux_label_Wm2.c_str()) ){
397 helios_runtime_error("ERROR (SolarPosition::calibrateTurbidityFromTimeseries): Timeseries variable " + timeseries_shortwave_flux_label_Wm2 + " does not exist.");
398 }
399
-
400 uint length = context->getTimeseriesLength(timeseries_shortwave_flux_label_Wm2.c_str() );
+
400 uint length = context->getTimeseriesLength(timeseries_shortwave_flux_label_Wm2.c_str() );
401
402 float min_flux = 1e6;
403 float max_flux = 0;
404 int max_flux_index = 0;
405 for( int t=0; t<length; t++ ){
-
406 float flux = context->queryTimeseriesData(timeseries_shortwave_flux_label_Wm2.c_str(), t );
+
406 float flux = context->queryTimeseriesData(timeseries_shortwave_flux_label_Wm2.c_str(), t );
407 if( flux<min_flux ){
408 min_flux = flux;
409 }
@@ -544,9 +551,9 @@
421
422 std::vector<float> parameters{ 101325, 300, 0.5, max_flux };
423
-
424 SolarPosition solarposition_copy( UTC, latitude, longitude, context );
-
425 Date date_max = context->queryTimeseriesDate(timeseries_shortwave_flux_label_Wm2.c_str(), max_flux_index );
-
426 Time time_max = context->queryTimeseriesTime(timeseries_shortwave_flux_label_Wm2.c_str(), max_flux_index );
+
424 SolarPosition solarposition_copy( UTC, latitude, longitude, context );
+
425 Date date_max = context->queryTimeseriesDate(timeseries_shortwave_flux_label_Wm2.c_str(), max_flux_index );
+
426 Time time_max = context->queryTimeseriesTime(timeseries_shortwave_flux_label_Wm2.c_str(), max_flux_index );
427
428 solarposition_copy.setSunDirection( solarposition_copy.calculateSunDirection( time_max, date_max) );
429
@@ -560,7 +567,7 @@
436void SolarPosition::enableCloudCalibration( const std::string &timeseries_shortwave_flux_label_Wm2 ){
437
-
438 if( !context->doesTimeseriesVariableExist( timeseries_shortwave_flux_label_Wm2.c_str()) ){
+
438 if( !context->doesTimeseriesVariableExist( timeseries_shortwave_flux_label_Wm2.c_str()) ){
439 helios_runtime_error("ERROR (SolarPosition::enableCloudCalibration): Timeseries variable " + timeseries_shortwave_flux_label_Wm2 + " does not exist.");
440 }
441
@@ -611,42 +618,35 @@
void setSunDirection(const helios::SphericalCoord &sundirection)
Override solar position calculation based on time in the Context by using a prescribed solar position...
helios::vec3 getSunDirectionVector() const
Get a unit vector pointing toward the sun for the current location. The sun angle is computed based o...
float getDiffuseFraction(float pressure_Pa, float temperature_K, float humidity_rel, float turbidity) const
Get the fraction of solar radiation flux that is diffuse.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
int getJulianDate() const
Get simulation date by Julian day.
Definition Context.cpp:1132
-
helios::Time getTime() const
Get the simulation time.
Definition Context.cpp:1166
-
helios::Date getDate() const
Get simulation date.
Definition Context.cpp:1099
helios::Location getLocation() const
Get the location of the simulation (latitude, longitude, and UTC offset)
Definition Context.cpp:1174
float fzero(float(*function)(float value, std::vector< float > &variables, const void *parameters), std::vector< float > &variables, const void *parameters, float init_guess, float err_tol=0.0001f, int max_iterations=100)
Use Newton-Raphson method to find the zero of a function.
Definition global.cpp:2977
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
float asin_safe(float x)
arcsine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:247
-
Time queryTimeseriesTime(const char *label, uint index) const
Get the time associated with a timeseries data point.
Definition Context.cpp:1958
-
uint getTimeseriesLength(const char *label) const
Get the length of timeseries data.
Definition Context.cpp:2014
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:1894
bool doesTimeseriesVariableExist(const char *label) const
Query whether a timeseries variable exists.
Definition Context.cpp:2026
-
Date queryTimeseriesDate(const char *label, uint index) const
Get the date associated with a timeseries data point.
Definition Context.cpp:1994
Time make_Time(int hour, int minute)
Make a Time vector.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
int JulianDay() const
Convert to Julian day.
Definition global.cpp:186
-
float longitude_deg
Longitude in degrees (+western hemisphere, -eastern hemisphere)
-
float latitude_deg
Latitude in degrees (+northern hemisphere, -southern hemisphere)
float UTC_offset
Offset from UTC in hours (+moving West)
Vector of spherical coordinates (elevation,azimuth)
-
const float & zenith
Zenithal angle (radians)
const float & elevation
Elevation angle (radians)
-
float azimuth
Azimuthal angle (radians)
int hour
Hour of day.
int minute
Minute of hour.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_solar_position_8h.html b/doc/html/_solar_position_8h.html index 60ce265b9..03a643c40 100644 --- a/doc/html/_solar_position_8h.html +++ b/doc/html/_solar_position_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -123,10 +129,13 @@

Definition in file SolarPosition.h.

- -
+ + diff --git a/doc/html/_solar_position_8h.js b/doc/html/_solar_position_8h.js new file mode 100644 index 000000000..bb7104b60 --- /dev/null +++ b/doc/html/_solar_position_8h.js @@ -0,0 +1,4 @@ +var _solar_position_8h = +[ + [ "SolarPosition", "class_solar_position.html", "class_solar_position" ] +]; \ No newline at end of file diff --git a/doc/html/_solar_position_8h_source.html b/doc/html/_solar_position_8h_source.html index d2c136d8b..4b657ac49 100644 --- a/doc/html/_solar_position_8h_source.html +++ b/doc/html/_solar_position_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
SolarPosition.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef SOLARPOSITION
17#define SOLARPOSITION
18
19#include "Context.h"
20
- +
22 public:
-
23
-
25
+
23
+
25
28 explicit SolarPosition( helios::Context* context_ptr );
29
-
31
+
31
37 SolarPosition(float UTC_hrs, float latitude_deg, float longitude_deg, helios::Context* context_ptr );
-
38
+
38
40 int selfTest() const;
-
41
+
41
-
44
+
44
-
47
+
47
49 float getSunElevation() const;
-
50
+
50
52 float getSunZenith() const;
-
53
+
53
55 float getSunAzimuth() const;
-
56
+
56
-
59
+
59
-
62
-
64
+
62
+
64
67 void setSunDirection( const helios::SphericalCoord &sundirection );
-
68
-
70
+
68
+
70
79 float getSolarFlux(float pressure_Pa, float temperature_K, float humidity_rel, float turbidity ) const;
-
80
-
82
+
80
+
82
91 float getSolarFluxPAR(float pressure_Pa, float temperature_K, float humidity_rel, float turbidity ) const;
-
92
-
94
+
92
+
94
103 float getSolarFluxNIR(float pressure_Pa, float temperature_K, float humidity_rel, float turbidity ) const;
-
104
-
106
+
104
+
106
113 float getDiffuseFraction(float pressure_Pa, float temperature_K, float humidity_rel, float turbidity ) const;
-
114
-
116
+
114
+
116
122 float getAmbientLongwaveFlux(float temperature_K, float humidity_rel ) const;
-
123
-
125
+
123
+
125
130 float calibrateTurbidityFromTimeseries( const std::string &timeseries_shortwave_flux_label_Wm2 ) const;
-
131
-
133
+
131
+
133
136 void enableCloudCalibration( const std::string &timeseries_shortwave_flux_label_Wm2 );
-
137
+
137
140
141 private:
@@ -189,7 +196,6 @@
164
165#endif
-
SolarPosition(helios::Context *context_ptr)
Solar position model default constructor. Initializes location based on the location set in the Conte...
void disableCloudCalibration()
Disable calibration of solar flux and diffuse fraction for clouds.
float getSunAzimuth() const
Get the current sun azimuthal angle in radians for the current location. The sun angle is computed ba...
@@ -208,16 +214,19 @@
void setSunDirection(const helios::SphericalCoord &sundirection)
Override solar position calculation based on time in the Context by using a prescribed solar position...
helios::vec3 getSunDirectionVector() const
Get a unit vector pointing toward the sun for the current location. The sun angle is computed based o...
float getDiffuseFraction(float pressure_Pa, float temperature_K, float humidity_rel, float turbidity) const
Get the fraction of solar radiation flux that is diffuse.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
Vector of spherical coordinates (elevation,azimuth)
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_solar_position_doc.html b/doc/html/_solar_position_doc.html index c17380a39..ef761b133 100644 --- a/doc/html/_solar_position_doc.html +++ b/doc/html/_solar_position_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Solar Position Plugin Documentation
@@ -308,21 +314,18 @@

The REST2 model for solar fluxes was developed for clear-sky conditions and cannot directly be used when clouds are present. If incident solar radiation data is available (e.g., from a weather station), this can be used to calibrate the model to account for the possible presence of clouds. A simple model is described below for doing so.

Consider $R_{meas,h}$ to be the measured all-wave incoming solar radiation flux on a horizontal plane (clear or cloudy conditions), and $R_{clear}$ to be the predicted all-wave incoming solar radiation flux predicted by the REST2 model for clear-sky conditions perpendicular to the direction of the sun. This flux can be projected onto the horizontal plane according to

-\[
-    R_{clear,h} = R_{clear}\mathrm{cos}\,\theta_s.
- \] +\[    R_{clear,h} = R_{clear}\mathrm{cos}\,\theta_s.
+\]

The diffuse fraction can be approximated as

-\[
-    f_{diff} = 1-\frac{R_{meas,h} - R_{clear,h}}{R_{clear,h}},
- \] +\[    f_{diff} = 1-\frac{R_{meas,h} - R_{clear,h}}{R_{clear,h}},
+\]

where it is enforced that $0\leq f_{diff} \leq 1$. The resulting flux that is output from the model is (flux perpendicular to the sun)

-\[
-   R_{model} = R_{clear}\frac{R_{meas,h}}{R_{clear,h}}.
- \] +\[   R_{model} = R_{clear}\frac{R_{meas,h}}{R_{clear,h}}.
+\]

In order to enable flux calibration for cloudy conditions, you must 1) Load timeseries data into the Context containing the measured all-wave solar radiation flux. This data must cover the entire period of the simulation. 2) Call SolarPosition::enableCloudCalibration(), which requires a string corresponding to the timeseries data value reference in (1). Below is a code example:

#include "SolarPosition"
@@ -370,10 +373,13 @@

The downwelling longwave radiation flux from the sky can be calculated using the SolarPosition::getAmbientLongwaveFlux() function. This function takes the air temperature and humidity as arguments, which are defined in the same was as for the SolarPosition::getSolarFlux() function described above. The value returned by the function is the clear-sky downwelling longwave radiation flux on a horizontal surface in W/m2.

- -
+ + diff --git a/doc/html/_stomatal_conductance_model_8cpp.html b/doc/html/_stomatal_conductance_model_8cpp.html index 4f32b41bf..660d5f581 100644 --- a/doc/html/_stomatal_conductance_model_8cpp.html +++ b/doc/html/_stomatal_conductance_model_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
StomatalConductanceModel.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file StomatalConductanceModel.cpp.

- -
+ + diff --git a/doc/html/_stomatal_conductance_model_8cpp_source.html b/doc/html/_stomatal_conductance_model_8cpp_source.html index be321fd22..fc913c73b 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
StomatalConductanceModel.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
17
18using namespace std;
@@ -177,7 +184,7 @@
82 MOPTcoefficients MOPTcoeffs;
83 BMFcoefficients BMFcoeffs;
84
-
85 StomatalConductanceModel gsm(&context_selftest);
+
85 StomatalConductanceModel gsm(&context_selftest);
86
87 float RMSE_BWB = 0.f;
88 float RMSE_BBL = 0.f;
@@ -463,7 +470,7 @@
337
-
339 run( context->getAllUUIDs() );
+
339 run( context->getAllUUIDs() );
340}
341
@@ -475,7 +482,7 @@
345
-
347 run( context->getAllUUIDs(), dt );
+
347 run( context->getAllUUIDs(), dt );
348}
349
@@ -491,7 +498,7 @@
358
359 for( uint UUID : UUIDs){
360
-
361 if( !context->doesPrimitiveExist(UUID) ){
+
361 if( !context->doesPrimitiveExist(UUID) ){
362 if( message_flag ) {
363 std::cout << "WARNING (StomatalConductance::run): primitive " << UUID << " does not exist in the Context." << std::endl;
364 }
@@ -500,15 +507,15 @@
367
368 //PAR radiation flux (W/m^2)
369 float i = i_default;
-
370 if( context->doesPrimitiveDataExist(UUID,"radiation_flux_PAR") && context->getPrimitiveDataType(UUID,"radiation_flux_PAR")==HELIOS_TYPE_FLOAT ){
-
371 context->getPrimitiveData(UUID,"radiation_flux_PAR",i); //W/m^2
+
370 if( context->doesPrimitiveDataExist(UUID,"radiation_flux_PAR") && context->getPrimitiveDataType(UUID,"radiation_flux_PAR")==HELIOS_TYPE_FLOAT ){
+
371 context->getPrimitiveData(UUID,"radiation_flux_PAR",i); //W/m^2
372 i = i*4.57f; //umol/m^2-s (ref https://www.controlledenvironments.org/wp-content/uploads/sites/6/2017/06/Ch01.pdf)
373 }
374
375 //surface temperature (K)
376 float TL = TL_default;
-
377 if( context->doesPrimitiveDataExist(UUID,"temperature") && context->getPrimitiveDataType(UUID,"temperature")==HELIOS_TYPE_FLOAT ){
-
378 context->getPrimitiveData(UUID,"temperature",TL); //Kelvin
+
377 if( context->doesPrimitiveDataExist(UUID,"temperature") && context->getPrimitiveDataType(UUID,"temperature")==HELIOS_TYPE_FLOAT ){
+
378 context->getPrimitiveData(UUID,"temperature",TL); //Kelvin
379 if( TL<250.f ) {
380 if( message_flag ) {
381 std::cout << "WARNING (StomatalConductanceModel::run): Specified surface temperature value is very low - assuming default value instead. Did you accidentally specify temperature in Celcius instead of Kelvin?" << std::endl;
@@ -519,8 +526,8 @@
386
387 //air pressure (Pa)
388 float press = pressure_default;
-
389 if( context->doesPrimitiveDataExist(UUID,"air_pressure") && context->getPrimitiveDataType(UUID,"air_pressure")==HELIOS_TYPE_FLOAT ){
-
390 context->getPrimitiveData(UUID,"air_pressure",press); //Pa
+
389 if( context->doesPrimitiveDataExist(UUID,"air_pressure") && context->getPrimitiveDataType(UUID,"air_pressure")==HELIOS_TYPE_FLOAT ){
+
390 context->getPrimitiveData(UUID,"air_pressure",press); //Pa
391 if( press<50000 ) {
392 if( message_flag ) {
393 std::cout << "WARNING (StomatalConductanceModel::run): Specified air pressure value is very low - assuming default value instead. Did you accidentally specify pressure in kPA instead of Pa?" << std::endl;
@@ -531,8 +538,8 @@
398
399 //air temperature (K)
400 float Ta = air_temperature_default;
-
401 if( context->doesPrimitiveDataExist(UUID,"air_temperature") && context->getPrimitiveDataType(UUID,"air_temperature")==HELIOS_TYPE_FLOAT ){
-
402 context->getPrimitiveData(UUID,"air_temperature",Ta); //Kelvin
+
401 if( context->doesPrimitiveDataExist(UUID,"air_temperature") && context->getPrimitiveDataType(UUID,"air_temperature")==HELIOS_TYPE_FLOAT ){
+
402 context->getPrimitiveData(UUID,"air_temperature",Ta); //Kelvin
403 if( Ta<250.f ) {
404 if( message_flag ) {
405 std::cout << "WARNING (StomatalConductanceModel::run): Specified air temperature value is very low - assuming default value instead. Did you accidentally specify temperature in Celcius instead of Kelvin?" << std::endl;
@@ -543,11 +550,11 @@
410
411 //boundary-layer conductance to heat/moisture (mol/m^2/s)
412 float gbw = blconductance_default;
-
413 if( context->doesPrimitiveDataExist(UUID,"boundarylayer_conductance") && context->getPrimitiveDataType(UUID,"boundarylayer_conductance")==HELIOS_TYPE_FLOAT ) {
-
414 context->getPrimitiveData(UUID, "boundarylayer_conductance", gbw);
+
413 if( context->doesPrimitiveDataExist(UUID,"boundarylayer_conductance") && context->getPrimitiveDataType(UUID,"boundarylayer_conductance")==HELIOS_TYPE_FLOAT ) {
+
414 context->getPrimitiveData(UUID, "boundarylayer_conductance", gbw);
415 gbw = gbw * 1.08; //assume bl conductance to moisture is 1.08 of conductance to heat
-
416 }else if( context->doesPrimitiveDataExist(UUID,"boundarylayer_conductance_out") && context->getPrimitiveDataType(UUID,"boundarylayer_conductance_out")==HELIOS_TYPE_FLOAT ){
-
417 context->getPrimitiveData(UUID,"boundarylayer_conductance_out",gbw);
+
416 }else if( context->doesPrimitiveDataExist(UUID,"boundarylayer_conductance_out") && context->getPrimitiveDataType(UUID,"boundarylayer_conductance_out")==HELIOS_TYPE_FLOAT ){
+
417 context->getPrimitiveData(UUID,"boundarylayer_conductance_out",gbw);
418 gbw = gbw*1.08; //assume bl conductance to moisture is 1.08 of conductance to heat
419 }
420 if( gbw<0 ){
@@ -559,14 +566,14 @@
426
427 //beta soil moisture factor
428 float beta = beta_default;
-
429 if( context->doesPrimitiveDataExist(UUID,"beta_soil") && context->getPrimitiveDataType(UUID,"beta_soil")==HELIOS_TYPE_FLOAT ){
-
430 context->getPrimitiveData(UUID,"beta_soil",beta);
+
429 if( context->doesPrimitiveDataExist(UUID,"beta_soil") && context->getPrimitiveDataType(UUID,"beta_soil")==HELIOS_TYPE_FLOAT ){
+
430 context->getPrimitiveData(UUID,"beta_soil",beta);
431 }
432
433 //air humidity
434 float rh = air_humidity_default;
-
435 if( context->doesPrimitiveDataExist(UUID,"air_humidity") && context->getPrimitiveDataType(UUID,"air_humidity")==HELIOS_TYPE_FLOAT ){
-
436 context->getPrimitiveData(UUID,"air_humidity",rh);
+
435 if( context->doesPrimitiveDataExist(UUID,"air_humidity") && context->getPrimitiveDataType(UUID,"air_humidity")==HELIOS_TYPE_FLOAT ){
+
436 context->getPrimitiveData(UUID,"air_humidity",rh);
437 if( rh>1.f ) {
438 if( message_flag ) {
439 std::cout << "WARNING (StomatalConductanceModel::run): Specified air humidity value is greater than 1 - clamping to 1. Did you accidentally specify in percent instead of a decimal?" << std::endl;
@@ -589,23 +596,23 @@
456 if( model == "BWB" || model == "BBL" || model == "MOPT" ){
457
458 //net photosynthesis
-
459 if( context->doesPrimitiveDataExist(UUID,"net_photosynthesis") && context->getPrimitiveDataType(UUID,"net_photosynthesis")==HELIOS_TYPE_FLOAT ) {
-
460 context->getPrimitiveData(UUID, "net_photosynthesis", An);
+
459 if( context->doesPrimitiveDataExist(UUID,"net_photosynthesis") && context->getPrimitiveDataType(UUID,"net_photosynthesis")==HELIOS_TYPE_FLOAT ) {
+
460 context->getPrimitiveData(UUID, "net_photosynthesis", An);
461 }else{
462 assumed_default_An++;
463 }
464
465 //CO2 compensation point - Gamma
-
466 if( context->doesPrimitiveDataExist(UUID,"Gamma_CO2") && context->getPrimitiveDataType(UUID,"Gamma_CO2")==HELIOS_TYPE_FLOAT ) {
-
467 context->getPrimitiveData(UUID, "Gamma_CO2", Gamma);
+
466 if( context->doesPrimitiveDataExist(UUID,"Gamma_CO2") && context->getPrimitiveDataType(UUID,"Gamma_CO2")==HELIOS_TYPE_FLOAT ) {
+
467 context->getPrimitiveData(UUID, "Gamma_CO2", Gamma);
468 }else{
469 assumed_default_Gamma++;
470 }
471
472 //ambient air CO2
473 float Ca = air_CO2_default;
-
474 if( context->doesPrimitiveDataExist(UUID,"air_CO2") && context->getPrimitiveDataType(UUID,"air_CO2")==HELIOS_TYPE_FLOAT ){
-
475 context->getPrimitiveData(UUID,"air_CO2",Ca);
+
474 if( context->doesPrimitiveDataExist(UUID,"air_CO2") && context->getPrimitiveDataType(UUID,"air_CO2")==HELIOS_TYPE_FLOAT ){
+
475 context->getPrimitiveData(UUID,"air_CO2",Ca);
476 }
477
478 float gbc = 0.75f*gbw; //bl conductance to CO2
@@ -618,8 +625,8 @@
485 float Psix = xylem_potential_default;
486 if( model == "BB" ){
487 //xylem moisture potential
-
488 if( context->doesPrimitiveDataExist(UUID,"xylem_water_potential") && context->getPrimitiveDataType(UUID,"xylem_water_potential")==HELIOS_TYPE_FLOAT ){
-
489 context->getPrimitiveData(UUID,"xylem_water_potential",Psix);
+
488 if( context->doesPrimitiveDataExist(UUID,"xylem_water_potential") && context->getPrimitiveDataType(UUID,"xylem_water_potential")==HELIOS_TYPE_FLOAT ){
+
489 context->getPrimitiveData(UUID,"xylem_water_potential",Psix);
490 }
491 }
492
@@ -724,7 +731,7 @@
591
592 for( const auto &data : output_prim_data ){
593 if( data=="vapor_pressure_deficit" ) {
-
594 context->setPrimitiveData(UUID, "vapor_pressure_deficit", Ds);
+
594 context->setPrimitiveData(UUID, "vapor_pressure_deficit", Ds);
595 }
596 }
597
@@ -738,10 +745,10 @@
605
606 if( !dynamic_time_constants.empty() && (dynamic_time_constants.find(UUID)!=dynamic_time_constants.end() || dynamic_time_constants.find(0)!=dynamic_time_constants.end() ) ) {
607
-
608 if (context->doesPrimitiveDataExist(UUID, "moisture_conductance") && context->getPrimitiveDataType(UUID, "moisture_conductance") == HELIOS_TYPE_FLOAT) {
+
608 if (context->doesPrimitiveDataExist(UUID, "moisture_conductance") && context->getPrimitiveDataType(UUID, "moisture_conductance") == HELIOS_TYPE_FLOAT) {
609
610 float gs_old;
-
611 context->getPrimitiveData(UUID, "moisture_conductance", gs_old);
+
611 context->getPrimitiveData(UUID, "moisture_conductance", gs_old);
612
613 float gs_ss = gs;
614
@@ -776,7 +783,7 @@
643
644 }
645
-
646 context->setPrimitiveData( UUID, "moisture_conductance", gs);
+
646 context->setPrimitiveData( UUID, "moisture_conductance", gs);
647
648 }
649
@@ -838,7 +845,7 @@
704
705 // We want to find the vapor pressure at the surface, esurf, that balances the equation gs(esurf)*(es-esurf) = gbw*(esurf-ea). This function returns the residual of this equation.
706
-
707 const auto* coeffs = reinterpret_cast<const BBLcoefficients*>(parameters);
+
707 const auto* coeffs = reinterpret_cast<const BBLcoefficients*>(parameters);
708
709 float gs0 = coeffs->gs0;
710 float a1 = coeffs->a1;
@@ -864,7 +871,7 @@
730
731 // We want to find the vapor pressure at the surface, esurf, that balances the equation gs(esurf)*(es-esurf) = gbw*(esurf-ea). This function returns the residual of this equation.
732
-
733 const auto* coeffs = reinterpret_cast<const MOPTcoefficients*>(parameters);
+
733 const auto* coeffs = reinterpret_cast<const MOPTcoefficients*>(parameters);
734
735 float gs0 = coeffs->gs0;
736 float g1 = coeffs->g1;
@@ -887,7 +894,7 @@
753
754 // We want to find the vapor pressure at the surface, esurf, that balances the equation gs(esurf)*(es-esurf) = gbw*(esurf-ea). This function returns the residual of this equation.
755
-
756 const auto* coeffs = reinterpret_cast<const BMFcoefficients*>(parameters);
+
756 const auto* coeffs = reinterpret_cast<const BMFcoefficients*>(parameters);
757
758 float Em = coeffs->Em;
759 float i0 = coeffs->i0;
@@ -913,7 +920,7 @@
779 float fe = 0.5;
780 float Rxe = 200.f;
781
-
782 const auto* coeffs = reinterpret_cast<const BBcoefficients*>(parameters);
+
782 const auto* coeffs = reinterpret_cast<const BBcoefficients*>(parameters);
783
784 float pi_0 = coeffs->pi_0;
785 float pi_m = coeffs->pi_m;
@@ -963,7 +970,7 @@
823
827
@@ -986,44 +993,44 @@
843
844 for (uint UUID: UUIDs) {
845
-
846 if (!context->doesPrimitiveDataExist(UUID, "radiation_flux_PAR") ||
-
847 context->getPrimitiveDataType(UUID, "radiation_flux_PAR") != HELIOS_TYPE_FLOAT) {
+
846 if (!context->doesPrimitiveDataExist(UUID, "radiation_flux_PAR") ||
+
847 context->getPrimitiveDataType(UUID, "radiation_flux_PAR") != HELIOS_TYPE_FLOAT) {
848 assumed_default_i++;
849 }
850
851 //surface temperature (K)
-
852 if (!context->doesPrimitiveDataExist(UUID, "temperature") ||
-
853 context->getPrimitiveDataType(UUID, "temperature") != HELIOS_TYPE_FLOAT) {
+
852 if (!context->doesPrimitiveDataExist(UUID, "temperature") ||
+
853 context->getPrimitiveDataType(UUID, "temperature") != HELIOS_TYPE_FLOAT) {
854 assumed_default_TL++;
855 }
856
857 //air pressure (Pa)
-
858 if (!context->doesPrimitiveDataExist(UUID, "air_pressure") ||
-
859 context->getPrimitiveDataType(UUID, "air_pressure") != HELIOS_TYPE_FLOAT) {
+
858 if (!context->doesPrimitiveDataExist(UUID, "air_pressure") ||
+
859 context->getPrimitiveDataType(UUID, "air_pressure") != HELIOS_TYPE_FLOAT) {
860 assumed_default_p++;
861 }
862
863 //air temperature (K)
-
864 if (!context->doesPrimitiveDataExist(UUID, "air_temperature") ||
-
865 context->getPrimitiveDataType(UUID, "air_temperature") != HELIOS_TYPE_FLOAT) {
+
864 if (!context->doesPrimitiveDataExist(UUID, "air_temperature") ||
+
865 context->getPrimitiveDataType(UUID, "air_temperature") != HELIOS_TYPE_FLOAT) {
866 assumed_default_Ta++;
867 }
868
869 //air humidity
-
870 if (!context->doesPrimitiveDataExist(UUID, "air_humidity") ||
-
871 context->getPrimitiveDataType(UUID, "air_humidity") != HELIOS_TYPE_FLOAT) {
+
870 if (!context->doesPrimitiveDataExist(UUID, "air_humidity") ||
+
871 context->getPrimitiveDataType(UUID, "air_humidity") != HELIOS_TYPE_FLOAT) {
872 assumed_default_rh++;
873 }
874
875 //boundary-layer conductance to heat/moisture (mol/m^2/s)
-
876 if ((!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance") || context->getPrimitiveDataType(UUID, "boundarylayer_conductance") != HELIOS_TYPE_FLOAT) &&
-
877 (!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance_out") || context->getPrimitiveDataType(UUID, "boundarylayer_conductance_out") != HELIOS_TYPE_FLOAT)) {
+
876 if ((!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance") || context->getPrimitiveDataType(UUID, "boundarylayer_conductance") != HELIOS_TYPE_FLOAT) &&
+
877 (!context->doesPrimitiveDataExist(UUID, "boundarylayer_conductance_out") || context->getPrimitiveDataType(UUID, "boundarylayer_conductance_out") != HELIOS_TYPE_FLOAT)) {
878 assumed_default_gbw++;
879 }
880
881 //beta soil moisture factor
-
882 if (!context->doesPrimitiveDataExist(UUID, "beta_soil") ||
-
883 context->getPrimitiveDataType(UUID, "beta_soil") != HELIOS_TYPE_FLOAT) {
+
882 if (!context->doesPrimitiveDataExist(UUID, "beta_soil") ||
+
883 context->getPrimitiveDataType(UUID, "beta_soil") != HELIOS_TYPE_FLOAT) {
884 assumed_default_beta++;
885 }
886
@@ -1031,26 +1038,26 @@
888 if (model == "BWB" || model == "BBL" || model == "MOPT") {
889
890 //net photosynthesis
-
891 if (!context->doesPrimitiveDataExist(UUID, "net_photosynthesis") ||
-
892 context->getPrimitiveDataType(UUID, "net_photosynthesis") != HELIOS_TYPE_FLOAT) {
+
891 if (!context->doesPrimitiveDataExist(UUID, "net_photosynthesis") ||
+
892 context->getPrimitiveDataType(UUID, "net_photosynthesis") != HELIOS_TYPE_FLOAT) {
893 assumed_default_An++;
894 }
895
896 //CO2 compensation point - Gamma
-
897 if (!context->doesPrimitiveDataExist(UUID, "Gamma_CO2") ||
-
898 context->getPrimitiveDataType(UUID, "Gamma_CO2") != HELIOS_TYPE_FLOAT) {
+
897 if (!context->doesPrimitiveDataExist(UUID, "Gamma_CO2") ||
+
898 context->getPrimitiveDataType(UUID, "Gamma_CO2") != HELIOS_TYPE_FLOAT) {
899 assumed_default_Gamma++;
900 }
901
902 //ambient air CO2
-
903 if (!context->doesPrimitiveDataExist(UUID, "air_CO2") ||
-
904 context->getPrimitiveDataType(UUID, "air_CO2") != HELIOS_TYPE_FLOAT) {
+
903 if (!context->doesPrimitiveDataExist(UUID, "air_CO2") ||
+
904 context->getPrimitiveDataType(UUID, "air_CO2") != HELIOS_TYPE_FLOAT) {
905 assumed_default_CO2++;
906 }
907 }else if( model == "BB" ){
908 //xylem moisture potential
-
909 if (!context->doesPrimitiveDataExist(UUID, "xylem_water_potential") ||
-
910 context->getPrimitiveDataType(UUID, "xylem_water_potential") != HELIOS_TYPE_FLOAT) {
+
909 if (!context->doesPrimitiveDataExist(UUID, "xylem_water_potential") ||
+
910 context->getPrimitiveDataType(UUID, "xylem_water_potential") != HELIOS_TYPE_FLOAT) {
911 assumed_default_Psix++;
912 }
913 }
@@ -1082,7 +1089,6 @@
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
-
void setDynamicTimeConstants(float tau_open, float tau_close)
Set time constants for dynamic stomatal opening and closing for all primitives.
void disableMessages()
Disable output messages to the standard output.
void printDefaultValueReport() const
Print a report detailing usage of default input values for all primitives in the Context.
@@ -1094,13 +1100,9 @@
void run()
Update the stomatal conductance for all primitives in the context.
BMFcoefficients getBMFCoefficientsFromLibrary(const std::string &species)
Get the model coefficient values using one of the available species in the library.
void setModelCoefficients(const BWBcoefficients &coeffs)
Set the model coefficient values for all primitives - Ball, Woodrow, Berry model.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
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 > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
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:1659
float fzero(float(*function)(float value, std::vector< float > &variables, const void *parameters), std::vector< float > &variables, const void *parameters, float init_guess, float err_tol=0.0001f, int max_iterations=100)
Use Newton-Raphson method to find the zero of a function.
Definition global.cpp:2977
float max(const std::vector< float > &vect)
Maximum value of a vector of floats.
Definition global.cpp:1146
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212
@@ -1111,10 +1113,13 @@
Coefficients for original Ball, Woodrow, Berry (1987) stomatal conductance model.
Coefficients for optimality-based Medlyn et al. (2011) stomatal conductance model.
- -
+ + diff --git a/doc/html/_stomatal_conductance_model_8h.html b/doc/html/_stomatal_conductance_model_8h.html index c509a1b23..031d4882f 100644 --- a/doc/html/_stomatal_conductance_model_8h.html +++ b/doc/html/_stomatal_conductance_model_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -138,10 +144,13 @@

Definition in file StomatalConductanceModel.h.

- -
+ + diff --git a/doc/html/_stomatal_conductance_model_8h.js b/doc/html/_stomatal_conductance_model_8h.js new file mode 100644 index 000000000..266b6b1b0 --- /dev/null +++ b/doc/html/_stomatal_conductance_model_8h.js @@ -0,0 +1,9 @@ +var _stomatal_conductance_model_8h = +[ + [ "BWBcoefficients", "struct_b_w_bcoefficients.html", null ], + [ "BBLcoefficients", "struct_b_b_lcoefficients.html", null ], + [ "MOPTcoefficients", "struct_m_o_p_tcoefficients.html", null ], + [ "BMFcoefficients", "struct_b_m_fcoefficients.html", null ], + [ "BBcoefficients", "struct_b_bcoefficients.html", null ], + [ "StomatalConductanceModel", "class_stomatal_conductance_model.html", "class_stomatal_conductance_model" ] +]; \ No newline at end of file diff --git a/doc/html/_stomatal_conductance_model_8h_source.html b/doc/html/_stomatal_conductance_model_8h_source.html index bff51f67b..b216550d5 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
StomatalConductanceModel.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef STOMATAL_CONDUCTANCE
17#define STOMATAL_CONDUCTANCE
18
19#include "Context.h"
-
20
+
20
- +
22struct BWBcoefficients{
23
- +
24 BWBcoefficients(){
25 gs0 = 0.0733;
26 a1 = 9.422;
27 }
@@ -123,11 +130,11 @@
31
32};
-
33
+
33
- +
35struct BBLcoefficients{
36
- +
37 BBLcoefficients(){
38 gs0 = 0.0743;
39 a1 = 4.265;
40 D0 = 14570.0;
@@ -139,11 +146,11 @@
46
47};
-
48
+
48
- +
50struct MOPTcoefficients{
51
- +
52 MOPTcoefficients(){
53 gs0 = 0.0825;
54 g1 = 2.637;
55 }
@@ -153,11 +160,11 @@
59
60};
-
61
+
61
- +
63struct BMFcoefficients{
64
- +
65 BMFcoefficients(){
66 Em = 258.25;
67 i0 = 38.65;
68 k = 232916.82;
@@ -176,11 +183,11 @@
81};
82
-
83
+
83
- +
85struct BBcoefficients{
86
- +
87 BBcoefficients(){
88 pi_0 = 1.0;
89 pi_m = 1.67;
90 theta = 211.22;
@@ -198,87 +205,87 @@
102
- +
104public:
-
105
-
107
+
105
+
107
110 explicit StomatalConductanceModel( helios::Context* m_context );
-
111
+
111
113 int selfTest();
-
114
-
116
+
114
+
116
119 void setModelCoefficients( const BWBcoefficients &coeffs );
-
120
-
122
+
120
+
122
126 void setModelCoefficients( const BWBcoefficients &coeffs, const std::vector<uint> &UUIDs );
-
127
-
129
+
127
+
129
132 void setModelCoefficients( const BBLcoefficients &coeffs );
-
133
-
135
+
133
+
135
139 void setModelCoefficients( const BBLcoefficients &coeffs, const std::vector<uint> &UUIDs );
-
140
-
142
+
140
+
142
145 void setModelCoefficients( const MOPTcoefficients &coeffs );
-
146
-
148
+
146
+
148
152 void setModelCoefficients( const MOPTcoefficients &coeffs, const std::vector<uint> &UUIDs );
-
153
-
155
+
153
+
155
158 void setModelCoefficients( const BMFcoefficients &coeffs );
-
159
-
161
+
159
+
161
165 void setModelCoefficients( const BMFcoefficients &coeffs, const std::vector<uint> &UUIDs );
-
166
-
168
+
166
+
168
171 void setModelCoefficients( const BBcoefficients &coeffs );
-
172
-
174
+
172
+
174
178 void setModelCoefficients( const BBcoefficients &coeffs, const std::vector<uint> &UUIDs );
-
179
-
181
+
179
+
181
185 void setModelCoefficients(const std::vector<BMFcoefficients> &coeffs, const std::vector<uint> &UUIDs);
-
186
-
188
+
186
+
188
191 void setBMFCoefficientsFromLibrary(const std::string &species);
-
192
-
194
+
192
+
194
198 void setBMFCoefficientsFromLibrary(const std::string &species, const std::vector<uint> &UUIDs);
-
199
-
201
+
199
+
201
204 BMFcoefficients getBMFCoefficientsFromLibrary(const std::string &species);
-
205
-
207
+
205
+
207
211 void setDynamicTimeConstants( float tau_open, float tau_close );
-
212
-
214
+
212
+
214
219 void setDynamicTimeConstants( float tau_open, float tau_close, const std::vector<uint> &UUIDs );
-
220
+
220
222 void run();
-
223
-
225
+
223
+
225
228 void run( const std::vector<uint> &UUIDs );
-
229
-
231
+
229
+
231
234 void run( float dt );
-
235
-
237
+
235
+
237
241 void run( const std::vector<uint> &UUIDs, float dt );
-
242
+
242
244 void disableMessages();
-
245
+
245
247 void enableMessages();
-
248
-
250
+
248
+
250
253 void optionalOutputPrimitiveData( const char* label );
-
254
+
254
256 void printDefaultValueReport() const;
-
257
-
259
+
257
+
259
262 void printDefaultValueReport(const std::vector<uint> &UUIDs) const;
263
264private:
-
265
+
265
267 helios::Context* context;
268
269 std::string model;
@@ -315,7 +322,7 @@
300 static float evaluate_BBmodel( float gs, std::vector<float> &variables, const void* parameters );
301
302 bool message_flag = true;
-
303
+
303
305 std::vector<std::string> output_prim_data;
306
307};
@@ -323,7 +330,6 @@
308
309#endif
-
void setDynamicTimeConstants(float tau_open, float tau_close)
Set time constants for dynamic stomatal opening and closing for all primitives.
void disableMessages()
Disable output messages to the standard output.
void setModelCoefficients(const std::vector< BMFcoefficients > &coeffs, const std::vector< uint > &UUIDs)
Set the model coefficient values for a subset of primitives based on their UUIDs.
@@ -336,17 +342,20 @@
void run()
Update the stomatal conductance for all primitives in the context.
BMFcoefficients getBMFCoefficientsFromLibrary(const std::string &species)
Get the model coefficient values using one of the available species in the library.
void setModelCoefficients(const BWBcoefficients &coeffs)
Set the model coefficient values for all primitives - Ball, Woodrow, Berry model.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
Coefficients for Ball, Berry, Leuning (Leuning 1990, 1995) stomatal conductance model.
Coefficients for simplified Bailey stomatal conductance model.
Coefficients for simplified Buckley, Mott, & Farquhar stomatal conductance model.
Coefficients for original Ball, Woodrow, Berry (1987) stomatal conductance model.
Coefficients for optimality-based Medlyn et al. (2011) stomatal conductance model.
- -
+ + diff --git a/doc/html/_stomatal_doc.html b/doc/html/_stomatal_doc.html index c85b6dbae..77681571f 100644 --- a/doc/html/_stomatal_doc.html +++ b/doc/html/_stomatal_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Stomatal Conductance Model Plugin Documentation
@@ -461,10 +467,13 @@

}

- -
+ + diff --git a/doc/html/_synthetic_annotation_8cpp.html b/doc/html/_synthetic_annotation_8cpp.html index da34c226d..b0c2e424d 100644 --- a/doc/html/_synthetic_annotation_8cpp.html +++ b/doc/html/_synthetic_annotation_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
SyntheticAnnotation.cpp File Reference
@@ -117,10 +123,13 @@

Definition in file SyntheticAnnotation.cpp.

- - + + diff --git a/doc/html/_synthetic_annotation_8cpp_source.html b/doc/html/_synthetic_annotation_8cpp_source.html index d51dbb88d..77d16ac67 100644 --- a/doc/html/_synthetic_annotation_8cpp_source.html +++ b/doc/html/_synthetic_annotation_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
SyntheticAnnotation.cpp
Go to the documentation of this file.
1
+
15
16#include "SyntheticAnnotation.h"
17#include "Visualizer.h"
18#include <iomanip>
@@ -187,9 +194,9 @@
91 IDs.resize(UUIDs.size());
92 for( size_t group=0; group<UUIDs.size(); group++ ) { //looping over label groups, which is the outer index of the UUIDs vector
93 for (size_t p = 0; p < UUIDs.at(group).size(); p++) { //looping over primitives in label group, which is hte inner index of the UUIDs vector
-
94 if (context->doesPrimitiveExist(UUIDs.at(group).at(p))) {
+
94 if (context->doesPrimitiveExist(UUIDs.at(group).at(p))) {
95 //set object_label primitive data for this group
-
96 context->setPrimitiveData(UUIDs.at(group).at(p), "object_label", currentLabelID);
+
96 context->setPrimitiveData(UUIDs.at(group).at(p), "object_label", currentLabelID);
97 }
98 }
99 IDs.at(group) = currentLabelID;
@@ -212,7 +219,7 @@
116
117void SyntheticAnnotation::labelUnlabeledPrimitives(const char *label) {
118
-
119 std::vector<uint> UUIDs_all = context->getAllUUIDs();
+
119 std::vector<uint> UUIDs_all = context->getAllUUIDs();
120 for( uint p=0; p<UUIDs_all.size(); p++ ){
121
122 }
@@ -296,19 +303,19 @@
187 return;
188 }
189
-
190 std::vector<uint> UUIDs_all = context->getAllUUIDs();
+
190 std::vector<uint> UUIDs_all = context->getAllUUIDs();
191
192 //get camera settings from global data if they were specified in a loaded XML file
-
193 if (context->doesGlobalDataExist("camera_position") ){
-
194 if( context->getGlobalDataType("camera_position")==helios::HELIOS_TYPE_VEC3 ) {
-
195 context->getGlobalData("camera_position", camera_position);
+
193 if (context->doesGlobalDataExist("camera_position") ){
+
194 if( context->getGlobalDataType("camera_position")==helios::HELIOS_TYPE_VEC3 ) {
+
195 context->getGlobalData("camera_position", camera_position);
196 }else{
197 std::cerr << "WARNING (SyntheticAnnotation::render): Camera position was specified in XML file but does not have type vec3. Ignoring.." << std::endl;
198 }
199 }
-
200 if (context->doesGlobalDataExist("camera_lookat") ){
-
201 if( context->getGlobalDataType("camera_lookat")==helios::HELIOS_TYPE_VEC3 ) {
-
202 context->getGlobalData("camera_lookat", camera_lookat);
+
200 if (context->doesGlobalDataExist("camera_lookat") ){
+
201 if( context->getGlobalDataType("camera_lookat")==helios::HELIOS_TYPE_VEC3 ) {
+
202 context->getGlobalData("camera_lookat", camera_lookat);
203 }else{
204 std::cerr << "WARNING (SyntheticAnnotation::render): Camera lookat coordinate was specified in XML file but does not have type vec3. Ignoring.." << std::endl;
205 }
@@ -319,10 +326,10 @@
210 }
211
212 //get window size from global data if they were specified in a loaded XML
-
213 if( context->doesGlobalDataExist( "image_resolution") ){
-
214 if( context->getGlobalDataType("image_resolution")==helios::HELIOS_TYPE_INT2 ) {
+
213 if( context->doesGlobalDataExist( "image_resolution") ){
+
214 if( context->getGlobalDataType("image_resolution")==helios::HELIOS_TYPE_INT2 ) {
215 int2 resolution;
-
216 context->getGlobalData("image_resolution", resolution);
+
216 context->getGlobalData("image_resolution", resolution);
217 window_width = resolution.x;
218 window_height = resolution.y;
219 }else{
@@ -331,10 +338,10 @@
222 }
223
224 //get output flags from global data if they were specified in a loaded XML
-
225 if( context->doesGlobalDataExist( "object_detection") ){
-
226 if( context->getGlobalDataType("object_detection")==helios::HELIOS_TYPE_STRING ) {
+
225 if( context->doesGlobalDataExist( "object_detection") ){
+
226 if( context->getGlobalDataType("object_detection")==helios::HELIOS_TYPE_STRING ) {
227 std::string objectdetection;
-
228 context->getGlobalData("object_detection", objectdetection);
+
228 context->getGlobalData("object_detection", objectdetection);
229 if( objectdetection.compare("enabled") ) {
230 objectdetection_enabled = true;
231 }else if( objectdetection.compare("disabled") ) {
@@ -344,10 +351,10 @@
235 std::cerr << "WARNING (SyntheticAnnotation::render): Object detection flag was specified in XML file, but does not have type string. Ignoring..." << std::endl;
236 }
237 }
-
238 if( context->doesGlobalDataExist( "semantic_segmentation") ){
-
239 if( context->getGlobalDataType("semantic_segmentation")==helios::HELIOS_TYPE_STRING ) {
+
238 if( context->doesGlobalDataExist( "semantic_segmentation") ){
+
239 if( context->getGlobalDataType("semantic_segmentation")==helios::HELIOS_TYPE_STRING ) {
240 std::string semanticsegmentation;
-
241 context->getGlobalData("semantic_segmentation", semanticsegmentation);
+
241 context->getGlobalData("semantic_segmentation", semanticsegmentation);
242 if( semanticsegmentation.compare("enabled") ) {
243 semanticsegmentation_enabled = true;
244 }else if( semanticsegmentation.compare("disabled") ) {
@@ -357,10 +364,10 @@
248 std::cerr << "WARNING (SyntheticAnnotation::render): Semantic segmentation flag was specified in XML file, but does not have type string. Ignoring..." << std::endl;
249 }
250 }
-
251 if( context->doesGlobalDataExist( "instance_segmentation") ){
-
252 if( context->getGlobalDataType("instance_segmentation")==helios::HELIOS_TYPE_STRING ) {
+
251 if( context->doesGlobalDataExist( "instance_segmentation") ){
+
252 if( context->getGlobalDataType("instance_segmentation")==helios::HELIOS_TYPE_STRING ) {
253 std::string instancesegmentation;
-
254 context->getGlobalData("instance_segmentation", instancesegmentation);
+
254 context->getGlobalData("instance_segmentation", instancesegmentation);
255 if( instancesegmentation.compare("enabled") ) {
256 instancesegmentation_enabled = true;
257 }else if( instancesegmentation.compare("disabled") ) {
@@ -450,8 +457,8 @@
341
342 //set color of all primitives based on label RGB color code
343 for (int p = 0; p < UUIDs_all.size(); p++) {
-
344 color_original.at(p) = context->getPrimitiveColorRGBA(UUIDs_all.at(p));
-
345 textureoverride_original.at(p) = context->isPrimitiveTextureColorOverridden(UUIDs_all.at(p));
+
344 color_original.at(p) = context->getPrimitiveColorRGBA(UUIDs_all.at(p));
+
345 textureoverride_original.at(p) = context->isPrimitiveTextureColorOverridden(UUIDs_all.at(p));
346 }
347
348 //------ Combined image labeled by RGB color code --------//
@@ -489,14 +496,14 @@
380 std::vector<uint> UUIDs_group = labelUUIDs.at(label).at(group);
381 for (int p = 0; p < UUIDs_group.size(); p++) { //looping over primitives in group
382
-
383 if (context->doesPrimitiveDataExist(UUIDs_group.at(p), "object_label")) { //primitive has been labeled
+
383 if (context->doesPrimitiveDataExist(UUIDs_group.at(p), "object_label")) { //primitive has been labeled
384
-
385 context->setPrimitiveColor(UUIDs_group.at(p),code);
+
385 context->setPrimitiveColor(UUIDs_group.at(p),code);
386
387 } else { //primitive was not labeled, assign default color of white
-
388 context->setPrimitiveColor( UUIDs_group.at(p), make_RGBcolor(1, 1, 1));
+
388 context->setPrimitiveColor( UUIDs_group.at(p), make_RGBcolor(1, 1, 1));
389 }
-
390 context->overridePrimitiveTextureColor(UUIDs_group.at(p));
+
390 context->overridePrimitiveTextureColor(UUIDs_group.at(p));
391 }
392
393 }
@@ -505,10 +512,10 @@
396 //make all unlabeled primitives white
397 for( size_t p=0; p<UUIDs_all.size(); p++ ){
398
-
399 if ( !context->doesPrimitiveDataExist(UUIDs_all.at(p), "object_label")) { //primitive has NOT been labeled
-
400 context->setPrimitiveColor(UUIDs_all.at(p),make_RGBcolor(1, 1, 1));
+
399 if ( !context->doesPrimitiveDataExist(UUIDs_all.at(p), "object_label")) { //primitive has NOT been labeled
+
400 context->setPrimitiveColor(UUIDs_all.at(p),make_RGBcolor(1, 1, 1));
401 }
-
402 context->overridePrimitiveTextureColor(UUIDs_all.at(p));
+
402 context->overridePrimitiveTextureColor(UUIDs_all.at(p));
403
404 }
405
@@ -739,9 +746,9 @@
630
631 //set primitive colors back to how they were before
632 for (int p = 0; p < UUIDs_all.size(); p++) {
-
633 context->setPrimitiveColor(UUIDs_all.at(p),color_original.at(p));
+
633 context->setPrimitiveColor(UUIDs_all.at(p),color_original.at(p));
634 if (!textureoverride_original.at(p)) {
-
635 context->usePrimitiveTextureColor(UUIDs_all.at(p));
+
635 context->usePrimitiveTextureColor(UUIDs_all.at(p));
636 }
637 }
638
@@ -915,32 +922,21 @@
Class for visualization of simulation results.
Definition Visualizer.h:275
void getWindowPixelsRGB(uint *buffer)
Get R-G-B pixel data in the current display window.
void printWindow()
Print the current graphics window to a JPEG image file. File will be given a default filename and sav...
-
void buildContextGeometry(helios::Context *context_ptr)
Add all geometry from the Context to the visualizer.
+
void buildContextGeometry(helios::Context *context_ptr)
Add all geometry from the Context to the visualizer.
void setLightDirection(const helios::vec3 &direction)
Set the direction of the light source.
-
@ LIGHTING_PHONG_SHADOWED
Phong lighting model plus shadowing is applied to add shading effects to the diffuse color.
Definition Visualizer.h:390
+
@ LIGHTING_PHONG_SHADOWED
Phong lighting model plus shadowing is applied to add shading effects to the diffuse color.
Definition Visualizer.h:390
void closeWindow()
Close the graphics window.
void setBackgroundColor(const helios::RGBcolor &color)
Set the background color for the visualizer window.
void clearGeometry()
Clear all geometry previously added to the visualizer.
void hideWatermark()
Make Helios logo watermark invisible.
-
void plotUpdate()
Update the graphics window based on current geometry, then continue the program.
+
void plotUpdate()
Update the graphics window based on current geometry, then continue the program.
void disableMessages()
Disable standard output from this plug-in.
void getFramebufferSize(uint &width, uint &height) const
Get the size of the framebuffer in pixels.
void addSkyDomeByCenter(float radius, const helios::vec3 &center, uint Ndivisions, const char *texture_file)
Add a Sky Dome, which is a hemispherical dome colored by a sky texture map.
void setCameraPosition(const helios::vec3 &cameraPosition, const helios::vec3 &lookAt)
Set camera position.
void setLightingModel(LightingModel lightingmodel)
Set the lighting model for shading of all primitives.
-
Stores the state associated with simulation.
Definition Context.h:1882
-
void setPrimitiveColor(uint UUID, const helios::RGBcolor &color)
Method to set the diffuse color of a Primitive.
Definition Context.cpp:7139
-
helios::RGBAcolor getPrimitiveColorRGBA(uint UUID) const
Method to return the diffuse color of a Primitive with transparency.
Definition Context.cpp:7135
-
void usePrimitiveTextureColor(uint UUID)
Use the texture map to color the primitive rather than the constant RGB color. This is function rever...
Definition Context.cpp:7207
-
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
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:7197
-
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)
+
Stores the state associated with simulation.
Definition Context.h:1888
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
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:7217
-
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:1659
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
void wait(float seconds)
Wait/sleep for a specified amount of time.
Definition global.cpp:306
@@ -952,20 +948,23 @@
float b
Blue color component.
float r
Red color component.
float g
Green color component.
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of four elements of type 'int'.
+
Vector of four elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int w
Fourth element in vector.
int y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_synthetic_annotation_8h.html b/doc/html/_synthetic_annotation_8h.html index 5aca9babf..f6437a6ab 100644 --- a/doc/html/_synthetic_annotation_8h.html +++ b/doc/html/_synthetic_annotation_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
@@ -124,10 +130,13 @@

Definition in file SyntheticAnnotation.h.

- - + + diff --git a/doc/html/_synthetic_annotation_8h.js b/doc/html/_synthetic_annotation_8h.js new file mode 100644 index 000000000..50b76a8d1 --- /dev/null +++ b/doc/html/_synthetic_annotation_8h.js @@ -0,0 +1,4 @@ +var _synthetic_annotation_8h = +[ + [ "SyntheticAnnotation", "class_synthetic_annotation.html", "class_synthetic_annotation" ] +]; \ No newline at end of file diff --git a/doc/html/_synthetic_annotation_8h_source.html b/doc/html/_synthetic_annotation_8h_source.html index 902e6bf7f..fe995150f 100644 --- a/doc/html/_synthetic_annotation_8h_source.html +++ b/doc/html/_synthetic_annotation_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
SyntheticAnnotation.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
16
17#ifndef __SYNTHETICANNOTATION__
18#define __SYNTHETICANNOTATION__
19
@@ -112,12 +119,12 @@
21#include "Visualizer.h"
22
- +
24public:
-
25
-
27
+
25
+
27
29 explicit SyntheticAnnotation( helios::Context* context );
-
30
+
30
32 int selfTest( ) const;
33
34 void labelPrimitives( const char* label );
@@ -139,19 +146,19 @@
50 void setCameraPosition( const helios::vec3 &camera_position, const helios::vec3 &camera_lookat );
51
52 void setCameraPosition( const std::vector<helios::vec3> &camera_position, const std::vector<helios::vec3> &camera_lookat );
-
53
+
53
-
56
+
56
-
59
+
59
-
62
+
62
-
65
+
65
-
68
+
68
-
71
+
71
73 /* \param[in] "outputdir" Base directory to save output files.
74 */
75 void render( const char* outputdir );
@@ -198,7 +205,6 @@
115#endif
-
void disableInstanceSegmentation()
Disable calculation and writing of un-occluded object masks for each object (instance segmentation)
void disableObjectDetection()
Disable calculation and writing of rectangular bounding boxes for object detection when render() func...
SyntheticAnnotation(helios::Context *context)
Synthetic image annotation plug-in default constructor.
@@ -209,15 +215,18 @@
void enableSemanticSegmentation()
Enable calculation and writing of object mask (full image) for semantic segmentation.
void enableInstanceSegmentation()
Enable calculation and writing of un-occluded object masks for each object (instance segmentation)
Class for visualization of simulation results.
Definition Visualizer.h:275
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
R-G-B color vector.
-
Vector of four elements of type 'int'.
-
Vector of three elements of type 'float'.
+
Vector of four elements of type 'int'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_tutorials.html b/doc/html/_tutorials.html index 8840443a2..ed3b5ae33 100644 --- a/doc/html/_tutorials.html +++ b/doc/html/_tutorials.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Tutorials
@@ -133,10 +143,12 @@

- - + + diff --git a/doc/html/_tutorials.js b/doc/html/_tutorials.js new file mode 100644 index 000000000..20544e3d3 --- /dev/null +++ b/doc/html/_tutorials.js @@ -0,0 +1,44 @@ +var _tutorials = +[ + [ "Context", "_tutorials.html#ContextTuts", [ + [ "Context Basics", "_tutorials.html#ContextBasicsTut", null ], + [ "Working with Context Data", "_tutorials.html#PrimDataTut", null ] + ] ], + [ "Visualizer Plug-In", "_tutorials.html#VisualizerTuts", null ], + [ "Radiation Model Plug-In", "_tutorials.html#RadiationTuts", null ], + [ "Tutorial 0: Context Self-Test Tutorial", "context_selftest.html", [ + [ "C++ Program", "context_selftest.html#program_1", null ], + [ "Building, Compiling, and Running", "context_selftest.html#build_2", null ] + ] ], + [ "Tutorial 1: Helios Vector Types Tutorial", "context_vectors.html", [ + [ "Vector of Integers", "context_vectors.html#int3tut", null ], + [ "Vector of Floats", "context_vectors.html#vec3tut", null ], + [ "RGB Color Vector", "context_vectors.html#RGBtut", null ], + [ "Time Vector", "context_vectors.html#Timetut", null ], + [ "Date Vector", "context_vectors.html#Datetut", null ] + ] ], + [ "Tutorial 2: Working with Context Geometry", "context_primitives.html", [ + [ "Overview", "context_primitives.html#context_primitives_overview", null ], + [ "Adding a Patch to the Context", "context_primitives.html#AddPatch", null ], + [ "Unique Universal Identifiers (UUIDs)", "context_primitives.html#AddPatch_UUIDs", null ] + ] ], + [ "Tutorial 5: Primitive Data", "context_primdata.html", [ + [ "Introduction to Primitive Data", "context_primdata.html#context_primdata_intro", null ], + [ "Creating Primitive Data (Scalars)", "context_primdata.html#context_primdata_scalar", null ], + [ "Creating Primitive Data (Arrays)", "context_primdata.html#context_primdata_arrays", null ] + ] ], + [ "Tutorial 6: Global Data", "context_globaldata.html", [ + [ "Introduction to Global Data", "context_globaldata.html#context_globaldata_intro", null ], + [ "Creating Global Data (Scalars)", "context_globaldata.html#context_globaldata_scalar", null ], + [ "Creating Global Data (Arrays)", "context_globaldata.html#context_globaldata_arrays", null ] + ] ], + [ "Tutorial 7: Visualizer Basics", "visualizer_basics.html", [ + [ "Step 1. Declare and initialize the Visualizer class", "visualizer_basics.html#vis_step1", null ], + [ "Step 2. Add geometry to the Visualizer", "visualizer_basics.html#vis_step2", null ], + [ "Step 3. Modify Visualizer options", "visualizer_basics.html#vis_step3", null ], + [ "Step 4. Plot the result", "visualizer_basics.html#vis_step4", null ] + ] ], + [ "Tutorial 8: Visualizing primitive data values", "visualizer_pdata.html", null ], + [ "Tutorial 10: Radiation model basics - tree light interception", "radiation_basics.html", null ], + [ "Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy", "radiation__beers_law.html", null ] +]; \ No newline at end of file diff --git a/doc/html/_visualizer_8cpp.html b/doc/html/_visualizer_8cpp.html index 09aa58f25..6f88a921c 100644 --- a/doc/html/_visualizer_8cpp.html +++ b/doc/html/_visualizer_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
Data Structures | @@ -276,7 +282,7 @@

-

Definition at line 4509 of file Visualizer.cpp.

+

Definition at line 4510 of file Visualizer.cpp.

@@ -306,7 +312,7 @@

Definition at line 4353 of file Visualizer.cpp.

+

Definition at line 4354 of file Visualizer.cpp.

@@ -325,7 +331,7 @@

-

Definition at line 4484 of file Visualizer.cpp.

+

Definition at line 4485 of file Visualizer.cpp.

@@ -379,7 +385,7 @@

Definition at line 4339 of file Visualizer.cpp.

+

Definition at line 4340 of file Visualizer.cpp.

@@ -497,7 +503,7 @@

Definition at line 4371 of file Visualizer.cpp.

+

Definition at line 4372 of file Visualizer.cpp.

@@ -602,7 +608,7 @@

-

Definition at line 3296 of file Visualizer.cpp.

+

Definition at line 3297 of file Visualizer.cpp.

@@ -618,7 +624,7 @@

-

Definition at line 3303 of file Visualizer.cpp.

+

Definition at line 3304 of file Visualizer.cpp.

@@ -634,7 +640,7 @@

-

Definition at line 3297 of file Visualizer.cpp.

+

Definition at line 3298 of file Visualizer.cpp.

@@ -650,7 +656,7 @@

-

Definition at line 3298 of file Visualizer.cpp.

+

Definition at line 3299 of file Visualizer.cpp.

@@ -666,7 +672,7 @@

-

Definition at line 3301 of file Visualizer.cpp.

+

Definition at line 3302 of file Visualizer.cpp.

@@ -682,7 +688,7 @@

-

Definition at line 3299 of file Visualizer.cpp.

+

Definition at line 3300 of file Visualizer.cpp.

@@ -698,7 +704,7 @@

-

Definition at line 3302 of file Visualizer.cpp.

+

Definition at line 3303 of file Visualizer.cpp.

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

-

Definition at line 3300 of file Visualizer.cpp.

+

Definition at line 3301 of file Visualizer.cpp.

@@ -730,7 +736,7 @@

-

Definition at line 4331 of file Visualizer.cpp.

+

Definition at line 4332 of file Visualizer.cpp.

@@ -746,7 +752,7 @@

-

Definition at line 4333 of file Visualizer.cpp.

+

Definition at line 4334 of file Visualizer.cpp.

@@ -762,7 +768,7 @@

-

Definition at line 4332 of file Visualizer.cpp.

+

Definition at line 4333 of file Visualizer.cpp.

@@ -778,7 +784,7 @@

-

Definition at line 4336 of file Visualizer.cpp.

+

Definition at line 4337 of file Visualizer.cpp.

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

-

Definition at line 4335 of file Visualizer.cpp.

+

Definition at line 4336 of file Visualizer.cpp.

@@ -810,7 +816,7 @@

-

Definition at line 4335 of file Visualizer.cpp.

+

Definition at line 4336 of file Visualizer.cpp.

@@ -826,7 +832,7 @@

-

Definition at line 4334 of file Visualizer.cpp.

+

Definition at line 4335 of file Visualizer.cpp.

@@ -842,15 +848,18 @@

-

Definition at line 4334 of file Visualizer.cpp.

+

Definition at line 4335 of file Visualizer.cpp.

- - + + diff --git a/doc/html/_visualizer_8cpp.js b/doc/html/_visualizer_8cpp.js new file mode 100644 index 000000000..66257fe74 --- /dev/null +++ b/doc/html/_visualizer_8cpp.js @@ -0,0 +1,10 @@ +var _visualizer_8cpp = +[ + [ "my_error_mgr", "structmy__error__mgr.html", null ], + [ "cursorCallback", "_visualizer_8cpp.html#a130a46ee7099395ef26b4c5e504bf14b", null ], + [ "mouseCallback", "_visualizer_8cpp.html#a8b8e3d832e0aeb8c7bf0e77f0ddf0c94", null ], + [ "read_JPEG_file", "_visualizer_8cpp.html#a1ffc8a34ba2895084c71e95ed615d10a", null ], + [ "read_png_file", "_visualizer_8cpp.html#a0e60a86e54784ea9f2b178ce9540713f", null ], + [ "scrollCallback", "_visualizer_8cpp.html#aa9b224479e8c1cc5251b8e7f3fdabacd", null ], + [ "write_JPEG_file", "_visualizer_8cpp.html#a72ab446b93211938da98a8eec0c5d33a", null ] +]; \ No newline at end of file diff --git a/doc/html/_visualizer_8cpp_source.html b/doc/html/_visualizer_8cpp_source.html index ec9d992b5..89800a709 100644 --- a/doc/html/_visualizer_8cpp_source.html +++ b/doc/html/_visualizer_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
Visualizer.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16//OpenGL Includes
17#include <GL/glew.h>
18#include <GLFW/glfw3.h>
@@ -140,10 +147,10 @@
47 jmp_buf setjmp_buffer; /* for return to caller */
48};
-
49typedef struct my_error_mgr * my_error_ptr;
+
49typedef struct my_error_mgr * my_error_ptr;
50METHODDEF(void) my_error_exit (j_common_ptr cinfo){
51 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
-
52 auto myerr = (my_error_ptr) cinfo->err;
+
52 auto myerr = (my_error_ptr) cinfo->err;
53
54 /* Always display the message. */
55 /* We could postpone this until after returning, if we chose. */
@@ -625,12 +632,12 @@
519
520 //~~~~~~~~~~~~~ Load the Shaders ~~~~~~~~~~~~~~~~~~~//
521
-
522 primaryShader.initialize( "plugins/visualizer/shaders/primaryShader.vert", "plugins/visualizer/shaders/primaryShader.frag" );
-
523 depthShader.initialize( "plugins/visualizer/shaders/shadow.vert", "plugins/visualizer/shaders/shadow.frag" );
+
522 primaryShader.initialize( "plugins/visualizer/shaders/primaryShader.vert", "plugins/visualizer/shaders/primaryShader.frag" );
+
523 depthShader.initialize( "plugins/visualizer/shaders/shadow.vert", "plugins/visualizer/shaders/shadow.frag" );
524
525 assert(checkerrors());
526
-
527 primaryShader.useShader();
+
527 primaryShader.useShader();
528 //currentShader = &primaryShader;
529
530 // Initialize frame buffer
@@ -689,8 +696,8 @@
583 // Default values
584
585 light_direction = make_vec3(1,1,1);
-
586 light_direction.normalize();
-
587 primaryShader.setLightDirection(light_direction);
+
586 light_direction.normalize();
+
587 primaryShader.setLightDirection(light_direction);
588
589 primaryLightingModel.push_back( Visualizer::LIGHTING_NONE );
590
@@ -804,7 +811,7 @@
697 std::cout << "Running visualizer self-test..." << std::flush;
698 }
699
-
700 Visualizer visualizer( 1000 );
+
700 Visualizer visualizer( 1000 );
701
702 visualizer.setCameraPosition( make_SphericalCoord(10,0.49*M_PI,0), make_vec3(0,0,0) );
703
@@ -911,7 +918,7 @@
793
794 light_direction = direction/direction.magnitude();
-
795 primaryShader.setLightDirection(direction);
+
795 primaryShader.setLightDirection(direction);
796
797}
@@ -1011,8 +1018,8 @@
880
881 char outfile[100];
882 if( context!=nullptr ){//context has been given to visualizer via buildContextGeometry()
-
883 Date date = context->getDate();
-
884 Time time = context->getTime();
+
883 Date date = context->getDate();
+
884 Time time = context->getTime();
885 std::snprintf(outfile,100,"%02d-%02d-%4d_%02d-%02d-%02d_frame%d.jpg",date.day,date.month,date.year,time.hour,time.minute,time.second,frame_counter);
886 }else{
887 std::snprintf(outfile,100,"frame%d.jpg",frame_counter);
@@ -1430,7 +1437,7 @@
1263
1264 uint textureID;
1265 int2 texture_size;
-
1266 primaryShader.setTextureMap(texture_file,textureID,texture_size);
+
1266 primaryShader.setTextureMap(texture_file,textureID,texture_size);
1267
1268 std::vector<float> position_data, color_data, normal_data, uv_data;
1269 position_data.resize(18,0);
@@ -1552,7 +1559,7 @@
1381
1382 uint textureID;
1383 int2 texture_size;
-
1384 primaryShader.setTextureMap(texture_file,textureID,texture_size);
+
1384 primaryShader.setTextureMap(texture_file,textureID,texture_size);
1385
1386 std::vector<float> position_data, color_data, normal_data, uv_data;
1387 position_data.resize(18,0);
@@ -1672,7 +1679,7 @@
1497
1498 uint textureID;
1499 int2 texture_size = glyph->size;
-
1500 primaryShader.setTextureMask(glyph,textureID);
+
1500 primaryShader.setTextureMask(glyph,textureID);
1501
1502 std::vector<float> position_data, color_data, normal_data, uv_data;
1503 position_data.resize(18,0);
@@ -1881,7 +1888,7 @@
1700
1701 uint textureID;
1702 int2 texture_size;
-
1703 primaryShader.setTextureMap(texture_file,textureID,texture_size);
+
1703 primaryShader.setTextureMap(texture_file,textureID,texture_size);
1704
1705 std::vector<GLfloat> position_data(9), color_data(12), normal_data(9), uv_data(6);
1706
@@ -1969,7 +1976,7 @@
1786
1787 uint textureID;
1788 int2 texture_size;
-
1789 primaryShader.setTextureMap(texture_file,textureID,texture_size);
+
1789 primaryShader.setTextureMap(texture_file,textureID,texture_size);
1790
1791 std::vector<GLfloat> position_data(9), color_data(12), normal_data(9), uv_data(6);
1792
@@ -2176,7 +2183,7 @@
1983
1984 uint textureID;
1985 int2 texture_size;
-
1986 primaryShader.setTextureMap(texture_file,textureID,texture_size);
+
1986 primaryShader.setTextureMap(texture_file,textureID,texture_size);
1987
1988 std::vector<float> position_data, color_data, normal_data, uv_data;
1989
@@ -2630,2305 +2637,2282 @@
2421
2422 }
2423
-
2424 FT_Done_FreeType(ft);
-
2425
-
2426}
+
2424 FT_Done_Face(face);
+
2425 FT_Done_FreeType(ft);
+
2426
+
2427}
-
2427
-
2428void Visualizer::addColorbarByCenter(const char* title, const helios::vec2 &size, const helios::vec3 &center, const helios::RGBcolor &font_color, const Colormap &colormap ){
-
2429
-
2430 uint Ndivs = 50;
-
2431
-
2432 uint Nticks = 4;
-
2433
-
2434 if( !colorbar_ticks.empty() ){
-
2435 Nticks = colorbar_ticks.size();
-
2436 }
-
2437
-
2438 float dx = size.x/float(Ndivs);
-
2439
-
2440 float cmin = clamp(colormap.getLowerLimit(), -1e7f, 1e7f);
-
2441 float cmax = clamp(colormap.getUpperLimit(), -1e7f, 1e7f);
-
2442
-
2443 for( uint i=0; i<Ndivs; i++ ){
-
2444
-
2445 float x = center.x -0.5f*size.x + (float(i)+0.5)*dx;
-
2446
-
2447 RGBcolor color = colormap.query( cmin+float(i)/float(Ndivs)*(cmax-cmin) );
-
2448
-
2449 addRectangleByCenter( make_vec3(x,center.y,center.z), make_vec2(dx,0.5f*size.y), make_SphericalCoord(0,0), color, COORDINATES_WINDOW_NORMALIZED );
-
2450
-
2451 }
-
2452
-
2453 std::vector<vec3> border;
-
2454 border.push_back( make_vec3( center.x-0.5*size.x, center.y+0.25*size.y, center.z-0.001 ) );
-
2455 border.push_back( make_vec3( center.x+0.5*size.x, center.y+0.25*size.y, center.z-0.001 ) );
-
2456 border.push_back( make_vec3( center.x+0.5*size.x, center.y-0.25*size.y, center.z-0.001 ) );
-
2457 border.push_back( make_vec3( center.x-0.5*size.x, center.y-0.25*size.y, center.z-0.001 ) );
-
2458 border.push_back( make_vec3( center.x-0.5*size.x, center.y+0.25*size.y, center.z-0.001 ) );
-
2459
-
2460 for( uint i=0; i<border.size()-1; i++ ){
-
2461 addLine( border.at(i), border.at(i+1), font_color, 1, COORDINATES_WINDOW_NORMALIZED );
-
2462 }
-
2463
-
2464 dx = size.x/float(Nticks-1);
-
2465
-
2466 std::vector<vec3> ticks;
-
2467 ticks.resize(2);
-
2468 for( uint i=0; i<Nticks; i++ ){
-
2469
-
2471 char textstr[10],precision[10];
-
2472
-
2473 float x;
-
2474 float value;
-
2475 if( colorbar_ticks.size()==0 ){
-
2476 x = center.x -0.5f*size.x + float(i)*dx;
-
2477 value = cmin+float(i)/float(Nticks-1)*(cmax-cmin);
-
2478 }else{
-
2479 value = colorbar_ticks.at(i);
-
2480 x = center.x -0.5f*size.x + (value-cmin)/(cmax-cmin)*size.x;
-
2481 }
-
2482
-
2483 int d1, d2;
-
2484 if( std::fabs(floor(value)-value)<1e-4 ){ //value is an integer
-
2485 std::snprintf(precision,10,"%%d");
-
2486 std::snprintf(textstr,10,precision,int(floor(value)));
-
2487 }else if( value!=0.f ){ //value needs decimal formatting
-
2488 d1 = floor(log10(std::fabs(value)));
-
2489 d2= -d1+1;
-
2490 if(d2<1){
-
2491 d2=1;
-
2492 }
-
2493 std::snprintf(precision,10,"%%%u.%uf",(char)abs(d1)+1,(char)d2);
-
2494 std::snprintf(textstr,10,precision,value);
-
2495 }
-
2496
-
2497 // tick labels
-
2498 addTextboxByCenter( textstr, make_vec3(x,center.y-0.4f*size.y,center.z), make_SphericalCoord(0,0), font_color, colorbar_fontsize, "OpenSans-Regular", COORDINATES_WINDOW_NORMALIZED );
-
2499
-
2500 if(i>0 && i<Nticks-1){
-
2501 ticks[0] = make_vec3( x, center.y-0.25f*size.y, center.z-0.001f );
-
2502 ticks[1] = make_vec3( x, center.y-0.25f*size.y+0.05f*size.y, center.z-0.001f );
-
2503 addLine(ticks[0],ticks[1],make_RGBcolor(0.25,0.25,0.25),1,COORDINATES_WINDOW_NORMALIZED);
-
2504 ticks[0] = make_vec3( x, center.y+0.25f*size.y, center.z-0.001f );
-
2505 ticks[1] = make_vec3( x, center.y+0.25f*size.y-0.05f*size.y, center.z-0.001f );
-
2506 addLine(ticks[0],ticks[1], make_RGBcolor(0.25,0.25,0.25),1,COORDINATES_WINDOW_NORMALIZED);
-
2507 }
-
2508
-
2509 }
-
2510
-
2511 //title
-
2512 addTextboxByCenter( title, make_vec3( center.x, center.y+0.4*size.y, center.z), make_SphericalCoord(0,0), font_color, colorbar_fontsize, "CantoraOne-Regular", COORDINATES_WINDOW_NORMALIZED );
-
2513
-
2514}
-
2515
-
- -
2517 addCoordinateAxes(helios::make_vec3(0,0,0), helios::make_vec3(1,1,1), "positive");
-
2518}
+
2428
+
2429void Visualizer::addColorbarByCenter(const char* title, const helios::vec2 &size, const helios::vec3 &center, const helios::RGBcolor &font_color, const Colormap &colormap ){
+
2430
+
2431 uint Ndivs = 50;
+
2432
+
2433 uint Nticks = 4;
+
2434
+
2435 if( !colorbar_ticks.empty() ){
+
2436 Nticks = colorbar_ticks.size();
+
2437 }
+
2438
+
2439 float dx = size.x/float(Ndivs);
+
2440
+
2441 float cmin = clamp(colormap.getLowerLimit(), -1e7f, 1e7f);
+
2442 float cmax = clamp(colormap.getUpperLimit(), -1e7f, 1e7f);
+
2443
+
2444 for( uint i=0; i<Ndivs; i++ ){
+
2445
+
2446 float x = center.x -0.5f*size.x + (float(i)+0.5)*dx;
+
2447
+
2448 RGBcolor color = colormap.query( cmin+float(i)/float(Ndivs)*(cmax-cmin) );
+
2449
+
2450 addRectangleByCenter( make_vec3(x,center.y,center.z), make_vec2(dx,0.5f*size.y), make_SphericalCoord(0,0), color, COORDINATES_WINDOW_NORMALIZED );
+
2451
+
2452 }
+
2453
+
2454 std::vector<vec3> border;
+
2455 border.push_back( make_vec3( center.x-0.5*size.x, center.y+0.25*size.y, center.z-0.001 ) );
+
2456 border.push_back( make_vec3( center.x+0.5*size.x, center.y+0.25*size.y, center.z-0.001 ) );
+
2457 border.push_back( make_vec3( center.x+0.5*size.x, center.y-0.25*size.y, center.z-0.001 ) );
+
2458 border.push_back( make_vec3( center.x-0.5*size.x, center.y-0.25*size.y, center.z-0.001 ) );
+
2459 border.push_back( make_vec3( center.x-0.5*size.x, center.y+0.25*size.y, center.z-0.001 ) );
+
2460
+
2461 for( uint i=0; i<border.size()-1; i++ ){
+
2462 addLine( border.at(i), border.at(i+1), font_color, 1, COORDINATES_WINDOW_NORMALIZED );
+
2463 }
+
2464
+
2465 dx = size.x/float(Nticks-1);
+
2466
+
2467 std::vector<vec3> ticks;
+
2468 ticks.resize(2);
+
2469 for( uint i=0; i<Nticks; i++ ){
+
2470
+
2472 char textstr[10],precision[10];
+
2473
+
2474 float x;
+
2475 float value;
+
2476 if( colorbar_ticks.size()==0 ){
+
2477 x = center.x -0.5f*size.x + float(i)*dx;
+
2478 value = cmin+float(i)/float(Nticks-1)*(cmax-cmin);
+
2479 }else{
+
2480 value = colorbar_ticks.at(i);
+
2481 x = center.x -0.5f*size.x + (value-cmin)/(cmax-cmin)*size.x;
+
2482 }
+
2483
+
2484 int d1, d2;
+
2485 if( std::fabs(floor(value)-value)<1e-4 ){ //value is an integer
+
2486 std::snprintf(precision,10,"%%d");
+
2487 std::snprintf(textstr,10,precision,int(floor(value)));
+
2488 }else if( value!=0.f ){ //value needs decimal formatting
+
2489 d1 = floor(log10(std::fabs(value)));
+
2490 d2= -d1+1;
+
2491 if(d2<1){
+
2492 d2=1;
+
2493 }
+
2494 std::snprintf(precision,10,"%%%u.%uf",(char)abs(d1)+1,(char)d2);
+
2495 std::snprintf(textstr,10,precision,value);
+
2496 }
+
2497
+
2498 // tick labels
+
2499 addTextboxByCenter( textstr, make_vec3(x,center.y-0.4f*size.y,center.z), make_SphericalCoord(0,0), font_color, colorbar_fontsize, "OpenSans-Regular", COORDINATES_WINDOW_NORMALIZED );
+
2500
+
2501 if(i>0 && i<Nticks-1){
+
2502 ticks[0] = make_vec3( x, center.y-0.25f*size.y, center.z-0.001f );
+
2503 ticks[1] = make_vec3( x, center.y-0.25f*size.y+0.05f*size.y, center.z-0.001f );
+
2504 addLine(ticks[0],ticks[1],make_RGBcolor(0.25,0.25,0.25),1,COORDINATES_WINDOW_NORMALIZED);
+
2505 ticks[0] = make_vec3( x, center.y+0.25f*size.y, center.z-0.001f );
+
2506 ticks[1] = make_vec3( x, center.y+0.25f*size.y-0.05f*size.y, center.z-0.001f );
+
2507 addLine(ticks[0],ticks[1], make_RGBcolor(0.25,0.25,0.25),1,COORDINATES_WINDOW_NORMALIZED);
+
2508 }
+
2509
+
2510 }
+
2511
+
2512 //title
+
2513 addTextboxByCenter( title, make_vec3( center.x, center.y+0.4*size.y, center.z), make_SphericalCoord(0,0), font_color, colorbar_fontsize, "CantoraOne-Regular", COORDINATES_WINDOW_NORMALIZED );
+
2514
+
2515}
+
2516
+
+ +
2518 addCoordinateAxes(helios::make_vec3(0,0,0), helios::make_vec3(1,1,1), "positive");
+
2519}
-
2519
-
-
2520void Visualizer::addCoordinateAxes(const helios::vec3 &origin, const helios::vec3 &length, const std::string &sign){
-
2521
+
2520
+
+
2521void Visualizer::addCoordinateAxes(const helios::vec3 &origin, const helios::vec3 &length, const std::string &sign){
2522
-
2523 float mult;
-
2524 if(sign == "both"){
-
2525 mult = 1.0;
-
2526 }else{
-
2527 mult = 0.0;
-
2528 }
-
2529
-
2530 float Lmag = length.magnitude();
-
2531
-
2532 // x axis
-
2533 addLine(make_vec3(mult*-1.0*length.x + origin.x, origin.y, origin.z), make_vec3(length.x + origin.x, origin.y, origin.z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
-
2534
-
2535 if(length.x > 0){
-
2536 addTextboxByCenter("+ X", helios::make_vec3(1.2*length.x + origin.x, origin.y, origin.z), helios::make_SphericalCoord(0,0), helios::make_RGBcolor( 0.f, 0.f, 0.f ), uint(200*Lmag), "OpenSans-Regular", Visualizer::COORDINATES_CARTESIAN);
-
2537 }
-
2538
-
2539 // y axis
-
2540 addLine(make_vec3(origin.x, mult*-1.0*length.y+origin.y, origin.z), make_vec3(origin.x, length.y+origin.y, origin.z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
-
2541
-
2542 if(length.y > 0){
-
2543 addTextboxByCenter("+ Y", helios::make_vec3( origin.x, 1.1*length.y+origin.y, origin.z), helios::make_SphericalCoord(0,0), helios::make_RGBcolor( 0.f, 0.f, 0.f ), uint(200*Lmag), "OpenSans-Regular", Visualizer::COORDINATES_CARTESIAN);
-
2544 }
-
2545
-
2546 // z axis
-
2547 addLine(make_vec3(origin.x, origin.y, mult*-1*length.z+origin.z), make_vec3(origin.x, origin.y, length.z+origin.z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
-
2548
-
2549 if(length.z > 0){
-
2550 addTextboxByCenter("+ Z", helios::make_vec3( origin.x, origin.y, length.z+origin.z), helios::make_SphericalCoord(0,0), helios::make_RGBcolor( 0.f, 0.f, 0.f ), uint(200*Lmag), "OpenSans-Regular", Visualizer::COORDINATES_CARTESIAN);
-
2551
-
2552 }
-
2553
+
2523
+
2524 float mult;
+
2525 if(sign == "both"){
+
2526 mult = 1.0;
+
2527 }else{
+
2528 mult = 0.0;
+
2529 }
+
2530
+
2531 float Lmag = length.magnitude();
+
2532
+
2533 // x axis
+
2534 addLine(make_vec3(mult*-1.0*length.x + origin.x, origin.y, origin.z), make_vec3(length.x + origin.x, origin.y, origin.z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
+
2535
+
2536 if(length.x > 0){
+
2537 addTextboxByCenter("+ X", helios::make_vec3(1.2*length.x + origin.x, origin.y, origin.z), helios::make_SphericalCoord(0,0), helios::make_RGBcolor( 0.f, 0.f, 0.f ), uint(200*Lmag), "OpenSans-Regular", Visualizer::COORDINATES_CARTESIAN);
+
2538 }
+
2539
+
2540 // y axis
+
2541 addLine(make_vec3(origin.x, mult*-1.0*length.y+origin.y, origin.z), make_vec3(origin.x, length.y+origin.y, origin.z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
+
2542
+
2543 if(length.y > 0){
+
2544 addTextboxByCenter("+ Y", helios::make_vec3( origin.x, 1.1*length.y+origin.y, origin.z), helios::make_SphericalCoord(0,0), helios::make_RGBcolor( 0.f, 0.f, 0.f ), uint(200*Lmag), "OpenSans-Regular", Visualizer::COORDINATES_CARTESIAN);
+
2545 }
+
2546
+
2547 // z axis
+
2548 addLine(make_vec3(origin.x, origin.y, mult*-1*length.z+origin.z), make_vec3(origin.x, origin.y, length.z+origin.z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
+
2549
+
2550 if(length.z > 0){
+
2551 addTextboxByCenter("+ Z", helios::make_vec3( origin.x, origin.y, length.z+origin.z), helios::make_SphericalCoord(0,0), helios::make_RGBcolor( 0.f, 0.f, 0.f ), uint(200*Lmag), "OpenSans-Regular", Visualizer::COORDINATES_CARTESIAN);
+
2552
+
2553 }
2554
-
2555}
+
2555
+
2556}
-
2556
2557
-
-
2558void Visualizer::addGridWireFrame(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &subdiv){
-
2559
-
2560 helios::vec3 boxmin, boxmax;
-
2561 boxmin = make_vec3(center.x - 0.5*size.x, center.y - 0.5*size.y, center.z - 0.5*size.z);
-
2562 boxmax = make_vec3(center.x + 0.5*size.x, center.y + 0.5*size.y, center.z + 0.5*size.z);
-
2563
-
2564 float spacing_x = size.x/subdiv.x;
-
2565 float spacing_y = size.y/subdiv.y;
-
2566 float spacing_z = size.z/subdiv.z;
-
2567
-
2568 for(int i=0; i <= subdiv.x; i++)
-
2569 {
-
2570 for(int j=0; j <= subdiv.y; j++)
-
2571 {
-
2572 addLine(make_vec3(boxmin.x + i*spacing_x, boxmin.y + j*spacing_y, boxmin.z), make_vec3(boxmin.x + i*spacing_x, boxmin.y + j*spacing_y, boxmax.z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
-
2573 }
-
2574 }
-
2575
-
2576 for(int i=0; i <= subdiv.z ; i++)
-
2577 {
-
2578 for(int j=0; j <= subdiv.y; j++)
-
2579 {
-
2580 addLine(make_vec3(boxmin.x , boxmin.y + j*spacing_y, boxmin.z + i*spacing_z), make_vec3(boxmax.x, boxmin.y + j*spacing_y, boxmin.z + i*spacing_z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
-
2581 }
-
2582 }
-
2583
-
2584 for(int i=0; i <= subdiv.x ; i++)
-
2585 {
-
2586 for(int j=0; j <= subdiv.z ; j++)
-
2587 {
-
2588 addLine(make_vec3(boxmin.x + i*spacing_x , boxmin.y, boxmin.z + j*spacing_z), make_vec3(boxmin.x + i*spacing_x, boxmax.y, boxmin.z + j*spacing_z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
-
2589 }
-
2590 }
-
2591
-
2592}
+
2558
+
+
2559void Visualizer::addGridWireFrame(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &subdiv){
+
2560
+
2561 helios::vec3 boxmin, boxmax;
+
2562 boxmin = make_vec3(center.x - 0.5*size.x, center.y - 0.5*size.y, center.z - 0.5*size.z);
+
2563 boxmax = make_vec3(center.x + 0.5*size.x, center.y + 0.5*size.y, center.z + 0.5*size.z);
+
2564
+
2565 float spacing_x = size.x/subdiv.x;
+
2566 float spacing_y = size.y/subdiv.y;
+
2567 float spacing_z = size.z/subdiv.z;
+
2568
+
2569 for(int i=0; i <= subdiv.x; i++)
+
2570 {
+
2571 for(int j=0; j <= subdiv.y; j++)
+
2572 {
+
2573 addLine(make_vec3(boxmin.x + i*spacing_x, boxmin.y + j*spacing_y, boxmin.z), make_vec3(boxmin.x + i*spacing_x, boxmin.y + j*spacing_y, boxmax.z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
+
2574 }
+
2575 }
+
2576
+
2577 for(int i=0; i <= subdiv.z ; i++)
+
2578 {
+
2579 for(int j=0; j <= subdiv.y; j++)
+
2580 {
+
2581 addLine(make_vec3(boxmin.x , boxmin.y + j*spacing_y, boxmin.z + i*spacing_z), make_vec3(boxmax.x, boxmin.y + j*spacing_y, boxmin.z + i*spacing_z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
+
2582 }
+
2583 }
+
2584
+
2585 for(int i=0; i <= subdiv.x ; i++)
+
2586 {
+
2587 for(int j=0; j <= subdiv.z ; j++)
+
2588 {
+
2589 addLine(make_vec3(boxmin.x + i*spacing_x , boxmin.y, boxmin.z + j*spacing_z), make_vec3(boxmin.x + i*spacing_x, boxmax.y, boxmin.z + j*spacing_z), RGB::black, 1, Visualizer::COORDINATES_CARTESIAN);
+
2590 }
+
2591 }
+
2592
+
2593}
-
2593
-
- -
2595 colorbar_flag = 2;
-
2596}
+
2594
+
+ +
2596 colorbar_flag = 2;
+
2597}
-
2597
-
- -
2599 colorbar_flag = 1;
-
2600}
+
2598
+
+ +
2600 colorbar_flag = 1;
+
2601}
-
2601
-
- -
2603 if( position.x < 0 || position.x>1 || position.y<0 || position.y>1 || position.z<-1 || position.z>1 ){
-
2604 helios_runtime_error("ERROR (Visualizer::setColorbarPosition): position is out of range. Coordinates must be: 0<x<1, 0<y<1, -1<z<1.");
-
2605 }
-
2606 colorbar_position = position;
-
2607}
+
2602
+
+ +
2604 if( position.x < 0 || position.x>1 || position.y<0 || position.y>1 || position.z<-1 || position.z>1 ){
+
2605 helios_runtime_error("ERROR (Visualizer::setColorbarPosition): position is out of range. Coordinates must be: 0<x<1, 0<y<1, -1<z<1.");
+
2606 }
+
2607 colorbar_position = position;
+
2608}
-
2608
-
- -
2610 if( size.x < 0 || size.x>1 || size.y<0 || size.y>1 ){
-
2611 helios_runtime_error("ERROR (Visualizer::setColorbarSize): Size must be greater than 0 and less than the window size (i.e., 1).");
-
2612 }
-
2613 colorbar_size = size;
-
2614}
+
2609
+
+ +
2611 if( size.x < 0 || size.x>1 || size.y<0 || size.y>1 ){
+
2612 helios_runtime_error("ERROR (Visualizer::setColorbarSize): Size must be greater than 0 and less than the window size (i.e., 1).");
+
2613 }
+
2614 colorbar_size = size;
+
2615}
-
2615
-
-
2616void Visualizer::setColorbarRange( float cmin, float cmax ){
-
2617 if( message_flag && cmin>cmax ) {
-
2618 std::cout << "WARNING (Visualizer::setColorbarRange): Maximum colorbar value must be greater than minimum value...Ignoring command." << std::endl;
-
2619 }
-
2620 return;
-
2621 colorbar_min = cmin;
-
2622 colorbar_max = cmax;
-
2623}
+
2616
+
+
2617void Visualizer::setColorbarRange( float cmin, float cmax ){
+
2618 if( message_flag && cmin>cmax ) {
+
2619 std::cout << "WARNING (Visualizer::setColorbarRange): Maximum colorbar value must be greater than minimum value...Ignoring command." << std::endl;
+
2620 }
+
2621 return;
+
2622 colorbar_min = cmin;
+
2623 colorbar_max = cmax;
+
2624}
-
2624
-
-
2625void Visualizer::setColorbarTicks(const std::vector<float> &ticks ){
-
2626
-
2627 //check that vector is not empty
-
2628 if( ticks.empty() ){
-
2629 helios_runtime_error("ERROR (Visualizer::setColorbarTicks): Colorbar ticks vector is empty.");
-
2630 }
-
2631
-
2632 //Check that ticks are monotonically increasing
-
2633 for( int i=1; i<ticks.size(); i++ ){
-
2634 if( ticks.at(i)<=ticks.at(i-1) ){
-
2635 helios_runtime_error("ERROR (Visualizer::setColorbarTicks): Colorbar ticks must be monotonically increasing.");
-
2636 }
-
2637 }
-
2638
-
2639 //Check that ticks are within the range of colorbar values
-
2640 for( int i=ticks.size()-1; i>=0; i-- ){
-
2641 if( ticks.at(i)<colorbar_min ){
-
2642 colorbar_min = ticks.at(i);
-
2643 }
-
2644 }
-
2645 for( float tick : ticks){
-
2646 if( tick>colorbar_max ){
-
2647 colorbar_max = tick;
-
2648 }
-
2649 }
-
2650
-
2651 colorbar_ticks = ticks;
-
2652}
+
2625
+
+
2626void Visualizer::setColorbarTicks(const std::vector<float> &ticks ){
+
2627
+
2628 //check that vector is not empty
+
2629 if( ticks.empty() ){
+
2630 helios_runtime_error("ERROR (Visualizer::setColorbarTicks): Colorbar ticks vector is empty.");
+
2631 }
+
2632
+
2633 //Check that ticks are monotonically increasing
+
2634 for( int i=1; i<ticks.size(); i++ ){
+
2635 if( ticks.at(i)<=ticks.at(i-1) ){
+
2636 helios_runtime_error("ERROR (Visualizer::setColorbarTicks): Colorbar ticks must be monotonically increasing.");
+
2637 }
+
2638 }
+
2639
+
2640 //Check that ticks are within the range of colorbar values
+
2641 for( int i=ticks.size()-1; i>=0; i-- ){
+
2642 if( ticks.at(i)<colorbar_min ){
+
2643 colorbar_min = ticks.at(i);
+
2644 }
+
2645 }
+
2646 for( float tick : ticks){
+
2647 if( tick>colorbar_max ){
+
2648 colorbar_max = tick;
+
2649 }
+
2650 }
+
2651
+
2652 colorbar_ticks = ticks;
+
2653}
-
2653
-
-
2654void Visualizer::setColorbarTitle( const char* title ){
-
2655 colorbar_title = title;
-
2656}
+
2654
+
+
2655void Visualizer::setColorbarTitle( const char* title ){
+
2656 colorbar_title = title;
+
2657}
-
2657
-
-
2658void Visualizer::setColorbarFontSize( uint font_size ){
-
2659 if( font_size<=0 ){
-
2660 helios_runtime_error("ERROR (Visualizer::setColorbarFontSize): Font size must be greater than zero.");
-
2661 }
-
2662 colorbar_fontsize = font_size;
-
2663}
+
2658
+
+
2659void Visualizer::setColorbarFontSize( uint font_size ){
+
2660 if( font_size<=0 ){
+
2661 helios_runtime_error("ERROR (Visualizer::setColorbarFontSize): Font size must be greater than zero.");
+
2662 }
+
2663 colorbar_fontsize = font_size;
+
2664}
-
2664
-
- -
2666 colorbar_fontcolor = fontcolor;
-
2667}
+
2665
+
+ +
2667 colorbar_fontcolor = fontcolor;
+
2668}
-
2668
-
-
2669void Visualizer::setColormap( Ctable colormap_name ){
-
2670 if( colormap_name==COLORMAP_HOT ){
-
2671 colormap_current = colormap_hot;
-
2672 }else if( colormap_name==COLORMAP_COOL ){
-
2673 colormap_current = colormap_cool;
-
2674 }else if( colormap_name==COLORMAP_LAVA ){
-
2675 colormap_current = colormap_lava;
-
2676 }else if( colormap_name==COLORMAP_RAINBOW ){
-
2677 colormap_current = colormap_rainbow;
-
2678 }else if( colormap_name==COLORMAP_PARULA ){
-
2679 colormap_current = colormap_parula;
-
2680 }else if( colormap_name==COLORMAP_GRAY ){
-
2681 colormap_current = colormap_gray;
-
2682 }else if( colormap_name==COLORMAP_CUSTOM ){
-
2683 helios_runtime_error("ERROR (Visualizer::setColormap): Setting a custom colormap requires calling setColormap with additional arguments defining the colormap.");
-
2684 }else{
-
2685 helios_runtime_error("ERROR (Visualizer::setColormap): Invalid colormap.");
-
2686 }
-
2687}
+
2669
+
+
2670void Visualizer::setColormap( Ctable colormap_name ){
+
2671 if( colormap_name==COLORMAP_HOT ){
+
2672 colormap_current = colormap_hot;
+
2673 }else if( colormap_name==COLORMAP_COOL ){
+
2674 colormap_current = colormap_cool;
+
2675 }else if( colormap_name==COLORMAP_LAVA ){
+
2676 colormap_current = colormap_lava;
+
2677 }else if( colormap_name==COLORMAP_RAINBOW ){
+
2678 colormap_current = colormap_rainbow;
+
2679 }else if( colormap_name==COLORMAP_PARULA ){
+
2680 colormap_current = colormap_parula;
+
2681 }else if( colormap_name==COLORMAP_GRAY ){
+
2682 colormap_current = colormap_gray;
+
2683 }else if( colormap_name==COLORMAP_CUSTOM ){
+
2684 helios_runtime_error("ERROR (Visualizer::setColormap): Setting a custom colormap requires calling setColormap with additional arguments defining the colormap.");
+
2685 }else{
+
2686 helios_runtime_error("ERROR (Visualizer::setColormap): Invalid colormap.");
+
2687 }
+
2688}
-
2688
-
-
2689void Visualizer::setColormap(const std::vector<RGBcolor> &colors, const std::vector<float> &divisions ){
-
2690
-
2691 if( colors.size() != divisions.size() ){
-
2692 helios_runtime_error("ERROR (Visualizer::setColormap): The number of colors must be equal to the number of divisions.");
-
2693 }
-
2694
-
2695 Colormap colormap_custom( colors, divisions, 100, 0, 1 );
-
2696
-
2697 colormap_current = colormap_custom;
-
2698
-
2699}
+
2689
+
+
2690void Visualizer::setColormap(const std::vector<RGBcolor> &colors, const std::vector<float> &divisions ){
+
2691
+
2692 if( colors.size() != divisions.size() ){
+
2693 helios_runtime_error("ERROR (Visualizer::setColormap): The number of colors must be equal to the number of divisions.");
+
2694 }
+
2695
+
2696 Colormap colormap_custom( colors, divisions, 100, 0, 1 );
+
2697
+
2698 colormap_current = colormap_custom;
+
2699
+
2700}
-
2700
-
- -
2702 return colormap_current;
-
2703}
+
2701
+
+ +
2703 return colormap_current;
+
2704}
-
2704
-
- -
2706 std::vector<uint> UUIDs = context_ptr->getAllUUIDs();
-
2707 buildContextGeometry(context_ptr, UUIDs);
-
2708}
+
2705
+
+ +
2707 std::vector<uint> UUIDs = context_ptr->getAllUUIDs();
+
2708 buildContextGeometry(context_ptr, UUIDs);
+
2709}
-
2709
-
-
2710void Visualizer::buildContextGeometry(helios::Context* context_ptr, const std::vector<uint>& UUIDs ){
-
2711
-
2712 if( UUIDs.empty() ){
-
2713 std::cerr << "WARNING (Visualizer::buildContextGeometry): There is no Context geometry to build...exiting." << std::endl;
-
2714 return;
-
2715 }else if( !colorPrimitives_UUIDs.empty() || !colorPrimitives_objIDs.empty() ){
-
2716 std::cerr << "WARNING (Visualizer::buildContextGeometry): Existing Context geometry already exists in the Visualizer and will not be removed. You may have intended to call Visualizer::clearGeometry() first to clear old Context geometry." << std::endl;
-
2717 }
-
2718
+
2710
+
+
2711void Visualizer::buildContextGeometry(helios::Context* context_ptr, const std::vector<uint>& UUIDs ){
+
2712
+
2713 if( UUIDs.empty() ){
+
2714 std::cerr << "WARNING (Visualizer::buildContextGeometry): There is no Context geometry to build...exiting." << std::endl;
+
2715 return;
+
2716 }else if( !colorPrimitives_UUIDs.empty() || !colorPrimitives_objIDs.empty() ){
+
2717 std::cerr << "WARNING (Visualizer::buildContextGeometry): Existing Context geometry already exists in the Visualizer and will not be removed. You may have intended to call Visualizer::clearGeometry() first to clear old Context geometry." << std::endl;
+
2718 }
2719
-
2720 context = context_ptr;
-
2721 contextGeomNeedsUpdate = true;
-
2722
-
2723 contextPrimitiveIDs.insert(contextPrimitiveIDs.begin(), UUIDs.begin(), UUIDs.end() );
-
2724
-
2725 //Set the view to fit window
-
2726 if( camera_lookat_center.x==0 && camera_lookat_center.y==0 && camera_lookat_center.z==0 ){ //default center
-
2727 if( camera_eye_location.x<1e-4 && camera_eye_location.y<1e-4 && camera_eye_location.z==2.f ){ //default eye position
-
2728
-
2729 vec3 center_sph;
-
2730 vec2 xbounds, ybounds, zbounds;
-
2731 float radius;
-
2732 context->getDomainBoundingSphere( UUIDs, center_sph, radius );
-
2733 context->getDomainBoundingBox( UUIDs, xbounds, ybounds, zbounds );
-
2734 camera_lookat_center = make_vec3( 0.5*(xbounds.x+xbounds.y), 0.5*(ybounds.x+ybounds.y), 0.5*(zbounds.x+zbounds.y) );
-
2735 camera_eye_location = camera_lookat_center + sphere2cart( make_SphericalCoord(2.f*radius,20.f*M_PI/180.f,0) );
-
2736
-
2737 }
-
2738 }
-
2739
-
2740}
+
2720
+
2721 context = context_ptr;
+
2722 contextGeomNeedsUpdate = true;
+
2723
+
2724 contextPrimitiveIDs.insert(contextPrimitiveIDs.begin(), UUIDs.begin(), UUIDs.end() );
+
2725
+
2726 //Set the view to fit window
+
2727 if( camera_lookat_center.x==0 && camera_lookat_center.y==0 && camera_lookat_center.z==0 ){ //default center
+
2728 if( camera_eye_location.x<1e-4 && camera_eye_location.y<1e-4 && camera_eye_location.z==2.f ){ //default eye position
+
2729
+
2730 vec3 center_sph;
+
2731 vec2 xbounds, ybounds, zbounds;
+
2732 float radius;
+
2733 context->getDomainBoundingSphere( UUIDs, center_sph, radius );
+
2734 context->getDomainBoundingBox( UUIDs, xbounds, ybounds, zbounds );
+
2735 camera_lookat_center = make_vec3( 0.5*(xbounds.x+xbounds.y), 0.5*(ybounds.x+ybounds.y), 0.5*(zbounds.x+zbounds.y) );
+
2736 camera_eye_location = camera_lookat_center + sphere2cart( make_SphericalCoord(2.f*radius,20.f*M_PI/180.f,0) );
+
2737
+
2738 }
+
2739 }
+
2740
+
2741}
-
2741
-
2742void Visualizer::buildContextGeometry_private() {
-
2743
-
2744 contextGeomNeedsUpdate = false;
-
2745
-
2746 if( !colorPrimitivesByData.empty() ){
-
2747
-
2748 if( colorPrimitives_UUIDs.empty() ) { //load all primitives
-
2749 for (uint UUID: contextPrimitiveIDs) {
-
2750 if (context->doesPrimitiveExist(UUID)) {
-
2751 colorPrimitives_UUIDs[UUID] = UUID;
-
2752 }
-
2753 }
-
2754 }else { //double check that primitives exist
-
2755 for (uint UUID: contextPrimitiveIDs) {
-
2756 if ( !context->doesPrimitiveExist(UUID)) {
-
2757 auto it = colorPrimitives_UUIDs.find(UUID);
-
2758 colorPrimitives_UUIDs.erase( it );
-
2759 }
-
2760 }
-
2761 }
-
2762
-
2763 }else if( !colorPrimitivesByObjectData.empty() ) {
-
2764
-
2765 if( colorPrimitives_objIDs.empty() ) { //load all primitives
-
2766 std::vector<uint> ObjIDs = context->getAllObjectIDs();
-
2767 for( uint objID: ObjIDs ) {
-
2768 if( context->doesObjectExist(objID) ) {
-
2769 std::vector<uint> UUIDs = context->getObjectPointer(objID)->getPrimitiveUUIDs();
-
2770 for( uint UUID : UUIDs ) {
-
2771 if (context->doesPrimitiveExist(UUID)) {
-
2772 colorPrimitives_UUIDs[UUID] = UUID;
-
2773 }
-
2774 }
-
2775 }
-
2776 }
-
2777 }else { //load primitives specified by user
-
2778 for ( const auto &objID: colorPrimitives_objIDs ) {
-
2779 if( context->doesObjectExist( objID.first )) {
-
2780 std::vector<uint> UUIDs = context->getObjectPointer(objID.first)->getPrimitiveUUIDs();
-
2781 for (uint UUID: UUIDs) {
-
2782 if (context->doesPrimitiveExist(UUID)) {
-
2783 colorPrimitives_UUIDs[UUID] = UUID;
-
2784 }
-
2785 }
-
2786 }
-
2787 }
-
2788 }
-
2789
-
2790 }
-
2791
-
2792 if( !colorPrimitives_UUIDs.empty() && colorbar_flag == 0) {
- -
2794 }
-
2795
-
2796 //------ Colormap ------//
-
2797
-
2798 uint psize = contextPrimitiveIDs.size();
-
2799 if( message_flag ){
-
2800 if( psize>0 ){
-
2801 if( psize>=1e3 && psize<1e6 ){
-
2802 std::cout << "Adding " << psize/1e3 << "K Context primitives to visualizer...." << std::flush;
-
2803 }else if( psize>=1e6 ){
-
2804 std::cout << "Adding " << psize/1e6 << "M Context primitives to visualizer...." << std::flush;
-
2805 }else{
-
2806 std::cout << "Adding " << psize << " Context primitives to visualizer...." << std::flush;
-
2807 }
-
2808 }else{
-
2809 std::cout << "WARNING (Visualizer::buildContextGeometry): No primitives were found in the Context..." << std::endl;
-
2810 }
-
2811 }
-
2812
-
2813 //do a pre-sort of primitive UUIDs by texture
-
2814 std::map<std::string,std::vector<uint> > UUID_texture;
-
2815 for( uint p=0; p<psize; p++ ){
-
2816
-
2817 uint UUID = contextPrimitiveIDs.at(p);
-
2818
-
2819 if( context->doesPrimitiveExist(UUID) ) {
-
2820
-
2821 std::string texture_file = context->getPrimitiveTextureFile(UUID);
-
2822
-
2823 UUID_texture[texture_file].push_back(UUID);
-
2824
-
2825 }
-
2826
-
2827 }
-
2828
-
2829 //figure out colorbar range
-
2830
-
2831 colormap_current.setRange( colorbar_min, colorbar_max );
-
2832 if( colorbar_min==0 && colorbar_max==0 ){//range was not set by user, use full range of values
-
2833
-
2834 colorbar_min = INFINITY;
-
2835 colorbar_max = -INFINITY;
-
2836
-
2837 for(auto iter = UUID_texture.begin(); iter != UUID_texture.end(); ++iter){
-
2838
-
2839 std::vector<uint> UUIDs = iter->second;
-
2840
-
2841 for( size_t u=0; u<UUIDs.size(); u++ ){
-
2842
-
2843 uint UUID = UUIDs.at(u);
-
2844
-
2845 float colorValue=-9999;
-
2846 if( !colorPrimitivesByData.empty() ){
-
2847 if( colorPrimitives_UUIDs.find(UUID) != colorPrimitives_UUIDs.end() ){
-
2848 if( context->doesPrimitiveDataExist( UUID, colorPrimitivesByData.c_str() ) ){
-
2849 HeliosDataType type = context->getPrimitiveDataType( UUID, colorPrimitivesByData.c_str() );
-
2850 if( type==HELIOS_TYPE_FLOAT ){
-
2851 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), colorValue );
-
2852 }else if( type==HELIOS_TYPE_INT ){
-
2853 int cv;
-
2854 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
-
2855 colorValue = float(cv);
-
2856 }else if( type==HELIOS_TYPE_UINT ){
-
2857 uint cv;
-
2858 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
-
2859 colorValue = float(cv);
-
2860 }else if( type==HELIOS_TYPE_DOUBLE ){
-
2861 double cv;
-
2862 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
-
2863 colorValue = float(cv);
-
2864 }else{
-
2865 colorValue = 0;
-
2866 }
-
2867 }else{
-
2868 colorValue = 0;
-
2869 }
-
2870 }
-
2871 }else if( !colorPrimitivesByObjectData.empty() ){
-
2872 if( colorPrimitives_UUIDs.find(UUID) != colorPrimitives_UUIDs.end() ){
-
2873 uint ObjID = context->getPrimitiveParentObjectID(UUID);
-
2874 if( ObjID==0 ){
-
2875 colorValue = 0;
-
2876 }else if( context->doesObjectDataExist( ObjID, colorPrimitivesByObjectData.c_str() ) ){
-
2877 HeliosDataType type = context->getObjectDataType( ObjID, colorPrimitivesByObjectData.c_str() );
-
2878 if( type==HELIOS_TYPE_FLOAT ){
-
2879 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), colorValue );
-
2880 }else if( type==HELIOS_TYPE_INT ){
-
2881 int cv;
-
2882 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
-
2883 colorValue = float(cv);
-
2884 }else if( type==HELIOS_TYPE_UINT ){
-
2885 uint cv;
-
2886 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
-
2887 colorValue = float(cv);
-
2888 }else if( type==HELIOS_TYPE_DOUBLE ){
-
2889 double cv;
-
2890 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
-
2891 colorValue = float(cv);
-
2892 }else{
-
2893 colorValue = 0;
-
2894 }
-
2895 }else{
-
2896 colorValue = 0;
-
2897 }
-
2898 }
-
2899 }
-
2900
-
2901 if( colorValue!=colorValue || colorValue==INFINITY ) {//check for NaN or infinity
-
2902 colorValue = 0;
-
2903 }
-
2904
-
2905 if( colorValue!=-9999 ){
-
2906 if( colorValue<colorbar_min ){
-
2907 colorbar_min = colorValue;;
-
2908 }
-
2909 if( colorValue>colorbar_max ){
-
2910 colorbar_max = colorValue;;
-
2911 }
-
2912 }
-
2913
-
2914 }
-
2915 }
-
2916
-
2917 if( colorbar_min!=INFINITY && colorbar_max!=-INFINITY ){
-
2918 colormap_current.setRange( colorbar_min, colorbar_max );
-
2919 }
-
2920 }
-
2921
-
2922 if( !colorPrimitivesByData.empty() ) {
-
2923 assert(colorbar_min <= colorbar_max);
-
2924 }
-
2925
-
2926 //------- Simulation Geometry -------//
-
2927
-
2928 //add primitives
-
2929
-
2930 for(auto iter = UUID_texture.begin(); iter != UUID_texture.end(); ++iter){
-
2931
-
2932 std::vector<uint> UUIDs = iter->second;
-
2933
-
2934 for( size_t u=0; u<UUIDs.size(); u++ ){
-
2935
-
2936 uint UUID = UUIDs.at(u);
-
2937
-
2938 if( !context->doesPrimitiveExist(UUID) ){
-
2939 std::cerr << "WARNING (Visualizer::buildContextGeometry): UUID vector contains ID(s) that do not exist in the Context...they will be ignored." << std::endl;
-
2940 continue;
-
2941 }
-
2942
-
2943 helios::PrimitiveType ptype = context->getPrimitiveType(UUID);
-
2944
-
2945 std::vector<vec3> verts = context->getPrimitiveVertices(UUID);
-
2946 std::string texture_file = context->getPrimitiveTextureFile(UUID);
-
2947
-
2948 RGBAcolor color;
-
2949 float colorValue;
-
2950 if( !colorPrimitivesByData.empty() ){
-
2951 if( colorPrimitives_UUIDs.find(UUID) != colorPrimitives_UUIDs.end() ){
-
2952 if( context->doesPrimitiveDataExist( UUID, colorPrimitivesByData.c_str() ) ){
-
2953 HeliosDataType type = context->getPrimitiveDataType( UUID, colorPrimitivesByData.c_str() );
-
2954 if( type==HELIOS_TYPE_FLOAT ){
-
2955 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), colorValue );
-
2956 }else if( type==HELIOS_TYPE_INT ){
-
2957 int cv;
-
2958 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
-
2959 colorValue = float(cv);
-
2960 }else if( type==HELIOS_TYPE_UINT ){
-
2961 uint cv;
-
2962 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
-
2963 colorValue = float(cv);
-
2964 }else if( type==HELIOS_TYPE_DOUBLE ){
-
2965 double cv;
-
2966 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
-
2967 colorValue = float(cv);
-
2968 }else{
-
2969 colorValue = 0;
-
2970 }
-
2971
-
2972 }else{
-
2973 colorValue = 0;
-
2974 }
-
2975
-
2976 if( colorValue!=colorValue || colorValue==INFINITY ) {//check for NaN or infinity
-
2977 colorValue = 0;
-
2978 }
-
2979
-
2980 color = make_RGBAcolor(colormap_current.query( colorValue ),1);
-
2981 }else{
-
2982 color = context->getPrimitiveColorRGBA(UUID);
-
2983 }
-
2984 }else if( !colorPrimitivesByObjectData.empty() ){
-
2985 if( colorPrimitives_UUIDs.find(UUID) != colorPrimitives_UUIDs.end() ){
-
2986 uint ObjID = context->getPrimitiveParentObjectID(UUID);
-
2987 if( ObjID==0 ){
-
2988 colorValue = 0;
-
2989 }else if( context->doesObjectDataExist( ObjID, colorPrimitivesByObjectData.c_str() ) ){
-
2990 HeliosDataType type = context->getObjectDataType( ObjID, colorPrimitivesByObjectData.c_str() );
-
2991 if( type==HELIOS_TYPE_FLOAT ){
-
2992 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), colorValue );
-
2993 }else if( type==HELIOS_TYPE_INT ){
-
2994 int cv;
-
2995 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
-
2996 colorValue = float(cv);
-
2997 }else if( type==HELIOS_TYPE_UINT ){
-
2998 uint cv;
-
2999 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
-
3000 colorValue = float(cv);
-
3001 }else if( type==HELIOS_TYPE_DOUBLE ){
-
3002 double cv;
-
3003 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
-
3004 colorValue = float(cv);
-
3005 }else{
-
3006 colorValue = 0;
-
3007 }
-
3008 }else{
-
3009 colorValue = 0;
-
3010 }
-
3011
-
3012 if( colorValue!=colorValue || colorValue==INFINITY ) {//check for NaN or infinity
-
3013 colorValue = 0;
-
3014 }
-
3015
-
3016 color = make_RGBAcolor(colormap_current.query( colorValue ),1);
-
3017 }else{
-
3018 color = context->getPrimitiveColorRGBA(UUID);
-
3019 }
-
3020 }else{
-
3021 color = context->getPrimitiveColorRGBA(UUID);
-
3022 }
-
3023
-
3024 if( ptype == helios::PRIMITIVE_TYPE_PATCH ){
-
3025
-
3026 if( texture_file.empty() ){//Patch does not have an associated texture or we are ignoring texture
- -
3028 }else{ //Patch has a texture
-
3029
-
3030 std::vector<vec2> uvs = context->getPrimitiveTextureUV(UUID);
-
3031
-
3032 if( colorPrimitives_UUIDs.find(UUID) == colorPrimitives_UUIDs.end() || colorPrimitives_UUIDs.empty() ){//coloring primitive based on texture
-
3033 if( uvs.size()==4 ){//custom (u,v) coordinates
-
3034 if( context->isPrimitiveTextureColorOverridden(UUID) ){
-
3035 addRectangleByVertices( verts, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), uvs, COORDINATES_CARTESIAN );
-
3036 }else{
-
3037 addRectangleByVertices( verts, texture_file.c_str(), uvs, COORDINATES_CARTESIAN );
-
3038 }
-
3039 }else{//default (u,v) coordinates
-
3040 if( context->isPrimitiveTextureColorOverridden(UUID) ){
-
3041 addRectangleByVertices( verts, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3042 }else{
-
3043 addRectangleByVertices( verts, texture_file.c_str(), COORDINATES_CARTESIAN );
-
3044 }
-
3045 }
-
3046 }else{//coloring primitive based on primitive data
-
3047 if( uvs.size()==4 ){//custom (u,v) coordinates
-
3048 addRectangleByVertices( verts, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), uvs, COORDINATES_CARTESIAN );
-
3049 }else{//default (u,v) coordinates
-
3050 addRectangleByVertices( verts, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3051 }
-
3052 }
-
3053 }
-
3054
-
3055 }else if( ptype == helios::PRIMITIVE_TYPE_TRIANGLE ){
-
3056
-
3057 if( texture_file.empty() ){//Triangle does not have an associated texture or we are ignoring texture
-
3058 addTriangle( verts.at(0), verts.at(1), verts.at(2), color, COORDINATES_CARTESIAN );
-
3059 }else{ //Triangle has a texture
-
3060
-
3061 std::vector<vec2> uvs = context->getPrimitiveTextureUV(UUID);
-
3062
-
3063 if( colorPrimitives_UUIDs.find(UUID) == colorPrimitives_UUIDs.end() || colorPrimitives_UUIDs.size()==0 ){//coloring primitive based on texture
-
3064 if( context->isPrimitiveTextureColorOverridden(UUID) ){
-
3065 addTriangle( verts.at(0), verts.at(1), verts.at(2), texture_file.c_str(), uvs.at(0), uvs.at(1), uvs.at(2), make_RGBAcolor(color.r,color.g,color.b,1), COORDINATES_CARTESIAN );
-
3066 }else{
-
3067 addTriangle( verts.at(0), verts.at(1), verts.at(2), texture_file.c_str(), uvs.at(0), uvs.at(1), uvs.at(2), COORDINATES_CARTESIAN );
-
3068 }
-
3069 }else{//coloring primitive based on primitive data
-
3070 addTriangle( verts.at(0), verts.at(1), verts.at(2), texture_file.c_str(), uvs.at(0), uvs.at(1), uvs.at(2), make_RGBAcolor(color.r,color.g,color.b,1), COORDINATES_CARTESIAN );
-
3071 }
-
3072
-
3073 }
-
3074
-
3075 }else if( ptype == helios::PRIMITIVE_TYPE_VOXEL ){
-
3076
-
3077 std::vector<vec3> v_vertices = context->getPrimitiveVertices(UUID);
-
3078
-
3079 std::vector<vec3> bottom_vertices, top_vertices, mx_vertices, px_vertices, my_vertices, py_vertices;
-
3080 bottom_vertices.resize(4);
-
3081 top_vertices.resize(4);
-
3082 mx_vertices.resize(4);
-
3083 px_vertices.resize(4);
-
3084 my_vertices.resize(4);
-
3085 py_vertices.resize(4);
-
3086
-
3087 //bottom
-
3088 bottom_vertices.at(0) = v_vertices.at(0);
-
3089 bottom_vertices.at(1) = v_vertices.at(1);
-
3090 bottom_vertices.at(2) = v_vertices.at(2);
-
3091 bottom_vertices.at(3) = v_vertices.at(3);
-
3092
-
3093 //top
-
3094 top_vertices.at(0) = v_vertices.at(4);
-
3095 top_vertices.at(1) = v_vertices.at(5);
-
3096 top_vertices.at(2) = v_vertices.at(6);
-
3097 top_vertices.at(3) = v_vertices.at(7);
-
3098
-
3099 //-x
-
3100 mx_vertices.at(0) = v_vertices.at(0);
-
3101 mx_vertices.at(1) = v_vertices.at(3);
-
3102 mx_vertices.at(2) = v_vertices.at(7);
-
3103 mx_vertices.at(3) = v_vertices.at(4);
-
3104
-
3105 //+x
-
3106 px_vertices.at(0) = v_vertices.at(1);
-
3107 px_vertices.at(1) = v_vertices.at(2);
-
3108 px_vertices.at(2) = v_vertices.at(6);
-
3109 px_vertices.at(3) = v_vertices.at(5);
-
3110
-
3111 //-y
-
3112 my_vertices.at(0) = v_vertices.at(0);
-
3113 my_vertices.at(1) = v_vertices.at(1);
-
3114 my_vertices.at(2) = v_vertices.at(5);
-
3115 my_vertices.at(3) = v_vertices.at(4);
-
3116
-
3117 //+y
-
3118 py_vertices.at(0) = v_vertices.at(2);
-
3119 py_vertices.at(1) = v_vertices.at(3);
-
3120 py_vertices.at(2) = v_vertices.at(7);
-
3121 py_vertices.at(3) = v_vertices.at(6);
-
3122
-
3123 if( texture_file.size()==0 ){//Voxel does not have an associated texture or we are ignoring texture
-
3124
-
3125 addRectangleByVertices( bottom_vertices, color, COORDINATES_CARTESIAN );
-
3126 addRectangleByVertices( top_vertices, color, COORDINATES_CARTESIAN );
-
3127 addRectangleByVertices( mx_vertices, color, COORDINATES_CARTESIAN );
-
3128 addRectangleByVertices( px_vertices, color, COORDINATES_CARTESIAN );
-
3129 addRectangleByVertices( my_vertices, color, COORDINATES_CARTESIAN );
-
3130 addRectangleByVertices( py_vertices, color, COORDINATES_CARTESIAN );
-
3131
-
3132 }else{ //Voxel has a texture
-
3133
-
3134 if( colorPrimitives_UUIDs.find(UUID) == colorPrimitives_UUIDs.end() || colorPrimitives_UUIDs.size()==0 ){//coloring primitive based on texture
-
3135 if( context->isPrimitiveTextureColorOverridden(UUID) ){
-
3136 addRectangleByVertices( bottom_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3137 addRectangleByVertices( top_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3138 addRectangleByVertices( mx_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3139 addRectangleByVertices( px_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3140 addRectangleByVertices( my_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3141 addRectangleByVertices( py_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3142 }else{
-
3143 addRectangleByVertices( bottom_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
-
3144 addRectangleByVertices( top_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
-
3145 addRectangleByVertices( mx_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
-
3146 addRectangleByVertices( px_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
-
3147 addRectangleByVertices( my_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
-
3148 addRectangleByVertices( py_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
-
3149 }
-
3150 }else{//coloring primitive based on primitive data
-
3151 addRectangleByVertices( bottom_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3152 addRectangleByVertices( top_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3153 addRectangleByVertices( mx_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3154 addRectangleByVertices( px_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3155 addRectangleByVertices( my_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3156 addRectangleByVertices( py_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
-
3157 }
-
3158
-
3159 }
-
3160
+
2742
+
2743void Visualizer::buildContextGeometry_private() {
+
2744
+
2745 contextGeomNeedsUpdate = false;
+
2746
+
2747 if( !colorPrimitivesByData.empty() ){
+
2748
+
2749 if( colorPrimitives_UUIDs.empty() ) { //load all primitives
+
2750 for (uint UUID: contextPrimitiveIDs) {
+
2751 if (context->doesPrimitiveExist(UUID)) {
+
2752 colorPrimitives_UUIDs[UUID] = UUID;
+
2753 }
+
2754 }
+
2755 }else { //double check that primitives exist
+
2756 for (uint UUID: contextPrimitiveIDs) {
+
2757 if ( !context->doesPrimitiveExist(UUID)) {
+
2758 auto it = colorPrimitives_UUIDs.find(UUID);
+
2759 colorPrimitives_UUIDs.erase( it );
+
2760 }
+
2761 }
+
2762 }
+
2763
+
2764 }else if( !colorPrimitivesByObjectData.empty() ) {
+
2765
+
2766 if( colorPrimitives_objIDs.empty() ) { //load all primitives
+
2767 std::vector<uint> ObjIDs = context->getAllObjectIDs();
+
2768 for( uint objID: ObjIDs ) {
+
2769 if( context->doesObjectExist(objID) ) {
+
2770 std::vector<uint> UUIDs = context->getObjectPointer(objID)->getPrimitiveUUIDs();
+
2771 for( uint UUID : UUIDs ) {
+
2772 if (context->doesPrimitiveExist(UUID)) {
+
2773 colorPrimitives_UUIDs[UUID] = UUID;
+
2774 }
+
2775 }
+
2776 }
+
2777 }
+
2778 }else { //load primitives specified by user
+
2779 for ( const auto &objID: colorPrimitives_objIDs ) {
+
2780 if( context->doesObjectExist( objID.first )) {
+
2781 std::vector<uint> UUIDs = context->getObjectPointer(objID.first)->getPrimitiveUUIDs();
+
2782 for (uint UUID: UUIDs) {
+
2783 if (context->doesPrimitiveExist(UUID)) {
+
2784 colorPrimitives_UUIDs[UUID] = UUID;
+
2785 }
+
2786 }
+
2787 }
+
2788 }
+
2789 }
+
2790
+
2791 }
+
2792
+
2793 if( !colorPrimitives_UUIDs.empty() && colorbar_flag == 0) {
+ +
2795 }
+
2796
+
2797 //------ Colormap ------//
+
2798
+
2799 uint psize = contextPrimitiveIDs.size();
+
2800 if( message_flag ){
+
2801 if( psize>0 ){
+
2802 if( psize>=1e3 && psize<1e6 ){
+
2803 std::cout << "Adding " << psize/1e3 << "K Context primitives to visualizer...." << std::flush;
+
2804 }else if( psize>=1e6 ){
+
2805 std::cout << "Adding " << psize/1e6 << "M Context primitives to visualizer...." << std::flush;
+
2806 }else{
+
2807 std::cout << "Adding " << psize << " Context primitives to visualizer...." << std::flush;
+
2808 }
+
2809 }else{
+
2810 std::cout << "WARNING (Visualizer::buildContextGeometry): No primitives were found in the Context..." << std::endl;
+
2811 }
+
2812 }
+
2813
+
2814 //do a pre-sort of primitive UUIDs by texture
+
2815 std::map<std::string,std::vector<uint> > UUID_texture;
+
2816 for( uint p=0; p<psize; p++ ){
+
2817
+
2818 uint UUID = contextPrimitiveIDs.at(p);
+
2819
+
2820 if( context->doesPrimitiveExist(UUID) ) {
+
2821
+
2822 std::string texture_file = context->getPrimitiveTextureFile(UUID);
+
2823
+
2824 UUID_texture[texture_file].push_back(UUID);
+
2825
+
2826 }
+
2827
+
2828 }
+
2829
+
2830 //figure out colorbar range
+
2831
+
2832 colormap_current.setRange( colorbar_min, colorbar_max );
+
2833 if( colorbar_min==0 && colorbar_max==0 ){//range was not set by user, use full range of values
+
2834
+
2835 colorbar_min = INFINITY;
+
2836 colorbar_max = -INFINITY;
+
2837
+
2838 for(auto iter = UUID_texture.begin(); iter != UUID_texture.end(); ++iter){
+
2839
+
2840 std::vector<uint> UUIDs = iter->second;
+
2841
+
2842 for( size_t u=0; u<UUIDs.size(); u++ ){
+
2843
+
2844 uint UUID = UUIDs.at(u);
+
2845
+
2846 float colorValue=-9999;
+
2847 if( !colorPrimitivesByData.empty() ){
+
2848 if( colorPrimitives_UUIDs.find(UUID) != colorPrimitives_UUIDs.end() ){
+
2849 if( context->doesPrimitiveDataExist( UUID, colorPrimitivesByData.c_str() ) ){
+
2850 HeliosDataType type = context->getPrimitiveDataType( UUID, colorPrimitivesByData.c_str() );
+
2851 if( type==HELIOS_TYPE_FLOAT ){
+
2852 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), colorValue );
+
2853 }else if( type==HELIOS_TYPE_INT ){
+
2854 int cv;
+
2855 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
+
2856 colorValue = float(cv);
+
2857 }else if( type==HELIOS_TYPE_UINT ){
+
2858 uint cv;
+
2859 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
+
2860 colorValue = float(cv);
+
2861 }else if( type==HELIOS_TYPE_DOUBLE ){
+
2862 double cv;
+
2863 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
+
2864 colorValue = float(cv);
+
2865 }else{
+
2866 colorValue = 0;
+
2867 }
+
2868 }else{
+
2869 colorValue = 0;
+
2870 }
+
2871 }
+
2872 }else if( !colorPrimitivesByObjectData.empty() ){
+
2873 if( colorPrimitives_UUIDs.find(UUID) != colorPrimitives_UUIDs.end() ){
+
2874 uint ObjID = context->getPrimitiveParentObjectID(UUID);
+
2875 if( ObjID==0 ){
+
2876 colorValue = 0;
+
2877 }else if( context->doesObjectDataExist( ObjID, colorPrimitivesByObjectData.c_str() ) ){
+
2878 HeliosDataType type = context->getObjectDataType( ObjID, colorPrimitivesByObjectData.c_str() );
+
2879 if( type==HELIOS_TYPE_FLOAT ){
+
2880 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), colorValue );
+
2881 }else if( type==HELIOS_TYPE_INT ){
+
2882 int cv;
+
2883 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
+
2884 colorValue = float(cv);
+
2885 }else if( type==HELIOS_TYPE_UINT ){
+
2886 uint cv;
+
2887 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
+
2888 colorValue = float(cv);
+
2889 }else if( type==HELIOS_TYPE_DOUBLE ){
+
2890 double cv;
+
2891 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
+
2892 colorValue = float(cv);
+
2893 }else{
+
2894 colorValue = 0;
+
2895 }
+
2896 }else{
+
2897 colorValue = 0;
+
2898 }
+
2899 }
+
2900 }
+
2901
+
2902 if( colorValue!=colorValue || colorValue==INFINITY ) {//check for NaN or infinity
+
2903 colorValue = 0;
+
2904 }
+
2905
+
2906 if( colorValue!=-9999 ){
+
2907 if( colorValue<colorbar_min ){
+
2908 colorbar_min = colorValue;;
+
2909 }
+
2910 if( colorValue>colorbar_max ){
+
2911 colorbar_max = colorValue;;
+
2912 }
+
2913 }
+
2914
+
2915 }
+
2916 }
+
2917
+
2918 if( colorbar_min!=INFINITY && colorbar_max!=-INFINITY ){
+
2919 colormap_current.setRange( colorbar_min, colorbar_max );
+
2920 }
+
2921 }
+
2922
+
2923 if( !colorPrimitivesByData.empty() ) {
+
2924 assert(colorbar_min <= colorbar_max);
+
2925 }
+
2926
+
2927 //------- Simulation Geometry -------//
+
2928
+
2929 //add primitives
+
2930
+
2931 for(auto iter = UUID_texture.begin(); iter != UUID_texture.end(); ++iter){
+
2932
+
2933 std::vector<uint> UUIDs = iter->second;
+
2934
+
2935 for( size_t u=0; u<UUIDs.size(); u++ ){
+
2936
+
2937 uint UUID = UUIDs.at(u);
+
2938
+
2939 if( !context->doesPrimitiveExist(UUID) ){
+
2940 std::cerr << "WARNING (Visualizer::buildContextGeometry): UUID vector contains ID(s) that do not exist in the Context...they will be ignored." << std::endl;
+
2941 continue;
+
2942 }
+
2943
+
2944 helios::PrimitiveType ptype = context->getPrimitiveType(UUID);
+
2945
+
2946 std::vector<vec3> verts = context->getPrimitiveVertices(UUID);
+
2947 std::string texture_file = context->getPrimitiveTextureFile(UUID);
+
2948
+
2949 RGBAcolor color;
+
2950 float colorValue;
+
2951 if( !colorPrimitivesByData.empty() ){
+
2952 if( colorPrimitives_UUIDs.find(UUID) != colorPrimitives_UUIDs.end() ){
+
2953 if( context->doesPrimitiveDataExist( UUID, colorPrimitivesByData.c_str() ) ){
+
2954 HeliosDataType type = context->getPrimitiveDataType( UUID, colorPrimitivesByData.c_str() );
+
2955 if( type==HELIOS_TYPE_FLOAT ){
+
2956 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), colorValue );
+
2957 }else if( type==HELIOS_TYPE_INT ){
+
2958 int cv;
+
2959 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
+
2960 colorValue = float(cv);
+
2961 }else if( type==HELIOS_TYPE_UINT ){
+
2962 uint cv;
+
2963 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
+
2964 colorValue = float(cv);
+
2965 }else if( type==HELIOS_TYPE_DOUBLE ){
+
2966 double cv;
+
2967 context->getPrimitiveData( UUID, colorPrimitivesByData.c_str(), cv );
+
2968 colorValue = float(cv);
+
2969 }else{
+
2970 colorValue = 0;
+
2971 }
+
2972
+
2973 }else{
+
2974 colorValue = 0;
+
2975 }
+
2976
+
2977 if( colorValue!=colorValue || colorValue==INFINITY ) {//check for NaN or infinity
+
2978 colorValue = 0;
+
2979 }
+
2980
+
2981 color = make_RGBAcolor(colormap_current.query( colorValue ),1);
+
2982 }else{
+
2983 color = context->getPrimitiveColorRGBA(UUID);
+
2984 }
+
2985 }else if( !colorPrimitivesByObjectData.empty() ){
+
2986 if( colorPrimitives_UUIDs.find(UUID) != colorPrimitives_UUIDs.end() ){
+
2987 uint ObjID = context->getPrimitiveParentObjectID(UUID);
+
2988 if( ObjID==0 ){
+
2989 colorValue = 0;
+
2990 }else if( context->doesObjectDataExist( ObjID, colorPrimitivesByObjectData.c_str() ) ){
+
2991 HeliosDataType type = context->getObjectDataType( ObjID, colorPrimitivesByObjectData.c_str() );
+
2992 if( type==HELIOS_TYPE_FLOAT ){
+
2993 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), colorValue );
+
2994 }else if( type==HELIOS_TYPE_INT ){
+
2995 int cv;
+
2996 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
+
2997 colorValue = float(cv);
+
2998 }else if( type==HELIOS_TYPE_UINT ){
+
2999 uint cv;
+
3000 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
+
3001 colorValue = float(cv);
+
3002 }else if( type==HELIOS_TYPE_DOUBLE ){
+
3003 double cv;
+
3004 context->getObjectData( ObjID, colorPrimitivesByObjectData.c_str(), cv );
+
3005 colorValue = float(cv);
+
3006 }else{
+
3007 colorValue = 0;
+
3008 }
+
3009 }else{
+
3010 colorValue = 0;
+
3011 }
+
3012
+
3013 if( colorValue!=colorValue || colorValue==INFINITY ) {//check for NaN or infinity
+
3014 colorValue = 0;
+
3015 }
+
3016
+
3017 color = make_RGBAcolor(colormap_current.query( colorValue ),1);
+
3018 }else{
+
3019 color = context->getPrimitiveColorRGBA(UUID);
+
3020 }
+
3021 }else{
+
3022 color = context->getPrimitiveColorRGBA(UUID);
+
3023 }
+
3024
+
3025 if( ptype == helios::PRIMITIVE_TYPE_PATCH ){
+
3026
+
3027 if( texture_file.empty() ){//Patch does not have an associated texture or we are ignoring texture
+ +
3029 }else{ //Patch has a texture
+
3030
+
3031 std::vector<vec2> uvs = context->getPrimitiveTextureUV(UUID);
+
3032
+
3033 if( colorPrimitives_UUIDs.find(UUID) == colorPrimitives_UUIDs.end() || colorPrimitives_UUIDs.empty() ){//coloring primitive based on texture
+
3034 if( uvs.size()==4 ){//custom (u,v) coordinates
+
3035 if( context->isPrimitiveTextureColorOverridden(UUID) ){
+
3036 addRectangleByVertices( verts, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), uvs, COORDINATES_CARTESIAN );
+
3037 }else{
+
3038 addRectangleByVertices( verts, texture_file.c_str(), uvs, COORDINATES_CARTESIAN );
+
3039 }
+
3040 }else{//default (u,v) coordinates
+
3041 if( context->isPrimitiveTextureColorOverridden(UUID) ){
+
3042 addRectangleByVertices( verts, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3043 }else{
+
3044 addRectangleByVertices( verts, texture_file.c_str(), COORDINATES_CARTESIAN );
+
3045 }
+
3046 }
+
3047 }else{//coloring primitive based on primitive data
+
3048 if( uvs.size()==4 ){//custom (u,v) coordinates
+
3049 addRectangleByVertices( verts, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), uvs, COORDINATES_CARTESIAN );
+
3050 }else{//default (u,v) coordinates
+
3051 addRectangleByVertices( verts, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3052 }
+
3053 }
+
3054 }
+
3055
+
3056 }else if( ptype == helios::PRIMITIVE_TYPE_TRIANGLE ){
+
3057
+
3058 if( texture_file.empty() ){//Triangle does not have an associated texture or we are ignoring texture
+
3059 addTriangle( verts.at(0), verts.at(1), verts.at(2), color, COORDINATES_CARTESIAN );
+
3060 }else{ //Triangle has a texture
+
3061
+
3062 std::vector<vec2> uvs = context->getPrimitiveTextureUV(UUID);
+
3063
+
3064 if( colorPrimitives_UUIDs.find(UUID) == colorPrimitives_UUIDs.end() || colorPrimitives_UUIDs.size()==0 ){//coloring primitive based on texture
+
3065 if( context->isPrimitiveTextureColorOverridden(UUID) ){
+
3066 addTriangle( verts.at(0), verts.at(1), verts.at(2), texture_file.c_str(), uvs.at(0), uvs.at(1), uvs.at(2), make_RGBAcolor(color.r,color.g,color.b,1), COORDINATES_CARTESIAN );
+
3067 }else{
+
3068 addTriangle( verts.at(0), verts.at(1), verts.at(2), texture_file.c_str(), uvs.at(0), uvs.at(1), uvs.at(2), COORDINATES_CARTESIAN );
+
3069 }
+
3070 }else{//coloring primitive based on primitive data
+
3071 addTriangle( verts.at(0), verts.at(1), verts.at(2), texture_file.c_str(), uvs.at(0), uvs.at(1), uvs.at(2), make_RGBAcolor(color.r,color.g,color.b,1), COORDINATES_CARTESIAN );
+
3072 }
+
3073
+
3074 }
+
3075
+
3076 }else if( ptype == helios::PRIMITIVE_TYPE_VOXEL ){
+
3077
+
3078 std::vector<vec3> v_vertices = context->getPrimitiveVertices(UUID);
+
3079
+
3080 std::vector<vec3> bottom_vertices, top_vertices, mx_vertices, px_vertices, my_vertices, py_vertices;
+
3081 bottom_vertices.resize(4);
+
3082 top_vertices.resize(4);
+
3083 mx_vertices.resize(4);
+
3084 px_vertices.resize(4);
+
3085 my_vertices.resize(4);
+
3086 py_vertices.resize(4);
+
3087
+
3088 //bottom
+
3089 bottom_vertices.at(0) = v_vertices.at(0);
+
3090 bottom_vertices.at(1) = v_vertices.at(1);
+
3091 bottom_vertices.at(2) = v_vertices.at(2);
+
3092 bottom_vertices.at(3) = v_vertices.at(3);
+
3093
+
3094 //top
+
3095 top_vertices.at(0) = v_vertices.at(4);
+
3096 top_vertices.at(1) = v_vertices.at(5);
+
3097 top_vertices.at(2) = v_vertices.at(6);
+
3098 top_vertices.at(3) = v_vertices.at(7);
+
3099
+
3100 //-x
+
3101 mx_vertices.at(0) = v_vertices.at(0);
+
3102 mx_vertices.at(1) = v_vertices.at(3);
+
3103 mx_vertices.at(2) = v_vertices.at(7);
+
3104 mx_vertices.at(3) = v_vertices.at(4);
+
3105
+
3106 //+x
+
3107 px_vertices.at(0) = v_vertices.at(1);
+
3108 px_vertices.at(1) = v_vertices.at(2);
+
3109 px_vertices.at(2) = v_vertices.at(6);
+
3110 px_vertices.at(3) = v_vertices.at(5);
+
3111
+
3112 //-y
+
3113 my_vertices.at(0) = v_vertices.at(0);
+
3114 my_vertices.at(1) = v_vertices.at(1);
+
3115 my_vertices.at(2) = v_vertices.at(5);
+
3116 my_vertices.at(3) = v_vertices.at(4);
+
3117
+
3118 //+y
+
3119 py_vertices.at(0) = v_vertices.at(2);
+
3120 py_vertices.at(1) = v_vertices.at(3);
+
3121 py_vertices.at(2) = v_vertices.at(7);
+
3122 py_vertices.at(3) = v_vertices.at(6);
+
3123
+
3124 if( texture_file.size()==0 ){//Voxel does not have an associated texture or we are ignoring texture
+
3125
+
3126 addRectangleByVertices( bottom_vertices, color, COORDINATES_CARTESIAN );
+
3127 addRectangleByVertices( top_vertices, color, COORDINATES_CARTESIAN );
+
3128 addRectangleByVertices( mx_vertices, color, COORDINATES_CARTESIAN );
+
3129 addRectangleByVertices( px_vertices, color, COORDINATES_CARTESIAN );
+
3130 addRectangleByVertices( my_vertices, color, COORDINATES_CARTESIAN );
+
3131 addRectangleByVertices( py_vertices, color, COORDINATES_CARTESIAN );
+
3132
+
3133 }else{ //Voxel has a texture
+
3134
+
3135 if( colorPrimitives_UUIDs.find(UUID) == colorPrimitives_UUIDs.end() || colorPrimitives_UUIDs.size()==0 ){//coloring primitive based on texture
+
3136 if( context->isPrimitiveTextureColorOverridden(UUID) ){
+
3137 addRectangleByVertices( bottom_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3138 addRectangleByVertices( top_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3139 addRectangleByVertices( mx_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3140 addRectangleByVertices( px_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3141 addRectangleByVertices( my_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3142 addRectangleByVertices( py_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3143 }else{
+
3144 addRectangleByVertices( bottom_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
+
3145 addRectangleByVertices( top_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
+
3146 addRectangleByVertices( mx_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
+
3147 addRectangleByVertices( px_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
+
3148 addRectangleByVertices( my_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
+
3149 addRectangleByVertices( py_vertices, texture_file.c_str(), COORDINATES_CARTESIAN );
+
3150 }
+
3151 }else{//coloring primitive based on primitive data
+
3152 addRectangleByVertices( bottom_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3153 addRectangleByVertices( top_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3154 addRectangleByVertices( mx_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3155 addRectangleByVertices( px_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3156 addRectangleByVertices( my_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3157 addRectangleByVertices( py_vertices, make_RGBcolor(color.r,color.g,color.b), texture_file.c_str(), COORDINATES_CARTESIAN );
+
3158 }
+
3159
+
3160 }
3161
-
3162 }
-
3163
-
3164 }
-
3165 }
-
3166
-
3167 if( message_flag ){
-
3168 std::cout << "done." << std::endl;
-
3169 }
-
3170
-
3171}
-
3172
-
-
3173void Visualizer::colorContextPrimitivesByData( const char* data_name ){
-
3174 colorPrimitivesByData = data_name;
-
3175 colorPrimitivesByObjectData = "";
-
3176 if( !colorPrimitives_UUIDs.empty() ){
-
3177 colorPrimitives_UUIDs.clear();
-
3178 }
-
3179 if( !colorPrimitives_objIDs.empty() ){
-
3180 colorPrimitives_objIDs.clear();
-
3181 }
-
3182}
+
3162
+
3163 }
+
3164
+
3165 }
+
3166 }
+
3167
+
3168 if( message_flag ){
+
3169 std::cout << "done." << std::endl;
+
3170 }
+
3171
+
3172}
+
3173
+
+
3174void Visualizer::colorContextPrimitivesByData( const char* data_name ){
+
3175 colorPrimitivesByData = data_name;
+
3176 colorPrimitivesByObjectData = "";
+
3177 if( !colorPrimitives_UUIDs.empty() ){
+
3178 colorPrimitives_UUIDs.clear();
+
3179 }
+
3180 if( !colorPrimitives_objIDs.empty() ){
+
3181 colorPrimitives_objIDs.clear();
+
3182 }
+
3183}
-
3183
-
-
3184void Visualizer::colorContextPrimitivesByData( const char* data_name, const std::vector<uint>& UUIDs ){
-
3185 colorPrimitivesByData = data_name;
-
3186 colorPrimitivesByObjectData = "";
-
3187 for( uint UUID : UUIDs ){
-
3188 colorPrimitives_UUIDs[UUID] = UUID;
-
3189 }
-
3190 if( !colorPrimitives_objIDs.empty() ){
-
3191 colorPrimitives_objIDs.clear();
-
3192 }
-
3193}
+
3184
+
+
3185void Visualizer::colorContextPrimitivesByData( const char* data_name, const std::vector<uint>& UUIDs ){
+
3186 colorPrimitivesByData = data_name;
+
3187 colorPrimitivesByObjectData = "";
+
3188 for( uint UUID : UUIDs ){
+
3189 colorPrimitives_UUIDs[UUID] = UUID;
+
3190 }
+
3191 if( !colorPrimitives_objIDs.empty() ){
+
3192 colorPrimitives_objIDs.clear();
+
3193 }
+
3194}
-
3194
-
- -
3196 colorPrimitivesByObjectData = data_name;
-
3197 colorPrimitivesByData = "";
-
3198 if( !colorPrimitives_UUIDs.empty() ){
-
3199 colorPrimitives_UUIDs.clear();
-
3200 }
-
3201 if( !colorPrimitives_objIDs.empty() ){
-
3202 colorPrimitives_objIDs.clear();
-
3203 }
-
3204}
+
3195
+
+ +
3197 colorPrimitivesByObjectData = data_name;
+
3198 colorPrimitivesByData = "";
+
3199 if( !colorPrimitives_UUIDs.empty() ){
+
3200 colorPrimitives_UUIDs.clear();
+
3201 }
+
3202 if( !colorPrimitives_objIDs.empty() ){
+
3203 colorPrimitives_objIDs.clear();
+
3204 }
+
3205}
-
3205
-
-
3206void Visualizer::colorContextPrimitivesByObjectData( const char* data_name, const std::vector<uint>& ObjIDs ){
-
3207 colorPrimitivesByObjectData = data_name;
-
3208 colorPrimitivesByData = "";
-
3209 for( uint objID : ObjIDs ){
-
3210 colorPrimitives_objIDs[objID] = objID;
-
3211 }
-
3212 if( !colorPrimitives_UUIDs.empty() ){
-
3213 colorPrimitives_UUIDs.clear();
-
3214 }
-
3215}
+
3206
+
+
3207void Visualizer::colorContextPrimitivesByObjectData( const char* data_name, const std::vector<uint>& ObjIDs ){
+
3208 colorPrimitivesByObjectData = data_name;
+
3209 colorPrimitivesByData = "";
+
3210 for( uint objID : ObjIDs ){
+
3211 colorPrimitives_objIDs[objID] = objID;
+
3212 }
+
3213 if( !colorPrimitives_UUIDs.empty() ){
+
3214 colorPrimitives_UUIDs.clear();
+
3215 }
+
3216}
-
3216
-
-
3217void Visualizer::colorContextPrimitivesRandomly(const std::vector<uint>& UUIDs ){
-
3218
- -
3220 if( !colorPrimitives_UUIDs.empty() ){
-
3221 colorPrimitives_UUIDs.clear();
-
3222 }
-
3223 for( uint UUID : UUIDs ){
-
3224 float rc = randu();
-
3225 context->setPrimitiveData(UUID, "random_color", rc);
-
3226 }
-
3227
-
3228 colorPrimitivesByData = "random_color";
-
3229 colorPrimitivesByObjectData = "";
-
3230 for( uint UUID : UUIDs ){
-
3231 colorPrimitives_UUIDs[UUID] = UUID;
-
3232 }
-
3233 if( !colorPrimitives_objIDs.empty() ){
-
3234 colorPrimitives_objIDs.clear();
-
3235 }
-
3236}
+
3217
+
+
3218void Visualizer::colorContextPrimitivesRandomly(const std::vector<uint>& UUIDs ){
+
3219
+ +
3221 if( !colorPrimitives_UUIDs.empty() ){
+
3222 colorPrimitives_UUIDs.clear();
+
3223 }
+
3224 for( uint UUID : UUIDs ){
+
3225 float rc = randu();
+
3226 context->setPrimitiveData(UUID, "random_color", rc);
+
3227 }
+
3228
+
3229 colorPrimitivesByData = "random_color";
+
3230 colorPrimitivesByObjectData = "";
+
3231 for( uint UUID : UUIDs ){
+
3232 colorPrimitives_UUIDs[UUID] = UUID;
+
3233 }
+
3234 if( !colorPrimitives_objIDs.empty() ){
+
3235 colorPrimitives_objIDs.clear();
+
3236 }
+
3237}
-
3237
-
- -
3239
- -
3241
-
3242 std::vector<uint> all_UUIDs = context->getAllUUIDs();
-
3243 for( uint UUID : all_UUIDs ){
-
3244 float rc = randu();
-
3245 context->setPrimitiveData(UUID, "random_color", rc);
-
3246 }
-
3247
-
3248 colorPrimitivesByData = "random_color";
-
3249 colorPrimitivesByObjectData = "";
-
3250 if( !colorPrimitives_UUIDs.empty() ){
-
3251 colorPrimitives_UUIDs.clear();
-
3252 }
-
3253 if( !colorPrimitives_objIDs.empty() ){
-
3254 colorPrimitives_objIDs.clear();
-
3255 }
-
3256
-
3257}
+
3238
+
+ +
3240
+ +
3242
+
3243 std::vector<uint> all_UUIDs = context->getAllUUIDs();
+
3244 for( uint UUID : all_UUIDs ){
+
3245 float rc = randu();
+
3246 context->setPrimitiveData(UUID, "random_color", rc);
+
3247 }
+
3248
+
3249 colorPrimitivesByData = "random_color";
+
3250 colorPrimitivesByObjectData = "";
+
3251 if( !colorPrimitives_UUIDs.empty() ){
+
3252 colorPrimitives_UUIDs.clear();
+
3253 }
+
3254 if( !colorPrimitives_objIDs.empty() ){
+
3255 colorPrimitives_objIDs.clear();
+
3256 }
+
3257
+
3258}
-
3258
3259
-
-
3260void Visualizer::colorContextObjectsRandomly(const std::vector<uint>& ObjIDs ){
-
3261
- -
3263 if( !colorPrimitives_UUIDs.empty() ){
-
3264 colorPrimitives_UUIDs.clear();
-
3265 }
-
3266 for( uint ObjID : ObjIDs ){
-
3267 float rc = randu();
-
3268 context->setObjectData(ObjID, "random_color", rc);
-
3269 }
-
3270
-
3271 colorPrimitivesByData = "";
-
3272 colorPrimitivesByObjectData = "random_color";
-
3273
-
3274}
+
3260
+
+
3261void Visualizer::colorContextObjectsRandomly(const std::vector<uint>& ObjIDs ){
+
3262
+ +
3264 if( !colorPrimitives_UUIDs.empty() ){
+
3265 colorPrimitives_UUIDs.clear();
+
3266 }
+
3267 for( uint ObjID : ObjIDs ){
+
3268 float rc = randu();
+
3269 context->setObjectData(ObjID, "random_color", rc);
+
3270 }
+
3271
+
3272 colorPrimitivesByData = "";
+
3273 colorPrimitivesByObjectData = "random_color";
+
3274
+
3275}
-
3275
-
- -
3277 std::vector<uint> all_ObjIDs = context->getAllObjectIDs();
- -
3279 if( !colorPrimitives_UUIDs.empty() ){
-
3280 colorPrimitives_UUIDs.clear();
-
3281 }
-
3282 for( uint ObjID : all_ObjIDs ){
-
3283 float rc = randu();
-
3284 context->setObjectData(ObjID, "random_color", rc);
-
3285 }
-
3286
-
3287 colorPrimitivesByData = "";
-
3288 colorPrimitivesByObjectData = "random_color";
-
3289
-
3290}
+
3276
+
+ +
3278 std::vector<uint> all_ObjIDs = context->getAllObjectIDs();
+ +
3280 if( !colorPrimitives_UUIDs.empty() ){
+
3281 colorPrimitives_UUIDs.clear();
+
3282 }
+
3283 for( uint ObjID : all_ObjIDs ){
+
3284 float rc = randu();
+
3285 context->setObjectData(ObjID, "random_color", rc);
+
3286 }
+
3287
+
3288 colorPrimitivesByData = "";
+
3289 colorPrimitivesByObjectData = "random_color";
+
3290
+
3291}
-
3291
3292
3293
3294
3295
-
3296float dphi = 0.0;
-
3297float dtheta = 0.0;
-
3298float dx = 0.0;
-
3299float dy = 0.0;
-
3300float dz = 0.0;
-
3301float dx_m = 0.0;
-
3302float dy_m = 0.0;
-
3303float dscroll = 0.0;
-
3304
+
3296
+
3297float dphi = 0.0;
+
3298float dtheta = 0.0;
+
3299float dx = 0.0;
+
3300float dy = 0.0;
+
3301float dz = 0.0;
+
3302float dx_m = 0.0;
+
3303float dy_m = 0.0;
+
3304float dscroll = 0.0;
3305
-
-
3306std::vector<helios::vec3> Visualizer::plotInteractive() {
-
3307
-
3308 if( message_flag ){
-
3309 std::cout << "Generating interactive plot..." << std::endl;
-
3310 }
-
3311
-
3312// glfwShowWindow( (GLFWwindow*) window);
-
3313
-
3314// openWindow();
-
3315
-
3316 //Update the Context geometry (if needed)
-
3317 if( contextGeomNeedsUpdate ){
-
3318 buildContextGeometry_private();
-
3319 }else{
-
3320 colormap_current.setRange( colorbar_min, colorbar_max );
-
3321 }
-
3322
-
3323 //Update
-
3324 if( colorbar_flag==2 ){
-
3325 addColorbarByCenter( colorbar_title.c_str(), colorbar_size, colorbar_position, colorbar_fontcolor, colormap_current );
-
3326 }
-
3327
-
3328 //Watermark
-
3329 if( isWatermarkVisible ){
-
3330 float hratio = float(Wdisplay)/float(Hdisplay);
-
3331 float width = 0.2389f/0.8f/hratio;
-
3332 addRectangleByCenter( make_vec3(0.75f*width,0.95f,0), make_vec2(width,0.07), make_SphericalCoord(0,0), "plugins/visualizer/textures/Helios_watermark.png", COORDINATES_WINDOW_NORMALIZED );
-
3333 }
-
3334
-
3335 setupPlot();
-
3336
-
3337 //domain bounding box
-
3338 vec2 xbounds, ybounds, zbounds;
-
3339 getDomainBoundingBox( xbounds, ybounds, zbounds );
-
3340
-
3341 glm::vec3 view_center = glm::vec3( xbounds.x+0.5*(xbounds.y-xbounds.x), ybounds.x+0.5*(ybounds.y-ybounds.x), zbounds.x+0.5*(zbounds.y-zbounds.x) );
-
3342 //float bound_R = 2.f*fmax(xbounds.y-xbounds.x,fmax(ybounds.y-ybounds.x,zbounds.y-zbounds.x));
-
3343 float bound_R = 0.75*sqrtf( pow(xbounds.y-xbounds.x,2) + pow(ybounds.y-ybounds.x,2) + pow(zbounds.y-zbounds.x,2) );
-
3344
-
3345 glm::vec3 lightInvDir = view_center + glm::vec3(light_direction.x,light_direction.y,light_direction.z);
-
3346
-
3347 bool shadow_flag = false;
-
3348 for( uint m=0; m<primaryLightingModel.size(); m++ ){
-
3349 if( primaryLightingModel.at(m) == Visualizer::LIGHTING_PHONG_SHADOWED ){
-
3350 shadow_flag = true;
-
3351 break;
-
3352 }
-
3353 }
-
3354
-
3355 glm::mat4 depthMVP;
-
3356
-
3357 if( shadow_flag ){
-
3358
-
3359 // Depth buffer for shadows
-
3360 glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
-
3361 glViewport(0,0,8192,8192); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3362 //glViewport(0,0,16384,16384); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3363
-
3364 // Clear the screen
-
3365 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
3366
-
3367 depthShader.useShader();
-
3368
-
3369 // Compute the MVP matrix from the light's point of view
-
3370 glm::mat4 depthProjectionMatrix = glm::ortho<float>(-bound_R,bound_R,-bound_R,bound_R,-bound_R,bound_R);
-
3371 glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, view_center, glm::vec3(0,0,1));
-
3372 depthMVP = depthProjectionMatrix * depthViewMatrix;
-
3373
-
3374 depthShader.setTransformationMatrix( depthMVP );
-
3375
-
3376 //bind depth texture
-
3377 glActiveTexture(GL_TEXTURE1);
-
3378 glBindTexture(GL_TEXTURE_2D, depthTexture);
-
3379
-
3380 depthShader.enableTextureMaps();
-
3381 depthShader.enableTextureMasks();
-
3382
-
3383 render( 1 );
-
3384
-
3385 }else{
-
3386
-
3387 depthMVP = glm::mat4(1.0);
-
3388
-
3389 }
-
3390
-
3391 assert(checkerrors());
-
3392
-
3393 std::vector<vec3> camera_output;
-
3394
-
3395 glfwShowWindow( (GLFWwindow*) window);
-
3396
-
3397 do{
-
3398
-
3399 // Render to the screen
-
3400 glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
3401 //glViewport(0,0,Wdisplay,Hdisplay); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3402 glViewport(0,0,Wframebuffer,Hframebuffer);
-
3403
-
3404 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 0.0f);
-
3405
-
3406 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
3407
-
3408 primaryShader.useShader();
-
3409
-
3410 updatePerspectiveTransformation( camera_lookat_center, camera_eye_location );
-
3411
-
3412 glm::mat4 biasMatrix(
-
3413 0.5, 0.0, 0.0, 0.0,
-
3414 0.0, 0.5, 0.0, 0.0,
-
3415 0.0, 0.0, 0.5, 0.0,
-
3416 0.5, 0.5, 0.5, 1.0
-
3417 );
-
3418
-
3419 glm::mat4 DepthBiasMVP = biasMatrix*depthMVP;
-
3420
-
3421 primaryShader.setDepthBiasMatrix( DepthBiasMVP );
-
3422
-
3423 primaryShader.setTransformationMatrix( perspectiveTransformationMatrix );
-
3424
-
3425 primaryShader.enableTextureMaps();
-
3426 primaryShader.enableTextureMasks();
-
3427
-
3428 primaryShader.setLightingModel( primaryLightingModel.at(0) );
-
3429 primaryShader.setLightIntensity( lightintensity );
-
3430
-
3431 glBindTexture(GL_TEXTURE_2D, depthTexture);
-
3432 glUniform1i(primaryShader.shadowmapUniform,1);
-
3433
-
3434 render( 0 );
-
3435
-
3436 glfwPollEvents();
-
3437 getViewKeystrokes( camera_eye_location, camera_lookat_center );
-
3438
-
3439 glfwSwapBuffers((GLFWwindow*)window);
-
3440
-
3441 glfwWaitEvents();
-
3442
-
3443 int width, height;
-
3444 //glfwGetWindowSize((GLFWwindow*)window, &width, &height );
-
3445 //Wdisplay = width;
-
3446 //Hdisplay = height;
-
3447 glfwGetFramebufferSize((GLFWwindow*)window, &width, &height );
-
3448 Wframebuffer = width;
-
3449 Hframebuffer = height;
-
3450
-
3451 }while( glfwGetKey((GLFWwindow*)window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose((GLFWwindow*)window) == 0 );
-
3452
-
3453 glfwPollEvents();
-
3454
-
3455 assert(checkerrors());
-
3456
-
3457 camera_output.push_back(camera_eye_location);
-
3458 camera_output.push_back(camera_lookat_center);
-
3459
-
3460 return camera_output;
-
3461
-
3462}
+
3306
+
+
3307std::vector<helios::vec3> Visualizer::plotInteractive() {
+
3308
+
3309 if( message_flag ){
+
3310 std::cout << "Generating interactive plot..." << std::endl;
+
3311 }
+
3312
+
3313// glfwShowWindow( (GLFWwindow*) window);
+
3314
+
3315// openWindow();
+
3316
+
3317 //Update the Context geometry (if needed)
+
3318 if( contextGeomNeedsUpdate ){
+
3319 buildContextGeometry_private();
+
3320 }else{
+
3321 colormap_current.setRange( colorbar_min, colorbar_max );
+
3322 }
+
3323
+
3324 //Update
+
3325 if( colorbar_flag==2 ){
+
3326 addColorbarByCenter( colorbar_title.c_str(), colorbar_size, colorbar_position, colorbar_fontcolor, colormap_current );
+
3327 }
+
3328
+
3329 //Watermark
+
3330 if( isWatermarkVisible ){
+
3331 float hratio = float(Wdisplay)/float(Hdisplay);
+
3332 float width = 0.2389f/0.8f/hratio;
+
3333 addRectangleByCenter( make_vec3(0.75f*width,0.95f,0), make_vec2(width,0.07), make_SphericalCoord(0,0), "plugins/visualizer/textures/Helios_watermark.png", COORDINATES_WINDOW_NORMALIZED );
+
3334 }
+
3335
+
3336 setupPlot();
+
3337
+
3338 //domain bounding box
+
3339 vec2 xbounds, ybounds, zbounds;
+
3340 getDomainBoundingBox( xbounds, ybounds, zbounds );
+
3341
+
3342 glm::vec3 view_center = glm::vec3( xbounds.x+0.5*(xbounds.y-xbounds.x), ybounds.x+0.5*(ybounds.y-ybounds.x), zbounds.x+0.5*(zbounds.y-zbounds.x) );
+
3343 //float bound_R = 2.f*fmax(xbounds.y-xbounds.x,fmax(ybounds.y-ybounds.x,zbounds.y-zbounds.x));
+
3344 float bound_R = 0.75*sqrtf( pow(xbounds.y-xbounds.x,2) + pow(ybounds.y-ybounds.x,2) + pow(zbounds.y-zbounds.x,2) );
+
3345
+
3346 glm::vec3 lightInvDir = view_center + glm::vec3(light_direction.x,light_direction.y,light_direction.z);
+
3347
+
3348 bool shadow_flag = false;
+
3349 for( uint m=0; m<primaryLightingModel.size(); m++ ){
+
3350 if( primaryLightingModel.at(m) == Visualizer::LIGHTING_PHONG_SHADOWED ){
+
3351 shadow_flag = true;
+
3352 break;
+
3353 }
+
3354 }
+
3355
+
3356 glm::mat4 depthMVP;
+
3357
+
3358 if( shadow_flag ){
+
3359
+
3360 // Depth buffer for shadows
+
3361 glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
+
3362 glViewport(0,0,8192,8192); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3363 //glViewport(0,0,16384,16384); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3364
+
3365 // Clear the screen
+
3366 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
3367
+
3368 depthShader.useShader();
+
3369
+
3370 // Compute the MVP matrix from the light's point of view
+
3371 glm::mat4 depthProjectionMatrix = glm::ortho<float>(-bound_R,bound_R,-bound_R,bound_R,-bound_R,bound_R);
+
3372 glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, view_center, glm::vec3(0,0,1));
+
3373 depthMVP = depthProjectionMatrix * depthViewMatrix;
+
3374
+
3375 depthShader.setTransformationMatrix( depthMVP );
+
3376
+
3377 //bind depth texture
+
3378 glActiveTexture(GL_TEXTURE1);
+
3379 glBindTexture(GL_TEXTURE_2D, depthTexture);
+
3380
+
3381 depthShader.enableTextureMaps();
+
3382 depthShader.enableTextureMasks();
+
3383
+
3384 render( 1 );
+
3385
+
3386 }else{
+
3387
+
3388 depthMVP = glm::mat4(1.0);
+
3389
+
3390 }
+
3391
+
3392 assert(checkerrors());
+
3393
+
3394 std::vector<vec3> camera_output;
+
3395
+
3396 glfwShowWindow( (GLFWwindow*) window);
+
3397
+
3398 do{
+
3399
+
3400 // Render to the screen
+
3401 glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
3402 //glViewport(0,0,Wdisplay,Hdisplay); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3403 glViewport(0,0,Wframebuffer,Hframebuffer);
+
3404
+
3405 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 0.0f);
+
3406
+
3407 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
3408
+
3409 primaryShader.useShader();
+
3410
+
3411 updatePerspectiveTransformation( camera_lookat_center, camera_eye_location );
+
3412
+
3413 glm::mat4 biasMatrix(
+
3414 0.5, 0.0, 0.0, 0.0,
+
3415 0.0, 0.5, 0.0, 0.0,
+
3416 0.0, 0.0, 0.5, 0.0,
+
3417 0.5, 0.5, 0.5, 1.0
+
3418 );
+
3419
+
3420 glm::mat4 DepthBiasMVP = biasMatrix*depthMVP;
+
3421
+
3422 primaryShader.setDepthBiasMatrix( DepthBiasMVP );
+
3423
+
3424 primaryShader.setTransformationMatrix( perspectiveTransformationMatrix );
+
3425
+
3426 primaryShader.enableTextureMaps();
+
3427 primaryShader.enableTextureMasks();
+
3428
+
3429 primaryShader.setLightingModel( primaryLightingModel.at(0) );
+
3430 primaryShader.setLightIntensity( lightintensity );
+
3431
+
3432 glBindTexture(GL_TEXTURE_2D, depthTexture);
+
3433 glUniform1i(primaryShader.shadowmapUniform,1);
+
3434
+
3435 render( 0 );
+
3436
+
3437 glfwPollEvents();
+
3438 getViewKeystrokes( camera_eye_location, camera_lookat_center );
+
3439
+
3440 glfwSwapBuffers((GLFWwindow*)window);
+
3441
+
3442 glfwWaitEvents();
+
3443
+
3444 int width, height;
+
3445 //glfwGetWindowSize((GLFWwindow*)window, &width, &height );
+
3446 //Wdisplay = width;
+
3447 //Hdisplay = height;
+
3448 glfwGetFramebufferSize((GLFWwindow*)window, &width, &height );
+
3449 Wframebuffer = width;
+
3450 Hframebuffer = height;
+
3451
+
3452 }while( glfwGetKey((GLFWwindow*)window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose((GLFWwindow*)window) == 0 );
+
3453
+
3454 glfwPollEvents();
+
3455
+
3456 assert(checkerrors());
+
3457
+
3458 camera_output.push_back(camera_eye_location);
+
3459 camera_output.push_back(camera_lookat_center);
+
3460
+
3461 return camera_output;
+
3462
+
3463}
-
3463
-
3464void Visualizer::setupPlot(){
-
3465
-
3466 glEnableVertexAttribArray(0); //position
-
3467 glEnableVertexAttribArray(1); //color
-
3468 glEnableVertexAttribArray(2); //normal
-
3469 glEnableVertexAttribArray(3); //uv
-
3470 glEnableVertexAttribArray(4); //texture flag
-
3471 glEnableVertexAttribArray(5); //coordinate flag
-
3472
-
3473 std::vector<float> position_data, color_data, normal_data, uv_data;
-
3474 std::vector<int> coordinate_data, texture_data, textureID_data;
-
3475
-
3476 std::vector<std::string> keys{"triangle", "line", "point", "sky" };
-
3477
-
3478 for( int i=0; i<keys.size(); i++ ){
-
3479 position_data.insert( position_data.end(), positionData[keys.at(i)].begin(), positionData[keys.at(i)].end() );
-
3480 color_data.insert( color_data.end(), colorData[keys.at(i)].begin(), colorData[keys.at(i)].end() );
-
3481 normal_data.insert( normal_data.end(), normalData[keys.at(i)].begin(), normalData[keys.at(i)].end() );
-
3482 uv_data.insert( uv_data.end(), uvData[keys.at(i)].begin(), uvData[keys.at(i)].end() );
-
3483 coordinate_data.insert( coordinate_data.end(), coordinateFlagData[keys.at(i)].begin(), coordinateFlagData[keys.at(i)].end() );
-
3484 texture_data.insert( texture_data.end(), textureFlagData[keys.at(i)].begin(), textureFlagData[keys.at(i)].end() );
-
3485 }
-
3486
-
3487 // 1st attribute buffer : vertex positions
-
3488 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer );
-
3489 glBufferData(GL_ARRAY_BUFFER, position_data.size()*sizeof(GLfloat), &position_data[0], GL_STATIC_DRAW);
-
3490 glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
-
3491
-
3492 // 2nd attribute buffer : vertex colors
-
3493 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer );
-
3494 glBufferData(GL_ARRAY_BUFFER, color_data.size()*sizeof(GLfloat), &color_data[0], GL_STATIC_DRAW);
-
3495 glVertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0 );
-
3496
-
3497 // 3rd attribute buffer : vertex normals
-
3498 glBindBuffer(GL_ARRAY_BUFFER, normalBuffer );
-
3499 glBufferData(GL_ARRAY_BUFFER, normal_data.size()*sizeof(GLfloat), &normal_data[0], GL_STATIC_DRAW);
-
3500 glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
-
3501
-
3502 // 4th attribute buffer : vertex uv
-
3503 glBindBuffer(GL_ARRAY_BUFFER, uvBuffer );
-
3504 glBufferData(GL_ARRAY_BUFFER, uv_data.size()*sizeof(GLfloat), &uv_data[0], GL_STATIC_DRAW);
-
3505 glVertexAttribPointer( 3, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
-
3506
-
3507 // 5th attribute buffer : vertex texture flag
-
3508 glBindBuffer(GL_ARRAY_BUFFER, textureFlagBuffer );
-
3509 glBufferData(GL_ARRAY_BUFFER, texture_data.size()*sizeof(GLint), &texture_data[0], GL_STATIC_DRAW);
-
3510 glVertexAttribIPointer( 4, 1, GL_INT, 0, (void*)0 );
-
3511
-
3512 // 6th attribute buffer : vertex coordinate flag
-
3513 glBindBuffer(GL_ARRAY_BUFFER, coordinateFlagBuffer );
-
3514 glBufferData(GL_ARRAY_BUFFER, coordinate_data.size()*sizeof(GLint), &coordinate_data[0], GL_STATIC_DRAW);
-
3515 glVertexAttribIPointer( 5, 1, GL_INT, 0, (void*)0 );
-
3516
-
3517 //figure out texture switches
-
3518
-
3519 uint textureID_current;
-
3520 if( textureIDData["triangle"].size()==0 ){
-
3521 textureID_current = 0;
-
3522 }else{
-
3523 textureID_current = textureIDData["triangle"].at(0);
-
3524 }
-
3525
-
3526 size_t start_current = 0;
-
3527 for( size_t p=1; p<textureIDData["triangle"].size(); p++ ){
-
3528
-
3529 if( textureID_current!=textureIDData["triangle"].at(p) || p == textureIDData["triangle"].size()-1 ){
-
3530 group_start[ start_current ] = make_int2(textureID_current,p-start_current+1);
-
3531 textureID_current = textureIDData["triangle"].at(p);
-
3532 start_current = p;
-
3533 }else{
-
3534 continue;
-
3535 }
-
3536
-
3537 }
-
3538
-
3539}
-
3540
-
3541void Visualizer::render( bool shadow ){
-
3542
-
3543 //--- Triangles------
-
3544
-
3545 uint textureID_current;
-
3546 if( textureIDData["triangle"].size()==0 ){
-
3547 textureID_current = 0;
-
3548 }else{
-
3549 textureID_current = textureIDData["triangle"].at(0);
-
3550 }
-
3551
-
3552 glBindTexture(GL_TEXTURE_RECTANGLE,0);
-
3553
-
3554 for( std::map<uint,int2>::iterator iter=group_start.begin(); iter!=group_start.end(); ++iter ){
-
3555
-
3556 if( iter->second.x!=0 ){
-
3557 glBindTexture(GL_TEXTURE_RECTANGLE,iter->second.x);
-
3558 }
-
3559
-
3560 glDrawArrays(GL_TRIANGLES, iter->first, iter->second.y );
-
3561
-
3562 }
-
3563
-
3564 if( !shadow ){
-
3565
-
3566 size_t triangle_size = positionData["triangle"].size()/3;
-
3567 size_t line_size = positionData["line"].size()/3;
-
3568 size_t point_size = positionData["point"].size()/3;
-
3569
-
3570 if( line_size>0 ){
-
3571 glDrawArrays(GL_LINES, triangle_size, line_size );
-
3572 }
-
3573
-
3574 if( point_size>0 ){
-
3575 glPointSize( point_width );
-
3576 glDrawArrays(GL_POINTS, triangle_size+line_size, point_size );
-
3577 }
-
3578
-
3579 if( positionData["sky"].size()>0 ){
-
3580 primaryShader.setLightingModel( LIGHTING_NONE );
-
3581 glBindTexture(GL_TEXTURE_RECTANGLE,textureIDData["sky"].at(0));
-
3582 glDrawArrays(GL_TRIANGLES, triangle_size+line_size+point_size, positionData["sky"].size()/3 );
-
3583 }
-
3584
-
3585 }
-
3586
-
3587}
-
3588
-
- -
3590 plotUpdate( false );
-
3591}
+
3464
+
3465void Visualizer::setupPlot(){
+
3466
+
3467 glEnableVertexAttribArray(0); //position
+
3468 glEnableVertexAttribArray(1); //color
+
3469 glEnableVertexAttribArray(2); //normal
+
3470 glEnableVertexAttribArray(3); //uv
+
3471 glEnableVertexAttribArray(4); //texture flag
+
3472 glEnableVertexAttribArray(5); //coordinate flag
+
3473
+
3474 std::vector<float> position_data, color_data, normal_data, uv_data;
+
3475 std::vector<int> coordinate_data, texture_data, textureID_data;
+
3476
+
3477 std::vector<std::string> keys{"triangle", "line", "point", "sky" };
+
3478
+
3479 for( int i=0; i<keys.size(); i++ ){
+
3480 position_data.insert( position_data.end(), positionData[keys.at(i)].begin(), positionData[keys.at(i)].end() );
+
3481 color_data.insert( color_data.end(), colorData[keys.at(i)].begin(), colorData[keys.at(i)].end() );
+
3482 normal_data.insert( normal_data.end(), normalData[keys.at(i)].begin(), normalData[keys.at(i)].end() );
+
3483 uv_data.insert( uv_data.end(), uvData[keys.at(i)].begin(), uvData[keys.at(i)].end() );
+
3484 coordinate_data.insert( coordinate_data.end(), coordinateFlagData[keys.at(i)].begin(), coordinateFlagData[keys.at(i)].end() );
+
3485 texture_data.insert( texture_data.end(), textureFlagData[keys.at(i)].begin(), textureFlagData[keys.at(i)].end() );
+
3486 }
+
3487
+
3488 // 1st attribute buffer : vertex positions
+
3489 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer );
+
3490 glBufferData(GL_ARRAY_BUFFER, position_data.size()*sizeof(GLfloat), &position_data[0], GL_STATIC_DRAW);
+
3491 glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
+
3492
+
3493 // 2nd attribute buffer : vertex colors
+
3494 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer );
+
3495 glBufferData(GL_ARRAY_BUFFER, color_data.size()*sizeof(GLfloat), &color_data[0], GL_STATIC_DRAW);
+
3496 glVertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0 );
+
3497
+
3498 // 3rd attribute buffer : vertex normals
+
3499 glBindBuffer(GL_ARRAY_BUFFER, normalBuffer );
+
3500 glBufferData(GL_ARRAY_BUFFER, normal_data.size()*sizeof(GLfloat), &normal_data[0], GL_STATIC_DRAW);
+
3501 glVertexAttribPointer( 2, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
+
3502
+
3503 // 4th attribute buffer : vertex uv
+
3504 glBindBuffer(GL_ARRAY_BUFFER, uvBuffer );
+
3505 glBufferData(GL_ARRAY_BUFFER, uv_data.size()*sizeof(GLfloat), &uv_data[0], GL_STATIC_DRAW);
+
3506 glVertexAttribPointer( 3, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
+
3507
+
3508 // 5th attribute buffer : vertex texture flag
+
3509 glBindBuffer(GL_ARRAY_BUFFER, textureFlagBuffer );
+
3510 glBufferData(GL_ARRAY_BUFFER, texture_data.size()*sizeof(GLint), &texture_data[0], GL_STATIC_DRAW);
+
3511 glVertexAttribIPointer( 4, 1, GL_INT, 0, (void*)0 );
+
3512
+
3513 // 6th attribute buffer : vertex coordinate flag
+
3514 glBindBuffer(GL_ARRAY_BUFFER, coordinateFlagBuffer );
+
3515 glBufferData(GL_ARRAY_BUFFER, coordinate_data.size()*sizeof(GLint), &coordinate_data[0], GL_STATIC_DRAW);
+
3516 glVertexAttribIPointer( 5, 1, GL_INT, 0, (void*)0 );
+
3517
+
3518 //figure out texture switches
+
3519
+
3520 uint textureID_current;
+
3521 if( textureIDData["triangle"].size()==0 ){
+
3522 textureID_current = 0;
+
3523 }else{
+
3524 textureID_current = textureIDData["triangle"].at(0);
+
3525 }
+
3526
+
3527 size_t start_current = 0;
+
3528 for( size_t p=1; p<textureIDData["triangle"].size(); p++ ){
+
3529
+
3530 if( textureID_current!=textureIDData["triangle"].at(p) || p == textureIDData["triangle"].size()-1 ){
+
3531 group_start[ start_current ] = make_int2(textureID_current,p-start_current+1);
+
3532 textureID_current = textureIDData["triangle"].at(p);
+
3533 start_current = p;
+
3534 }else{
+
3535 continue;
+
3536 }
+
3537
+
3538 }
+
3539
+
3540}
+
3541
+
3542void Visualizer::render( bool shadow ){
+
3543
+
3544 //--- Triangles------
+
3545
+
3546 uint textureID_current;
+
3547 if( textureIDData["triangle"].size()==0 ){
+
3548 textureID_current = 0;
+
3549 }else{
+
3550 textureID_current = textureIDData["triangle"].at(0);
+
3551 }
+
3552
+
3553 glBindTexture(GL_TEXTURE_RECTANGLE,0);
+
3554
+
3555 for( std::map<uint,int2>::iterator iter=group_start.begin(); iter!=group_start.end(); ++iter ){
+
3556
+
3557 if( iter->second.x!=0 ){
+
3558 glBindTexture(GL_TEXTURE_RECTANGLE,iter->second.x);
+
3559 }
+
3560
+
3561 glDrawArrays(GL_TRIANGLES, iter->first, iter->second.y );
+
3562
+
3563 }
+
3564
+
3565 if( !shadow ){
+
3566
+
3567 size_t triangle_size = positionData["triangle"].size()/3;
+
3568 size_t line_size = positionData["line"].size()/3;
+
3569 size_t point_size = positionData["point"].size()/3;
+
3570
+
3571 if( line_size>0 ){
+
3572 glDrawArrays(GL_LINES, triangle_size, line_size );
+
3573 }
+
3574
+
3575 if( point_size>0 ){
+
3576 glPointSize( point_width );
+
3577 glDrawArrays(GL_POINTS, triangle_size+line_size, point_size );
+
3578 }
+
3579
+
3580 if( positionData["sky"].size()>0 ){
+
3581 primaryShader.setLightingModel( LIGHTING_NONE );
+
3582 glBindTexture(GL_TEXTURE_RECTANGLE,textureIDData["sky"].at(0));
+
3583 glDrawArrays(GL_TRIANGLES, triangle_size+line_size+point_size, positionData["sky"].size()/3 );
+
3584 }
+
3585
+
3586 }
+
3587
+
3588}
+
3589
+
+ +
3591 plotUpdate( false );
+
3592}
-
3592
-
-
3593void Visualizer::plotUpdate( bool hide_window ){
-
3594
-
3595 if( message_flag ){
-
3596 std::cout << "Updating the plot..." << std::flush;
-
3597 }
-
3598
-
3599 if( !hide_window ) {
-
3600 glfwShowWindow((GLFWwindow *) window);
-
3601 }
-
3602
-
3603 //Update the Context geometry (if needed)
-
3604 if( contextGeomNeedsUpdate ){
-
3605 buildContextGeometry_private();
-
3606 }else{
-
3607 colormap_current.setRange( colorbar_min, colorbar_max );
-
3608 }
-
3609
-
3610 //Update
-
3611 if( colorbar_flag==2 ){
-
3612 addColorbarByCenter( colorbar_title.c_str(), colorbar_size, colorbar_position, colorbar_fontcolor, colormap_current );
-
3613 }
-
3614
-
3615 //Watermark
-
3616 if( isWatermarkVisible ){
-
3617 float hratio = float(Wdisplay)/float(Hdisplay);
-
3618 float width = 0.2389f/0.8f/hratio;
-
3619 addRectangleByCenter( make_vec3(0.75f*width,0.95f,0), make_vec2(width,0.07), make_SphericalCoord(0,0), "plugins/visualizer/textures/Helios_watermark.png", COORDINATES_WINDOW_NORMALIZED );
-
3620 }
-
3621
-
3622 setupPlot();
-
3623
-
3624 //domain bounding box
-
3625 vec2 xbounds, ybounds, zbounds;
-
3626 getDomainBoundingBox( xbounds, ybounds, zbounds );
-
3627
-
3628 glm::vec3 view_center = glm::vec3( xbounds.x+0.5*(xbounds.y-xbounds.x), ybounds.x+0.5*(ybounds.y-ybounds.x), zbounds.x+0.5*(zbounds.y-zbounds.x) );
-
3629 //float bound_R = 2.f*fmax(xbounds.y-xbounds.x,fmax(ybounds.y-ybounds.x,zbounds.y-zbounds.x));
-
3630 float bound_R = 0.75*sqrtf( pow(xbounds.y-xbounds.x,2) + pow(ybounds.y-ybounds.x,2) + pow(zbounds.y-zbounds.x,2) );
-
3631
-
3632 glm::vec3 lightInvDir = view_center + glm::vec3(light_direction.x,light_direction.y,light_direction.z);
-
3633
-
3634 bool shadow_flag = false;
-
3635 for( uint m=0; m<primaryLightingModel.size(); m++ ){
-
3636 if( primaryLightingModel.at(m) == Visualizer::LIGHTING_PHONG_SHADOWED ){
-
3637 shadow_flag = true;
-
3638 break;
-
3639 }
-
3640 }
-
3641
-
3642 glm::mat4 depthMVP;
-
3643
-
3644 if( shadow_flag ){
-
3645
-
3646 // Depth buffer for shadows
-
3647 glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
-
3648 glViewport(0,0,8192,8192); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3649 //glViewport(0,0,16384,16384); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3650
-
3651 // Clear the screen
-
3652 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
3653
-
3654 depthShader.useShader();
-
3655
-
3656 // Compute the MVP matrix from the light's point of view
-
3657 glm::mat4 depthProjectionMatrix = glm::ortho<float>(-bound_R,bound_R,-bound_R,bound_R,-bound_R,bound_R);
-
3658 glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, view_center, glm::vec3(0,0,1));
-
3659 depthMVP = depthProjectionMatrix * depthViewMatrix;
-
3660
-
3661 depthShader.setTransformationMatrix( depthMVP );
-
3662
-
3663 //bind depth texture
-
3664 glActiveTexture(GL_TEXTURE1);
-
3665 glBindTexture(GL_TEXTURE_2D, depthTexture);
-
3666
-
3667 depthShader.enableTextureMaps();
-
3668 depthShader.enableTextureMasks();
-
3669
-
3670 render( 1 );
-
3671
-
3672 }else{
-
3673
-
3674 depthMVP = glm::mat4(1.0);
-
3675
-
3676 }
-
3677
-
3678 assert(checkerrors());
-
3679
-
3680 // Render to the screen
-
3681 glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
3682 //glViewport(0,0,Wdisplay,Hdisplay); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3683 glViewport(0,0,Wframebuffer,Hframebuffer);
-
3684
-
3685 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 0.0f);
-
3686
-
3687 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
3688
-
3689 primaryShader.useShader();
-
3690
-
3691 updatePerspectiveTransformation( camera_lookat_center, camera_eye_location );
-
3692
-
3693 glm::mat4 biasMatrix(
-
3694 0.5, 0.0, 0.0, 0.0,
-
3695 0.0, 0.5, 0.0, 0.0,
-
3696 0.0, 0.0, 0.5, 0.0,
-
3697 0.5, 0.5, 0.5, 1.0
-
3698 );
-
3699
-
3700 glm::mat4 DepthBiasMVP = biasMatrix*depthMVP;
-
3701
-
3702 primaryShader.setDepthBiasMatrix( DepthBiasMVP );
-
3703
-
3704 primaryShader.setTransformationMatrix( perspectiveTransformationMatrix );
-
3705
-
3706 primaryShader.enableTextureMaps();
-
3707 primaryShader.enableTextureMasks();
-
3708
-
3709 primaryShader.setLightingModel( primaryLightingModel.at(0) );
-
3710 primaryShader.setLightIntensity( lightintensity );
-
3711
-
3712 glBindTexture(GL_TEXTURE_2D, depthTexture);
-
3713 glUniform1i(primaryShader.shadowmapUniform,1);
-
3714
-
3715 render( 0 );
-
3716
-
3717 glfwPollEvents();
-
3718 getViewKeystrokes( camera_eye_location, camera_lookat_center );
-
3719
-
3720 int width, height;
-
3721 glfwGetFramebufferSize((GLFWwindow *) window, &width, &height);
-
3722 Wframebuffer = width;
-
3723 Hframebuffer = height;
-
3724
-
3725 glfwSwapBuffers((GLFWwindow*)window);
-
3726
-
3727 if( message_flag ){
-
3728 std::cout << "done." << std::endl;
-
3729 }
-
3730
-
3731}
+
3593
+
+
3594void Visualizer::plotUpdate( bool hide_window ){
+
3595
+
3596 if( message_flag ){
+
3597 std::cout << "Updating the plot..." << std::flush;
+
3598 }
+
3599
+
3600 if( !hide_window ) {
+
3601 glfwShowWindow((GLFWwindow *) window);
+
3602 }
+
3603
+
3604 //Update the Context geometry (if needed)
+
3605 if( contextGeomNeedsUpdate ){
+
3606 buildContextGeometry_private();
+
3607 }else{
+
3608 colormap_current.setRange( colorbar_min, colorbar_max );
+
3609 }
+
3610
+
3611 //Update
+
3612 if( colorbar_flag==2 ){
+
3613 addColorbarByCenter( colorbar_title.c_str(), colorbar_size, colorbar_position, colorbar_fontcolor, colormap_current );
+
3614 }
+
3615
+
3616 //Watermark
+
3617 if( isWatermarkVisible ){
+
3618 float hratio = float(Wdisplay)/float(Hdisplay);
+
3619 float width = 0.2389f/0.8f/hratio;
+
3620 addRectangleByCenter( make_vec3(0.75f*width,0.95f,0), make_vec2(width,0.07), make_SphericalCoord(0,0), "plugins/visualizer/textures/Helios_watermark.png", COORDINATES_WINDOW_NORMALIZED );
+
3621 }
+
3622
+
3623 setupPlot();
+
3624
+
3625 //domain bounding box
+
3626 vec2 xbounds, ybounds, zbounds;
+
3627 getDomainBoundingBox( xbounds, ybounds, zbounds );
+
3628
+
3629 glm::vec3 view_center = glm::vec3( xbounds.x+0.5*(xbounds.y-xbounds.x), ybounds.x+0.5*(ybounds.y-ybounds.x), zbounds.x+0.5*(zbounds.y-zbounds.x) );
+
3630 //float bound_R = 2.f*fmax(xbounds.y-xbounds.x,fmax(ybounds.y-ybounds.x,zbounds.y-zbounds.x));
+
3631 float bound_R = 0.75*sqrtf( pow(xbounds.y-xbounds.x,2) + pow(ybounds.y-ybounds.x,2) + pow(zbounds.y-zbounds.x,2) );
+
3632
+
3633 glm::vec3 lightInvDir = view_center + glm::vec3(light_direction.x,light_direction.y,light_direction.z);
+
3634
+
3635 bool shadow_flag = false;
+
3636 for( uint m=0; m<primaryLightingModel.size(); m++ ){
+
3637 if( primaryLightingModel.at(m) == Visualizer::LIGHTING_PHONG_SHADOWED ){
+
3638 shadow_flag = true;
+
3639 break;
+
3640 }
+
3641 }
+
3642
+
3643 glm::mat4 depthMVP;
+
3644
+
3645 if( shadow_flag ){
+
3646
+
3647 // Depth buffer for shadows
+
3648 glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
+
3649 glViewport(0,0,8192,8192); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3650 //glViewport(0,0,16384,16384); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3651
+
3652 // Clear the screen
+
3653 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
3654
+
3655 depthShader.useShader();
+
3656
+
3657 // Compute the MVP matrix from the light's point of view
+
3658 glm::mat4 depthProjectionMatrix = glm::ortho<float>(-bound_R,bound_R,-bound_R,bound_R,-bound_R,bound_R);
+
3659 glm::mat4 depthViewMatrix = glm::lookAt(lightInvDir, view_center, glm::vec3(0,0,1));
+
3660 depthMVP = depthProjectionMatrix * depthViewMatrix;
+
3661
+
3662 depthShader.setTransformationMatrix( depthMVP );
+
3663
+
3664 //bind depth texture
+
3665 glActiveTexture(GL_TEXTURE1);
+
3666 glBindTexture(GL_TEXTURE_2D, depthTexture);
+
3667
+
3668 depthShader.enableTextureMaps();
+
3669 depthShader.enableTextureMasks();
+
3670
+
3671 render( 1 );
+
3672
+
3673 }else{
+
3674
+
3675 depthMVP = glm::mat4(1.0);
+
3676
+
3677 }
+
3678
+
3679 assert(checkerrors());
+
3680
+
3681 // Render to the screen
+
3682 glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
3683 //glViewport(0,0,Wdisplay,Hdisplay); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3684 glViewport(0,0,Wframebuffer,Hframebuffer);
+
3685
+
3686 glClearColor(backgroundColor.r, backgroundColor.g, backgroundColor.b, 0.0f);
+
3687
+
3688 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
3689
+
3690 primaryShader.useShader();
+
3691
+
3692 updatePerspectiveTransformation( camera_lookat_center, camera_eye_location );
+
3693
+
3694 glm::mat4 biasMatrix(
+
3695 0.5, 0.0, 0.0, 0.0,
+
3696 0.0, 0.5, 0.0, 0.0,
+
3697 0.0, 0.0, 0.5, 0.0,
+
3698 0.5, 0.5, 0.5, 1.0
+
3699 );
+
3700
+
3701 glm::mat4 DepthBiasMVP = biasMatrix*depthMVP;
+
3702
+
3703 primaryShader.setDepthBiasMatrix( DepthBiasMVP );
+
3704
+
3705 primaryShader.setTransformationMatrix( perspectiveTransformationMatrix );
+
3706
+
3707 primaryShader.enableTextureMaps();
+
3708 primaryShader.enableTextureMasks();
+
3709
+
3710 primaryShader.setLightingModel( primaryLightingModel.at(0) );
+
3711 primaryShader.setLightIntensity( lightintensity );
+
3712
+
3713 glBindTexture(GL_TEXTURE_2D, depthTexture);
+
3714 glUniform1i(primaryShader.shadowmapUniform,1);
+
3715
+
3716 render( 0 );
+
3717
+
3718 glfwPollEvents();
+
3719 getViewKeystrokes( camera_eye_location, camera_lookat_center );
+
3720
+
3721 int width, height;
+
3722 glfwGetFramebufferSize((GLFWwindow *) window, &width, &height);
+
3723 Wframebuffer = width;
+
3724 Hframebuffer = height;
+
3725
+
3726 glfwSwapBuffers((GLFWwindow*)window);
+
3727
+
3728 if( message_flag ){
+
3729 std::cout << "done." << std::endl;
+
3730 }
+
3731
+
3732}
-
3732
-
- -
3734
-
3735 if( message_flag ){
-
3736 std::cout << "Rendering depth map..." << std::flush;
-
3737 }
-
3738
-
3739 //Update the Context geometry (if needed)
-
3740 if( contextGeomNeedsUpdate ){
-
3741 buildContextGeometry_private();
-
3742 }
-
3743
-
3744 setupPlot();
-
3745
-
3746 //domain bounding box
-
3747 vec2 xbounds, ybounds, zbounds;
-
3748 getDomainBoundingBox( xbounds, ybounds, zbounds );
-
3749
-
3750 glm::vec3 view_center = glm::vec3( xbounds.x+0.5*(xbounds.y-xbounds.x), ybounds.x+0.5*(ybounds.y-ybounds.x), zbounds.x+0.5*(zbounds.y-zbounds.x) );
-
3751 float bound_R = 1.4f*0.5f*fmax(xbounds.y-xbounds.x,fmax(ybounds.y-ybounds.x,zbounds.y-zbounds.x));
-
3752
-
3753 glm::mat4 depthMVP;
-
3754
-
3755 // Depth buffer for shadows
-
3756 glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
-
3757 //glViewport(0,0, 8192, 8192); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3758 //glViewport(0,0, Wdisplay, Hdisplay); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3759 glViewport(0,0,Wframebuffer,Hframebuffer);
-
3760
-
3761 //bind depth texture
-
3762 glActiveTexture(GL_TEXTURE1);
-
3763 glBindTexture(GL_TEXTURE_2D, depthTexture);
-
3764 //glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, Wdisplay, Hdisplay, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
-
3765 glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, Wframebuffer, Hframebuffer, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
-
3766
-
3767 // Clear the screen
-
3768 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
3769
-
3770 depthShader.useShader();
-
3771
-
3772 updatePerspectiveTransformation( camera_lookat_center, camera_eye_location );
-
3773 depthShader.setTransformationMatrix( perspectiveTransformationMatrix );
-
3774
-
3775 depthShader.enableTextureMaps();
-
3776 depthShader.enableTextureMasks();
-
3777
-
3778 render( 1 );
-
3779
-
3780 assert(checkerrors());
-
3781
-
3782 depth_buffer_data.resize( Wframebuffer*Hframebuffer );
-
3783
-
3784 glfwSwapBuffers((GLFWwindow*)window);
-
3785 glReadPixels(0, 0, Wframebuffer, Hframebuffer, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_buffer_data[0] );
-
3786
-
3787 //depending on the active frame buffer, we may get all zero data and need to swap it again.
-
3788 bool zeros = true;
-
3789 for( int i=0; i<3*Wframebuffer*Hframebuffer; i++){
-
3790 if( depth_buffer_data[i]!=0 ){
-
3791 zeros = false;
-
3792 }
-
3793 }
-
3794 if( zeros ){
-
3795
-
3796 glfwSwapBuffers((GLFWwindow*)window);
-
3797
-
3798 glReadPixels(0, 0, Wframebuffer, Hframebuffer, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_buffer_data[0] );
-
3799
-
3800 }
-
3801
-
3802 assert(checkerrors());
-
3803
-
3804 glEnableVertexAttribArray(0); //position
-
3805 glEnableVertexAttribArray(1); //color
-
3806 glDisableVertexAttribArray(2); //normal
-
3807 glEnableVertexAttribArray(3); //uv
-
3808 glEnableVertexAttribArray(4); //texture flag
-
3809 glEnableVertexAttribArray(5); //coordinate flag
-
3810
-
3811 std::vector<float> position_data, color_data, normal_data, uv_data;
-
3812 std::vector<int> coordinate_data, texture_data;
-
3813
-
3814 position_data.assign(12,0);
-
3815 color_data.assign(16,0);
-
3816 normal_data.assign(12,0);
-
3817 uv_data.assign(8,0);
-
3818 coordinate_data.assign(4,0);
-
3819 texture_data.assign(4,0);
-
3820
-
3821 position_data[0] = -1;
-
3822 position_data[1] = 1;
-
3823 position_data[2] = 0;
-
3824 uv_data[0] = 0;
-
3825 uv_data[1] = 1;
-
3826 color_data[0] = 1;
-
3827 color_data[1] = 0;
-
3828 color_data[2] = 0;
-
3829 color_data[3] = 1;
-
3830 texture_data[0] = 4;
-
3831 coordinate_data[0] = 0;
-
3832
-
3833 position_data[3] = 1;
-
3834 position_data[4] = 1;
-
3835 position_data[5] = 0;
-
3836 uv_data[2] = 1;
-
3837 uv_data[3] = 1;
-
3838 color_data[4] = 1;
-
3839 color_data[5] = 0;
-
3840 color_data[6] = 0;
-
3841 color_data[7] = 1;
-
3842 texture_data[1] = 4;
-
3843 coordinate_data[1] = 0;
-
3844
-
3845 position_data[6] = 1;
-
3846 position_data[7] = -1;
-
3847 position_data[8] = 0;
-
3848 uv_data[4] = 1;
-
3849 uv_data[5] = 0;
-
3850 color_data[8] = 1;
-
3851 color_data[9] = 0;
-
3852 color_data[10] = 0;
-
3853 color_data[11] = 1;
-
3854 texture_data[2] = 4;
-
3855 coordinate_data[2] = 0;
-
3856
-
3857 position_data[9] = -1;
-
3858 position_data[10] = -1;
-
3859 position_data[11] = 0;
-
3860 uv_data[6] = 0;
-
3861 uv_data[7] = 0;
-
3862 color_data[12] = 1;
-
3863 color_data[13] = 0;
-
3864 color_data[14] = 0;
-
3865 color_data[15] = 1;
-
3866 texture_data[3] = 4;
-
3867 coordinate_data[3] = 0;
-
3868
-
3869 // 1st attribute buffer : vertex positions
-
3870 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer );
-
3871 glBufferData(GL_ARRAY_BUFFER, position_data.size()*sizeof(GLfloat), &position_data[0], GL_STATIC_DRAW);
-
3872 glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
-
3873
-
3874 // 2nd attribute buffer : vertex colors
-
3875 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer );
-
3876 glBufferData(GL_ARRAY_BUFFER, color_data.size()*sizeof(GLfloat), &color_data[0], GL_STATIC_DRAW);
-
3877 glVertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0 );
-
3878
-
3879 // 4th attribute buffer : vertex uv
-
3880 glBindBuffer(GL_ARRAY_BUFFER, uvBuffer );
-
3881 glBufferData(GL_ARRAY_BUFFER, uv_data.size()*sizeof(GLfloat), &uv_data[0], GL_STATIC_DRAW);
-
3882 glVertexAttribPointer( 3, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
-
3883
-
3884 // 5th attribute buffer : vertex texture flag
-
3885 glBindBuffer(GL_ARRAY_BUFFER, textureFlagBuffer );
-
3886 glBufferData(GL_ARRAY_BUFFER, texture_data.size()*sizeof(GLint), &texture_data[0], GL_STATIC_DRAW);
-
3887 glVertexAttribIPointer( 4, 1, GL_INT, 0, (void*)0 );
-
3888
-
3889 // 6th attribute buffer : vertex coordinate flag
-
3890 glBindBuffer(GL_ARRAY_BUFFER, coordinateFlagBuffer );
-
3891 glBufferData(GL_ARRAY_BUFFER, coordinate_data.size()*sizeof(GLint), &coordinate_data[0], GL_STATIC_DRAW);
-
3892 glVertexAttribIPointer( 5, 1, GL_INT, 0, (void*)0 );
-
3893
+
3733
+
+ +
3735
+
3736 if( message_flag ){
+
3737 std::cout << "Rendering depth map..." << std::flush;
+
3738 }
+
3739
+
3740 //Update the Context geometry (if needed)
+
3741 if( contextGeomNeedsUpdate ){
+
3742 buildContextGeometry_private();
+
3743 }
+
3744
+
3745 setupPlot();
+
3746
+
3747 //domain bounding box
+
3748 vec2 xbounds, ybounds, zbounds;
+
3749 getDomainBoundingBox( xbounds, ybounds, zbounds );
+
3750
+
3751 glm::vec3 view_center = glm::vec3( xbounds.x+0.5*(xbounds.y-xbounds.x), ybounds.x+0.5*(ybounds.y-ybounds.x), zbounds.x+0.5*(zbounds.y-zbounds.x) );
+
3752 float bound_R = 1.4f*0.5f*fmax(xbounds.y-xbounds.x,fmax(ybounds.y-ybounds.x,zbounds.y-zbounds.x));
+
3753
+
3754 glm::mat4 depthMVP;
+
3755
+
3756 // Depth buffer for shadows
+
3757 glBindFramebuffer(GL_FRAMEBUFFER, framebufferID);
+
3758 //glViewport(0,0, 8192, 8192); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3759 //glViewport(0,0, Wdisplay, Hdisplay); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3760 glViewport(0,0,Wframebuffer,Hframebuffer);
+
3761
+
3762 //bind depth texture
+
3763 glActiveTexture(GL_TEXTURE1);
+
3764 glBindTexture(GL_TEXTURE_2D, depthTexture);
+
3765 //glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, Wdisplay, Hdisplay, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
+
3766 glTexImage2D(GL_TEXTURE_2D, 0,GL_DEPTH_COMPONENT16, Wframebuffer, Hframebuffer, 0,GL_DEPTH_COMPONENT, GL_FLOAT, 0);
+
3767
+
3768 // Clear the screen
+
3769 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
3770
+
3771 depthShader.useShader();
+
3772
+
3773 updatePerspectiveTransformation( camera_lookat_center, camera_eye_location );
+
3774 depthShader.setTransformationMatrix( perspectiveTransformationMatrix );
+
3775
+
3776 depthShader.enableTextureMaps();
+
3777 depthShader.enableTextureMasks();
+
3778
+
3779 render( 1 );
+
3780
+
3781 assert(checkerrors());
+
3782
+
3783 depth_buffer_data.resize( Wframebuffer*Hframebuffer );
+
3784
+
3785 glfwSwapBuffers((GLFWwindow*)window);
+
3786 glReadPixels(0, 0, Wframebuffer, Hframebuffer, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_buffer_data[0] );
+
3787
+
3788 //depending on the active frame buffer, we may get all zero data and need to swap it again.
+
3789 bool zeros = true;
+
3790 for( int i=0; i<3*Wframebuffer*Hframebuffer; i++){
+
3791 if( depth_buffer_data[i]!=0 ){
+
3792 zeros = false;
+
3793 }
+
3794 }
+
3795 if( zeros ){
+
3796
+
3797 glfwSwapBuffers((GLFWwindow*)window);
+
3798
+
3799 glReadPixels(0, 0, Wframebuffer, Hframebuffer, GL_DEPTH_COMPONENT, GL_FLOAT, &depth_buffer_data[0] );
+
3800
+
3801 }
+
3802
+
3803 assert(checkerrors());
+
3804
+
3805 glEnableVertexAttribArray(0); //position
+
3806 glEnableVertexAttribArray(1); //color
+
3807 glDisableVertexAttribArray(2); //normal
+
3808 glEnableVertexAttribArray(3); //uv
+
3809 glEnableVertexAttribArray(4); //texture flag
+
3810 glEnableVertexAttribArray(5); //coordinate flag
+
3811
+
3812 std::vector<float> position_data, color_data, normal_data, uv_data;
+
3813 std::vector<int> coordinate_data, texture_data;
+
3814
+
3815 position_data.assign(12,0);
+
3816 color_data.assign(16,0);
+
3817 normal_data.assign(12,0);
+
3818 uv_data.assign(8,0);
+
3819 coordinate_data.assign(4,0);
+
3820 texture_data.assign(4,0);
+
3821
+
3822 position_data[0] = -1;
+
3823 position_data[1] = 1;
+
3824 position_data[2] = 0;
+
3825 uv_data[0] = 0;
+
3826 uv_data[1] = 1;
+
3827 color_data[0] = 1;
+
3828 color_data[1] = 0;
+
3829 color_data[2] = 0;
+
3830 color_data[3] = 1;
+
3831 texture_data[0] = 4;
+
3832 coordinate_data[0] = 0;
+
3833
+
3834 position_data[3] = 1;
+
3835 position_data[4] = 1;
+
3836 position_data[5] = 0;
+
3837 uv_data[2] = 1;
+
3838 uv_data[3] = 1;
+
3839 color_data[4] = 1;
+
3840 color_data[5] = 0;
+
3841 color_data[6] = 0;
+
3842 color_data[7] = 1;
+
3843 texture_data[1] = 4;
+
3844 coordinate_data[1] = 0;
+
3845
+
3846 position_data[6] = 1;
+
3847 position_data[7] = -1;
+
3848 position_data[8] = 0;
+
3849 uv_data[4] = 1;
+
3850 uv_data[5] = 0;
+
3851 color_data[8] = 1;
+
3852 color_data[9] = 0;
+
3853 color_data[10] = 0;
+
3854 color_data[11] = 1;
+
3855 texture_data[2] = 4;
+
3856 coordinate_data[2] = 0;
+
3857
+
3858 position_data[9] = -1;
+
3859 position_data[10] = -1;
+
3860 position_data[11] = 0;
+
3861 uv_data[6] = 0;
+
3862 uv_data[7] = 0;
+
3863 color_data[12] = 1;
+
3864 color_data[13] = 0;
+
3865 color_data[14] = 0;
+
3866 color_data[15] = 1;
+
3867 texture_data[3] = 4;
+
3868 coordinate_data[3] = 0;
+
3869
+
3870 // 1st attribute buffer : vertex positions
+
3871 glBindBuffer(GL_ARRAY_BUFFER, positionBuffer );
+
3872 glBufferData(GL_ARRAY_BUFFER, position_data.size()*sizeof(GLfloat), &position_data[0], GL_STATIC_DRAW);
+
3873 glVertexAttribPointer( 0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0 );
+
3874
+
3875 // 2nd attribute buffer : vertex colors
+
3876 glBindBuffer(GL_ARRAY_BUFFER, colorBuffer );
+
3877 glBufferData(GL_ARRAY_BUFFER, color_data.size()*sizeof(GLfloat), &color_data[0], GL_STATIC_DRAW);
+
3878 glVertexAttribPointer( 1, 4, GL_FLOAT, GL_FALSE, 0, (void*)0 );
+
3879
+
3880 // 4th attribute buffer : vertex uv
+
3881 glBindBuffer(GL_ARRAY_BUFFER, uvBuffer );
+
3882 glBufferData(GL_ARRAY_BUFFER, uv_data.size()*sizeof(GLfloat), &uv_data[0], GL_STATIC_DRAW);
+
3883 glVertexAttribPointer( 3, 2, GL_FLOAT, GL_FALSE, 0, (void*)0 );
+
3884
+
3885 // 5th attribute buffer : vertex texture flag
+
3886 glBindBuffer(GL_ARRAY_BUFFER, textureFlagBuffer );
+
3887 glBufferData(GL_ARRAY_BUFFER, texture_data.size()*sizeof(GLint), &texture_data[0], GL_STATIC_DRAW);
+
3888 glVertexAttribIPointer( 4, 1, GL_INT, 0, (void*)0 );
+
3889
+
3890 // 6th attribute buffer : vertex coordinate flag
+
3891 glBindBuffer(GL_ARRAY_BUFFER, coordinateFlagBuffer );
+
3892 glBufferData(GL_ARRAY_BUFFER, coordinate_data.size()*sizeof(GLint), &coordinate_data[0], GL_STATIC_DRAW);
+
3893 glVertexAttribIPointer( 5, 1, GL_INT, 0, (void*)0 );
3894
-
3895 //do{
-
3896
-
3897 // Render to the screen
-
3898 glBindFramebuffer(GL_FRAMEBUFFER, 0);
-
3899 //glViewport(0,0,Wdisplay,Hdisplay); // Render on the whole framebuffer, complete from the lower left corner to the upper right
-
3900 glViewport(0,0,Wframebuffer,Hframebuffer);
-
3901
-
3902 glClearColor(0,0,0, 0.0f);
-
3903
-
3904 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
-
3905
-
3906 primaryShader.useShader();
-
3907
-
3908 primaryShader.enableTextureMaps();
-
3909 primaryShader.enableTextureMasks();
-
3910
-
3911 primaryShader.setLightingModel( LIGHTING_NONE );
-
3912
-
3913 glActiveTexture(GL_TEXTURE1);
-
3914 glBindTexture(GL_TEXTURE_2D, depthTexture);
-
3915
-
3916 glUniform1i(primaryShader.RboundUniform,bound_R);
-
3917
-
3918 glDrawArrays(GL_TRIANGLE_FAN, 0, 4 );
-
3919
-
3920 glfwSwapBuffers((GLFWwindow*)window);
-
3921
-
3922 //glfwWaitEvents();
-
3923 //}while( glfwGetKey((GLFWwindow*)window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose((GLFWwindow*)window) == 0 );
-
3924
-
3925 if( message_flag ){
-
3926 std::cout << "done." << std::endl;
-
3927 }
-
3928
-
3929}
+
3895
+
3896 //do{
+
3897
+
3898 // Render to the screen
+
3899 glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
3900 //glViewport(0,0,Wdisplay,Hdisplay); // Render on the whole framebuffer, complete from the lower left corner to the upper right
+
3901 glViewport(0,0,Wframebuffer,Hframebuffer);
+
3902
+
3903 glClearColor(0,0,0, 0.0f);
+
3904
+
3905 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+
3906
+
3907 primaryShader.useShader();
+
3908
+
3909 primaryShader.enableTextureMaps();
+
3910 primaryShader.enableTextureMasks();
+
3911
+
3912 primaryShader.setLightingModel( LIGHTING_NONE );
+
3913
+
3914 glActiveTexture(GL_TEXTURE1);
+
3915 glBindTexture(GL_TEXTURE_2D, depthTexture);
+
3916
+
3917 glUniform1i(primaryShader.RboundUniform,bound_R);
+
3918
+
3919 glDrawArrays(GL_TRIANGLE_FAN, 0, 4 );
+
3920
+
3921 glfwSwapBuffers((GLFWwindow*)window);
+
3922
+
3923 //glfwWaitEvents();
+
3924 //}while( glfwGetKey((GLFWwindow*)window, GLFW_KEY_ESCAPE ) != GLFW_PRESS && glfwWindowShouldClose((GLFWwindow*)window) == 0 );
+
3925
+
3926 if( message_flag ){
+
3927 std::cout << "done." << std::endl;
+
3928 }
+
3929
+
3930}
-
3930
-
-
3931void Shader::initialize( const char* vertex_shader_file, const char* fragment_shader_file ){
-
3932
-
3933 // ~~~~~~~~~~~~~~~ COMPILE SHADERS ~~~~~~~~~~~~~~~~~~~~~~~~~//
-
3934
-
3935 assert(checkerrors());
-
3936
-
3937 // Create the shaders
-
3938 unsigned int VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
-
3939 unsigned int FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
-
3940
-
3941 // Read the Vertex Shader code from the file
-
3942 std::string VertexShaderCode;
-
3943 std::ifstream VertexShaderStream(vertex_shader_file, std::ios::in);
-
3944 assert(VertexShaderStream.is_open());
-
3945 std::string Line = "";
-
3946 while(getline(VertexShaderStream, Line))
-
3947 VertexShaderCode += "\n" + Line;
-
3948 VertexShaderStream.close();
-
3949
-
3950 // Read the Fragment Shader code from the file
-
3951 std::string FragmentShaderCode;
-
3952 std::ifstream FragmentShaderStream(fragment_shader_file, std::ios::in);
-
3953 assert(FragmentShaderStream.is_open());
-
3954 Line = "";
-
3955 while(getline(FragmentShaderStream, Line))
-
3956 FragmentShaderCode += "\n" + Line;
-
3957 FragmentShaderStream.close();
-
3958
-
3959 int Result = GL_FALSE;
-
3960 int InfoLogLength;
-
3961
-
3962 // Compile Vertex Shader
-
3963 char const * VertexSourcePointer = VertexShaderCode.c_str();
-
3964 glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
-
3965 glCompileShader(VertexShaderID);
-
3966
-
3967 assert(checkerrors());
-
3968
-
3969 // Check Vertex Shader
-
3970 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
-
3971 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
-
3972 std::vector<char> VertexShaderErrorMessage(InfoLogLength);
-
3973 if( !VertexShaderErrorMessage.empty() ) {
-
3974 glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
-
3975 }
-
3976 int success = 0;
-
3977 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &success);
-
3978 if( success==GL_FALSE ){
-
3979 fprintf(stderr, "%s\n", &VertexShaderErrorMessage[0]);
-
3980 throw(1);
-
3981 }
-
3982
-
3983 // Compile Fragment Shader
-
3984 char const * FragmentSourcePointer = FragmentShaderCode.c_str();
-
3985 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
-
3986 glCompileShader(FragmentShaderID);
-
3987
-
3988 assert(checkerrors());
-
3989
-
3990 // Check Fragment Shader
-
3991 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
-
3992 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
-
3993 std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
-
3994 if( !VertexShaderErrorMessage.empty() ) {
-
3995 glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
-
3996 }
-
3997 success = 0;
-
3998 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &success);
-
3999 if( success==GL_FALSE ){
-
4000 fprintf(stderr, "%s\n", &FragmentShaderErrorMessage[0]);
-
4001 throw(1);
-
4002 }
-
4003
-
4004 // Link the program
-
4005 shaderID = glCreateProgram();
-
4006 glAttachShader(shaderID, VertexShaderID);
-
4007 glAttachShader(shaderID, FragmentShaderID);
-
4008 glLinkProgram(shaderID);
-
4009
-
4010 assert(checkerrors());
-
4011
-
4012 // Check the program
-
4013 glGetProgramiv(shaderID, GL_LINK_STATUS, &Result);
-
4014 glGetProgramiv(shaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
-
4015 std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
-
4016 glGetProgramInfoLog(shaderID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
-
4017 if( isspace( ProgramErrorMessage[0] ) ){
-
4018 fprintf(stderr, "%s\n", &ProgramErrorMessage[0]);
-
4019 throw(1);
-
4020 }
-
4021
-
4022 assert(checkerrors());
-
4023
-
4024 glDeleteShader(VertexShaderID);
-
4025 glDeleteShader(FragmentShaderID);
-
4026
-
4027 assert(checkerrors());
-
4028
-
4029 glUseProgram(shaderID);
-
4030
-
4031 assert(checkerrors());
-
4032
-
4033 // ~~~~~~~~~~~ Create a Vertex Array Object (VAO) ~~~~~~~~~~//
-
4034 glGenVertexArrays(1, &VertexArrayID);
-
4035 glBindVertexArray(VertexArrayID);
-
4036
-
4037 assert(checkerrors());
-
4038
-
4039 // ~~~~~~~~~~~ Primary Shader Uniforms ~~~~~~~~~~//
-
4040
-
4041 //Transformation Matrix
-
4042 transformMatrixUniform = glGetUniformLocation(shaderID, "MVP");
-
4043
-
4044 //Depth Bias Matrix (for shadows)
-
4045 depthBiasUniform = glGetUniformLocation(shaderID, "DepthBiasMVP");
-
4046
-
4047 //Texture Sampler
-
4048 textureUniform = glGetUniformLocation(shaderID, "textureSampler");
-
4049 glUniform1i(textureUniform,0); //tell shader we are using GL_TEXTURE0
-
4050
-
4051 //Shadow Map Sampler
-
4052 shadowmapUniform = glGetUniformLocation(shaderID, "shadowMap");
-
4053 glUniform1i(shadowmapUniform, 1);
-
4054
-
4055 //Flag to tell how to shade fragments. See also: setTextureMap, setMaskTexture, disableTextures
-
4056 //textureFlagUniform = glGetUniformLocation(shaderID, "textureFlag");
-
4057 //glUniform1i(textureFlagUniform,0); //Default is zero, which is to disable textures
-
4058
-
4059 //Unit vector in the direction of the light (sun)
-
4060 lightDirectionUniform = glGetUniformLocation(shaderID, "lightDirection" );
-
4061 glUniform3f( lightDirectionUniform, 0, 0, 1 ); //Default is directly above
-
4062
-
4063 //Lighting model used for shading primitives
-
4064 lightingModelUniform = glGetUniformLocation(shaderID, "lightingModel" );
-
4065 glUniform1i( lightingModelUniform, 0 ); //Default is none
-
4066
-
4067 RboundUniform = glGetUniformLocation(shaderID, "Rbound");
-
4068 glUniform1i(RboundUniform,0);
-
4069
-
4070 //Lighting intensity factor
-
4071 lightIntensityUniform = glGetUniformLocation(shaderID, "lightIntensity" );
-
4072 glUniform1f( lightIntensityUniform, 1.f );
-
4073
-
4074 //initialize default texture in case none are added to the scene
-
4075 glBindTexture(GL_TEXTURE_RECTANGLE,0);
-
4076 glTexImage2D(GL_TEXTURE_RECTANGLE, 0,GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
-
4077
-
4078 assert(checkerrors());
-
4079
-
4080}
+
3931
+
+
3932void Shader::initialize( const char* vertex_shader_file, const char* fragment_shader_file ){
+
3933
+
3934 // ~~~~~~~~~~~~~~~ COMPILE SHADERS ~~~~~~~~~~~~~~~~~~~~~~~~~//
+
3935
+
3936 assert(checkerrors());
+
3937
+
3938 // Create the shaders
+
3939 unsigned int VertexShaderID = glCreateShader(GL_VERTEX_SHADER);
+
3940 unsigned int FragmentShaderID = glCreateShader(GL_FRAGMENT_SHADER);
+
3941
+
3942 // Read the Vertex Shader code from the file
+
3943 std::string VertexShaderCode;
+
3944 std::ifstream VertexShaderStream(vertex_shader_file, std::ios::in);
+
3945 assert(VertexShaderStream.is_open());
+
3946 std::string Line = "";
+
3947 while(getline(VertexShaderStream, Line))
+
3948 VertexShaderCode += "\n" + Line;
+
3949 VertexShaderStream.close();
+
3950
+
3951 // Read the Fragment Shader code from the file
+
3952 std::string FragmentShaderCode;
+
3953 std::ifstream FragmentShaderStream(fragment_shader_file, std::ios::in);
+
3954 assert(FragmentShaderStream.is_open());
+
3955 Line = "";
+
3956 while(getline(FragmentShaderStream, Line))
+
3957 FragmentShaderCode += "\n" + Line;
+
3958 FragmentShaderStream.close();
+
3959
+
3960 int Result = GL_FALSE;
+
3961 int InfoLogLength;
+
3962
+
3963 // Compile Vertex Shader
+
3964 char const * VertexSourcePointer = VertexShaderCode.c_str();
+
3965 glShaderSource(VertexShaderID, 1, &VertexSourcePointer , NULL);
+
3966 glCompileShader(VertexShaderID);
+
3967
+
3968 assert(checkerrors());
+
3969
+
3970 // Check Vertex Shader
+
3971 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &Result);
+
3972 glGetShaderiv(VertexShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+
3973 std::vector<char> VertexShaderErrorMessage(InfoLogLength);
+
3974 if( !VertexShaderErrorMessage.empty() ) {
+
3975 glGetShaderInfoLog(VertexShaderID, InfoLogLength, NULL, &VertexShaderErrorMessage[0]);
+
3976 }
+
3977 int success = 0;
+
3978 glGetShaderiv(VertexShaderID, GL_COMPILE_STATUS, &success);
+
3979 if( success==GL_FALSE ){
+
3980 fprintf(stderr, "%s\n", &VertexShaderErrorMessage[0]);
+
3981 throw(1);
+
3982 }
+
3983
+
3984 // Compile Fragment Shader
+
3985 char const * FragmentSourcePointer = FragmentShaderCode.c_str();
+
3986 glShaderSource(FragmentShaderID, 1, &FragmentSourcePointer , NULL);
+
3987 glCompileShader(FragmentShaderID);
+
3988
+
3989 assert(checkerrors());
+
3990
+
3991 // Check Fragment Shader
+
3992 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &Result);
+
3993 glGetShaderiv(FragmentShaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+
3994 std::vector<char> FragmentShaderErrorMessage(InfoLogLength);
+
3995 if( !VertexShaderErrorMessage.empty() ) {
+
3996 glGetShaderInfoLog(FragmentShaderID, InfoLogLength, NULL, &FragmentShaderErrorMessage[0]);
+
3997 }
+
3998 success = 0;
+
3999 glGetShaderiv(FragmentShaderID, GL_COMPILE_STATUS, &success);
+
4000 if( success==GL_FALSE ){
+
4001 fprintf(stderr, "%s\n", &FragmentShaderErrorMessage[0]);
+
4002 throw(1);
+
4003 }
+
4004
+
4005 // Link the program
+
4006 shaderID = glCreateProgram();
+
4007 glAttachShader(shaderID, VertexShaderID);
+
4008 glAttachShader(shaderID, FragmentShaderID);
+
4009 glLinkProgram(shaderID);
+
4010
+
4011 assert(checkerrors());
+
4012
+
4013 // Check the program
+
4014 glGetProgramiv(shaderID, GL_LINK_STATUS, &Result);
+
4015 glGetProgramiv(shaderID, GL_INFO_LOG_LENGTH, &InfoLogLength);
+
4016 std::vector<char> ProgramErrorMessage( std::max(InfoLogLength, int(1)) );
+
4017 glGetProgramInfoLog(shaderID, InfoLogLength, NULL, &ProgramErrorMessage[0]);
+
4018 if( isspace( ProgramErrorMessage[0] ) ){
+
4019 fprintf(stderr, "%s\n", &ProgramErrorMessage[0]);
+
4020 throw(1);
+
4021 }
+
4022
+
4023 assert(checkerrors());
+
4024
+
4025 glDeleteShader(VertexShaderID);
+
4026 glDeleteShader(FragmentShaderID);
+
4027
+
4028 assert(checkerrors());
+
4029
+
4030 glUseProgram(shaderID);
+
4031
+
4032 assert(checkerrors());
+
4033
+
4034 // ~~~~~~~~~~~ Create a Vertex Array Object (VAO) ~~~~~~~~~~//
+
4035 glGenVertexArrays(1, &VertexArrayID);
+
4036 glBindVertexArray(VertexArrayID);
+
4037
+
4038 assert(checkerrors());
+
4039
+
4040 // ~~~~~~~~~~~ Primary Shader Uniforms ~~~~~~~~~~//
+
4041
+
4042 //Transformation Matrix
+
4043 transformMatrixUniform = glGetUniformLocation(shaderID, "MVP");
+
4044
+
4045 //Depth Bias Matrix (for shadows)
+
4046 depthBiasUniform = glGetUniformLocation(shaderID, "DepthBiasMVP");
+
4047
+
4048 //Texture Sampler
+
4049 textureUniform = glGetUniformLocation(shaderID, "textureSampler");
+
4050 glUniform1i(textureUniform,0); //tell shader we are using GL_TEXTURE0
+
4051
+
4052 //Shadow Map Sampler
+
4053 shadowmapUniform = glGetUniformLocation(shaderID, "shadowMap");
+
4054 glUniform1i(shadowmapUniform, 1);
+
4055
+
4056 //Flag to tell how to shade fragments. See also: setTextureMap, setMaskTexture, disableTextures
+
4057 //textureFlagUniform = glGetUniformLocation(shaderID, "textureFlag");
+
4058 //glUniform1i(textureFlagUniform,0); //Default is zero, which is to disable textures
+
4059
+
4060 //Unit vector in the direction of the light (sun)
+
4061 lightDirectionUniform = glGetUniformLocation(shaderID, "lightDirection" );
+
4062 glUniform3f( lightDirectionUniform, 0, 0, 1 ); //Default is directly above
+
4063
+
4064 //Lighting model used for shading primitives
+
4065 lightingModelUniform = glGetUniformLocation(shaderID, "lightingModel" );
+
4066 glUniform1i( lightingModelUniform, 0 ); //Default is none
+
4067
+
4068 RboundUniform = glGetUniformLocation(shaderID, "Rbound");
+
4069 glUniform1i(RboundUniform,0);
+
4070
+
4071 //Lighting intensity factor
+
4072 lightIntensityUniform = glGetUniformLocation(shaderID, "lightIntensity" );
+
4073 glUniform1f( lightIntensityUniform, 1.f );
+
4074
+
4075 //initialize default texture in case none are added to the scene
+
4076 glBindTexture(GL_TEXTURE_RECTANGLE,0);
+
4077 glTexImage2D(GL_TEXTURE_RECTANGLE, 0,GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
+
4078
+
4079 assert(checkerrors());
+
4080
+
4081}
-
4081
-
4082Shader::~Shader( void ){
-
4083 glDeleteVertexArrays( 1, &VertexArrayID);
-
4084 glDeleteProgram(shaderID);
-
4085}
-
4086
-
- -
4088 glEnable(GL_BLEND);
-
4089 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
4090}
+
4082
+
4083Shader::~Shader( void ){
+
4084 glDeleteVertexArrays( 1, &VertexArrayID);
+
4085 glDeleteProgram(shaderID);
+
4086}
+
4087
+
+ +
4089 glEnable(GL_BLEND);
+
4090 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
4091}
-
4091
-
-
4092void Shader::setTextureMap( const char* texture_file, uint& textureID, int2& texture_size ){
-
4093
-
4094 //Check if the file exists
-
4095 std::ifstream f(texture_file);
-
4096 assert( f.good() );
-
4097 f.close();
-
4098
-
4099 //Check if this texture has already been added to the shader
-
4100 //Note: if the texture_file is empy, it will automatically load a new texture
-
4101 for( uint i=0; i<textureMapFiles.size(); i++ ){
-
4102 if( textureMapFiles.at(i)==texture_file && strlen(texture_file)>0 ){
-
4103 textureID = textureMaps.at(i); //copy the handle
-
4104 texture_size = textureSizes.at(i); //copy the size
-
4105 return;
-
4106 }
-
4107 }
-
4108
-
4109 //--- Load the Texture ----//
-
4110
-
4111 int Nchannels=3;
-
4112 std::vector<unsigned char> texture;
-
4113 uint texture_height, texture_width;
-
4114 std::string file = texture_file;
-
4115 if(file.substr(file.find_last_of('.') + 1) == "jpg" || file.substr(file.find_last_of('.') + 1) == "jpeg" ){
-
4116 read_JPEG_file (texture_file,texture,texture_height,texture_width);
-
4117 } else if(file.substr(file.find_last_of('.') + 1) == "png") {
-
4118 read_png_file (texture_file,texture,texture_height,texture_width);
-
4119 }else {
-
4120 assert(false);
-
4121 }
-
4122
-
4123 texture_size = make_int2( texture_width, texture_height );
-
4124
-
4125 //Find next power of two up from size
-
4126 int POT = 0;
-
4127 while( pow(2,POT)<texture_size.x ){
-
4128 POT++;
-
4129 }
-
4130 int2 texture_size_POT = make_int2( int(pow(2,POT)), texture_size.y );
-
4131
-
4132 //OpenGL is a pain, so we need to pad the first dimension of the texture so that it size is a power of two
-
4133 std::vector<unsigned char> texture_;
-
4134 texture_.resize(texture_size_POT.y*texture_size_POT.x*4);
-
4135 for( int i=0; i<texture_size_POT.y*texture_size_POT.x*4; i++ ){
-
4136 texture_.at(i) = 0;
-
4137 }
-
4138 for(int j=0;j<texture_size.y;j++){
-
4139 for(int i=0;i<texture_size.x;i++){
-
4140 for( int c=0; c<4; c++ ){
-
4141 texture_[c+i*4+j*texture_size_POT.x*4] = texture[ c + i*4 + j*texture_size.x*4 ];
-
4142 }
-
4143 }
-
4144 }
-
4145 for(int j=texture_size.y-1; j<texture_size_POT.y; j++){
-
4146 for(int i=texture_size.x-1; i<texture_size_POT.x; i++){
-
4147 for( int c=0; c<4; c++ ){
-
4148 texture_[c+i*4+j*texture_size_POT.x*4] = 255.f;
-
4149 }
-
4150 }
-
4151 }
-
4152
-
4153 unsigned char* texture_ptr = &texture_[0];
-
4154
-
4155 glGenTextures(1, &textureID);
-
4156
-
4157 glActiveTexture(GL_TEXTURE0);
-
4158 glBindTexture(GL_TEXTURE_RECTANGLE,textureID);
-
4159 glTexImage2D(GL_TEXTURE_RECTANGLE, 0,GL_RGBA, texture_size_POT.x, texture_size_POT.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_ptr);
-
4160 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
4161 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
4162 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
4163 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
4164
-
4165 textureMaps.push_back(textureID);
-
4166 textureSizes.push_back(texture_size);
-
4167 textureMapFiles.push_back(texture_file);
-
4168
-
4169}
+
4092
+
+
4093void Shader::setTextureMap( const char* texture_file, uint& textureID, int2& texture_size ){
+
4094
+
4095 //Check if the file exists
+
4096 std::ifstream f(texture_file);
+
4097 assert( f.good() );
+
4098 f.close();
+
4099
+
4100 //Check if this texture has already been added to the shader
+
4101 //Note: if the texture_file is empy, it will automatically load a new texture
+
4102 for( uint i=0; i<textureMapFiles.size(); i++ ){
+
4103 if( textureMapFiles.at(i)==texture_file && strlen(texture_file)>0 ){
+
4104 textureID = textureMaps.at(i); //copy the handle
+
4105 texture_size = textureSizes.at(i); //copy the size
+
4106 return;
+
4107 }
+
4108 }
+
4109
+
4110 //--- Load the Texture ----//
+
4111
+
4112 int Nchannels=3;
+
4113 std::vector<unsigned char> texture;
+
4114 uint texture_height, texture_width;
+
4115 std::string file = texture_file;
+
4116 if(file.substr(file.find_last_of('.') + 1) == "jpg" || file.substr(file.find_last_of('.') + 1) == "jpeg" ){
+
4117 read_JPEG_file (texture_file,texture,texture_height,texture_width);
+
4118 } else if(file.substr(file.find_last_of('.') + 1) == "png") {
+
4119 read_png_file (texture_file,texture,texture_height,texture_width);
+
4120 }else {
+
4121 assert(false);
+
4122 }
+
4123
+
4124 texture_size = make_int2( texture_width, texture_height );
+
4125
+
4126 //Find next power of two up from size
+
4127 int POT = 0;
+
4128 while( pow(2,POT)<texture_size.x ){
+
4129 POT++;
+
4130 }
+
4131 int2 texture_size_POT = make_int2( int(pow(2,POT)), texture_size.y );
+
4132
+
4133 //OpenGL is a pain, so we need to pad the first dimension of the texture so that it size is a power of two
+
4134 std::vector<unsigned char> texture_;
+
4135 texture_.resize(texture_size_POT.y*texture_size_POT.x*4);
+
4136 for( int i=0; i<texture_size_POT.y*texture_size_POT.x*4; i++ ){
+
4137 texture_.at(i) = 0;
+
4138 }
+
4139 for(int j=0;j<texture_size.y;j++){
+
4140 for(int i=0;i<texture_size.x;i++){
+
4141 for( int c=0; c<4; c++ ){
+
4142 texture_[c+i*4+j*texture_size_POT.x*4] = texture[ c + i*4 + j*texture_size.x*4 ];
+
4143 }
+
4144 }
+
4145 }
+
4146 for(int j=texture_size.y-1; j<texture_size_POT.y; j++){
+
4147 for(int i=texture_size.x-1; i<texture_size_POT.x; i++){
+
4148 for( int c=0; c<4; c++ ){
+
4149 texture_[c+i*4+j*texture_size_POT.x*4] = 255.f;
+
4150 }
+
4151 }
+
4152 }
+
4153
+
4154 unsigned char* texture_ptr = &texture_[0];
+
4155
+
4156 glGenTextures(1, &textureID);
+
4157
+
4158 glActiveTexture(GL_TEXTURE0);
+
4159 glBindTexture(GL_TEXTURE_RECTANGLE,textureID);
+
4160 glTexImage2D(GL_TEXTURE_RECTANGLE, 0,GL_RGBA, texture_size_POT.x, texture_size_POT.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_ptr);
+
4161 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
4162 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
4163 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
4164 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
4165
+
4166 textureMaps.push_back(textureID);
+
4167 textureSizes.push_back(texture_size);
+
4168 textureMapFiles.push_back(texture_file);
+
4169
+
4170}
-
4170
-
- -
4172 glActiveTexture(GL_TEXTURE0);
-
4173 glUniform1i(textureUniform,0);
-
4174 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
4175 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
4176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
4177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
4178 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
4179 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
4180 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
4181 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
4182 glEnable(GL_BLEND);
-
4183 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
4184}
+
4171
+
+ +
4173 glActiveTexture(GL_TEXTURE0);
+
4174 glUniform1i(textureUniform,0);
+
4175 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
4176 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
4177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
4178 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
4179 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
4180 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
4181 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
4182 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
4183 glEnable(GL_BLEND);
+
4184 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
4185}
-
4185
4186
-
-
4187void Shader::setTextureMask( const Glyph* glyph, uint& textureID ){
-
4188
-
4189 int2 texture_size = glyph->size;
-
4190
-
4191 //Check if this texture has already been added to the shader
-
4192 for( uint i=0; i<textureMaskFiles.size(); i++ ){
-
4193 if( textureMaskFiles.at(i).compare(glyph->filename)==0 ){
-
4194 textureID = textureMasks.at(i); //copy the handle
-
4195 return;
-
4196 }
-
4197 }
-
4198
-
4199 //OpenGL is a pain, so we need to pad the first dimension of the texture so that it size is a power of two
-
4200 int POT = 0;
-
4201 while( pow(2,POT)<texture_size.x ){
-
4202 POT++;
-
4203 }
-
4204 int2 texture_size_POT = make_int2( pow(2,POT), texture_size.y );
-
4205
-
4206 std::vector<unsigned char> texture(texture_size_POT.x*texture_size_POT.y);
-
4207 for(int j=0;j<texture_size.y;j++){
-
4208 for(int i=0;i<texture_size.x;i++){
-
4209 texture[i+j*texture_size_POT.x]=glyph->data.at(j).at(i);
-
4210 }
-
4211 }
-
4212 unsigned char* texture_ptr = &texture[0];
-
4213
-
4214 glGenTextures(1, &textureID);
-
4215
-
4216 glActiveTexture(GL_TEXTURE0);
-
4217 glBindTexture(GL_TEXTURE_RECTANGLE,textureID);
-
4218 glTexImage2D(GL_TEXTURE_RECTANGLE, 0,GL_RED, texture_size_POT.x, texture_size_POT.y, 0, GL_RED, GL_UNSIGNED_BYTE, texture_ptr);
-
4219 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
4220 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
4221 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
4222 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
4223
-
4224 if( strlen(glyph->filename)>0 ){
-
4225 textureMasks.push_back(textureID);
-
4226 textureMaskFiles.push_back(glyph->filename);
-
4227 }
-
4228
-
4229}
+
4187
+
+
4188void Shader::setTextureMask( const Glyph* glyph, uint& textureID ){
+
4189
+
4190 int2 texture_size = glyph->size;
+
4191
+
4192 //Check if this texture has already been added to the shader
+
4193 for( uint i=0; i<textureMaskFiles.size(); i++ ){
+
4194 if( textureMaskFiles.at(i).compare(glyph->filename)==0 ){
+
4195 textureID = textureMasks.at(i); //copy the handle
+
4196 return;
+
4197 }
+
4198 }
+
4199
+
4200 //OpenGL is a pain, so we need to pad the first dimension of the texture so that it size is a power of two
+
4201 int POT = 0;
+
4202 while( pow(2,POT)<texture_size.x ){
+
4203 POT++;
+
4204 }
+
4205 int2 texture_size_POT = make_int2( pow(2,POT), texture_size.y );
+
4206
+
4207 std::vector<unsigned char> texture(texture_size_POT.x*texture_size_POT.y);
+
4208 for(int j=0;j<texture_size.y;j++){
+
4209 for(int i=0;i<texture_size.x;i++){
+
4210 texture[i+j*texture_size_POT.x]=glyph->data.at(j).at(i);
+
4211 }
+
4212 }
+
4213 unsigned char* texture_ptr = &texture[0];
+
4214
+
4215 glGenTextures(1, &textureID);
+
4216
+
4217 glActiveTexture(GL_TEXTURE0);
+
4218 glBindTexture(GL_TEXTURE_RECTANGLE,textureID);
+
4219 glTexImage2D(GL_TEXTURE_RECTANGLE, 0,GL_RED, texture_size_POT.x, texture_size_POT.y, 0, GL_RED, GL_UNSIGNED_BYTE, texture_ptr);
+
4220 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
4221 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
4222 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
4223 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
4224
+
4225 if( strlen(glyph->filename)>0 ){
+
4226 textureMasks.push_back(textureID);
+
4227 textureMaskFiles.push_back(glyph->filename);
+
4228 }
+
4229
+
4230}
-
4230
-
-
4231void Shader::setTextureMask( const char* texture_file, uint& textureID, int2& texture_size ){
-
4232
-
4233 //Check if this texture has already been added to the shader
-
4234 //Note: if the texture_file is empy, it will automatically load a new texture
-
4235 for( uint i=0; i<textureMapFiles.size(); i++ ){
-
4236 if( textureMapFiles.at(i).compare(texture_file)==0 && strlen(texture_file)>0 ){
-
4237 textureID = textureMaps.at(i); //copy the handle
-
4238 texture_size = textureSizes.at(i); //copy the size
-
4239 return;
-
4240 }
-
4241 }
-
4242
-
4243 //--- Load the Texture ----//
-
4244
-
4245 int Nchannels=3;
-
4246 std::vector<unsigned char> texture;
-
4247 uint texture_height, texture_width;
-
4248 std::string file = texture_file;
-
4249 if(file.substr(file.find_last_of(".") + 1) == "png") {
-
4250 read_png_file (texture_file,texture,texture_height,texture_width);
-
4251 }else {
-
4252 std::cerr << "ERROR: texture mask file " << texture_file << " must be a PNG image." << std::endl;
-
4253 }
-
4254
-
4255 texture_size = make_int2( texture_width, texture_height );
-
4256
-
4257 //Find next power of two up from size
-
4258 int POT = 0;
-
4259 while( pow(2,POT)<texture_size.x ){
-
4260 POT++;
-
4261 }
-
4262 int2 texture_size_POT = make_int2( int(pow(2,POT)), texture_size.y );
-
4263
-
4264 //OpenGL is a pain, so we need to pad the first dimension of the texture so that it size is a power of two
-
4265 std::vector<unsigned char> texture_;
-
4266 texture_.assign(texture_size_POT.y*texture_size_POT.x,0);
-
4267 for(int j=0;j<texture_size.y;j++){
-
4268 for(int i=0;i<texture_size.x;i++){
-
4269 texture_[j*texture_size_POT.x+i] = texture[ 3 + i*4 + j*texture_size.x*4 ];
-
4270 }
-
4271 }
-
4272
-
4273 unsigned char* texture_ptr = &texture_[0];
-
4274
-
4275 glGenTextures(1, &textureID);
-
4276
-
4277 glActiveTexture(GL_TEXTURE0);
-
4278 glBindTexture(GL_TEXTURE_RECTANGLE,textureID);
-
4279 glTexImage2D(GL_TEXTURE_RECTANGLE, 0,GL_RED, texture_size_POT.x, texture_size_POT.y, 0, GL_RED, GL_UNSIGNED_BYTE, texture_ptr);
-
4280 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
4281 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
4282 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
4283 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
4284
-
4285 textureMaps.push_back(textureID);
-
4286 textureSizes.push_back(texture_size);
-
4287 textureMapFiles.push_back(texture_file);
-
4288
-
4289}
+
4231
+
+
4232void Shader::setTextureMask( const char* texture_file, uint& textureID, int2& texture_size ){
+
4233
+
4234 //Check if this texture has already been added to the shader
+
4235 //Note: if the texture_file is empy, it will automatically load a new texture
+
4236 for( uint i=0; i<textureMapFiles.size(); i++ ){
+
4237 if( textureMapFiles.at(i).compare(texture_file)==0 && strlen(texture_file)>0 ){
+
4238 textureID = textureMaps.at(i); //copy the handle
+
4239 texture_size = textureSizes.at(i); //copy the size
+
4240 return;
+
4241 }
+
4242 }
+
4243
+
4244 //--- Load the Texture ----//
+
4245
+
4246 int Nchannels=3;
+
4247 std::vector<unsigned char> texture;
+
4248 uint texture_height, texture_width;
+
4249 std::string file = texture_file;
+
4250 if(file.substr(file.find_last_of(".") + 1) == "png") {
+
4251 read_png_file (texture_file,texture,texture_height,texture_width);
+
4252 }else {
+
4253 std::cerr << "ERROR: texture mask file " << texture_file << " must be a PNG image." << std::endl;
+
4254 }
+
4255
+
4256 texture_size = make_int2( texture_width, texture_height );
+
4257
+
4258 //Find next power of two up from size
+
4259 int POT = 0;
+
4260 while( pow(2,POT)<texture_size.x ){
+
4261 POT++;
+
4262 }
+
4263 int2 texture_size_POT = make_int2( int(pow(2,POT)), texture_size.y );
+
4264
+
4265 //OpenGL is a pain, so we need to pad the first dimension of the texture so that it size is a power of two
+
4266 std::vector<unsigned char> texture_;
+
4267 texture_.assign(texture_size_POT.y*texture_size_POT.x,0);
+
4268 for(int j=0;j<texture_size.y;j++){
+
4269 for(int i=0;i<texture_size.x;i++){
+
4270 texture_[j*texture_size_POT.x+i] = texture[ 3 + i*4 + j*texture_size.x*4 ];
+
4271 }
+
4272 }
+
4273
+
4274 unsigned char* texture_ptr = &texture_[0];
+
4275
+
4276 glGenTextures(1, &textureID);
+
4277
+
4278 glActiveTexture(GL_TEXTURE0);
+
4279 glBindTexture(GL_TEXTURE_RECTANGLE,textureID);
+
4280 glTexImage2D(GL_TEXTURE_RECTANGLE, 0,GL_RED, texture_size_POT.x, texture_size_POT.y, 0, GL_RED, GL_UNSIGNED_BYTE, texture_ptr);
+
4281 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
4282 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
4283 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
4284 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
4285
+
4286 textureMaps.push_back(textureID);
+
4287 textureSizes.push_back(texture_size);
+
4288 textureMapFiles.push_back(texture_file);
+
4289
+
4290}
-
4290
-
- -
4292 glActiveTexture(GL_TEXTURE0);
-
4293 glUniform1i(textureUniform,0);
-
4294 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
4295 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-
4296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
4297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
4298 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
-
4299 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
-
4300 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
-
4301 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
-
4302 glEnable(GL_BLEND);
-
4303 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
4304}
+
4291
+
+ +
4293 glActiveTexture(GL_TEXTURE0);
+
4294 glUniform1i(textureUniform,0);
+
4295 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
4296 //glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+
4297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
4298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
4299 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+
4300 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
4301 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+
4302 glTexParameteri(GL_TEXTURE_RECTANGLE, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+
4303 glEnable(GL_BLEND);
+
4304 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
4305}
-
4305
-
-
4306void Shader::setTransformationMatrix(const glm::mat4 &matrix ) const{
-
4307 glUniformMatrix4fv(transformMatrixUniform, 1, GL_FALSE, &matrix[0][0]);
-
4308}
+
4306
+
+
4307void Shader::setTransformationMatrix(const glm::mat4 &matrix ) const{
+
4308 glUniformMatrix4fv(transformMatrixUniform, 1, GL_FALSE, &matrix[0][0]);
+
4309}
-
4309
-
-
4310void Shader::setDepthBiasMatrix(const glm::mat4 &matrix ) const{
-
4311 glUniformMatrix4fv(depthBiasUniform, 1, GL_FALSE, &matrix[0][0]);
-
4312}
+
4310
+
+
4311void Shader::setDepthBiasMatrix(const glm::mat4 &matrix ) const{
+
4312 glUniformMatrix4fv(depthBiasUniform, 1, GL_FALSE, &matrix[0][0]);
+
4313}
-
4313
-
-
4314void Shader::setLightDirection(const helios::vec3 &direction ) const{
-
4315 glUniform3f( lightDirectionUniform, direction.x, direction.y, direction.z );
-
4316}
+
4314
+
+
4315void Shader::setLightDirection(const helios::vec3 &direction ) const{
+
4316 glUniform3f( lightDirectionUniform, direction.x, direction.y, direction.z );
+
4317}
-
4317
-
-
4318void Shader::setLightingModel( uint lightingmodel ) const{
-
4319 glUniform1i( lightingModelUniform, lightingmodel );
-
4320}
+
4318
+
+
4319void Shader::setLightingModel( uint lightingmodel ) const{
+
4320 glUniform1i( lightingModelUniform, lightingmodel );
+
4321}
-
4321
-
-
4322void Shader::setLightIntensity( float lightintensity ) const{
-
4323 glUniform1f( lightIntensityUniform, lightintensity );
-
4324}
+
4322
+
+
4323void Shader::setLightIntensity( float lightintensity ) const{
+
4324 glUniform1f( lightIntensityUniform, lightintensity );
+
4325}
-
4325
-
-
4326void Shader::useShader() const {
-
4327 glUseProgram(shaderID);
-
4328}
+
4326
+
+
4327void Shader::useShader() const {
+
4328 glUseProgram(shaderID);
+
4329}
-
4329
4330
-
4331bool lbutton_down = false;
-
4332bool rbutton_down = false;
-
4333bool mbutton_down = false;
-
4334double startX, startY;
-
4335double scrollX, scrollY;
-
4336bool scroll = false;
-
4337
+
4331
+
4332bool lbutton_down = false;
+
4333bool rbutton_down = false;
+
4334bool mbutton_down = false;
+
4335double startX, startY;
+
4336double scrollX, scrollY;
+
4337bool scroll = false;
4338
-
-
4339void mouseCallback( GLFWwindow *window, int button, int action, int mods ){
-
4340 if (button == GLFW_MOUSE_BUTTON_LEFT){
-
4341 if (GLFW_PRESS == action) {lbutton_down = true;}
-
4342 else if (GLFW_RELEASE == action) {lbutton_down = false;}
-
4343 } else if (button == GLFW_MOUSE_BUTTON_MIDDLE){
-
4344 if (GLFW_PRESS == action) {mbutton_down = true;}
-
4345 else if (GLFW_RELEASE == action) {mbutton_down = false;}
-
4346 } else if (button == GLFW_MOUSE_BUTTON_RIGHT){
-
4347 if (GLFW_PRESS == action) {rbutton_down = true;}
-
4348 else if (GLFW_RELEASE == action) {rbutton_down = false;}
-
4349 }
-
4350}
+
4339
+
+
4340void mouseCallback( GLFWwindow *window, int button, int action, int mods ){
+
4341 if (button == GLFW_MOUSE_BUTTON_LEFT){
+
4342 if (GLFW_PRESS == action) {lbutton_down = true;}
+
4343 else if (GLFW_RELEASE == action) {lbutton_down = false;}
+
4344 } else if (button == GLFW_MOUSE_BUTTON_MIDDLE){
+
4345 if (GLFW_PRESS == action) {mbutton_down = true;}
+
4346 else if (GLFW_RELEASE == action) {mbutton_down = false;}
+
4347 } else if (button == GLFW_MOUSE_BUTTON_RIGHT){
+
4348 if (GLFW_PRESS == action) {rbutton_down = true;}
+
4349 else if (GLFW_RELEASE == action) {rbutton_down = false;}
+
4350 }
+
4351}
-
4351
4352
-
-
4353void cursorCallback( GLFWwindow* window, double xpos, double ypos ){
-
4354 if (lbutton_down){
-
4355 dphi = (float) xpos - startX;
-
4356 dtheta = (float) ypos - startY;
-
4357 } else {dphi = 0; dtheta = 0;}
-
4358 if (rbutton_down){
-
4359 dx = (float) xpos - startX;
-
4360 dy = (float) ypos - startY;
-
4361 } else {dx = 0; dy = 0;}
-
4362 if (mbutton_down){
-
4363 dx_m = (float) xpos - startX;
-
4364 dy_m = (float) ypos - startY;
-
4365 } else {dx_m = 0; dy_m = 0;}
-
4366 startX = xpos;
-
4367 startY = ypos;
-
4368}
+
4353
+
+
4354void cursorCallback( GLFWwindow* window, double xpos, double ypos ){
+
4355 if (lbutton_down){
+
4356 dphi = (float) xpos - startX;
+
4357 dtheta = (float) ypos - startY;
+
4358 } else {dphi = 0; dtheta = 0;}
+
4359 if (rbutton_down){
+
4360 dx = (float) xpos - startX;
+
4361 dy = (float) ypos - startY;
+
4362 } else {dx = 0; dy = 0;}
+
4363 if (mbutton_down){
+
4364 dx_m = (float) xpos - startX;
+
4365 dy_m = (float) ypos - startY;
+
4366 } else {dx_m = 0; dy_m = 0;}
+
4367 startX = xpos;
+
4368 startY = ypos;
+
4369}
-
4369
4370
-
-
4371void scrollCallback( GLFWwindow* window, double xoffset, double yoffset ){
-
4372 dscroll = (float) yoffset;
-
4373 scrollY = yoffset;
-
4374 if (yoffset > 0.0 or yoffset < 0.0){
-
4375 scroll = true;
-
4376 } else {scroll = false;}
-
4377}
+
4371
+
+
4372void scrollCallback( GLFWwindow* window, double xoffset, double yoffset ){
+
4373 dscroll = (float) yoffset;
+
4374 scrollY = yoffset;
+
4375 if (yoffset > 0.0 or yoffset < 0.0){
+
4376 scroll = true;
+
4377 } else {scroll = false;}
+
4378}
-
4378
4379
-
4380void Visualizer::getViewKeystrokes( vec3& eye, vec3& center ){
-
4381
-
4382 vec3 forward = center - eye;
-
4383 forward = forward.normalize();
-
4384
-
4385 vec3 right = cross(forward, vec3(0, 0, 1));
-
4386 right = right.normalize();
-
4387
-
4388 vec3 up = cross(right, forward);
-
4389 up = up.normalize();
-
4390
-
4391 SphericalCoord Spherical = cart2sphere( eye-center );
-
4392 float radius = Spherical.radius;
-
4393 float theta = Spherical.elevation;
-
4394 float phi = Spherical.azimuth;
-
4395
-
4396 phi+=M_PI * (dphi/160.f);
-
4397 if( dtheta > 0 && theta + M_PI/80.f < 0.49f*M_PI ){
-
4398 theta+=M_PI * (dtheta/120.f);
-
4399 } else if( dtheta < 0 && theta>-0.25*M_PI ){
-
4400 theta+=M_PI * (dtheta/120.f);
-
4401 }
-
4402 if (rbutton_down){
-
4403 center += 0.05 * dy * up;
-
4404 center -= 0.05 * dx * right;
-
4405 }
-
4406 if (mbutton_down){
-
4407 eye += 0.05 * dy_m * up;
-
4408 eye -= 0.05 * dx_m * right;
-
4409 }
-
4410 if (scroll){
-
4411 center -= 0.2 * dscroll * forward;
-
4412 }
-
4413 scroll = false;
-
4414
-
4415 GLFWwindow* _window = (GLFWwindow*) window;
-
4416
-
4417 //----- Holding SPACEBAR -----//
-
4418 if (glfwGetKey( _window, GLFW_KEY_SPACE ) == GLFW_PRESS){
-
4419
-
4420 // Move center to the left - SPACE + LEFT KEY
-
4421 if (glfwGetKey( _window, GLFW_KEY_LEFT ) == GLFW_PRESS){
-
4422 center.x +=0.1*sin(phi);
-
4423 center.y +=0.1*cos(phi);
-
4424 }
-
4425 // Move center to the right - SPACE + RIGHT KEY
-
4426 else if (glfwGetKey( _window, GLFW_KEY_RIGHT ) == GLFW_PRESS){
-
4427 center.x -=0.1*sin(phi);
-
4428 center.y -=0.1*cos(phi);
-
4429 }
-
4430 // Move center upward - SPACE + UP KEY
-
4431 else if (glfwGetKey( _window, GLFW_KEY_UP ) == GLFW_PRESS){
-
4432 center.z +=0.2;
-
4433 }
-
4434 // Move center downward - SPACE + DOWN KEY
-
4435 else if (glfwGetKey( _window, GLFW_KEY_DOWN ) == GLFW_PRESS){
-
4436 center.z -=0.2;
-
4437 }
-
4438
-
4439 //----- Not Holding SPACEBAR -----//
-
4440 }else{
-
4441
-
4442 // Orbit left - LEFT ARROW KEY
-
4443 if (glfwGetKey( _window, GLFW_KEY_LEFT ) == GLFW_PRESS){
-
4444 phi+=M_PI/40.f;
-
4445 }
-
4446 // Orbit right - RIGHT ARROW KEY
-
4447 else if (glfwGetKey( _window, GLFW_KEY_RIGHT ) == GLFW_PRESS){
-
4448 phi-=M_PI/40.f;
-
4449 }
-
4450
-
4451 // Increase Elevation - UP ARROW KEY
-
4452 else if (glfwGetKey( _window, GLFW_KEY_UP ) == GLFW_PRESS){
-
4453 if( theta + M_PI/80.f < 0.49f*M_PI ){
-
4454 theta+=M_PI/80.f;
-
4455 }
-
4456 }
-
4457 // Decrease Elevation - DOWN ARROW KEY
-
4458 else if (glfwGetKey( _window, GLFW_KEY_DOWN ) == GLFW_PRESS){
-
4459 if( theta>-0.25*M_PI ){
-
4460 theta-=M_PI/80.f;
-
4461 }
-
4462 }
-
4463
-
4464 // Zoom in - "+" KEY
-
4465 if (glfwGetKey( _window, GLFW_KEY_EQUAL ) == GLFW_PRESS){
-
4466 radius *= 0.9;
-
4467 }
-
4468 // Zoom out - "-" KEY
-
4469 else if (glfwGetKey( _window, GLFW_KEY_MINUS ) == GLFW_PRESS){
-
4470 radius *= 1.1;
-
4471 }
-
4472 }
-
4473
-
4474 if (glfwGetKey( _window, GLFW_KEY_P ) == GLFW_PRESS){
-
4475 std::cout << "View is angle: (R,theta,phi)=(" << radius << "," << theta << "," << phi << ") at from position (" << camera_eye_location.x << "," << camera_eye_location.y << "," << camera_eye_location.z << ") looking at (" << center.x << "," << center.y << "," << center.z << ")" << std::endl;
-
4476 }
-
4477
+
4380
+
4381void Visualizer::getViewKeystrokes( vec3& eye, vec3& center ){
+
4382
+
4383 vec3 forward = center - eye;
+
4384 forward = forward.normalize();
+
4385
+
4386 vec3 right = cross(forward, vec3(0, 0, 1));
+
4387 right = right.normalize();
+
4388
+
4389 vec3 up = cross(right, forward);
+
4390 up = up.normalize();
+
4391
+
4392 SphericalCoord Spherical = cart2sphere( eye-center );
+
4393 float radius = Spherical.radius;
+
4394 float theta = Spherical.elevation;
+
4395 float phi = Spherical.azimuth;
+
4396
+
4397 phi+=M_PI * (dphi/160.f);
+
4398 if( dtheta > 0 && theta + M_PI/80.f < 0.49f*M_PI ){
+
4399 theta+=M_PI * (dtheta/120.f);
+
4400 } else if( dtheta < 0 && theta>-0.25*M_PI ){
+
4401 theta+=M_PI * (dtheta/120.f);
+
4402 }
+
4403 if (rbutton_down){
+
4404 center += 0.05 * dy * up;
+
4405 center -= 0.05 * dx * right;
+
4406 }
+
4407 if (mbutton_down){
+
4408 eye += 0.05 * dy_m * up;
+
4409 eye -= 0.05 * dx_m * right;
+
4410 }
+
4411 if (scroll){
+
4412 center -= 0.2 * dscroll * forward;
+
4413 }
+
4414 scroll = false;
+
4415
+
4416 GLFWwindow* _window = (GLFWwindow*) window;
+
4417
+
4418 //----- Holding SPACEBAR -----//
+
4419 if (glfwGetKey( _window, GLFW_KEY_SPACE ) == GLFW_PRESS){
+
4420
+
4421 // Move center to the left - SPACE + LEFT KEY
+
4422 if (glfwGetKey( _window, GLFW_KEY_LEFT ) == GLFW_PRESS){
+
4423 center.x +=0.1*sin(phi);
+
4424 center.y +=0.1*cos(phi);
+
4425 }
+
4426 // Move center to the right - SPACE + RIGHT KEY
+
4427 else if (glfwGetKey( _window, GLFW_KEY_RIGHT ) == GLFW_PRESS){
+
4428 center.x -=0.1*sin(phi);
+
4429 center.y -=0.1*cos(phi);
+
4430 }
+
4431 // Move center upward - SPACE + UP KEY
+
4432 else if (glfwGetKey( _window, GLFW_KEY_UP ) == GLFW_PRESS){
+
4433 center.z +=0.2;
+
4434 }
+
4435 // Move center downward - SPACE + DOWN KEY
+
4436 else if (glfwGetKey( _window, GLFW_KEY_DOWN ) == GLFW_PRESS){
+
4437 center.z -=0.2;
+
4438 }
+
4439
+
4440 //----- Not Holding SPACEBAR -----//
+
4441 }else{
+
4442
+
4443 // Orbit left - LEFT ARROW KEY
+
4444 if (glfwGetKey( _window, GLFW_KEY_LEFT ) == GLFW_PRESS){
+
4445 phi+=M_PI/40.f;
+
4446 }
+
4447 // Orbit right - RIGHT ARROW KEY
+
4448 else if (glfwGetKey( _window, GLFW_KEY_RIGHT ) == GLFW_PRESS){
+
4449 phi-=M_PI/40.f;
+
4450 }
+
4451
+
4452 // Increase Elevation - UP ARROW KEY
+
4453 else if (glfwGetKey( _window, GLFW_KEY_UP ) == GLFW_PRESS){
+
4454 if( theta + M_PI/80.f < 0.49f*M_PI ){
+
4455 theta+=M_PI/80.f;
+
4456 }
+
4457 }
+
4458 // Decrease Elevation - DOWN ARROW KEY
+
4459 else if (glfwGetKey( _window, GLFW_KEY_DOWN ) == GLFW_PRESS){
+
4460 if( theta>-0.25*M_PI ){
+
4461 theta-=M_PI/80.f;
+
4462 }
+
4463 }
+
4464
+
4465 // Zoom in - "+" KEY
+
4466 if (glfwGetKey( _window, GLFW_KEY_EQUAL ) == GLFW_PRESS){
+
4467 radius *= 0.9;
+
4468 }
+
4469 // Zoom out - "-" KEY
+
4470 else if (glfwGetKey( _window, GLFW_KEY_MINUS ) == GLFW_PRESS){
+
4471 radius *= 1.1;
+
4472 }
+
4473 }
+
4474
+
4475 if (glfwGetKey( _window, GLFW_KEY_P ) == GLFW_PRESS){
+
4476 std::cout << "View is angle: (R,theta,phi)=(" << radius << "," << theta << "," << phi << ") at from position (" << camera_eye_location.x << "," << camera_eye_location.y << "," << camera_eye_location.z << ") looking at (" << center.x << "," << center.y << "," << center.z << ")" << std::endl;
+
4477 }
4478
-
4479 camera_eye_location = sphere2cart( make_SphericalCoord(radius,theta,phi) ) + center;
-
4480
+
4479
+
4480 camera_eye_location = sphere2cart( make_SphericalCoord(radius,theta,phi) ) + center;
4481
-
4482}
-
4483
-
4484std::string errorString( GLenum err ){
-
4485
-
4486 std::string message;
-
4487 message.assign("");
-
4488
-
4489 if( err==GL_INVALID_ENUM ){
-
4490 message.assign("GL_INVALID_ENUM - An unacceptable value is specified for an enumerated argument.");
-
4491 }else if( err==GL_INVALID_VALUE ){
-
4492 message.assign("GL_INVALID_VALUE - A numeric argument is out of range.");
-
4493 }else if( err==GL_INVALID_OPERATION ){
-
4494 message.assign("GL_INVALID_OPERATION - The specified operation is not allowed in the current state.");
-
4495 }else if( err==GL_STACK_OVERFLOW ){
-
4496 message.assign("GL_STACK_OVERFLOW - This command would cause a stack overflow.");
-
4497 }else if( err==GL_STACK_UNDERFLOW ){
-
4498 message.assign("GL_STACK_UNDERFLOW - This command would cause a stack underflow.");
-
4499 }else if( err==GL_OUT_OF_MEMORY ){
-
4500 message.assign("GL_OUT_OF_MEMORY - There is not enough memory left to execute the command.");
-
4501 }else if( err==GL_TABLE_TOO_LARGE ){
-
4502 message.assign("GL_TABLE_TOO_LARGE - The specified table exceeds the implementation's maximum supported table size.");
-
4503 }
-
4504
-
4505 return message;
-
4506
-
4507}
-
4508
-
4509int checkerrors() {
-
4510
-
4511 GLenum err;
-
4512 int err_count=0;
-
4513 while ((err = glGetError()) != GL_NO_ERROR) {
-
4514 std::cerr << "glError #" << err_count << ": " << errorString(err) << std::endl;
-
4515 err_count++;
-
4516 }
-
4517 if(err_count>0){
-
4518 return 0;
-
4519 }else{
-
4520 return 1;
-
4521 }
-
4522
-
4523}
+
4482
+
4483}
+
4484
+
4485std::string errorString( GLenum err ){
+
4486
+
4487 std::string message;
+
4488 message.assign("");
+
4489
+
4490 if( err==GL_INVALID_ENUM ){
+
4491 message.assign("GL_INVALID_ENUM - An unacceptable value is specified for an enumerated argument.");
+
4492 }else if( err==GL_INVALID_VALUE ){
+
4493 message.assign("GL_INVALID_VALUE - A numeric argument is out of range.");
+
4494 }else if( err==GL_INVALID_OPERATION ){
+
4495 message.assign("GL_INVALID_OPERATION - The specified operation is not allowed in the current state.");
+
4496 }else if( err==GL_STACK_OVERFLOW ){
+
4497 message.assign("GL_STACK_OVERFLOW - This command would cause a stack overflow.");
+
4498 }else if( err==GL_STACK_UNDERFLOW ){
+
4499 message.assign("GL_STACK_UNDERFLOW - This command would cause a stack underflow.");
+
4500 }else if( err==GL_OUT_OF_MEMORY ){
+
4501 message.assign("GL_OUT_OF_MEMORY - There is not enough memory left to execute the command.");
+
4502 }else if( err==GL_TABLE_TOO_LARGE ){
+
4503 message.assign("GL_TABLE_TOO_LARGE - The specified table exceeds the implementation's maximum supported table size.");
+
4504 }
+
4505
+
4506 return message;
+
4507
+
4508}
+
4509
+
4510int checkerrors() {
+
4511
+
4512 GLenum err;
+
4513 int err_count=0;
+
4514 while ((err = glGetError()) != GL_NO_ERROR) {
+
4515 std::cerr << "glError #" << err_count << ": " << errorString(err) << std::endl;
+
4516 err_count++;
+
4517 }
+
4518 if(err_count>0){
+
4519 return 0;
+
4520 }else{
+
4521 return 1;
+
4522 }
+
4523
+
4524}
HeliosDataType
Data types.
Definition Context.h:41
PrimitiveType
Type of primitive element.
Definition Context.h:31
void read_png_file(const char *filename, std::vector< unsigned char > &texture, uint &height, uint &width)
Function to create a texture map from a PNG image.
-
void cursorCallback(GLFWwindow *window, double xpos, double ypos)
Callback function for mouse cursor movements.
+
void cursorCallback(GLFWwindow *window, double xpos, double ypos)
Callback function for mouse cursor movements.
int read_JPEG_file(const char *filename, std::vector< unsigned char > &texture, uint &height, uint &width)
Function to create a texture map from a JPEG image.
int write_JPEG_file(const char *filename, uint width, uint height, void *_window, bool print_messages)
Write current graphics window to a JPEG image file.
-
void mouseCallback(GLFWwindow *window, int button, int action, int mods)
Callback function for mouse button presses.
-
void scrollCallback(GLFWwindow *window, double xoffset, double yoffset)
Callback function for mouse scroll.
+
void mouseCallback(GLFWwindow *window, int button, int action, int mods)
Callback function for mouse button presses.
+
void scrollCallback(GLFWwindow *window, double xoffset, double yoffset)
Callback function for mouse scroll.
void read_png_file(const char *filename, std::vector< unsigned char > &texture, uint &height, uint &width)
Function to create a texture map from a PNG image.
int read_JPEG_file(const char *filename, std::vector< unsigned char > &texture, uint &height, uint &width)
Function to create a texture map from a JPEG image.
-
void cursorCallback(GLFWwindow *window, double x, double y)
Callback function for mouse cursor movements.
-
void mouseCallback(GLFWwindow *window, int button, int action, int mods)
Callback function for mouse button presses.
+
void cursorCallback(GLFWwindow *window, double x, double y)
Callback function for mouse cursor movements.
+
void mouseCallback(GLFWwindow *window, int button, int action, int mods)
Callback function for mouse button presses.
int write_JPEG_file(const char *filename, uint width, uint height, void *_window, bool print_messages=true)
Write current graphics window to a JPEG image file.
-
void scrollCallback(GLFWwindow *window, double xoffset, double yoffset)
Callback function for mouse scroll.
+
void scrollCallback(GLFWwindow *window, double xoffset, double yoffset)
Callback function for mouse scroll.
Glyph object - 2D matrix shape.
Definition Visualizer.h:77
-
Class for visualization of simulation results.
Definition Visualizer.h:275
-
void enableColorbar()
Enable the colorbar.
+
void enableColorbar()
Enable the colorbar.
CoordinateSystem
Coordinate system to be used when specifying spatial coordinates.
Definition Visualizer.h:320
-
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
+
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
@ COORDINATES_WINDOW_NORMALIZED
Coordinates are normalized to unity and are window-aligned. The point (x,y)=(0,0) is in the bottom le...
Definition Visualizer.h:323
Ctable
Pseudocolor map tables.
Definition Visualizer.h:331
@ COLORMAP_HOT
"Hot" colormap
Definition Visualizer.h:333
@ COLORMAP_COOL
"Cool" colormap
Definition Visualizer.h:335
-
@ COLORMAP_CUSTOM
Custom colormap.
Definition Visualizer.h:345
+
@ COLORMAP_CUSTOM
Custom colormap.
Definition Visualizer.h:345
@ COLORMAP_GRAY
"Gray" colormap
Definition Visualizer.h:343
@ COLORMAP_PARULA
"Parula" colormap
Definition Visualizer.h:341
@ COLORMAP_RAINBOW
"Rainbow" colormap
Definition Visualizer.h:337
@ COLORMAP_LAVA
"Lava" colormap
Definition Visualizer.h:339
-
void colorContextPrimitivesByData(const char *data_name)
Color primitives from Context by color mapping their ‘Primitive Data’.
-
void plotDepthMap()
Plot the depth map (distance from camera to nearest object)
+
void colorContextPrimitivesByData(const char *data_name)
Color primitives from Context by color mapping their ‘Primitive Data’.
+
void plotDepthMap()
Plot the depth map (distance from camera to nearest object)
void getWindowPixelsRGB(uint *buffer)
Get R-G-B pixel data in the current display window.
-
void colorContextObjectsRandomly()
Color objects from Context with a random color.
+
void colorContextObjectsRandomly()
Color objects from Context with a random color.
int selfTest()
Visualizer self-test routine.
void addPoint(const helios::vec3 &position, const helios::RGBcolor &color, uint pointsize, CoordinateSystem coordFlag)
Add a point by giving its coordinates and size.
void printWindow()
Print the current graphics window to a JPEG image file. File will be given a default filename and sav...
void addTextboxByCenter(const char *textstring, const helios::vec3 &center, const helios::SphericalCoord &rotation, const helios::RGBcolor &fontcolor, uint fontsize, const char *fontname, CoordinateSystem coordFlag)
Add a text box by giving the coordinates of its center.
void showWatermark()
Make Helios logo watermark visible.
void addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a triangle by giving the coordinates of its three vertices.
-
void disableColorbar()
Disable the colorbar.
-
void setColorbarFontSize(uint font_size)
Set the font size of the colorbar text.
-
void setColorbarFontColor(helios::RGBcolor color)
Set the RGB color of the colorbar text.
-
void buildContextGeometry(helios::Context *context_ptr)
Add all geometry from the Context to the visualizer.
+
void disableColorbar()
Disable the colorbar.
+
void setColorbarFontSize(uint font_size)
Set the font size of the colorbar text.
+
void setColorbarFontColor(helios::RGBcolor color)
Set the RGB color of the colorbar text.
+
void buildContextGeometry(helios::Context *context_ptr)
Add all geometry from the Context to the visualizer.
void addLine(const helios::vec3 &start, const helios::vec3 &end, const helios::RGBcolor &color, uint linewidth, CoordinateSystem coordFlag)
Add Lines by giving the coordinates of points along the Lines.
void setLightDirection(const helios::vec3 &direction)
Set the direction of the light source.
void addVoxelByCenter(const helios::vec3 &center, const helios::vec3 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a voxel by giving the coordinates of its center.
void setCameraFieldOfView(float angle_FOV)
Set the camera field of view (angle width) in degrees. Default value is 45 degrees.
LightingModel
Lighting model to use for shading primitives.
Definition Visualizer.h:382
@ LIGHTING_NONE
No shading, primitive is colored by its diffuse color.
Definition Visualizer.h:384
-
@ LIGHTING_PHONG_SHADOWED
Phong lighting model plus shadowing is applied to add shading effects to the diffuse color.
Definition Visualizer.h:390
+
@ LIGHTING_PHONG_SHADOWED
Phong lighting model plus shadowing is applied to add shading effects to the diffuse color.
Definition Visualizer.h:390
void closeWindow()
Close the graphics window.
-
void addGridWireFrame(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &subdiv)
Add a coordinate axis.
+
void addGridWireFrame(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &subdiv)
Add a coordinate axis.
void addSphereByCenter(float radius, const helios::vec3 &center, uint Ndivisions, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a sphere by giving the radius and center.
void setBackgroundColor(const helios::RGBcolor &color)
Set the background color for the visualizer window.
void clearGeometry()
Clear all geometry previously added to the visualizer.
float getDomainBoundingRadius() const
Get the radius of a sphere that bounds all primitives in the domain.
void getDepthMap(float *buffer)
Get depth buffer data for the current display window.
-
void setColorbarSize(helios::vec2 size)
Set the size of the colorbar in normalized window units (0-1)
-
void addCoordinateAxes()
Add a coordinate axis with at the origin with unit length.
+
void setColorbarSize(helios::vec2 size)
Set the size of the colorbar in normalized window units (0-1)
+
void addCoordinateAxes()
Add a coordinate axis with at the origin with unit length.
void hideWatermark()
Make Helios logo watermark invisible.
Visualizer(uint Wdisplay)
Visualizer constructor.
-
void setColormap(Ctable colormap_name)
Set the colormap used in Colorbar/visualization based on pre-defined colormaps.
-
void plotUpdate()
Update the graphics window based on current geometry, then continue the program.
-
void setColorbarTicks(const std::vector< float > &ticks)
Set the values in the colorbar where ticks and labels should be placed.
+
void setColormap(Ctable colormap_name)
Set the colormap used in Colorbar/visualization based on pre-defined colormaps.
+
void plotUpdate()
Update the graphics window based on current geometry, then continue the program.
+
void setColorbarTicks(const std::vector< float > &ticks)
Set the values in the colorbar where ticks and labels should be placed.
void enableMessages()
Enable standard output from this plug-in (default)
void disableMessages()
Disable standard output from this plug-in.
void getFramebufferSize(uint &width, uint &height) const
Get the size of the framebuffer in pixels.
-
std::vector< helios::vec3 > plotInteractive()
Plot current geometry into an interactive graphics window.
+
std::vector< helios::vec3 > plotInteractive()
Plot current geometry into an interactive graphics window.
void addSkyDomeByCenter(float radius, const helios::vec3 &center, uint Ndivisions, const char *texture_file)
Add a Sky Dome, which is a hemispherical dome colored by a sky texture map.
-
void setColorbarRange(float cmin, float cmax)
Set the range of the Colorbar.
+
void setColorbarRange(float cmin, float cmax)
Set the range of the Colorbar.
void setCameraPosition(const helios::vec3 &cameraPosition, const helios::vec3 &lookAt)
Set camera position.
void addRectangleByVertices(const std::vector< helios::vec3 > &vertices, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a rectangle by giving the coordinates of its four vertices.
-
void colorContextPrimitivesRandomly()
Color primitives from Context with a random color.
+
void colorContextPrimitivesRandomly()
Color primitives from Context with a random color.
void addRectangleByCenter(const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a rectangle by giving the coordinates of its center.
void addDiskByCenter(const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, uint Ndivisions, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a disk by giving the coordinates of its center.
-
void setColorbarPosition(helios::vec3 position)
Set the position of the colorbar in normalized window coordinates (0-1)
-
void colorContextPrimitivesByObjectData(const char *data_name)
Color primitives from Context by color mapping their ‘Object Data’.
+
void setColorbarPosition(helios::vec3 position)
Set the position of the colorbar in normalized window coordinates (0-1)
+
void colorContextPrimitivesByObjectData(const char *data_name)
Color primitives from Context by color mapping their ‘Object Data’.
void setLightIntensityFactor(float lightintensityfactor)
Set the light intensity scaling factor.
-
Colormap getCurrentColormap() const
Get the current colormap used in Colorbar/visualization.
-
void setColorbarTitle(const char *title)
Set the title of the Colorbar.
+
Colormap getCurrentColormap() const
Get the current colormap used in Colorbar/visualization.
+
void setColorbarTitle(const char *title)
Set the title of the Colorbar.
void getWindowSize(uint &width, uint &height) const
Get the size of the display window in pixels.
void getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const
Get a box that bounds all primitives in the domain.
void setLightingModel(LightingModel lightingmodel)
Set the lighting model for shading of all primitives.
-
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
-
Stores the state associated with simulation.
Definition Context.h:1882
-
void getPrimitiveData(uint UUID, const char *label, int &data) const
Get data associated with a primitive element.
-
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
-
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7017
-
std::vector< uint > getAllObjectIDs() const
Get the IDs for all Compound Objects in the Context.
Definition Context.cpp:2589
-
void getObjectData(uint objID, const char *label, int &data) const
Get data associated with a compound object.
-
void getDomainBoundingSphere(helios::vec3 &center, float &radius) const
Get the center and radius of a sphere that bounds all primitives in the domain.
Definition Context.cpp:2116
-
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
-
helios::RGBAcolor getPrimitiveColorRGBA(uint UUID) const
Method to return the diffuse color of a Primitive with transparency.
Definition Context.cpp:7135
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7159
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7175
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
-
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
-
helios::Time getTime() const
Get the simulation time.
Definition Context.cpp:1166
-
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:2046
-
helios::Date getDate() const
Get simulation date.
Definition Context.cpp:1099
+
Stores the state associated with simulation.
Definition Context.h:1888
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
bool doesObjectExist(uint ObjID) const
Check whether Compound Object exists in the Context.
Definition Context.cpp:2585
-
HeliosDataType getPrimitiveDataType(uint UUID, const char *label) const
Get the Helios data type of primitive data.
-
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:7217
-
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:1659
-
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:7122
-
HeliosDataType getObjectDataType(uint objID, const char *label) const
Get the Helios data type of primitive data.
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
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:3102
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
@@ -4945,18 +4929,18 @@
vec3 cross(const vec3 &a, const vec3 &b)
Cross product of two vec3 vectors.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
RGB color map.
Definition Visualizer.h:175
-
void useShader() const
Set shader as current.
-
void setLightingModel(uint lightingmodel) const
Set the lighting model.
-
void setDepthBiasMatrix(const glm::mat4 &matrix) const
Set the depth bias matrix for shadows.
-
void initialize(const char *vertex_shader_file, const char *fragment_shader_file)
Initialize the shader.
-
void setLightDirection(const helios::vec3 &direction) const
Set the direction of the light (sun)
-
void enableTextureMasks() const
Enable texture masks and color fragments by interpolating vertex colors.
-
void disableTextures() const
Disable texture maps and color fragments by interpolating vertex colors.
-
void setTextureMask(const Glyph *glyph, uint &textureID)
Set fragment opacity using a Glyph (red channel)
-
void enableTextureMaps() const
Enable texture maps and color fragments using an RGB texture map.
-
void setTextureMap(const char *texture_file, uint &textureID, helios::int2 &texture_size)
Color fragments using an RGB texture map.
-
void setLightIntensity(float lightintensity) const
Set the intensity of the light source.
-
void setTransformationMatrix(const glm::mat4 &matrix) const
Set the shader transformation matrix, i.e., the Affine transformation applied to all vertices.
+
void useShader() const
Set shader as current.
+
void setLightingModel(uint lightingmodel) const
Set the lighting model.
+
void setDepthBiasMatrix(const glm::mat4 &matrix) const
Set the depth bias matrix for shadows.
+
void initialize(const char *vertex_shader_file, const char *fragment_shader_file)
Initialize the shader.
+
void setLightDirection(const helios::vec3 &direction) const
Set the direction of the light (sun)
+
void enableTextureMasks() const
Enable texture masks and color fragments by interpolating vertex colors.
+
void disableTextures() const
Disable texture maps and color fragments by interpolating vertex colors.
+
void setTextureMask(const Glyph *glyph, uint &textureID)
Set fragment opacity using a Glyph (red channel)
+
void enableTextureMaps() const
Enable texture maps and color fragments using an RGB texture map.
+
void setTextureMap(const char *texture_file, uint &textureID, helios::int2 &texture_size)
Color fragments using an RGB texture map.
+
void setLightIntensity(float lightintensity) const
Set the intensity of the light source.
+
void setTransformationMatrix(const glm::mat4 &matrix) const
Set the shader transformation matrix, i.e., the Affine transformation applied to all vertices.
int month
Month of year.
int day
Day of month.
@@ -4978,17 +4962,17 @@
int second
Second of minute.
int hour
Hour of day.
int minute
Minute of hour.
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
@@ -4996,10 +4980,13 @@
float magnitude() const
Compute the vector magnitude.
- -
+ + diff --git a/doc/html/_visualizer_8h.html b/doc/html/_visualizer_8h.html index d67824470..522ab48a8 100644 --- a/doc/html/_visualizer_8h.html +++ b/doc/html/_visualizer_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Data Structures | @@ -197,7 +203,7 @@

-

Definition at line 4509 of file Visualizer.cpp.

+

Definition at line 4510 of file Visualizer.cpp.

@@ -227,7 +233,7 @@

Definition at line 4353 of file Visualizer.cpp.

+

Definition at line 4354 of file Visualizer.cpp.

@@ -262,7 +268,7 @@

Definition at line 4339 of file Visualizer.cpp.

+

Definition at line 4340 of file Visualizer.cpp.

@@ -380,7 +386,7 @@

Definition at line 4371 of file Visualizer.cpp.

+

Definition at line 4372 of file Visualizer.cpp.

@@ -483,10 +489,13 @@

+ + diff --git a/doc/html/_visualizer_8h.js b/doc/html/_visualizer_8h.js new file mode 100644 index 000000000..d71cc6a8b --- /dev/null +++ b/doc/html/_visualizer_8h.js @@ -0,0 +1,14 @@ +var _visualizer_8h = +[ + [ "Glyph", "class_glyph.html", null ], + [ "Shader", "struct_shader.html", "struct_shader" ], + [ "Colormap", "struct_colormap.html", null ], + [ "Visualizer", "class_visualizer.html", "class_visualizer" ], + [ "cursorCallback", "_visualizer_8h.html#a4a3702f5fdcf4f8328bab6638ece5a37", null ], + [ "mouseCallback", "_visualizer_8h.html#a8b8e3d832e0aeb8c7bf0e77f0ddf0c94", null ], + [ "read_JPEG_file", "_visualizer_8h.html#a1ffc8a34ba2895084c71e95ed615d10a", null ], + [ "read_png_file", "_visualizer_8h.html#a0e60a86e54784ea9f2b178ce9540713f", null ], + [ "scrollCallback", "_visualizer_8h.html#aa9b224479e8c1cc5251b8e7f3fdabacd", null ], + [ "write_JPEG_file", "_visualizer_8h.html#a76a6dfb6593ca66bbd332f6ad6f6a1ea", null ], + [ "write_JPEG_file", "_visualizer_8h.html#aa1897ed232569d651810d146af02d878", null ] +]; \ No newline at end of file diff --git a/doc/html/_visualizer_8h_source.html b/doc/html/_visualizer_8h_source.html index 6cde6e65f..2d78f0e59 100644 --- a/doc/html/_visualizer_8h_source.html +++ b/doc/html/_visualizer_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Visualizer.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef HELIOS_VISUALIZER
17#define HELIOS_VISUALIZER
18
@@ -116,26 +123,26 @@
24#include "glm/gtc/matrix_transform.hpp"
25#include <GLFW/glfw3.h>
26#include "glm/gtx/transform.hpp"
-
27
-
29
+
27
+
29
35int read_JPEG_file (const char * filename, std::vector<unsigned char> &texture, uint & height, uint & width);
-
36
-
38
+
36
+
38
45int write_JPEG_file(const char *filename, uint width, uint height, void *_window, bool print_messages = true);
46
-
47
-
49
+
47
+
49
56int write_JPEG_file(const char *filename, const uint width, const uint height, const std::vector<helios::RGBcolor> &data, bool print_messages = true);
-
57
-
59
+
57
+
59
65void read_png_file( const char* filename, std::vector<unsigned char> &texture, uint & height, uint & width);
-
66
+
66
68void mouseCallback( GLFWwindow* window, int button, int action, int mods );
-
69
+
69
71void cursorCallback( GLFWwindow* window, double x, double y);
-
72
+
72
74void scrollCallback( GLFWwindow* window, double xoffset, double yoffset );
-
75
+
75
77class Glyph{
78 public:
@@ -149,39 +156,39 @@
86
87};
-
88
+
88
90struct Shader{
91public:
92
94 void disableTextures() const;
95
-
97
+
97
102 void setTextureMap( const char* texture_file, uint& textureID, helios::int2& texture_size );
-
103
+
103
105 void enableTextureMaps() const;
106
-
108
+
108
112 void setTextureMask( const Glyph* glyph, uint& textureID );
-
113
-
115
+
113
+
115
120 void setTextureMask( const char* texture_file, uint& textureID, helios::int2& texture_size );
121
123 void enableTextureMasks() const;
-
124
+
124
126 void setTransformationMatrix(const glm::mat4 &matrix ) const;
-
127
+
127
129 void setDepthBiasMatrix(const glm::mat4 &matrix ) const;
-
130
+
130
132 void setLightDirection(const helios::vec3 &direction ) const;
-
133
+
133
135 void setLightingModel( uint lightingmodel ) const;
-
136
+
136
138 void setLightIntensity( float lightintensity ) const;
-
139
+
139
141 void useShader() const;
142
-
144
+
144
148 void initialize( const char* vertex_shader_file, const char* fragment_shader_file );
149
150 ~Shader();
@@ -208,14 +215,14 @@
171
172};
-
173
+
173
-
175struct Colormap{
+
175struct Colormap{
176public:
177
-
178 Colormap() : cmapsize(0), minval(0.0f), maxval(1.0f) {};
+
178 Colormap() : cmapsize(0), minval(0.0f), maxval(1.0f) {};
179
-
180 Colormap(const std::vector<helios::RGBcolor> &ctable, const std::vector<float> &clocs, int size, float minval_, float maxval_ ) : cmapsize(size), minval(minval_), maxval(maxval_){
+
180 Colormap(const std::vector<helios::RGBcolor> &ctable, const std::vector<float> &clocs, int size, float minval_, float maxval_ ) : cmapsize(size), minval(minval_), maxval(maxval_){
181
182 set( ctable, clocs, size, minval_, maxval_ );
183
@@ -309,28 +316,28 @@
271
272};
-
273
+
273
- +
276public:
-
277
-
279
+
277
+
279
282 explicit Visualizer( uint Wdisplay );
-
283
-
285
+
283
+
285
289 Visualizer( uint Wdisplay, uint Hdisplay );
290
291 Visualizer( uint Wdisplay, uint Hdisplay, int aliasing_samples );
-
292
+
292
294 Visualizer( uint Wdisplay, uint Hdisplay, int aliasing_samples, bool window_decorations );
295
296 // !Visualizer destructor
-
297 ~Visualizer();
-
298
+
297 ~Visualizer();
+
298
300 int selfTest();
-
301
+
301
303 void enableMessages();
-
304
+
304
306 void disableMessages();
307
308 /* //! Type of transformation applied to a geometric object */
@@ -346,14 +353,14 @@
318 /* }; */
-
321
+
321
-
324
- +
324
+
327
-
328 };
+
328 };
-
329
+
329
331 enum Ctable{
@@ -362,242 +369,242 @@ - -
346 };
+ +
346 };
-
347
-
349
+
347
+
349
353 void setCameraPosition(const helios::vec3 &cameraPosition, const helios::vec3 &lookAt );
-
354
-
356
+
354
+
356
361 void setCameraPosition(const helios::SphericalCoord &cameraAngle, const helios::vec3 &lookAt );
-
362
-
364
+
362
+
364
367 void setCameraFieldOfView( float angle_FOV );
-
368
-
370
+
368
+
370
373 void setLightDirection(const helios::vec3 &direction );
-
374
+
374
376 void getDomainBoundingBox( helios::vec2& xbounds, helios::vec2& ybounds, helios::vec2& zbounds ) const;
-
377
+
377
379 float getDomainBoundingRadius() const;
-
380
+
380
-
392
-
394
+
392
+
394
398 void setLightingModel(LightingModel lightingmodel );
-
399
-
401
+
399
+
401
404 void setLightIntensityFactor( float lightintensityfactor );
-
405
-
407
+
405
+
407
410 void setBackgroundColor(const helios::RGBcolor &color );
-
411
-
413
+
411
+
413
420 void addRectangleByCenter( const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag );
-
421
-
423
+
421
+
423
430 void addRectangleByCenter( const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, const helios::RGBAcolor &color, CoordinateSystem coordFlag );
-
431
-
433
+
431
+
433
440 void addRectangleByCenter( const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, const char* texture_file, CoordinateSystem coordFlag );
-
441
-
443
+
441
+
443
451 void addRectangleByCenter( const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, const char* texture_file, CoordinateSystem coordFlag );
-
452
-
454
+
452
+
454
462 void addRectangleByCenter( const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, const Glyph* glyph, CoordinateSystem coordFlag );
-
463
-
465
+
463
+
465
470 void addRectangleByVertices( const std::vector<helios::vec3>& vertices, const helios::RGBcolor &color, CoordinateSystem coordFlag );
-
471
-
473
+
471
+
473
478 void addRectangleByVertices( const std::vector<helios::vec3>& vertices, const helios::RGBAcolor &color, CoordinateSystem coordFlag );
-
479
-
481
+
479
+
481
486 void addRectangleByVertices( const std::vector<helios::vec3>& vertices, const char* texture_file, CoordinateSystem coordFlag );
487
-
489
+
489
495 void addRectangleByVertices(const std::vector<helios::vec3>& vertices, const char* texture_file, const std::vector<helios::vec2> &uvs, CoordinateSystem coordFlag );
-
496
-
498
+
496
+
498
505 void addRectangleByVertices( const std::vector<helios::vec3>& vertices, const helios::RGBcolor &color, const char* texture_file, const std::vector<helios::vec2> &uvs, CoordinateSystem coordFlag );
-
506
-
508
+
506
+
508
514 void addRectangleByVertices( const std::vector<helios::vec3>& vertices, const helios::RGBcolor &color, const char* texture_file, CoordinateSystem coordFlag);
515
-
517
+
517
523 void addRectangleByVertices( const std::vector<helios::vec3>& vertices, const helios::RGBcolor &color, const Glyph* glyph, CoordinateSystem coordFlag );
-
524
-
526
+
524
+
526
532 void addRectangleByVertices( const std::vector<helios::vec3>& vertices, const helios::RGBAcolor &color, const Glyph* glyph, CoordinateSystem coordFlag );
533
-
535
+
535
542 void addTriangle( const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2, const helios::RGBcolor &color, CoordinateSystem coordFlag );
-
543
-
545
+
543
+
545
552 void addTriangle( const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2, const helios::RGBAcolor &color, CoordinateSystem coordFlag );
-
553
-
555
+
553
+
555
565 void addTriangle( const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2, const char* texture_file, const helios::vec2 &uv0, const helios::vec2 &uv1, const helios::vec2 &uv2, CoordinateSystem coordFlag );
-
566
-
568
+
566
+
568
579 void addTriangle( const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2, const char* texture_file, const helios::vec2 &uv0, const helios::vec2 &uv1, const helios::vec2 &uv2, const helios::RGBAcolor &color, CoordinateSystem coordFlag );
-
580
-
582
+
580
+
582
588 void addVoxelByCenter( const helios::vec3 &center, const helios::vec3 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag );
-
589
-
591
+
589
+
591
597 void addVoxelByCenter( const helios::vec3 &center, const helios::vec3 &size, const helios::SphericalCoord &rotation, const helios::RGBAcolor &color, CoordinateSystem coordFlag );
-
598
-
600
+
598
+
600
607 void addDiskByCenter( const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, uint Ndivisions, const helios::RGBcolor &color, CoordinateSystem coordFlag );
-
608
-
610
+
608
+
610
617 void addDiskByCenter( const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, uint Ndivisions, const helios::RGBAcolor &color, CoordinateSystem coordFlag );
-
618
-
620
+
618
+
620
627 void addDiskByCenter( const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, uint Ndivisions, const char* texture_file, CoordinateSystem coordFlag );
-
628
-
630
+
628
+
630
637 void addLine( const helios::vec3 &start, const helios::vec3 &end, const helios::RGBcolor &color, uint linewidth, CoordinateSystem coordFlag );
-
638
-
640
+
638
+
640
647 void addLine( const helios::vec3 &start, const helios::vec3 &end, const helios::RGBAcolor &color, uint linewidth, CoordinateSystem coordFlag );
-
648
-
650
+
648
+
650
656 void addPoint( const helios::vec3 &position, const helios::RGBcolor &color, uint pointsize, CoordinateSystem coordFlag);
-
657
-
659
+
657
+
659
665 void addPoint( const helios::vec3 &position, const helios::RGBAcolor &color, uint pointsize, CoordinateSystem coordFlag );
666
-
668
+
668
675 void addSphereByCenter( float radius, const helios::vec3 &center, uint Ndivisions, const helios::RGBcolor &color, CoordinateSystem coordFlag );
-
676
-
678
+
676
+
678
685 void addSphereByCenter( float radius, const helios::vec3 &center, uint Ndivisions, const helios::RGBAcolor &color, CoordinateSystem coordFlag );
-
686
-
688
+
686
+
688
694 void addSkyDomeByCenter( float radius, const helios::vec3 &center, uint Ndivisions, const char* texture_file );
-
695
-
697
+
695
+
697
698 DEPRECATED( void addSkyDomeByCenter( float radius, const helios::vec3 &center, uint Ndivisions, const char* texture_file, int layer ) );
-
699
-
701
+
699
+
701
709 void addTextboxByCenter( const char* textstring, const helios::vec3 &center, const helios::SphericalCoord &rotation, const helios::RGBcolor &fontcolor, uint fontsize, const char* fontname, CoordinateSystem coordFlag );
-
710
+
710
712 void addCoordinateAxes();
-
713
-
715
+
713
+
715
720 void addCoordinateAxes(const helios::vec3 &origin, const helios::vec3 &length, const std::string &sign);
-
721
-
723
+
721
+
723
728 void addGridWireFrame(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &subdiv);
-
729
+
729
731 void enableColorbar();
-
732
+
732
734 void disableColorbar();
-
735
-
737
+
735
+
737
740 void setColorbarPosition( helios::vec3 position );
-
741
-
743
+
741
+
743
746 void setColorbarSize( helios::vec2 size );
-
747
-
749
+
747
+
749
753 void setColorbarRange( float cmin, float cmax );
-
754
-
756
+
754
+
756
760 void setColorbarTicks(const std::vector<float> &ticks );
-
761
-
763
+
761
+
763
766 void setColorbarTitle( const char* title );
-
767
-
769
+
767
+
769
-
773
-
775
+
773
+
775
778 void setColorbarFontSize( uint font_size );
-
779
-
781
+
779
+
781
785 void setColormap( Ctable colormap_name );
-
786
-
788
+
786
+
788
792 void setColormap(const std::vector<helios::RGBcolor> &colors, const std::vector<float> &divisions );
-
793
+
793
796
-
798
+
798
801 void buildContextGeometry( helios::Context* context_ptr );
-
802
-
804
+
802
+
804
808 void buildContextGeometry(helios::Context* context_ptr, const std::vector<uint>& UUIDs );
-
809
-
811
+
809
+
811
815 void colorContextPrimitivesByData( const char* data_name );
-
816
-
818
+
816
+
818
823 void colorContextPrimitivesByData( const char* data_name, const std::vector<uint>& UUIDs );
-
824
-
826
+
824
+
826
830 void colorContextPrimitivesByObjectData( const char* data_name );
-
831
-
833
+
831
+
833
838 void colorContextPrimitivesByObjectData( const char* data_name, const std::vector<uint>& ObjIDs );
-
839
-
841
+
839
+
841
845 void colorContextPrimitivesRandomly(const std::vector<uint>& UUIDs );
846
-
848
+
848
852
-
854
+
854
857 void colorContextObjectsRandomly(const std::vector<uint>& ObjIDs );
858
-
860
+
860
864
865
867 void hideWatermark();
-
868
+
868
870 void showWatermark();
-
871
+
871
873 std::vector<helios::vec3> plotInteractive();
-
874
+
874
876 void plotDepthMap();
-
877
+
877
879 void plotUpdate();
-
880
-
882
+
880
+
882
885 void plotUpdate( bool hide_window );
-
886
+
886
888 void printWindow();
889
-
891
+
891
895 void printWindow( const char* outfile );
-
896
-
898
+
896
+
898
901 void getWindowPixelsRGB( uint * buffer );
-
902
-
904
+
902
+
904
908 void getDepthMap( float * buffer );
-
909
-
911
+
909
+
911
915 void getWindowSize( uint &width, uint &height ) const;
-
916
-
918
+
916
+
918
922 void getFramebufferSize( uint &width, uint &height ) const;
-
923
+
923
925 void clearGeometry();
-
926
+
926
928 void closeWindow();
929
930private:
@@ -622,58 +629,58 @@
949 std::map<uint,helios::int2> group_start;
950
951 void getViewKeystrokes( helios::vec3& eye, helios::vec3& center );
-
952
+
952
954 void addColorbarByCenter(const char* title, const helios::vec2 &size, const helios::vec3 &center, const helios::RGBcolor &font_color, const Colormap &colormap );
-
955
+
955
957 uint Wdisplay;
959 uint Hdisplay;
-
960
+
960
962 uint Wframebuffer;
964 uint Hframebuffer;
965
966 uint frame_counter;
-
967
-
969
+
967
+
969
970 void* window;
-
971
+
971
973 helios::vec3 camera_lookat_center;
-
974
+
974
976 helios::vec3 camera_eye_location;
-
977
+
977
979 Shader primaryShader;
-
980
+
980
982 Shader depthShader;
983
984 Shader* currentShader;
985
986 uint framebufferID;
987 uint depthTexture;
-
988
+
988
990 std::vector<LightingModel> primaryLightingModel;
991
992 float lightintensity = 1.f;
993
994 bool isWatermarkVisible;
-
995
+
995
997 helios::RGBcolor backgroundColor;
-
998
+
998
1000 helios::vec3 light_direction;
-
1001
-
1003
+
1001
+
1003
1004 uint colorbar_flag;
-
1005
+
1005
1007 std::string colorbar_title;
-
1008
+
1008
1010 uint colorbar_fontsize;
-
1011
+
1011
1013 uint point_width;
-
1014
+
1014
1016 uint line_width;
-
1017
+
1017
1019 helios::RGBcolor colorbar_fontcolor;
-
1020
+
1020
1022 helios::vec3 colorbar_position;
-
1023
+
1023
1025 helios::vec2 colorbar_size;
1026
1027 uint positionBuffer, colorBuffer, normalBuffer, uvBuffer, textureFlagBuffer, coordinateFlagBuffer;
@@ -687,7 +694,7 @@
1035 void updateCustomTransformation(const glm::mat4 &matrix );
1036
1037 glm::mat4 customTransformationMatrix;
-
1038
+
1038
1040 float camera_FOV;
1041
1042 bool contextGeomNeedsUpdate;
@@ -695,25 +702,25 @@
1044 bool primitiveColorsNeedUpdate;
1045
1046 helios::Context* context;
-
1047
+
1047
1049 void buildContextGeometry_private();
1050
1051 float colorbar_min;
1052 float colorbar_max;
1053 std::vector<float> colorbar_ticks;
-
1054
+
1054
1056 Colormap colormap_current;
-
1057
+
1057
1059 Colormap colormap_hot;
-
1060
+
1060
1062 Colormap colormap_cool;
-
1063
+
1063
1065 Colormap colormap_lava;
-
1066
+
1066
1068 Colormap colormap_rainbow;
-
1069
+
1069
1071 Colormap colormap_parula;
-
1072
+
1072
1074 Colormap colormap_gray;
1075
1076 bool message_flag;
@@ -730,38 +737,37 @@
void read_png_file(const char *filename, std::vector< unsigned char > &texture, uint &height, uint &width)
Function to create a texture map from a PNG image.
int read_JPEG_file(const char *filename, std::vector< unsigned char > &texture, uint &height, uint &width)
Function to create a texture map from a JPEG image.
-
void cursorCallback(GLFWwindow *window, double x, double y)
Callback function for mouse cursor movements.
-
void mouseCallback(GLFWwindow *window, int button, int action, int mods)
Callback function for mouse button presses.
+
void cursorCallback(GLFWwindow *window, double x, double y)
Callback function for mouse cursor movements.
+
void mouseCallback(GLFWwindow *window, int button, int action, int mods)
Callback function for mouse button presses.
int write_JPEG_file(const char *filename, uint width, uint height, void *_window, bool print_messages=true)
Write current graphics window to a JPEG image file.
-
void scrollCallback(GLFWwindow *window, double xoffset, double yoffset)
Callback function for mouse scroll.
+
void scrollCallback(GLFWwindow *window, double xoffset, double yoffset)
Callback function for mouse scroll.
Glyph object - 2D matrix shape.
Definition Visualizer.h:77
-
Class for visualization of simulation results.
Definition Visualizer.h:275
-
void enableColorbar()
Enable the colorbar.
+
void enableColorbar()
Enable the colorbar.
CoordinateSystem
Coordinate system to be used when specifying spatial coordinates.
Definition Visualizer.h:320
-
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
+
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
@ COORDINATES_WINDOW_NORMALIZED
Coordinates are normalized to unity and are window-aligned. The point (x,y)=(0,0) is in the bottom le...
Definition Visualizer.h:323
Ctable
Pseudocolor map tables.
Definition Visualizer.h:331
@ COLORMAP_HOT
"Hot" colormap
Definition Visualizer.h:333
@ COLORMAP_COOL
"Cool" colormap
Definition Visualizer.h:335
-
@ COLORMAP_CUSTOM
Custom colormap.
Definition Visualizer.h:345
+
@ COLORMAP_CUSTOM
Custom colormap.
Definition Visualizer.h:345
@ COLORMAP_GRAY
"Gray" colormap
Definition Visualizer.h:343
@ COLORMAP_PARULA
"Parula" colormap
Definition Visualizer.h:341
@ COLORMAP_RAINBOW
"Rainbow" colormap
Definition Visualizer.h:337
@ COLORMAP_LAVA
"Lava" colormap
Definition Visualizer.h:339
-
void colorContextPrimitivesByData(const char *data_name)
Color primitives from Context by color mapping their ‘Primitive Data’.
-
void plotDepthMap()
Plot the depth map (distance from camera to nearest object)
+
void colorContextPrimitivesByData(const char *data_name)
Color primitives from Context by color mapping their ‘Primitive Data’.
+
void plotDepthMap()
Plot the depth map (distance from camera to nearest object)
void getWindowPixelsRGB(uint *buffer)
Get R-G-B pixel data in the current display window.
-
void colorContextObjectsRandomly()
Color objects from Context with a random color.
+
void colorContextObjectsRandomly()
Color objects from Context with a random color.
int selfTest()
Visualizer self-test routine.
void addPoint(const helios::vec3 &position, const helios::RGBcolor &color, uint pointsize, CoordinateSystem coordFlag)
Add a point by giving its coordinates and size.
void printWindow()
Print the current graphics window to a JPEG image file. File will be given a default filename and sav...
void addTextboxByCenter(const char *textstring, const helios::vec3 &center, const helios::SphericalCoord &rotation, const helios::RGBcolor &fontcolor, uint fontsize, const char *fontname, CoordinateSystem coordFlag)
Add a text box by giving the coordinates of its center.
void showWatermark()
Make Helios logo watermark visible.
void addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a triangle by giving the coordinates of its three vertices.
-
void disableColorbar()
Disable the colorbar.
-
void setColorbarFontSize(uint font_size)
Set the font size of the colorbar text.
-
void setColorbarFontColor(helios::RGBcolor color)
Set the RGB color of the colorbar text.
-
void buildContextGeometry(helios::Context *context_ptr)
Add all geometry from the Context to the visualizer.
+
void disableColorbar()
Disable the colorbar.
+
void setColorbarFontSize(uint font_size)
Set the font size of the colorbar text.
+
void setColorbarFontColor(helios::RGBcolor color)
Set the RGB color of the colorbar text.
+
void buildContextGeometry(helios::Context *context_ptr)
Add all geometry from the Context to the visualizer.
void addLine(const helios::vec3 &start, const helios::vec3 &end, const helios::RGBcolor &color, uint linewidth, CoordinateSystem coordFlag)
Add Lines by giving the coordinates of points along the Lines.
void setLightDirection(const helios::vec3 &direction)
Set the direction of the light source.
void addVoxelByCenter(const helios::vec3 &center, const helios::vec3 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a voxel by giving the coordinates of its center.
@@ -769,72 +775,75 @@
LightingModel
Lighting model to use for shading primitives.
Definition Visualizer.h:382
@ LIGHTING_NONE
No shading, primitive is colored by its diffuse color.
Definition Visualizer.h:384
@ LIGHTING_PHONG
Phong lighting model is applied to add shading effects to the diffuse color.
Definition Visualizer.h:387
-
@ LIGHTING_PHONG_SHADOWED
Phong lighting model plus shadowing is applied to add shading effects to the diffuse color.
Definition Visualizer.h:390
+
@ LIGHTING_PHONG_SHADOWED
Phong lighting model plus shadowing is applied to add shading effects to the diffuse color.
Definition Visualizer.h:390
DEPRECATED(void addSkyDomeByCenter(float radius, const helios::vec3 &center, uint Ndivisions, const char *texture_file, int layer))
Add a Sky Dome, which is a hemispherical dome colored by a sky texture map.
void closeWindow()
Close the graphics window.
-
void addGridWireFrame(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &subdiv)
Add a coordinate axis.
+
void addGridWireFrame(const helios::vec3 &center, const helios::vec3 &size, const helios::int3 &subdiv)
Add a coordinate axis.
void addSphereByCenter(float radius, const helios::vec3 &center, uint Ndivisions, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a sphere by giving the radius and center.
void setBackgroundColor(const helios::RGBcolor &color)
Set the background color for the visualizer window.
void clearGeometry()
Clear all geometry previously added to the visualizer.
float getDomainBoundingRadius() const
Get the radius of a sphere that bounds all primitives in the domain.
void getDepthMap(float *buffer)
Get depth buffer data for the current display window.
-
void setColorbarSize(helios::vec2 size)
Set the size of the colorbar in normalized window units (0-1)
-
void addCoordinateAxes()
Add a coordinate axis with at the origin with unit length.
+
void setColorbarSize(helios::vec2 size)
Set the size of the colorbar in normalized window units (0-1)
+
void addCoordinateAxes()
Add a coordinate axis with at the origin with unit length.
void hideWatermark()
Make Helios logo watermark invisible.
Visualizer(uint Wdisplay)
Visualizer constructor.
-
void setColormap(Ctable colormap_name)
Set the colormap used in Colorbar/visualization based on pre-defined colormaps.
-
void plotUpdate()
Update the graphics window based on current geometry, then continue the program.
-
void setColorbarTicks(const std::vector< float > &ticks)
Set the values in the colorbar where ticks and labels should be placed.
+
void setColormap(Ctable colormap_name)
Set the colormap used in Colorbar/visualization based on pre-defined colormaps.
+
void plotUpdate()
Update the graphics window based on current geometry, then continue the program.
+
void setColorbarTicks(const std::vector< float > &ticks)
Set the values in the colorbar where ticks and labels should be placed.
void enableMessages()
Enable standard output from this plug-in (default)
void disableMessages()
Disable standard output from this plug-in.
void getFramebufferSize(uint &width, uint &height) const
Get the size of the framebuffer in pixels.
-
std::vector< helios::vec3 > plotInteractive()
Plot current geometry into an interactive graphics window.
+
std::vector< helios::vec3 > plotInteractive()
Plot current geometry into an interactive graphics window.
void addSkyDomeByCenter(float radius, const helios::vec3 &center, uint Ndivisions, const char *texture_file)
Add a Sky Dome, which is a hemispherical dome colored by a sky texture map.
-
void setColorbarRange(float cmin, float cmax)
Set the range of the Colorbar.
+
void setColorbarRange(float cmin, float cmax)
Set the range of the Colorbar.
void setCameraPosition(const helios::vec3 &cameraPosition, const helios::vec3 &lookAt)
Set camera position.
void addRectangleByVertices(const std::vector< helios::vec3 > &vertices, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a rectangle by giving the coordinates of its four vertices.
-
void colorContextPrimitivesRandomly()
Color primitives from Context with a random color.
+
void colorContextPrimitivesRandomly()
Color primitives from Context with a random color.
void addRectangleByCenter(const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a rectangle by giving the coordinates of its center.
void addDiskByCenter(const helios::vec3 &center, const helios::vec2 &size, const helios::SphericalCoord &rotation, uint Ndivisions, const helios::RGBcolor &color, CoordinateSystem coordFlag)
Add a disk by giving the coordinates of its center.
-
void setColorbarPosition(helios::vec3 position)
Set the position of the colorbar in normalized window coordinates (0-1)
-
void colorContextPrimitivesByObjectData(const char *data_name)
Color primitives from Context by color mapping their ‘Object Data’.
+
void setColorbarPosition(helios::vec3 position)
Set the position of the colorbar in normalized window coordinates (0-1)
+
void colorContextPrimitivesByObjectData(const char *data_name)
Color primitives from Context by color mapping their ‘Object Data’.
void setLightIntensityFactor(float lightintensityfactor)
Set the light intensity scaling factor.
-
Colormap getCurrentColormap() const
Get the current colormap used in Colorbar/visualization.
-
void setColorbarTitle(const char *title)
Set the title of the Colorbar.
+
Colormap getCurrentColormap() const
Get the current colormap used in Colorbar/visualization.
+
void setColorbarTitle(const char *title)
Set the title of the Colorbar.
void getWindowSize(uint &width, uint &height) const
Get the size of the display window in pixels.
void getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const
Get a box that bounds all primitives in the domain.
void setLightingModel(LightingModel lightingmodel)
Set the lighting model for shading of all primitives.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
RGB color map.
Definition Visualizer.h:175
OpenGL Shader data structure.
Definition Visualizer.h:90
-
void useShader() const
Set shader as current.
-
void setLightingModel(uint lightingmodel) const
Set the lighting model.
-
void setDepthBiasMatrix(const glm::mat4 &matrix) const
Set the depth bias matrix for shadows.
-
void initialize(const char *vertex_shader_file, const char *fragment_shader_file)
Initialize the shader.
-
void setLightDirection(const helios::vec3 &direction) const
Set the direction of the light (sun)
-
void enableTextureMasks() const
Enable texture masks and color fragments by interpolating vertex colors.
-
void disableTextures() const
Disable texture maps and color fragments by interpolating vertex colors.
-
void setTextureMask(const Glyph *glyph, uint &textureID)
Set fragment opacity using a Glyph (red channel)
-
void enableTextureMaps() const
Enable texture maps and color fragments using an RGB texture map.
-
void setTextureMap(const char *texture_file, uint &textureID, helios::int2 &texture_size)
Color fragments using an RGB texture map.
-
void setLightIntensity(float lightintensity) const
Set the intensity of the light source.
-
void setTransformationMatrix(const glm::mat4 &matrix) const
Set the shader transformation matrix, i.e., the Affine transformation applied to all vertices.
+
void useShader() const
Set shader as current.
+
void setLightingModel(uint lightingmodel) const
Set the lighting model.
+
void setDepthBiasMatrix(const glm::mat4 &matrix) const
Set the depth bias matrix for shadows.
+
void initialize(const char *vertex_shader_file, const char *fragment_shader_file)
Initialize the shader.
+
void setLightDirection(const helios::vec3 &direction) const
Set the direction of the light (sun)
+
void enableTextureMasks() const
Enable texture masks and color fragments by interpolating vertex colors.
+
void disableTextures() const
Disable texture maps and color fragments by interpolating vertex colors.
+
void setTextureMask(const Glyph *glyph, uint &textureID)
Set fragment opacity using a Glyph (red channel)
+
void enableTextureMaps() const
Enable texture maps and color fragments using an RGB texture map.
+
void setTextureMap(const char *texture_file, uint &textureID, helios::int2 &texture_size)
Color fragments using an RGB texture map.
+
void setLightIntensity(float lightintensity) const
Set the intensity of the light source.
+
void setTransformationMatrix(const glm::mat4 &matrix) const
Set the shader transformation matrix, i.e., the Affine transformation applied to all vertices.
R-G-B-A color vector.
R-G-B color vector.
float b
Blue color component.
float r
Red color component.
float g
Green color component.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of two elements of type 'int'.
-
Vector of three elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_visualizer_doc.html b/doc/html/_visualizer_doc.html index 6942206a8..80f249de3 100644 --- a/doc/html/_visualizer_doc.html +++ b/doc/html/_visualizer_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Visualizer Plugin Documentation
@@ -375,7 +381,7 @@

SphericalCoord rotation = make_SphericalCoord(0,0);
vis.addRectangleByCenter(center, size, rotation, RGB::red, Visualizer::COORDINATES_CARTESIAN);
}
-
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326
+
@ COORDINATES_CARTESIAN
Coordinates are specified in a 3D Cartesian system (right-handed), where +z is vertical.
Definition Visualizer.h:326

Automatically importing Context geometry

The visualizer can automatically import some or all geometry from the Context. This is accomplished using the buildContextGeometry command. To add all primitives in the Context, the buildContextGeometry command would be issued, which is passed the Context. We can add a subset of the Context geometry through an additional argument which takes a vector of UUID's.

@@ -396,8 +402,8 @@

int main(){
Context context;
-
vec3 center = make_vec3(0,0,0);
-
vec2 size = make_vec2(1,1);
+
vec3 center = make_vec3(0,0,0);
+
vec2 size = make_vec2(1,1);
context.addPatch(center,size);
Visualizer vis( 1200 );
@@ -405,10 +411,12 @@

vis.buildContextGeometry(&context);
}
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
+
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.

Plotting Geometry

To this point, we have not actually plotted anything in the Visualizer window. A final command is neede to display all of the geometry added to the Visualizer in the window we have opened. There are two functions for doing this, which are detailed below.

@@ -423,8 +431,8 @@

int main(){
Context context;
-
vec3 center = make_vec3(0,0,0);
-
vec2 size = make_vec2(1,1);
+
vec3 center = make_vec3(0,0,0);
+
vec2 size = make_vec2(1,1);
context.addRectangleByCenter(center,size);
Visualizer vis( 1200 );
@@ -479,8 +487,8 @@

int main(){
Context context;
-
vec3 center = make_vec3(0,0,0);
-
vec2 size = make_vec2(1,1);
+
vec3 center = make_vec3(0,0,0);
+
vec2 size = make_vec2(1,1);
context.addPatch(center,size);
Visualizer vis( 1200 );
@@ -563,11 +571,11 @@

Visualizer vis(1000);
std::vector<RGBcolor> ctable_colors;
-
ctable_colors.push_back( make_RGBcolor( 0.f, 0.f, 0.f ) );
-
ctable_colors.push_back( make_RGBcolor( 0.5f, 0.f, 0.5f ) );
-
ctable_colors.push_back( make_RGBcolor( 1.f, 0.f, 0.f ) );
-
ctable_colors.push_back( make_RGBcolor( 1.f, 0.5f, 0.f ) );
-
ctable_colors.push_back( make_RGBcolor( 1.f, 1.f, 0.f ) );
+
ctable_colors.push_back( make_RGBcolor( 0.f, 0.f, 0.f ) );
+
ctable_colors.push_back( make_RGBcolor( 0.5f, 0.f, 0.5f ) );
+
ctable_colors.push_back( make_RGBcolor( 1.f, 0.f, 0.f ) );
+
ctable_colors.push_back( make_RGBcolor( 1.f, 0.5f, 0.f ) );
+
ctable_colors.push_back( make_RGBcolor( 1.f, 1.f, 0.f ) );
std::vector<float> ctable_positions;
ctable_positions.push_back( 0.f );
@@ -577,7 +585,8 @@

ctable_positions.push_back( 1.f );
vis.setColormap( Visualizer::COLORMAP_CUSTOM, ctable_colors, ctable_positions );
-
@ COLORMAP_CUSTOM
Custom colormap.
Definition Visualizer.h:345
+
@ COLORMAP_CUSTOM
Custom colormap.
Definition Visualizer.h:345
+
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor vector.

Colorbar

The colorbar is the legend showing how values are mapped to the color table. The table below gives functions for customizing colorbar behavior, including for example its position, size, and visibility.

@@ -625,17 +634,18 @@

int main(){
Visualizer vis( 1200 );
-
vec3 center = make_vec3(0,0,0);
-
vec2 size = make_vec2(1,1);
-
SphericalCoord rotation = make_SphericalCoord(0,0);
+
vec3 center = make_vec3(0,0,0);
+
vec2 size = make_vec2(1,1);
+
vis.addRectangleByCenter(center,size,rotation,RGB::red,Visualizer::COORDINATES_CARTESIAN,0);
-
vec3 light_direction = make_vec3(1,1,1);
+
vec3 light_direction = make_vec3(1,1,1);
vis.setLightingModel( Visualizer::LIGHTING_PHONG_SHADOWED );
vis.setLightDirection( light_direction );
}
-
@ LIGHTING_PHONG_SHADOWED
Phong lighting model plus shadowing is applied to add shading effects to the diffuse color.
Definition Visualizer.h:390
+
@ LIGHTING_PHONG_SHADOWED
Phong lighting model plus shadowing is applied to add shading effects to the diffuse color.
Definition Visualizer.h:390
+
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
Vector of spherical coordinates (elevation,azimuth)

View Options

@@ -656,10 +666,13 @@

libpng: Copyright (c) 1995-2019 The PNG Reference Library Authors. Copyright (c) 2018-2019 Cosmin Truta. Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson. Copyright (c) 1996-1997 Andreas Dilger. Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.

- -
+ + diff --git a/doc/html/_voxel_intersection_8cpp.html b/doc/html/_voxel_intersection_8cpp.html index 16d25403b..4a00934ea 100644 --- a/doc/html/_voxel_intersection_8cpp.html +++ b/doc/html/_voxel_intersection_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
VoxelIntersection.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file VoxelIntersection.cpp.

- -
+ + diff --git a/doc/html/_voxel_intersection_8cpp_source.html b/doc/html/_voxel_intersection_8cpp_source.html index 0270d9d3f..d44e362b4 100644 --- a/doc/html/_voxel_intersection_8cpp_source.html +++ b/doc/html/_voxel_intersection_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
VoxelIntersection.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "VoxelIntersection.h"
17
18using namespace helios;
@@ -127,13 +134,13 @@
32 }
33
34 int error_count = 0;
-
35
+
35
37 //------ single patch entirely on one side of voxel face should not be sliced ------//
38 Context context_1;
39 if( printmessages ){
40 std::cout << "Running Test 1: patch with no slices..." << std::flush;
41 }
-
42 VoxelIntersection vi_1(&context_1);
+
42 VoxelIntersection vi_1(&context_1);
43 vi_1.disableMessages();
44
45 //create single patch
@@ -159,7 +166,7 @@
66
67 Context context_2;
68
-
69 VoxelIntersection vi_2(&context_2);
+
69 VoxelIntersection vi_2(&context_2);
70 vi_2.disableMessages();
71
72 //create single patch
@@ -188,7 +195,7 @@
96
97 Context context_3;
98
-
99 VoxelIntersection vi_3(&context_3);
+
99 VoxelIntersection vi_3(&context_3);
100 vi_3.disableMessages();
101
102 //create single patch
@@ -216,7 +223,7 @@
125
126 Context context_4;
127
-
128 VoxelIntersection vi_4(&context_4);
+
128 VoxelIntersection vi_4(&context_4);
129 vi_4.disableMessages();
130
131 //create single patch
@@ -256,7 +263,7 @@
166 std::cout << "Running Test 5: areas after slicing..." << std::flush;
167 }
168 Context context_5;
-
169 VoxelIntersection vi_5(&context_5);
+
169 VoxelIntersection vi_5(&context_5);
170 vi_5.disableMessages();
171
172 for(uint i=0;i<100;i++)
@@ -307,7 +314,7 @@
218 std::cout << "Running Test 6: textured areas after slicing..." << std::flush;
219 }
220 Context context_6;
-
221 VoxelIntersection vi_6(&context_6);
+
221 VoxelIntersection vi_6(&context_6);
222 vi_6.disableMessages();
223
224 for(uint i=0;i<100;i++)
@@ -351,13 +358,13 @@
262 error_count ++;
263 std::cerr << "failed: area before and after slicing different by" << pdiff_6 << "%" << std::endl;
264 }
-
265
+
265
267 //------ many non-textured patches, check total area is consistent ------//
268 if( printmessages ){
269 std::cout << "Running Test 7: cropping non-textured primitives..." << std::flush;
270 }
271 Context context_7;
-
272 VoxelIntersection vi_7(&context_7);
+
272 VoxelIntersection vi_7(&context_7);
273 vi_7.disableMessages();
274
275 for(uint i=0;i<100;i++)
@@ -397,13 +404,13 @@
309 error_count ++;
310 std::cerr << "failed: number of primitives after cropping doesn't match number in grid cells: " << UUIDs_after_crop_7.size() << " vs. " << UUIDs_in_cells_7 << std::endl;
311 }
-
312
+
312
314 //------ many textured patches, check number of primitives in cells matches number after cropping ------//
315 if( printmessages ){
316 std::cout << "Running Test 8: cropping textured primitives..." << std::flush;
317 }
318 Context context_8;
-
319 VoxelIntersection vi_8(&context_8);
+
319 VoxelIntersection vi_8(&context_8);
320 vi_8.disableMessages();
321 for(uint i=0;i<100;i++)
322 {
@@ -441,7 +448,7 @@
354 error_count ++;
355 std::cerr << "failed: number of primitives after cropping doesn't match number in grid cells: " << UUIDs_after_crop_8.size() << " vs. " << UUIDs_in_cells_8 << std::endl;
356 }
-
357
+
357
359 //------ Voxel-patch intersection test ------//
360 if( printmessages ){
361 std::cout << "Running Test 9: intersection of voxels and patches..." << std::flush;
@@ -477,7 +484,7 @@
391 UUID_outside.push_back( context_test.addPatch( vorigin + 10*vsize, psize ) );
392 UUID_outside.push_back( context_test.addPatch( vorigin - 10*vsize, psize ) );
393
-
394 VoxelIntersection vintersection(&context_test);
+
394 VoxelIntersection vintersection(&context_test);
395 vintersection.disableMessages();
396
@@ -594,20 +601,20 @@
504 helios::vec3 face_normal = cross(voxel_face_vertices.at(1) - voxel_face_vertices.at(0), voxel_face_vertices.at(2) - voxel_face_vertices.at(1));
505 face_normal.normalize();
506
-
507 std::vector<helios::vec3> primitive_vertices = context->getPrimitiveVertices(UUID);
-
508 helios::vec3 primitive_normal = context->getPrimitiveNormal(UUID);
+
507 std::vector<helios::vec3> primitive_vertices = context->getPrimitiveVertices(UUID);
+
508 helios::vec3 primitive_normal = context->getPrimitiveNormal(UUID);
509 primitive_normal.normalize();
510
-
511 helios::RGBAcolor primitive_color = context->getPrimitiveColorRGBA(UUID);
+
511 helios::RGBAcolor primitive_color = context->getPrimitiveColorRGBA(UUID);
512
513 std::string texa;
514 const char * tex;
-
515 texa = context->getPrimitiveTextureFile(UUID);
+
515 texa = context->getPrimitiveTextureFile(UUID);
516 tex = texa.c_str();
517 bool primitiveHasTexture = !texa.empty();
518
519 //get the area of the original primitive for comparison with the area of the sliced primitives later
-
520 float original_area = context->getPrimitiveArea(UUID);
+
520 float original_area = context->getPrimitiveArea(UUID);
521
523 // find the equation of the line where the planes of the patch and voxel face intersect
524
@@ -965,52 +972,52 @@
878 if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 1))
879 {
880 diag_1 = 1;
-
881 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
-
882 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
-
883 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
881 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
+
882 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
+
883 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
884 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 0)){
885 diag_1 = 2;
-
886 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
-
887 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, primitive_color);
-
888 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
+
886 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
+
887 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, primitive_color);
+
888 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
889 }else if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 2)){
890 diag_1 = 3;
-
891 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
892 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
-
893 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
891 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
892 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
+
893 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
894 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 0)){
895 diag_1 = 4;
-
896 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
-
897 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
898 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
896 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
+
897 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
898 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
899 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 2)){
900 diag_1 = 5;
-
901 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);//
-
902 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);//
-
903 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
901 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);//
+
902 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);//
+
903 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
904 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 1)){
905 diag_1 = 6;
-
906 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);//
-
907 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);//
-
908 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
906 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);//
+
907 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);//
+
908 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
909 }
910
911 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
912 if(context->getPrimitiveArea(t0) < minArea)
+
912 if(context->getPrimitiveArea(t0) < minArea)
913 {
-
914 context->deletePrimitive(t0);
+
914 context->deletePrimitive(t0);
915 }else{
916 resulting_UUIDs.push_back(t0);
917 }
-
918 if(context->getPrimitiveArea(t1) < minArea)
+
918 if(context->getPrimitiveArea(t1) < minArea)
919 {
-
920 context->deletePrimitive(t1);
+
920 context->deletePrimitive(t1);
921 }else{
922 resulting_UUIDs.push_back(t1);
923 }
-
924 if(context->getPrimitiveArea(t2) < minArea)
+
924 if(context->getPrimitiveArea(t2) < minArea)
925 {
-
926 context->deletePrimitive(t2);
+
926 context->deletePrimitive(t2);
927 }else{
928 resulting_UUIDs.push_back(t2);
929 }
@@ -1022,28 +1029,28 @@
935 if(slice_points_edge_ID.at(0) == 0)
936 {
937 diag_1 = 7;
-
938 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
939 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
+
938 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
939 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
940 }else if(slice_points_edge_ID.at(0) == 1){
941 diag_1 = 8;
-
942 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, primitive_color);
-
943 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
+
942 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, primitive_color);
+
943 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
944 }else if(slice_points_edge_ID.at(0) == 2){
945 diag_1 = 9;
-
946 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
-
947 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
946 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
+
947 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
948 }
949
950 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
951 if(context->getPrimitiveArea(t0) < minArea)
+
951 if(context->getPrimitiveArea(t0) < minArea)
952 {
-
953 context->deletePrimitive(t0);
+
953 context->deletePrimitive(t0);
954 }else{
955 resulting_UUIDs.push_back(t0);
956 }
-
957 if(context->getPrimitiveArea(t1) < minArea)
+
957 if(context->getPrimitiveArea(t1) < minArea)
958 {
-
959 context->deletePrimitive(t1);
+
959 context->deletePrimitive(t1);
960 }else{
961 resulting_UUIDs.push_back(t1);
962 }
@@ -1058,107 +1065,107 @@
971 if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 2))
972 {
973 diag_1 = 10;
-
974 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
975 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
-
976 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
977 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
974 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
975 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
+
976 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
977 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
978
979
980 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 0)){
981 diag_1 = 11;
-
982 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
-
983 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
984 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
985 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
982 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
+
983 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
984 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
985 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
986
987 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 3)){
988 diag_1 = 12;
-
989 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
990 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, primitive_color);
-
991 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
992 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
989 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
990 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, primitive_color);
+
991 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
992 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
993
994 }else if((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 1)){
995 diag_1 = 13;
-
996 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, primitive_color);
-
997 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
-
998 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
999 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
996 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, primitive_color);
+
997 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
998 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
999 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
1000
1001 //cases where intersection points are on adjacent sides
1002 }else if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 3)){
1003 diag_1 = 14;
-
1004 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
1005 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
-
1006 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
1007 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
1004 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1005 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
+
1006 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1007 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
1008 }else if((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 0)){
1009 diag_1 = 15;
-
1010 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
-
1011 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
1012 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
1013 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
1010 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
+
1011 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1012 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1013 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
1014
1015 }else if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 1)){
1016 diag_1 = 16;
-
1017 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
-
1018 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
-
1019 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
-
1020 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1017 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
+
1018 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
+
1019 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
+
1020 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
1021 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 0)){
1022 diag_1 = 17;
-
1023 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
-
1024 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
-
1025 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
-
1026 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1023 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_color);
+
1024 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
+
1025 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
+
1026 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
1027 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 2)){
1028 diag_1 = 18;
-
1029 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
-
1030 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
1031 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
1032 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1029 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
+
1030 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1031 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1032 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
1033 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 1)){
1034 diag_1 = 19;
-
1035 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
1036 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
-
1037 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
1038 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1035 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1036 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
+
1037 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1038 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
1039 }else if((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 2)){
1040 diag_1 = 20;
-
1041 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
-
1042 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, primitive_color);
-
1043 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
1044 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
+
1041 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
1042 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, primitive_color);
+
1043 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1044 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
1045 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 3)){
1046 diag_1 = 21;
-
1047 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, primitive_color);
-
1048 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
1049 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
1050 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
+
1047 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, primitive_color);
+
1048 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1049 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1050 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_color);
1051 }
1052
1053 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
1054 if(context->getPrimitiveArea(t0) < minArea)
+
1054 if(context->getPrimitiveArea(t0) < minArea)
1055 {
-
1056 context->deletePrimitive(t0);
+
1056 context->deletePrimitive(t0);
1057 }else{
1058 resulting_UUIDs.push_back(t0);
1059 }
-
1060 if(context->getPrimitiveArea(t1) < minArea)
+
1060 if(context->getPrimitiveArea(t1) < minArea)
1061 {
-
1062 context->deletePrimitive(t1);
+
1062 context->deletePrimitive(t1);
1063 }else{
1064 resulting_UUIDs.push_back(t1);
1065 }
-
1066 if(context->getPrimitiveArea(t2) < minArea)
+
1066 if(context->getPrimitiveArea(t2) < minArea)
1067 {
-
1068 context->deletePrimitive(t2);
+
1068 context->deletePrimitive(t2);
1069 }else{
1070 resulting_UUIDs.push_back(t2);
1071 }
-
1072 if(context->getPrimitiveArea(t3) < minArea)
+
1072 if(context->getPrimitiveArea(t3) < minArea)
1073 {
-
1074 context->deletePrimitive(t3);
+
1074 context->deletePrimitive(t3);
1075 }else{
1076 resulting_UUIDs.push_back(t3);
1077 }
@@ -1169,62 +1176,62 @@
1082 if(slice_points_edge_ID.at(0) == 0 && vertex_index == 2)
1083 {
1084 diag_1 = 22;
-
1085 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
1086 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
-
1087 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1085 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1086 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
+
1087 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
1088 }else if(slice_points_edge_ID.at(0) == 0 && vertex_index == 3){
1089 diag_1 = 23;
-
1090 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
-
1091 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
-
1092 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1090 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1091 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, primitive_color);
+
1092 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
1093 }else if(slice_points_edge_ID.at(0) == 1 && vertex_index == 3){
1094 diag_1 = 24;
-
1095 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
1096 t1 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
1097 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
+
1095 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1096 t1 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1097 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
1098 }else if(slice_points_edge_ID.at(0) == 1 && vertex_index == 0){
1099 diag_1 = 25;
-
1100 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
1101 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
-
1102 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
1100 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1101 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, primitive_color);
+
1102 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
1103 }else if(slice_points_edge_ID.at(0) == 2 && vertex_index == 1){
1104 diag_1 = 26;
-
1105 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
1106 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
-
1107 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1105 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1106 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
+
1107 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
1108 }else if(slice_points_edge_ID.at(0) == 2 && vertex_index == 0){
1109 diag_1 = 27;
-
1110 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
-
1111 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
1112 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1110 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, primitive_color);
+
1111 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1112 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
1113 }else if(slice_points_edge_ID.at(0) == 3 && vertex_index == 2){
1114 diag_1 = 28;
-
1115 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
-
1116 t1 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
-
1117 t2 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
1115 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
+
1116 t1 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_color);
+
1117 t2 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
1118 }else if(slice_points_edge_ID.at(0) == 3 && vertex_index == 1){
1119 diag_1 = 29;
-
1120 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
-
1121 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
-
1122 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
1120 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, primitive_color);
+
1121 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
1122 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
1123 }
1124
1125 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
1126 if(context->getPrimitiveArea(t0) < minArea)
+
1126 if(context->getPrimitiveArea(t0) < minArea)
1127 {
-
1128 context->deletePrimitive(t0);
+
1128 context->deletePrimitive(t0);
1129 }else{
1130 resulting_UUIDs.push_back(t0);
1131 }
-
1132 if(context->getPrimitiveArea(t1) < minArea)
+
1132 if(context->getPrimitiveArea(t1) < minArea)
1133 {
-
1134 context->deletePrimitive(t1);
+
1134 context->deletePrimitive(t1);
1135 }else{
1136 resulting_UUIDs.push_back(t1);
1137 }
-
1138 if(context->getPrimitiveArea(t2) < minArea)
+
1138 if(context->getPrimitiveArea(t2) < minArea)
1139 {
-
1140 context->deletePrimitive(t2);
+
1140 context->deletePrimitive(t2);
1141 }else{
1142 resulting_UUIDs.push_back(t2);
1143 }
@@ -1234,25 +1241,25 @@
1147 if(vertex_index == 0 || vertex_index == 2)
1148 {
1149 diag_1 = 30;
-
1150 t0 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
-
1151 t1 = context->addTriangle(primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
+
1150 t0 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_color);
+
1151 t1 = context->addTriangle(primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_color);
1152
1153 }else if(vertex_index == 1 || vertex_index == 3){
1154 diag_1 = 31;
-
1155 t0 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
-
1156 t1 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
+
1155 t0 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, primitive_color);
+
1156 t1 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_color);
1157 }
1158
1159 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
1160 if(context->getPrimitiveArea(t0) < minArea)
+
1160 if(context->getPrimitiveArea(t0) < minArea)
1161 {
-
1162 context->deletePrimitive(t0);
+
1162 context->deletePrimitive(t0);
1163 }else{
1164 resulting_UUIDs.push_back(t0);
1165 }
-
1166 if(context->getPrimitiveArea(t1) < minArea)
+
1166 if(context->getPrimitiveArea(t1) < minArea)
1167 {
-
1168 context->deletePrimitive(t1);
+
1168 context->deletePrimitive(t1);
1169 }else{
1170 resulting_UUIDs.push_back(t1);
1171 }
@@ -1263,7 +1270,7 @@
1176 }else if(primitiveHasTexture){
1177
1178 //get uv coordinates of the vertices
-
1179 std::vector<helios::vec2> v_uv = context->getPrimitiveTextureUV(UUID);
+
1179 std::vector<helios::vec2> v_uv = context->getPrimitiveTextureUV(UUID);
1180
1181 //get uv coordinates of the intersection points
1182 std::vector<helios::vec2> ip_uv;
@@ -1313,52 +1320,52 @@
1226 if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 1))
1227 {
1228 diag_1 = 101;
-
1229 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(1), ip_uv.at(1));
-
1230 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
-
1231 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
+
1229 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0), v_uv.at(1), ip_uv.at(1));
+
1230 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
+
1231 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
1232 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 0)){
1233 diag_1 = 102;
-
1234 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(1));
-
1235 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
-
1236 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1) ,v_uv.at(2), v_uv.at(0));
+
1234 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(1));
+
1235 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
+
1236 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1) ,v_uv.at(2), v_uv.at(0));
1237 }else if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 2)){
1238 diag_1 = 103;
-
1239 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
-
1240 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
-
1241 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(2));
+
1239 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
+
1240 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
+
1241 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(2));
1242 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 0)){
1243 diag_1 = 104;
-
1244 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
-
1245 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
-
1246 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1) ,v_uv.at(2));
+
1244 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
+
1245 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
+
1246 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1) ,v_uv.at(2));
1247 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 2)){
1248 diag_1 = 105;
-
1249 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
-
1250 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
-
1251 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0) ,v_uv.at(1));
+
1249 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
+
1250 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
+
1251 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0) ,v_uv.at(1));
1252 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 1)){
1253 diag_1 = 106;
-
1254 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
-
1255 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
-
1256 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0) ,v_uv.at(1));
+
1254 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
+
1255 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
+
1256 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0) ,v_uv.at(1));
1257 }
1258
1259 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
1260 if(context->getPrimitiveArea(t0) < minArea)
+
1260 if(context->getPrimitiveArea(t0) < minArea)
1261 {
-
1262 context->deletePrimitive(t0);
+
1262 context->deletePrimitive(t0);
1263 }else{
1264 resulting_UUIDs.push_back(t0);
1265 }
-
1266 if(context->getPrimitiveArea(t1) < minArea)
+
1266 if(context->getPrimitiveArea(t1) < minArea)
1267 {
-
1268 context->deletePrimitive(t1);
+
1268 context->deletePrimitive(t1);
1269 }else{
1270 resulting_UUIDs.push_back(t1);
1271 }
-
1272 if(context->getPrimitiveArea(t2) < minArea)
+
1272 if(context->getPrimitiveArea(t2) < minArea)
1273 {
-
1274 context->deletePrimitive(t2);
+
1274 context->deletePrimitive(t2);
1275 }else{
1276 resulting_UUIDs.push_back(t2);
1277 }
@@ -1410,28 +1417,28 @@
1323 if(slice_points_edge_ID.at(0) == 0)
1324 {
1325 diag_1 = 107;
-
1326 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
-
1327 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(1), ip_uv.at(1));
+
1326 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
+
1327 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(1), ip_uv.at(1));
1328 }else if(slice_points_edge_ID.at(0) == 1){
1329 diag_1 = 108;
-
1330 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
-
1331 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1) , v_uv.at(1));
+
1330 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(2), ip_uv.at(1));
+
1331 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1) , v_uv.at(1));
1332 }else if(slice_points_edge_ID.at(0) == 2){
1333 diag_1 = 109;
-
1334 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), ip_uv.at(1));
-
1335 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) , v_uv.at(2));
+
1334 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), ip_uv.at(1));
+
1335 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) , v_uv.at(2));
1336 }
1337
1338 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
1339 if(context->getPrimitiveArea(t0) < minArea)
+
1339 if(context->getPrimitiveArea(t0) < minArea)
1340 {
-
1341 context->deletePrimitive(t0);
+
1341 context->deletePrimitive(t0);
1342 }else{
1343 resulting_UUIDs.push_back(t0);
1344 }
-
1345 if(context->getPrimitiveArea(t1) < minArea)
+
1345 if(context->getPrimitiveArea(t1) < minArea)
1346 {
-
1347 context->deletePrimitive(t1);
+
1347 context->deletePrimitive(t1);
1348 }else{
1349 resulting_UUIDs.push_back(t1);
1350 }
@@ -1496,101 +1503,101 @@
1409 if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 2))
1410 {
1411 diag_1 = 110;
-
1412 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
-
1413 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
-
1414 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1), v_uv.at(3) ,v_uv.at(0));
-
1415 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(2));
+
1412 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
+
1413 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
+
1414 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1), v_uv.at(3) ,v_uv.at(0));
+
1415 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(2));
1416 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 0)){
1417 diag_1 = 111;
-
1418 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
-
1419 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
-
1420 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3) ,v_uv.at(0));
-
1421 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1) ,v_uv.at(2));
+
1418 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
+
1419 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
+
1420 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3) ,v_uv.at(0));
+
1421 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1) ,v_uv.at(2));
1422 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 3)){
1423 diag_1 = 112;
-
1424 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(1));
-
1425 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(3), ip_uv.at(1));
-
1426 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0) ,v_uv.at(1));
-
1427 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2) ,v_uv.at(3));
+
1424 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(1));
+
1425 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(3), ip_uv.at(1));
+
1426 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0) ,v_uv.at(1));
+
1427 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2) ,v_uv.at(3));
1428 }else if((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 1)){
1429 diag_1 = 113;
-
1430 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(1), ip_uv.at(1));
-
1431 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(3));
-
1432 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0) ,v_uv.at(1));
-
1433 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(1), v_uv.at(2) ,v_uv.at(3));
+
1430 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(1), ip_uv.at(1));
+
1431 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(3));
+
1432 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0) ,v_uv.at(1));
+
1433 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(1), v_uv.at(2) ,v_uv.at(3));
1434 //cases where intersection points are on adjacent sides
1435 }else if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 3)){
1436 diag_1 = 114;
-
1437 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
-
1438 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
-
1439 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(2));
-
1440 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(1), v_uv.at(2) ,v_uv.at(3));
+
1437 t0 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
+
1438 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
+
1439 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(2));
+
1440 t3 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(1), v_uv.at(2) ,v_uv.at(3));
1441 }else if((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 0)){
1442 diag_1 = 115;
-
1443 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
-
1444 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
-
1445 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1) ,v_uv.at(2));
-
1446 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2) ,v_uv.at(3));
+
1443 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
+
1444 t1 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
+
1445 t2 = context->addTriangle(slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(1), v_uv.at(1) ,v_uv.at(2));
+
1446 t3 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2) ,v_uv.at(3));
1447 }else if((slice_points_edge_ID.at(0) == 0 && slice_points_edge_ID.at(1) == 1)){
1448 diag_1 = 116;
-
1449 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(1), ip_uv.at(1));
-
1450 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(3));
-
1451 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(1), v_uv.at(2) ,v_uv.at(3));
-
1452 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0) ,v_uv.at(3), v_uv.at(0));
+
1449 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(1), ip_uv.at(1));
+
1450 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(3));
+
1451 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(1), v_uv.at(2) ,v_uv.at(3));
+
1452 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0) ,v_uv.at(3), v_uv.at(0));
1453 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 0)){
1454 diag_1 = 117;
-
1455 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(1));
-
1456 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(3), ip_uv.at(1));
-
1457 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(0), v_uv.at(2) ,v_uv.at(3));
-
1458 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1) ,v_uv.at(3), v_uv.at(0));
+
1455 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(1) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(1));
+
1456 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(3), ip_uv.at(1));
+
1457 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, ip_uv.at(0), v_uv.at(2) ,v_uv.at(3));
+
1458 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1) ,v_uv.at(3), v_uv.at(0));
1459 }else if((slice_points_edge_ID.at(0) == 1 && slice_points_edge_ID.at(1) == 2)){
1460 diag_1 = 118;
-
1461 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
-
1462 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
-
1463 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1), v_uv.at(03) ,v_uv.at(0));
-
1464 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0) ,v_uv.at(1));
+
1461 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(2), ip_uv.at(1));
+
1462 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(0));
+
1463 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(1), v_uv.at(03) ,v_uv.at(0));
+
1464 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0) ,v_uv.at(1));
1465 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 1)){
1466 diag_1 = 119;
-
1467 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
-
1468 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
-
1469 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3) ,v_uv.at(0));
-
1470 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0) ,v_uv.at(1));
+
1467 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(2));
+
1468 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(0), ip_uv.at(1));
+
1469 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3) ,v_uv.at(0));
+
1470 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0) ,v_uv.at(1));
1471 }else if((slice_points_edge_ID.at(0) == 3 && slice_points_edge_ID.at(1) == 2)){
1472 diag_1 = 120;
-
1473 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(3));
-
1474 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(1), ip_uv.at(1));
-
1475 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0) ,v_uv.at(1));
-
1476 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(1), v_uv.at(1) ,v_uv.at(2));
+
1473 t0 = context->addTriangle(slice_points.at(0) - buffer, slice_points.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(3));
+
1474 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, slice_points.at(1) + buffer, tex, ip_uv.at(0) ,v_uv.at(1), ip_uv.at(1));
+
1475 t2 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0) ,v_uv.at(1));
+
1476 t3 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(1), v_uv.at(1) ,v_uv.at(2));
1477 }else if((slice_points_edge_ID.at(0) == 2 && slice_points_edge_ID.at(1) == 3)){
1478 diag_1 = 121;
-
1479 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(3), ip_uv.at(1));
-
1480 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(1));
-
1481 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0) ,v_uv.at(1));
-
1482 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(2));
+
1479 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(3) - buffer, slice_points.at(1) - buffer, tex, ip_uv.at(0) ,v_uv.at(3), ip_uv.at(1));
+
1480 t1 = context->addTriangle(slice_points.at(0) + buffer, slice_points.at(1) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), ip_uv.at(1) ,v_uv.at(1));
+
1481 t2 = context->addTriangle(slice_points.at(1) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(1), v_uv.at(0) ,v_uv.at(1));
+
1482 t3 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(1) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(2));
1483 }
1484
1485 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
1486 if(context->getPrimitiveArea(t0) < minArea)
+
1486 if(context->getPrimitiveArea(t0) < minArea)
1487 {
-
1488 context->deletePrimitive(t0);
+
1488 context->deletePrimitive(t0);
1489 }else{
1490 resulting_UUIDs.push_back(t0);
1491 }
-
1492 if(context->getPrimitiveArea(t1) < minArea)
+
1492 if(context->getPrimitiveArea(t1) < minArea)
1493 {
-
1494 context->deletePrimitive(t1);
+
1494 context->deletePrimitive(t1);
1495 }else{
1496 resulting_UUIDs.push_back(t1);
1497 }
-
1498 if(context->getPrimitiveArea(t2) < minArea)
+
1498 if(context->getPrimitiveArea(t2) < minArea)
1499 {
-
1500 context->deletePrimitive(t2);
+
1500 context->deletePrimitive(t2);
1501 }else{
1502 resulting_UUIDs.push_back(t2);
1503 }
-
1504 if(context->getPrimitiveArea(t3) < minArea)
+
1504 if(context->getPrimitiveArea(t3) < minArea)
1505 {
-
1506 context->deletePrimitive(t3);
+
1506 context->deletePrimitive(t3);
1507 }else{
1508 resulting_UUIDs.push_back(t3);
1509 }
@@ -1652,62 +1659,62 @@
1565 if(slice_points_edge_ID.at(0) == 0 && vertex_index == 2)
1566 {
1567 diag_1 = 122;
-
1568 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
-
1569 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
-
1570 t2 = context->addTriangle(primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(2), v_uv.at(3), v_uv.at(0));
+
1568 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
+
1569 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
+
1570 t2 = context->addTriangle(primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(2), v_uv.at(3), v_uv.at(0));
1571 }else if(slice_points_edge_ID.at(0) == 0 && vertex_index == 3){
1572 diag_1 = 123;
-
1573 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
-
1574 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0) , v_uv.at(1), v_uv.at(3));
-
1575 t2 = context->addTriangle(primitive_vertices.at(3) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(3), v_uv.at(1) , v_uv.at(2));
+
1573 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
+
1574 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0) , v_uv.at(1), v_uv.at(3));
+
1575 t2 = context->addTriangle(primitive_vertices.at(3) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(3), v_uv.at(1) , v_uv.at(2));
1576 }else if(slice_points_edge_ID.at(0) == 1 && vertex_index == 3){
1577 diag_1 = 124;
-
1578 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(3) , v_uv.at(1));
-
1579 t1 = context->addTriangle(primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, v_uv.at(3), v_uv.at(0), v_uv.at(1));
-
1580 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
+
1578 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(3) , v_uv.at(1));
+
1579 t1 = context->addTriangle(primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, v_uv.at(3), v_uv.at(0), v_uv.at(1));
+
1580 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
1581 }else if(slice_points_edge_ID.at(0) == 1 && vertex_index == 0){
1582 diag_1 = 125;
-
1583 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1));
-
1584 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(0) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
-
1585 t2 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(0), v_uv.at(2), v_uv.at(3));
+
1583 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1));
+
1584 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(0) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(0));
+
1585 t2 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(0), v_uv.at(2), v_uv.at(3));
1586 }else if(slice_points_edge_ID.at(0) == 2 && vertex_index == 1){
1587 diag_1 = 126;
-
1588 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
-
1589 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(1));
-
1590 t2 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(1), v_uv.at(3) , v_uv.at(0));
+
1588 t0 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(1), v_uv.at(2));
+
1589 t1 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(1));
+
1590 t2 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(1), v_uv.at(3) , v_uv.at(0));
1591 }else if(slice_points_edge_ID.at(0) == 2 && vertex_index == 0){
1592 diag_1 = 127;
-
1593 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
-
1594 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(0) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(2));
-
1595 t2 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(0), v_uv.at(1), v_uv.at(2));
+
1593 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, ip_uv.at(0), v_uv.at(3), v_uv.at(0));
+
1594 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(0) - buffer, primitive_vertices.at(2) - buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(2));
+
1595 t2 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(0), v_uv.at(1), v_uv.at(2));
1596 }else if(slice_points_edge_ID.at(0) == 3 && vertex_index == 2){
1597 diag_1 = 128;
-
1598 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(2));
-
1599 t1 = context->addTriangle(primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, v_uv.at(2), v_uv.at(0), v_uv.at(1));
-
1600 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
+
1598 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(2));
+
1599 t1 = context->addTriangle(primitive_vertices.at(2) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, v_uv.at(2), v_uv.at(0), v_uv.at(1));
+
1600 t2 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(2), v_uv.at(3));
1601 }else if(slice_points_edge_ID.at(0) == 3 && vertex_index == 1){
1602 diag_1 = 129;
-
1603 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1) );
-
1604 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(3));
-
1605 t2 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(1) , v_uv.at(2), v_uv.at(3));
+
1603 t0 = context->addTriangle(slice_points.at(0) + buffer, primitive_vertices.at(0) + buffer, primitive_vertices.at(1) + buffer, tex, ip_uv.at(0), v_uv.at(0), v_uv.at(1) );
+
1604 t1 = context->addTriangle(slice_points.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(3) - buffer, tex, ip_uv.at(0), v_uv.at(1) ,v_uv.at(3));
+
1605 t2 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(1) , v_uv.at(2), v_uv.at(3));
1606 }
1607
1608 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
1609 if(context->getPrimitiveArea(t0) < minArea)
+
1609 if(context->getPrimitiveArea(t0) < minArea)
1610 {
-
1611 context->deletePrimitive(t0);
+
1611 context->deletePrimitive(t0);
1612 }else{
1613 resulting_UUIDs.push_back(t0);
1614 }
-
1615 if(context->getPrimitiveArea(t1) < minArea)
+
1615 if(context->getPrimitiveArea(t1) < minArea)
1616 {
-
1617 context->deletePrimitive(t1);
+
1617 context->deletePrimitive(t1);
1618 }else{
1619 resulting_UUIDs.push_back(t1);
1620 }
-
1621 if(context->getPrimitiveArea(t2) < minArea)
+
1621 if(context->getPrimitiveArea(t2) < minArea)
1622 {
-
1623 context->deletePrimitive(t2);
+
1623 context->deletePrimitive(t2);
1624 }else{
1625 resulting_UUIDs.push_back(t2);
1626 }
@@ -1718,25 +1725,25 @@
1631 if(vertex_index == 0 || vertex_index == 2)
1632 {
1633 diag_1 = 130;
-
1634 t0 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(0), v_uv.at(1), v_uv.at(2));
-
1635 t1 = context->addTriangle(primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, v_uv.at(0), v_uv.at(2), v_uv.at(3));
+
1634 t0 = context->addTriangle(primitive_vertices.at(0) - buffer, primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, tex, v_uv.at(0), v_uv.at(1), v_uv.at(2));
+
1635 t1 = context->addTriangle(primitive_vertices.at(0) + buffer, primitive_vertices.at(2) + buffer, primitive_vertices.at(3) + buffer, tex, v_uv.at(0), v_uv.at(2), v_uv.at(3));
1636
1637 }else if(vertex_index == 1 || vertex_index == 3){
1638 diag_1 = 131;
-
1639 t0 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(1), v_uv.at(2), v_uv.at(3));
-
1640 t1 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(1), v_uv.at(3), v_uv.at(0));
+
1639 t0 = context->addTriangle(primitive_vertices.at(1) - buffer, primitive_vertices.at(2) - buffer, primitive_vertices.at(3) - buffer, tex, v_uv.at(1), v_uv.at(2), v_uv.at(3));
+
1640 t1 = context->addTriangle(primitive_vertices.at(1) + buffer, primitive_vertices.at(3) + buffer, primitive_vertices.at(0) + buffer, tex, v_uv.at(1), v_uv.at(3), v_uv.at(0));
1641 }
1642
1643 //delete triangles with area of zero, otherwise add to resulting_UUIDs vector
-
1644 if(context->getPrimitiveArea(t0) < minArea)
+
1644 if(context->getPrimitiveArea(t0) < minArea)
1645 {
-
1646 context->deletePrimitive(t0);
+
1646 context->deletePrimitive(t0);
1647 }else{
1648 resulting_UUIDs.push_back(t0);
1649 }
-
1650 if(context->getPrimitiveArea(t1) < minArea)
+
1650 if(context->getPrimitiveArea(t1) < minArea)
1651 {
-
1652 context->deletePrimitive(t1);
+
1652 context->deletePrimitive(t1);
1653 }else{
1654 resulting_UUIDs.push_back(t1);
1655 }
@@ -1749,20 +1756,20 @@
1662
1663 // copy over primitive data to the new triangles
1664 for(uint i=0;i<resulting_UUIDs.size();i++){
-
1665 context->copyPrimitiveData(UUID, resulting_UUIDs.at(i));
-
1666 uint parentID = context->getPrimitiveParentObjectID(UUID);
-
1667 if( parentID>0 && context->getObjectType(parentID)==helios::OBJECT_TYPE_TILE ){
-
1668 context->setPrimitiveParentObjectID(resulting_UUIDs.at(i),0);
+
1665 context->copyPrimitiveData(UUID, resulting_UUIDs.at(i));
+
1666 uint parentID = context->getPrimitiveParentObjectID(UUID);
+
1667 if( parentID>0 && context->getObjectType(parentID)==helios::OBJECT_TYPE_TILE ){
+
1668 context->setPrimitiveParentObjectID(resulting_UUIDs.at(i),0);
1669 }else {
-
1670 context->setPrimitiveParentObjectID(resulting_UUIDs.at(i), parentID);
+
1670 context->setPrimitiveParentObjectID(resulting_UUIDs.at(i), parentID);
1671 }
-
1672 if( context->isPrimitiveTextureColorOverridden(UUID) ){
-
1673 context->overridePrimitiveTextureColor(resulting_UUIDs.at(i));
+
1672 if( context->isPrimitiveTextureColorOverridden(UUID) ){
+
1673 context->overridePrimitiveTextureColor(resulting_UUIDs.at(i));
1674 }
1675 }
1676
1677 // compare original and resulting primitive areas to make sure they approximately match
-
1678 float resulting_area = context->sumPrimitiveSurfaceArea(resulting_UUIDs);
+
1678 float resulting_area = context->sumPrimitiveSurfaceArea(resulting_UUIDs);
1679 float pdiff_area = (resulting_area - original_area)/original_area*100.0;
1680 float pdiff_area_abs = fabs(pdiff_area);
1681 if(pdiff_area_abs > 1)
@@ -1779,7 +1786,7 @@
1692 relTol = 0.4;
1693 for(uint aa=0;aa<resulting_UUIDs.size();aa++)
1694 {
-
1695 helios::vec3 this_normal = context->getPrimitiveNormal(resulting_UUIDs.at(aa));
+
1695 helios::vec3 this_normal = context->getPrimitiveNormal(resulting_UUIDs.at(aa));
1696 this_normal.normalize();
1697 if(!approxSame(primitive_normal.x, this_normal.x, absTol, relTol) || !approxSame(primitive_normal.y, this_normal.y, absTol, relTol) || !approxSame(primitive_normal.z, this_normal.z, absTol, relTol) )
1698 {
@@ -1788,7 +1795,7 @@
1701 }
1702
1703 // delete the original primitive
-
1704 context->deletePrimitive(UUID);
+
1704 context->deletePrimitive(UUID);
1705
1706 return resulting_UUIDs;
1707}
@@ -1849,7 +1856,7 @@
1761 cell_primitives.resize(grid_divisions.x*grid_divisions.y*grid_divisions.z + 1);
1762
1763 //initially set all UUIDs as outside any voxel
-
1764 context->setPrimitiveData(UUIDs, "cell_ID", int(-1));
+
1764 context->setPrimitiveData(UUIDs, "cell_ID", int(-1));
1765
1766 //vectors for UUIDs that do and do not need to be sliced
1767 std::vector<uint> UUIDs_to_slice;
@@ -1868,7 +1875,7 @@
1780 {
1781 helios::vec3 cell_min = make_vec3(grid_min.x + float(i)*grid_spacing.x, grid_min.y + float(j)*grid_spacing.y, grid_min.z + float(k)*grid_spacing.z);
1782 helios::vec3 cell_max = make_vec3(grid_min.x + float(i)*grid_spacing.x + grid_spacing.x, grid_min.y + float(j)*grid_spacing.y + grid_spacing.y, grid_min.z + float(k)*grid_spacing.z + grid_spacing.z);
-
1783 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUIDs.at(p));
+
1783 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUIDs.at(p));
1784
1785 uint v_in = 0;
1786 for(uint v=0;v<verts.size();v++)
@@ -1887,7 +1894,7 @@
1799 if(v_in == verts.size())
1800 {
1801 //the UUID doesn't need to be sliced since its vertices all are within a cell
-
1802 context->setPrimitiveData(UUIDs.at(p), "cell_ID", cell_ID);
+
1802 context->setPrimitiveData(UUIDs.at(p), "cell_ID", cell_ID);
1803 cell_primitives.at(cell_ID).push_back(UUIDs.at(p));
1804 UUIDs_no_slice.push_back(UUIDs.at(p));
1805 cell_ID ++;
@@ -1940,7 +1947,7 @@
1853 resulting_UUIDs = slicePrimitive(UUIDs_to_slice.at(j), grid_face_vertices.at(i));
1854
1855 //update the UUIDs_to_slice vector so it doesn't include deleted primitives (the originals that were split)
-
1856 bool exists = context->doesPrimitiveExist(UUIDs_to_slice.at(j));
+
1856 bool exists = context->doesPrimitiveExist(UUIDs_to_slice.at(j));
1857 if(!exists)
1858 {
1859 primitives_to_remove.push_back(j);
@@ -1988,7 +1995,7 @@
1902 helios::vec3 cell_min = make_vec3(grid_min.x + i*grid_spacing.x, grid_min.y + j*grid_spacing.y, grid_min.z + k*grid_spacing.z);
1903 helios::vec3 cell_max = make_vec3(grid_min.x + i*grid_spacing.x + grid_spacing.x, grid_min.y + j*grid_spacing.y + grid_spacing.y, grid_min.z + k*grid_spacing.z + grid_spacing.z);
1904
-
1905 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUIDs_to_slice.at(p));
+
1905 std::vector<helios::vec3> verts = context->getPrimitiveVertices(UUIDs_to_slice.at(p));
1906 uint v_in = 0;
1907 for(uint v=0;v<verts.size();v++)
1908 {
@@ -2007,7 +2014,7 @@
1921
1922 if(v_in == verts.size())
1923 {
-
1924 context->setPrimitiveData(UUIDs_to_slice.at(p), "cell_ID", cell_ID);
+
1924 context->setPrimitiveData(UUIDs_to_slice.at(p), "cell_ID", cell_ID);
1925 cell_primitives.at(cell_ID).push_back(UUIDs_to_slice.at(p));
1926 cell_ID ++;
1927 flag = true;
@@ -2161,7 +2168,6 @@
@ OBJECT_TYPE_TILE
< Tile
Definition Context.h:130
-
std::vector< uint > slicePrimitivesUsingGrid(std::vector< uint > UUIDs, helios::vec3 grid_center, helios::vec3 grid_size, helios::int3 grid_divisions)
Slice a primitives based on a defined grid of voxels.
void calculatePrimitiveVoxelIntersection(void)
Calculate primitives that reside in all voxels for every primitive in the Context.
std::vector< uint > slicePrimitive(uint UUID, std::vector< helios::vec3 > voxel_face_vertices)
Slice a primitive (patch or triangle) into multiple triangles using a defined plane (often a voxel fa...
@@ -2172,29 +2178,13 @@
std::vector< std::vector< uint > > getCellPrimitives()
get 2D vector storing the UUIDs within each grid cell
void disableMessages()
Disable output messages (enabled by default)
helios::vec2 interpolate_texture_UV_to_slice_point(helios::vec3 p1, helios::vec2 uv1, helios::vec3 p2, helios::vec2 uv2, helios::vec3 ps)
find the uv coordinate of a slice point
-
Stores the state associated with simulation.
Definition Context.h:1882
-
void copyPrimitiveData(uint sourceUUID, uint destinationUUID)
copy all primitive data from one primitive to another
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
Stores the state associated with simulation.
Definition Context.h:1888
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
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:1536
-
uint getPrimitiveParentObjectID(uint UUID) const
Method to return the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7017
-
helios::RGBAcolor getPrimitiveColorRGBA(uint UUID) const
Method to return the diffuse color of a Primitive with transparency.
Definition Context.cpp:7135
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7159
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7175
-
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:6988
-
helios::ObjectType getObjectType(uint ObjID) const
Get an enumeration specifying the type of the object.
Definition Context.cpp:2940
-
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:7197
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
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:7217
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7104
-
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:1659
-
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:7122
void cropDomain(std::vector< uint > &UUIDs, const vec2 &xbounds, const vec2 &ybounds, const vec2 &zbounds)
Crop specified UUIDs such that they lie within some specified axis-aligned box.
Definition Context.cpp:2213
-
float sumPrimitiveSurfaceArea(const std::vector< uint > &UUIDs) const
Sum the one-sided surface area of a group of primitives.
float randu()
Random number from a uniform distribution between 0 and 1.
Definition global.cpp:223
float min(const std::vector< float > &vect)
Minimum value of a vector of floats.
Definition global.cpp:1100
-
uint addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
Add new Triangle geometric primitive.
Definition Context.cpp:1328
uint addVoxel(const helios::vec3 &center, const helios::vec3 &size)
Add new Voxel geometric primitive.
Definition Context.cpp:1372
uint addPatch()
Add new default Patch geometric primitive, which is centered at the origin (0,0,0),...
Definition Context.cpp:1212
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
@@ -2204,23 +2194,26 @@
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
R-G-B-A color vector.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/_voxel_intersection_8cu.html b/doc/html/_voxel_intersection_8cu.html index 274228341..d3e619062 100644 --- a/doc/html/_voxel_intersection_8cu.html +++ b/doc/html/_voxel_intersection_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Macros | @@ -204,7 +210,7 @@

-inline +inline

+ + diff --git a/doc/html/_voxel_intersection_8cu_source.html b/doc/html/_voxel_intersection_8cu_source.html index adc4e67a6..67021fda1 100644 --- a/doc/html/_voxel_intersection_8cu_source.html +++ b/doc/html/_voxel_intersection_8cu_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
VoxelIntersection.cu
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "VoxelIntersection.h"
17
18using namespace helios;
@@ -315,7 +322,7 @@
219
223
@@ -339,7 +346,7 @@
240 for( size_t u = 0; u<UUIDs.size(); u++ ){
241 size_t p = UUIDs[u];
242
-
243 PrimitiveType type = context->getPrimitiveType(p);
+
243 PrimitiveType type = context->getPrimitiveType(p);
244
245 if( type == PRIMITIVE_TYPE_VOXEL ){
246 UUIDs_voxels.at(Nvoxels) = p;
@@ -377,7 +384,7 @@
278
279 //copy scan data into the host buffer
280 for( std::size_t r=0; r<N; r++ ){
-
281 hit_xyz[r] = vec3tofloat3( context->getPrimitiveVertices(UUIDs_prims.at(r)).front() );
+
281 hit_xyz[r] = vec3tofloat3( context->getPrimitiveVertices(UUIDs_prims.at(r)).front() );
282 }
283
284 //copy from host to device memory
@@ -402,11 +409,11 @@
303
304 //copy grid data into the host buffer
305 for( int c=0; c<Ncells; c++ ){
-
306 center[c] = vec3tofloat3( context->getVoxelCenter(UUIDs_voxels.at(c)) );
-
307 size[c] = vec3tofloat3( context->getVoxelSize(UUIDs_voxels.at(c)) );
+
306 center[c] = vec3tofloat3( context->getVoxelCenter(UUIDs_voxels.at(c)) );
+
307 size[c] = vec3tofloat3( context->getVoxelSize(UUIDs_voxels.at(c)) );
308 //rotation[c] = voxel->getRotation();
309 rotation[c] = 0.f;
-
310 context->setPrimitiveData( UUIDs_voxels.at(c), "inside_UUIDs", HELIOS_TYPE_UINT, 0, NULL );
+
310 context->setPrimitiveData( UUIDs_voxels.at(c), "inside_UUIDs", HELIOS_TYPE_UINT, 0, NULL );
311 }
312
313 //copy from host to device memory
@@ -442,7 +449,7 @@
343 for( std::map<uint,std::vector<uint> >::iterator it = vint.begin(); it!=vint.end(); ++it ){
344 uint UUID = it->first;
345 size_t s = vint.at(UUID).size();
-
346 context->setPrimitiveData( UUID, "inside_UUIDs", HELIOS_TYPE_UINT, s, &vint.at(UUID)[0] );
+
346 context->setPrimitiveData( UUID, "inside_UUIDs", HELIOS_TYPE_UINT, s, &vint.at(UUID)[0] );
347 }
348
349 free(hit_vol);
@@ -461,26 +468,23 @@
@ HELIOS_TYPE_UINT
unsigned integer data type
Definition Context.h:45
PrimitiveType
Type of primitive element.
Definition Context.h:31
-
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
+
@ PRIMITIVE_TYPE_VOXEL
Rectangular prism primitive.
Definition Context.h:37
void calculatePrimitiveVoxelIntersection(void)
Calculate primitives that reside in all voxels for every primitive in the Context.
void enableMessages()
Re-enable output messages.
void disableMessages()
Disable output messages (enabled by default)
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
-
helios::vec3 getVoxelSize(uint UUID) const
Get the size of a voxel element.
Definition Context.cpp:1741
-
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
-
helios::vec3 getVoxelCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a voxel element.
Definition Context.cpp:1750
-
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:7122
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/_voxel_intersection_8h.html b/doc/html/_voxel_intersection_8h.html index 65cf3971b..30df3d3a8 100644 --- a/doc/html/_voxel_intersection_8h.html +++ b/doc/html/_voxel_intersection_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -123,10 +129,13 @@

Definition in file VoxelIntersection.h.

- -
+ + diff --git a/doc/html/_voxel_intersection_8h.js b/doc/html/_voxel_intersection_8h.js new file mode 100644 index 000000000..ffd09319c --- /dev/null +++ b/doc/html/_voxel_intersection_8h.js @@ -0,0 +1,4 @@ +var _voxel_intersection_8h = +[ + [ "VoxelIntersection", "class_voxel_intersection.html", "class_voxel_intersection" ] +]; \ No newline at end of file diff --git a/doc/html/_voxel_intersection_8h_source.html b/doc/html/_voxel_intersection_8h_source.html index cde26eef8..c161a5f45 100644 --- a/doc/html/_voxel_intersection_8h_source.html +++ b/doc/html/_voxel_intersection_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
VoxelIntersection.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef VOXELINTERSECTION
17#define VOXELINTERSECTION
18
19#include "Context.h"
20
- +
22 public:
-
23
-
25
+
23
+
25
-
29
+
29
31 int selfTest( void );
32
-
35
-
37
+
35
+
37
40 void calculatePrimitiveVoxelIntersection( std::vector<uint> UUIDs );
-
41
+
41
43 void disableMessages();
-
44
+
44
46 void enableMessages();
-
47
-
49
+
47
+
49
57 helios::vec3 linesIntersection(helios::vec3 line1_point, helios::vec3 line1_direction, helios::vec3 line2_point, helios::vec3 line2_direction);
58
-
60
+
60
65 std::vector<uint> slicePrimitive(uint UUID, std::vector<helios::vec3> voxel_face_vertices);
66
-
68
+
68
75 std::vector<uint> slicePrimitivesUsingGrid(std::vector<uint> UUIDs, helios::vec3 grid_center, helios::vec3 grid_size, helios::int3 grid_divisions);
-
76
-
78
+
76
+
78
82 std::vector<std::vector<uint>> getCellPrimitives();
83
-
85
+
85
92 bool approxSame(float a, float b, float absTol, float relTol);
-
93
-
95
+
93
+
95
101 bool approxSame(helios::vec3 a, helios::vec3 b, float absTol);
102
-
104
+
104
113
114 private:
@@ -162,7 +169,6 @@
123
124#endif
-
std::vector< uint > slicePrimitivesUsingGrid(std::vector< uint > UUIDs, helios::vec3 grid_center, helios::vec3 grid_size, helios::int3 grid_divisions)
Slice a primitives based on a defined grid of voxels.
void calculatePrimitiveVoxelIntersection(void)
Calculate primitives that reside in all voxels for every primitive in the Context.
void enableMessages()
Re-enable output messages.
@@ -174,15 +180,18 @@
std::vector< std::vector< uint > > getCellPrimitives()
get 2D vector storing the UUIDs within each grid cell
void disableMessages()
Disable output messages (enabled by default)
helios::vec2 interpolate_texture_UV_to_slice_point(helios::vec3 p1, helios::vec2 uv1, helios::vec3 p2, helios::vec2 uv2, helios::vec3 ps)
find the uv coordinate of a slice point
-
Stores the state associated with simulation.
Definition Context.h:1882
-
Vector of three elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Stores the state associated with simulation.
Definition Context.h:1888
+
Vector of three elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/_voxel_intersection_doc.html b/doc/html/_voxel_intersection_doc.html index d478ae963..9272ae6c9 100644 --- a/doc/html/_voxel_intersection_doc.html +++ b/doc/html/_voxel_intersection_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Voxel Intersection Plugin Documentation
@@ -291,10 +297,13 @@

}

- -
+ + diff --git a/doc/html/_weber_penn_doc.html b/doc/html/_weber_penn_doc.html index 66ff96406..8f5c1675e 100644 --- a/doc/html/_weber_penn_doc.html +++ b/doc/html/_weber_penn_doc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Weber-Penn Tree Plugin Documentation
@@ -481,10 +487,13 @@

</helios>

- -
+ + diff --git a/doc/html/_weber_penn_tree_8cpp.html b/doc/html/_weber_penn_tree_8cpp.html index f5ed21d92..d85713fa2 100644 --- a/doc/html/_weber_penn_tree_8cpp.html +++ b/doc/html/_weber_penn_tree_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
WeberPennTree.cpp File Reference
@@ -117,10 +123,13 @@

Definition in file WeberPennTree.cpp.

- -
+ + diff --git a/doc/html/_weber_penn_tree_8cpp_source.html b/doc/html/_weber_penn_tree_8cpp_source.html index 07b92c754..81c638585 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
WeberPennTree.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "WeberPennTree.h"
17#ifndef _WIN32
18#include <chrono>
@@ -157,7 +164,7 @@
62
63 Context context_1;
64
-
65 WeberPennTree weberpenntree_1( &context_1 );
+
65 WeberPennTree weberpenntree_1( &context_1 );
66
67 weberpenntree_1.setBranchRecursionLevel(1);
68 weberpenntree_1.setLeafSubdivisions( make_int2(3,3) );
@@ -207,7 +214,7 @@
108 #endif
109 }
110
-
111 uint ID_leaf_template = context->addTileObject( make_vec3(0,0,0), make_vec2(parameters.LeafScale*scale, parameters.LeafScale*parameters.LeafScaleX*scale), make_SphericalCoord(0,M_PI), leaf_segs, parameters.LeafFile.c_str() );
+
111 uint ID_leaf_template = context->addTileObject( make_vec3(0,0,0), make_vec2(parameters.LeafScale*scale, parameters.LeafScale*parameters.LeafScaleX*scale), make_SphericalCoord(0,M_PI), leaf_segs, parameters.LeafFile.c_str() );
112
113 uint base_nodes = 20;
114
@@ -400,9 +407,9 @@
301
302 //draw the trunk
303 if( strcmp(parameters.WoodFile.c_str(),"none")==0 || parameters.WoodFile.size()==0 ){
-
304 UUID_trunk.back() = context->addTube(trunk_segs,nodes,radius,color);
+
304 UUID_trunk.back() = context->addTube(trunk_segs,nodes,radius,color);
305 }else{
-
306 UUID_trunk.back() = context->addTube(trunk_segs,nodes,radius,parameters.WoodFile.c_str());
+
306 UUID_trunk.back() = context->addTube(trunk_segs,nodes,radius,parameters.WoodFile.c_str());
307 }
308
309 // printf("size of UUID_trunk = %d\n",UUID_trunk.back().size());
@@ -420,17 +427,17 @@
321 // }
322
323 //context->deletePrimitive( UUID_leaf_template );
-
324 context->deleteObject( ID_leaf_template );
+
324 context->deleteObject( ID_leaf_template );
325
326 uint flag=1;
327 for( size_t i=0; i<UUID_leaf.at(TreeID).size(); i++ ){
-
328 context->setPrimitiveData(UUID_leaf.at(TreeID).at(i),"twosided_flag",HELIOS_TYPE_UINT,1,&flag);
+
328 context->setPrimitiveData(UUID_leaf.at(TreeID).at(i),"twosided_flag",HELIOS_TYPE_UINT,1,&flag);
329 }
330 for( size_t i=0; i<UUID_branch.at(TreeID).size(); i++ ){
-
331 context->setPrimitiveData(UUID_branch.at(TreeID).at(i),"twosided_flag",HELIOS_TYPE_UINT,1,&flag);
+
331 context->setPrimitiveData(UUID_branch.at(TreeID).at(i),"twosided_flag",HELIOS_TYPE_UINT,1,&flag);
332 }
333 for( size_t i=0; i<UUID_trunk.at(TreeID).size(); i++ ){
-
334 context->setPrimitiveData(UUID_trunk.at(TreeID).at(i),"twosided_flag",HELIOS_TYPE_UINT,1,&flag);
+
334 context->setPrimitiveData(UUID_trunk.at(TreeID).at(i),"twosided_flag",HELIOS_TYPE_UINT,1,&flag);
335 }
336
337 return TreeID;
@@ -525,7 +532,7 @@
425 nodes.at(0) = base_position;
426 color.at(0) = parameters.WoodColor;
427
-
428 SphericalCoord parent_rotation = cart2sphere(parent_normal);
+
428 SphericalCoord parent_rotation = cart2sphere(parent_normal);
429
430 float phi = getVariation(2.f*M_PI);
431 float phi_child = getVariation(2.f*M_PI);
@@ -551,7 +558,7 @@
451
452 //---- nodes ----//
453
-
454 vec3 child_normal = sphere2cart(make_SphericalCoord(parent_rotation.elevation-child_rotation.elevation,parent_rotation.azimuth));
+
454 vec3 child_normal = sphere2cart(make_SphericalCoord(parent_rotation.elevation-child_rotation.elevation,parent_rotation.azimuth));
455 child_normal.normalize();
456
457 child_normal = rotatePointAboutLine( child_normal, make_vec3(0,0,0), parent_normal, child_rotation.azimuth );
@@ -577,13 +584,13 @@
477 f= float(s+1)/float(stems_per_segment);
478 }
479
-
480 vec3 base_position = nodes.at(i-seg_start-1) + (nodes.at(i-seg_start)-nodes.at(i-seg_start-1))*f;
+
480 vec3 base_position = nodes.at(i-seg_start-1) + (nodes.at(i-seg_start)-nodes.at(i-seg_start-1))*f;
481
482 if( base_splits > 0 && n==0 && base_position.z<base_size*length_parent ){
483 continue;
484 }
485
-
486 vec3 normal = nodes.at(i-seg_start)-nodes.at(i-seg_start-1);
+
486 vec3 normal = nodes.at(i-seg_start)-nodes.at(i-seg_start-1);
487 normal.normalize();
488
489 float radius_p = radius.at(i-seg_start-1);
@@ -591,7 +598,7 @@
491 float offset_child = dlength_child*(i-seg_start-1)+dlength_child*float(s)/float(stems_per_segment);
492
493 float downangle = (parameters.nDownAngle.at(n+1)+getVariation(parameters.nDownAngleV.at(n+1)))*M_PI/180.f;
-
494 SphericalCoord rotation = make_SphericalCoord(downangle,phi_child);
+
494 SphericalCoord rotation = make_SphericalCoord(downangle,phi_child);
495
496 recursiveBranch( parameters, n+1, 0, base_position, normal, rotation, length_child, radius_p, offset_child, origin, scale, leaf_template, base_size, base_splits );
497
@@ -608,7 +615,7 @@
508
509 float angle_split = (parameters.nSplitAngle.at(n+1)-getVariation(parameters.nSplitAngleV.at(n+1)))*M_PI/180.f;
510
-
511 vec3 base_position = nodes.back();
+
511 vec3 base_position = nodes.back();
512
513 float phi_split = 2.f*M_PI*getVariation(1);
514
@@ -616,10 +623,10 @@
516
517 for( uint j=0; j<parameters.nSegSplits.at(n)+1; j++ ){ //looping over clones (splits)
518
-
519 vec3 normal = nodes.at(i-seg_start)-nodes.at(i-seg_start-1);
+
519 vec3 normal = nodes.at(i-seg_start)-nodes.at(i-seg_start-1);
520 normal.normalize();
521
-
522 helios::SphericalCoord rotation = make_SphericalCoord(angle_split,phi_split);
+
522 helios::SphericalCoord rotation = make_SphericalCoord(angle_split,phi_split);
523
524 recursiveBranch( parameters, n, i, base_position, normal, rotation, length_parent, radius_p, offset_child, origin, scale, leaf_template, base_size, base_splits );
525
@@ -641,9 +648,9 @@
541 //add to context
542 std::vector<uint> branches;
543 if( strcmp(parameters.WoodFile.c_str(),"none")==0 ){
-
544 branches = context->addTube(branch_segs,nodes,radius,color);
+
544 branches = context->addTube(branch_segs,nodes,radius,color);
545 }else{
-
546 branches = context->addTube(branch_segs,nodes,radius,parameters.WoodFile.c_str());
+
546 branches = context->addTube(branch_segs,nodes,radius,parameters.WoodFile.c_str());
547 }
548 UUID_branch.back().insert(UUID_branch.back().end(),branches.begin(),branches.end());
549 }
@@ -652,9 +659,9 @@
552
553 float phi = child_rotation.azimuth;
554
-
555 vec3 position = base_position;
+
555 vec3 position = base_position;
556
-
557 SphericalCoord rotation = cart2sphere(parent_normal);
+
557 SphericalCoord rotation = cart2sphere(parent_normal);
558
559 //shift to origin
560 position = position + origin;
@@ -663,54 +670,54 @@
563
564 //calculate leaf angle from distibution
565 if( parameters.leafAngleCDF.size()>0 ){
-
566 float rt = context->randu();
+
566 float rt = context->randu();
567 float dTheta = M_PI/float(parameters.leafAngleCDF.size());
568 for( int i=0; i<parameters.leafAngleCDF.size(); i++ ){
569 if( rt<parameters.leafAngleCDF.at(i) ){
-
570 float theta = (i+context->randu())*dTheta;
-
571 rotation = make_SphericalCoord(theta,context->randu()*2.f*M_PI);
+
570 float theta = (i+context->randu())*dTheta;
+
571 rotation = make_SphericalCoord(theta,context->randu()*2.f*M_PI);
572 break;
573 }
574 }
575 }
576
577 //add to Context
-
578 uint ID = context->copyObject( leaf_template );
-
579 std::vector<uint> UUIDs = context->getObjectPointer(ID)->getPrimitiveUUIDs();
+
578 uint ID = context->copyObject( leaf_template );
+
579 std::vector<uint> UUIDs = context->getObjectPointer(ID)->getPrimitiveUUIDs();
580 UUID_leaf.back().insert( UUID_leaf.back().end(), UUIDs.begin(), UUIDs.end() );
581
582 //perform transformations
583 if( parameters.leafAngleCDF.size()>0 ){
-
584 context->getObjectPointer(ID)->rotate( rotation.elevation, "y" );
-
585 context->getObjectPointer(ID)->rotate( rotation.azimuth, "z" );
-
586 context->getObjectPointer(ID)->translate(position);
+
584 context->getObjectPointer(ID)->rotate( rotation.elevation, "y" );
+
585 context->getObjectPointer(ID)->rotate( rotation.azimuth, "z" );
+
586 context->getObjectPointer(ID)->translate(position);
587 }else{
588
-
589 context->getObjectPointer(ID)->rotate( M_PI, "x" ); //flip leaf (this is so lighting looks right based on leaf normal)
+
589 context->getObjectPointer(ID)->rotate( M_PI, "x" ); //flip leaf (this is so lighting looks right based on leaf normal)
590
591 //rotate leaf so the tip is pointing in the same direction as the branch
-
592 context->getObjectPointer(ID)->rotate( 0.5*M_PI - rotation.zenith, "y" );
-
593 context->getObjectPointer(ID)->rotate( -0.5*M_PI - rotation.azimuth, "z" );
+
592 context->getObjectPointer(ID)->rotate( 0.5*M_PI - rotation.zenith, "y" );
+
593 context->getObjectPointer(ID)->rotate( -0.5*M_PI - rotation.azimuth, "z" );
594
-
595 vec3 lnorm = context->getTileObjectPointer(ID)->getNormal(); // current leaf normal vector
-
596 vec3 pvec = cross( parent_normal, lnorm );
+
595 vec3 lnorm = context->getTileObjectPointer(ID)->getNormal(); // current leaf normal vector
+
596 vec3 pvec = cross( parent_normal, lnorm );
597
598 //rotate leaf based on downangle
599 if( downangle<0.f ){
600 downangle = M_PI+downangle;
601 }
-
602 context->getObjectPointer(ID)->rotate( -downangle, pvec );
+
602 context->getObjectPointer(ID)->rotate( -downangle, pvec );
603
604 //shift leaf perpendicular to the direction of the branch
-
605 vec3 offset = -0.6*parameters.LeafScale*scale*fabs(sinf(downangle))*lnorm;
+
605 vec3 offset = -0.6*parameters.LeafScale*scale*fabs(sinf(downangle))*lnorm;
606
-
607 context->getObjectPointer(ID)->translate( offset );
+
607 context->getObjectPointer(ID)->translate( offset );
608
609 //random azimuthal rotation about the branch
-
610 context->getObjectPointer(ID)->rotate( phi, parent_normal );
+
610 context->getObjectPointer(ID)->rotate( phi, parent_normal );
611
612 //translate to the position of the branch
-
613 context->getObjectPointer(ID)->translate(position);
+
613 context->getObjectPointer(ID)->translate(position);
614
615 }
616
@@ -1601,7 +1608,6 @@
@ HELIOS_TYPE_UINT
unsigned integer data type
Definition Context.h:45
-
void setLeafSubdivisions(const helios::int2 leaf_segs)
Set the number of sub-patch divisions for leaves.
std::vector< uint > getAllUUIDs(const uint TreeID)
Get the unique universal identifiers (UUIDs) for all primitives that make up the tree.
void loadXML(const char *filename)
Load tree library from an XML file.
@@ -1618,20 +1624,8 @@
void setTrunkSegmentResolution(const uint trunk_segs)
Set the radial triangle subdivisions for trunks.
void optionalOutputPrimitiveData(const char *label)
Add optional output primitive data values to the Context.
std::vector< uint > getLeafUUIDs(const uint TreeID)
Get the unique universal identifiers (UUIDs) for the primitives that make up the tree leaves.
-
void rotate(float rotation_radians, const char *rotation_axis_xyz_string)
Method to rotate a Compound Object about the x-, y-, or z-axis.
Definition Context.cpp:2377
-
void translate(const helios::vec3 &shift)
Method to translate/shift a Compound Object.
Definition Context.cpp:2353
-
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
-
Stores the state associated with simulation.
Definition Context.h:1882
-
uint copyObject(uint ObjID)
Make a copy of a Compound Objects from the context.
Definition Context.cpp:2642
-
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
-
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
-
void deleteObject(uint ObjID)
Delete a single Compound Object from the context.
Definition Context.cpp:2609
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
-
Tile * getTileObjectPointer(uint ObjID) const
Get a pointer to a Tile Compound Object.
Definition Context.cpp:3312
-
vec3 getNormal() const
Get a unit vector normal to the tile object surface.
Definition Context.cpp:3385
+
Stores the state associated with simulation.
Definition Context.h:1888
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< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
vec3 rotatePoint(const vec3 &position, const SphericalCoord &rotation)
Function to rotate a 3D vector given spherical angles elevation and azimuth.
Definition global.cpp:79
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
RGBAcolor string2RGBcolor(const char *str)
Convert a space-delimited string into an RGBcolor vector.
Definition global.cpp:743
@@ -1653,17 +1647,20 @@
const float & zenith
Zenithal angle (radians)
const float & elevation
Elevation angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float z
Third element in vector.
- -
+ + diff --git a/doc/html/_weber_penn_tree_8h.html b/doc/html/_weber_penn_tree_8h.html index 96ba188b5..dbce6e91c 100644 --- a/doc/html/_weber_penn_tree_8h.html +++ b/doc/html/_weber_penn_tree_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -126,10 +132,13 @@

Definition in file WeberPennTree.h.

- -
+ + diff --git a/doc/html/_weber_penn_tree_8h.js b/doc/html/_weber_penn_tree_8h.js new file mode 100644 index 000000000..2c13e8c36 --- /dev/null +++ b/doc/html/_weber_penn_tree_8h.js @@ -0,0 +1,5 @@ +var _weber_penn_tree_8h = +[ + [ "WeberPennTreeParameters", "struct_weber_penn_tree_parameters.html", null ], + [ "WeberPennTree", "class_weber_penn_tree.html", "class_weber_penn_tree" ] +]; \ No newline at end of file diff --git a/doc/html/_weber_penn_tree_8h_source.html b/doc/html/_weber_penn_tree_8h_source.html index 2ab7c8139..6eec12346 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
WeberPennTree.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "Context.h"
17#include <random>
18
@@ -187,72 +194,72 @@
94
- +
96 public:
-
97
-
99
+
97
+
99
101 WeberPennTree( helios::Context* context );
-
102
+
102
104 int selfTest( void );
-
105
-
107
+
105
+
107
109 void loadXML( const char* filename );
-
110
-
112
+
110
+
112
116 uint buildTree( const char* treename, helios::vec3 origin );
-
117
-
119
+
117
+
119
124 uint buildTree( const char* treename, helios::vec3 origin, float scale );
125
-
127
+
127
129 std::vector<uint> getTrunkUUIDs( const uint TreeID );
-
130
-
132
+
130
+
132
134 std::vector<uint> getBranchUUIDs( const uint TreeID );
-
135
-
137
+
135
+
137
139 std::vector<uint> getLeafUUIDs( const uint TreeID );
-
140
-
142
+
140
+
142
144 std::vector<uint> getAllUUIDs( const uint TreeID );
-
145
+
145
147
150 void setBranchRecursionLevel( const uint level );
-
151
-
153
+
151
+
153
156 void setTrunkSegmentResolution( const uint trunk_segs );
-
157
-
159
+
157
+
159
162 void setBranchSegmentResolution( const uint branch_segs );
-
163
-
165
+
163
+
165
167 void setLeafSubdivisions( const helios::int2 leaf_segs );
-
168
-
170
+
168
+
170
173 WeberPennTreeParameters getTreeParameters( const char* treename );
-
174
-
176
+
174
+
176
179 void setTreeParameters( const char* treename, const WeberPennTreeParameters parameters );
-
180
-
182
+
180
+
182
183 void seedRandomGenerator( const uint seed );
-
184
-
186
+
184
+
186
188 void optionalOutputPrimitiveData( const char* label );
189
190 private:
191
192 helios::Context* context;
-
193
+
193
195 std::vector<std::vector<uint> > UUID_trunk;
-
196
+
196
198 std::vector<std::vector<uint> > UUID_branch;
-
199
+
199
201 std::vector<std::vector<uint> > UUID_leaf;
202
203 std::map<std::string,WeberPennTreeParameters> trees_library;
204
-
206
+
206
218 void recursiveBranch( WeberPennTreeParameters parameters, uint n, uint seg_start, helios::vec3 base_position, helios::vec3 parent_normal, helios::SphericalCoord child_rotation, float length_parent, float radius_parent, float offset_child, helios::vec3 origin, float scale, const uint leaf_template, float base_size, uint base_splits );
219
220 float getVariation( float V );
@@ -268,13 +275,12 @@
230 uint branch_segs;
231
232 helios::int2 leaf_segs;
-
233
+
233
235 std::vector<std::string> output_prim_data;
236
237};
-
void setLeafSubdivisions(const helios::int2 leaf_segs)
Set the number of sub-patch divisions for leaves.
std::vector< uint > getAllUUIDs(const uint TreeID)
Get the unique universal identifiers (UUIDs) for all primitives that make up the tree.
void loadXML(const char *filename)
Load tree library from an XML file.
@@ -291,17 +297,20 @@
void setTrunkSegmentResolution(const uint trunk_segs)
Set the radial triangle subdivisions for trunks.
void optionalOutputPrimitiveData(const char *label)
Add optional output primitive data values to the Context.
std::vector< uint > getLeafUUIDs(const uint TreeID)
Get the unique universal identifiers (UUIDs) for the primitives that make up the tree leaves.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
R-G-B color vector.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of two elements of type 'int'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/aeriallidar_2include_2random_8h_source.html b/doc/html/aeriallidar_2include_2random_8h_source.html index 77094eb7a..9fac6289b 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
random.h
@@ -159,10 +165,13 @@
53 return ((float) lcg(prev) / (float) 0x01000000);
54}
- -
+ + diff --git a/doc/html/aeriallidar_2src_2file_i_o_8cpp.html b/doc/html/aeriallidar_2src_2file_i_o_8cpp.html index 1f65b2b21..0b47debd0 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
fileIO.cpp File Reference
@@ -116,10 +122,13 @@

Definition in file fileIO.cpp.

- -
+ + 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 e620d7e27..0fe198906 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
fileIO.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "AerialLiDAR.h"
17#include "pugixml.hpp"
18
@@ -413,7 +420,7 @@
320
321 gridextent = string2vec3( gsize_str ); //note: pugi loads xml data as a character. need to separate it into 3 floats
322
-
323 if( gridextent.x<=0 || gridextent.y<=0 || gridextent.z<=0 ){
+
323 if( gridextent.x<=0 || gridextent.y<=0 || gridextent.z<=0 ){
324 cerr << "failed.\nERROR (AerialLiDARcloud::loadXML): The grid size/extent must be positive." << endl;
325 exit(EXIT_FAILURE);
326 }
@@ -500,18 +507,21 @@
float r
Red color component.
float g
Green color component.
Vector of spherical coordinates (elevation,azimuth)
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/annotated.html b/doc/html/annotated.html index c80081801..459d811e4 100644 --- a/doc/html/annotated.html +++ b/doc/html/annotated.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
- -
+ + diff --git a/doc/html/annotated_dup.js b/doc/html/annotated_dup.js new file mode 100644 index 000000000..eb375d74b --- /dev/null +++ b/doc/html/annotated_dup.js @@ -0,0 +1,103 @@ +var annotated_dup = +[ + [ "helios", null, [ + [ "Box", "classhelios_1_1_box.html", "classhelios_1_1_box" ], + [ "CompoundObject", "classhelios_1_1_compound_object.html", "classhelios_1_1_compound_object" ], + [ "Cone", "classhelios_1_1_cone.html", "classhelios_1_1_cone" ], + [ "Context", "classhelios_1_1_context.html", "classhelios_1_1_context" ], + [ "Date", "structhelios_1_1_date.html", "structhelios_1_1_date" ], + [ "Disk", "classhelios_1_1_disk.html", "classhelios_1_1_disk" ], + [ "GlobalData", "structhelios_1_1_global_data.html", null ], + [ "int2", "structhelios_1_1int2.html", "structhelios_1_1int2" ], + [ "int3", "structhelios_1_1int3.html", "structhelios_1_1int3" ], + [ "int4", "structhelios_1_1int4.html", "structhelios_1_1int4" ], + [ "Location", "structhelios_1_1_location.html", "structhelios_1_1_location" ], + [ "Polymesh", "classhelios_1_1_polymesh.html", "classhelios_1_1_polymesh" ], + [ "RGBAcolor", "structhelios_1_1_r_g_b_acolor.html", "structhelios_1_1_r_g_b_acolor" ], + [ "RGBcolor", "structhelios_1_1_r_g_bcolor.html", "structhelios_1_1_r_g_bcolor" ], + [ "Sphere", "classhelios_1_1_sphere.html", "classhelios_1_1_sphere" ], + [ "SphericalCoord", "structhelios_1_1_spherical_coord.html", "structhelios_1_1_spherical_coord" ], + [ "Texture", "classhelios_1_1_texture.html", "classhelios_1_1_texture" ], + [ "Tile", "classhelios_1_1_tile.html", "classhelios_1_1_tile" ], + [ "Time", "structhelios_1_1_time.html", "structhelios_1_1_time" ], + [ "Timer", "structhelios_1_1_timer.html", "structhelios_1_1_timer" ], + [ "Tube", "classhelios_1_1_tube.html", "classhelios_1_1_tube" ], + [ "vec2", "structhelios_1_1vec2.html", "structhelios_1_1vec2" ], + [ "vec3", "structhelios_1_1vec3.html", "structhelios_1_1vec3" ], + [ "vec4", "structhelios_1_1vec4.html", "structhelios_1_1vec4" ], + [ "XMLparser", "classhelios_1_1_x_m_lparser.html", null ] + ] ], + [ "AerialHitPoint", "struct_aerial_hit_point.html", null ], + [ "AerialLiDARcloud", "class_aerial_li_d_a_rcloud.html", "class_aerial_li_d_a_rcloud" ], + [ "AerialScanMetadata", "struct_aerial_scan_metadata.html", "struct_aerial_scan_metadata" ], + [ "AxisRotation", "struct_axis_rotation.html", null ], + [ "BaseCanopyParameters", "struct_base_canopy_parameters.html", "struct_base_canopy_parameters" ], + [ "BaseGrapeVineParameters", "struct_base_grape_vine_parameters.html", "struct_base_grape_vine_parameters" ], + [ "BBcoefficients", "struct_b_bcoefficients.html", null ], + [ "BBLcoefficients", "struct_b_b_lcoefficients.html", null ], + [ "BeanParameters", "struct_bean_parameters.html", "struct_bean_parameters" ], + [ "BLConductanceModel", "class_b_l_conductance_model.html", "class_b_l_conductance_model" ], + [ "BMFcoefficients", "struct_b_m_fcoefficients.html", null ], + [ "BWBcoefficients", "struct_b_w_bcoefficients.html", null ], + [ "CameraCalibration", "struct_camera_calibration.html", "struct_camera_calibration" ], + [ "CameraProperties", "struct_camera_properties.html", "struct_camera_properties" ], + [ "CanopyGenerator", "class_canopy_generator.html", "class_canopy_generator" ], + [ "Colormap", "struct_colormap.html", null ], + [ "ConicalCrownsCanopyParameters", "struct_conical_crowns_canopy_parameters.html", "struct_conical_crowns_canopy_parameters" ], + [ "DummyModel", "class_dummy_model.html", "class_dummy_model" ], + [ "Dupex", "struct_dupex.html", null ], + [ "EmpiricalModelCoefficients", "struct_empirical_model_coefficients.html", null ], + [ "EnergyBalanceModel", "class_energy_balance_model.html", "class_energy_balance_model" ], + [ "FarquharModelCoefficients", "struct_farquhar_model_coefficients.html", null ], + [ "FloralBud", "struct_floral_bud.html", null ], + [ "Glyph", "class_glyph.html", null ], + [ "GobletGrapevineParameters", "struct_goblet_grapevine_parameters.html", "struct_goblet_grapevine_parameters" ], + [ "GridCell", "struct_grid_cell.html", null ], + [ "HitPoint", "struct_hit_point.html", null ], + [ "HitTable", "class_hit_table.html", null ], + [ "HomogeneousCanopyParameters", "struct_homogeneous_canopy_parameters.html", "struct_homogeneous_canopy_parameters" ], + [ "jpg_error_mgr", "structjpg__error__mgr.html", null ], + [ "LeafOptics", "class_leaf_optics.html", "class_leaf_optics" ], + [ "LeafOpticsProperties", "struct_leaf_optics_properties.html", null ], + [ "LeafPrototype", "struct_leaf_prototype.html", "struct_leaf_prototype" ], + [ "LiDARcloud", "class_li_d_a_rcloud.html", "class_li_d_a_rcloud" ], + [ "MOPTcoefficients", "struct_m_o_p_tcoefficients.html", null ], + [ "my_error_mgr", "structmy__error__mgr.html", null ], + [ "PerRayData", "struct_per_ray_data.html", "struct_per_ray_data" ], + [ "PhotosynthesisModel", "class_photosynthesis_model.html", "class_photosynthesis_model" ], + [ "PhotosyntheticTemperatureResponseParameters", "struct_photosynthetic_temperature_response_parameters.html", null ], + [ "Phytomer", "struct_phytomer.html", "struct_phytomer" ], + [ "PhytomerParameters", "struct_phytomer_parameters.html", "struct_phytomer_parameters" ], + [ "PlantArchitecture", "class_plant_architecture.html", "class_plant_architecture" ], + [ "PlantInstance", "struct_plant_instance.html", null ], + [ "RadiationBand", "struct_radiation_band.html", "struct_radiation_band" ], + [ "RadiationCamera", "struct_radiation_camera.html", null ], + [ "RadiationModel", "class_radiation_model.html", "class_radiation_model" ], + [ "RadiationSource", "struct_radiation_source.html", "struct_radiation_source" ], + [ "RandomParameter_float", "struct_random_parameter__float.html", "struct_random_parameter__float" ], + [ "RandomParameter_int", "struct_random_parameter__int.html", null ], + [ "ScanMetadata", "struct_scan_metadata.html", "struct_scan_metadata" ], + [ "Shader", "struct_shader.html", "struct_shader" ], + [ "Shoot", "struct_shoot.html", "struct_shoot" ], + [ "ShootParameters", "struct_shoot_parameters.html", "struct_shoot_parameters" ], + [ "Shx", "struct_shx.html", null ], + [ "SolarPosition", "class_solar_position.html", "class_solar_position" ], + [ "SorghumCanopyParameters", "struct_sorghum_canopy_parameters.html", "struct_sorghum_canopy_parameters" ], + [ "SphericalCrownsCanopyParameters", "struct_spherical_crowns_canopy_parameters.html", "struct_spherical_crowns_canopy_parameters" ], + [ "SplitGrapevineParameters", "struct_split_grapevine_parameters.html", "struct_split_grapevine_parameters" ], + [ "StomatalConductanceModel", "class_stomatal_conductance_model.html", "class_stomatal_conductance_model" ], + [ "StrawberryParameters", "struct_strawberry_parameters.html", "struct_strawberry_parameters" ], + [ "SyntheticAnnotation", "class_synthetic_annotation.html", "class_synthetic_annotation" ], + [ "TomatoParameters", "struct_tomato_parameters.html", "struct_tomato_parameters" ], + [ "Triad", "struct_triad.html", null ], + [ "Triangulation", "struct_triangulation.html", null ], + [ "UnilateralGrapevineParameters", "struct_unilateral_grapevine_parameters.html", "struct_unilateral_grapevine_parameters" ], + [ "VegetativeBud", "struct_vegetative_bud.html", null ], + [ "Visualizer", "class_visualizer.html", "class_visualizer" ], + [ "VoxelIntersection", "class_voxel_intersection.html", "class_voxel_intersection" ], + [ "VSPGrapevineParameters", "struct_v_s_p_grapevine_parameters.html", "struct_v_s_p_grapevine_parameters" ], + [ "WalnutCanopyParameters", "struct_walnut_canopy_parameters.html", "struct_walnut_canopy_parameters" ], + [ "WeberPennTree", "class_weber_penn_tree.html", "class_weber_penn_tree" ], + [ "WeberPennTreeParameters", "struct_weber_penn_tree_parameters.html", null ], + [ "WhiteSpruceCanopyParameters", "struct_white_spruce_canopy_parameters.html", "struct_white_spruce_canopy_parameters" ] +]; \ No newline at end of file diff --git a/doc/html/bean_8cpp_source.html b/doc/html/bean_8cpp_source.html index 9de1f12f6..c1538e0f5 100644 --- a/doc/html/bean_8cpp_source.html +++ b/doc/html/bean_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
bean.cpp
@@ -409,7 +415,7 @@
302 UUID_branch.push_back( branch_UUIDs );
303 UUID_fruit.push_back( fruit_UUIDs );
304
-
305 context->deletePrimitive( leaf_prototype );
+
305 context->deletePrimitive( leaf_prototype );
306
307 return UUID_leaf.size()-1;
308
@@ -419,14 +425,13 @@
helios::vec3 interpolateTube(const std::vector< helios::vec3 > &P, float frac)
Interpolate the position of a point along a tube.
float getVariation(float V, std::minstd_rand0 &generator, bool positive=false)
Draw a random number (float) from a uniform distribution between -V and V.
uint bean(const BeanParameters &params, const helios::vec3 &origin)
Function to add an individual bean plant.
Definition bean.cpp:291
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1491
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
+
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5957
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
uint addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
Add new Triangle geometric primitive.
Definition Context.cpp:1328
@@ -449,14 +454,17 @@
float azimuth
Azimuthal angle (radians)
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
- -
+ + diff --git a/doc/html/build_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html b/doc/html/build_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html new file mode 100644 index 000000000..ccfbedffb --- /dev/null +++ b/doc/html/build_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html @@ -0,0 +1,992 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
CMakeCXXCompilerId.cpp
+
+
+
1/* This source file must have a .cpp extension so that all C++ compilers
+
2 recognize the extension without flags. Borland does not know .cxx for
+
3 example. */
+
4#ifndef __cplusplus
+
5# error "A C compiler has been selected for C++."
+
6#endif
+
7
+
8#if !defined(__has_include)
+
9/* If the compiler does not have __has_include, pretend the answer is
+
10 always no. */
+
11# define __has_include(x) 0
+
12#endif
+
13
+
14
+
15/* Version number components: V=Version, R=Revision, P=Patch
+
16 Version date components: YYYY=Year, MM=Month, DD=Day */
+
17
+
18#if defined(__COMO__)
+
19# define COMPILER_ID "Comeau"
+
20 /* __COMO_VERSION__ = VRR */
+
21# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
+
22# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
+
23
+
24#elif defined(__INTEL_COMPILER) || defined(__ICC)
+
25# define COMPILER_ID "Intel"
+
26# if defined(_MSC_VER)
+
27# define SIMULATE_ID "MSVC"
+
28# endif
+
29# if defined(__GNUC__)
+
30# define SIMULATE_ID "GNU"
+
31# endif
+
32 /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later,
+
33 except that a few beta releases use the old format with V=2021. */
+
34# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111
+
35# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+
36# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+
37# if defined(__INTEL_COMPILER_UPDATE)
+
38# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+
39# else
+
40# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+
41# endif
+
42# else
+
43# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER)
+
44# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE)
+
45 /* The third version component from --version is an update index,
+
46 but no macro is provided for it. */
+
47# define COMPILER_VERSION_PATCH DEC(0)
+
48# endif
+
49# if defined(__INTEL_COMPILER_BUILD_DATE)
+
50 /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+
51# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+
52# endif
+
53# if defined(_MSC_VER)
+
54 /* _MSC_VER = VVRR */
+
55# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+
56# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+
57# endif
+
58# if defined(__GNUC__)
+
59# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+
60# elif defined(__GNUG__)
+
61# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+
62# endif
+
63# if defined(__GNUC_MINOR__)
+
64# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+
65# endif
+
66# if defined(__GNUC_PATCHLEVEL__)
+
67# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+
68# endif
+
69
+
70#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER)
+
71# define COMPILER_ID "IntelLLVM"
+
72#if defined(_MSC_VER)
+
73# define SIMULATE_ID "MSVC"
+
74#endif
+
75#if defined(__GNUC__)
+
76# define SIMULATE_ID "GNU"
+
77#endif
+
78/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
+
79 * later. Look for 6 digit vs. 8 digit version number to decide encoding.
+
80 * VVVV is no smaller than the current year when a version is released.
+
81 */
+
82#if __INTEL_LLVM_COMPILER < 1000000L
+
83# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
+
84# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
+
85# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
+
86#else
+
87# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
+
88# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
+
89# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
+
90#endif
+
91#if defined(_MSC_VER)
+
92 /* _MSC_VER = VVRR */
+
93# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+
94# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+
95#endif
+
96#if defined(__GNUC__)
+
97# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+
98#elif defined(__GNUG__)
+
99# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+
100#endif
+
101#if defined(__GNUC_MINOR__)
+
102# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+
103#endif
+
104#if defined(__GNUC_PATCHLEVEL__)
+
105# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+
106#endif
+
107
+
108#elif defined(__PATHCC__)
+
109# define COMPILER_ID "PathScale"
+
110# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+
111# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+
112# if defined(__PATHCC_PATCHLEVEL__)
+
113# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+
114# endif
+
115
+
116#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+
117# define COMPILER_ID "Embarcadero"
+
118# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+
119# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+
120# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
121
+
122#elif defined(__BORLANDC__)
+
123# define COMPILER_ID "Borland"
+
124 /* __BORLANDC__ = 0xVRR */
+
125# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+
126# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
127
+
128#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+
129# define COMPILER_ID "Watcom"
+
130 /* __WATCOMC__ = VVRR */
+
131# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+
132# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+
133# if (__WATCOMC__ % 10) > 0
+
134# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+
135# endif
+
136
+
137#elif defined(__WATCOMC__)
+
138# define COMPILER_ID "OpenWatcom"
+
139 /* __WATCOMC__ = VVRP + 1100 */
+
140# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+
141# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+
142# if (__WATCOMC__ % 10) > 0
+
143# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+
144# endif
+
145
+
146#elif defined(__SUNPRO_CC)
+
147# define COMPILER_ID "SunPro"
+
148# if __SUNPRO_CC >= 0x5100
+
149 /* __SUNPRO_CC = 0xVRRP */
+
150# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
+
151# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
+
152# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+
153# else
+
154 /* __SUNPRO_CC = 0xVRP */
+
155# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
+
156# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
+
157# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+
158# endif
+
159
+
160#elif defined(__HP_aCC)
+
161# define COMPILER_ID "HP"
+
162 /* __HP_aCC = VVRRPP */
+
163# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
+
164# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
+
165# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
+
166
+
167#elif defined(__DECCXX)
+
168# define COMPILER_ID "Compaq"
+
169 /* __DECCXX_VER = VVRRTPPPP */
+
170# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
+
171# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
+
172# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
+
173
+
174#elif defined(__IBMCPP__) && defined(__COMPILER_VER__)
+
175# define COMPILER_ID "zOS"
+
176 /* __IBMCPP__ = VRP */
+
177# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+
178# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+
179# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
180
+
181#elif defined(__open_xl__) && defined(__clang__)
+
182# define COMPILER_ID "IBMClang"
+
183# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__)
+
184# define COMPILER_VERSION_MINOR DEC(__open_xl_release__)
+
185# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__)
+
186# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__)
+
187
+
188
+
189#elif defined(__ibmxl__) && defined(__clang__)
+
190# define COMPILER_ID "XLClang"
+
191# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+
192# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+
193# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+
194# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
195
+
196
+
197#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800
+
198# define COMPILER_ID "XL"
+
199 /* __IBMCPP__ = VRP */
+
200# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+
201# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+
202# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
203
+
204#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800
+
205# define COMPILER_ID "VisualAge"
+
206 /* __IBMCPP__ = VRP */
+
207# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+
208# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+
209# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
210
+
211#elif defined(__NVCOMPILER)
+
212# define COMPILER_ID "NVHPC"
+
213# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
+
214# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
+
215# if defined(__NVCOMPILER_PATCHLEVEL__)
+
216# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
+
217# endif
+
218
+
219#elif defined(__PGI)
+
220# define COMPILER_ID "PGI"
+
221# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+
222# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+
223# if defined(__PGIC_PATCHLEVEL__)
+
224# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+
225# endif
+
226
+
227#elif defined(__clang__) && defined(__cray__)
+
228# define COMPILER_ID "CrayClang"
+
229# define COMPILER_VERSION_MAJOR DEC(__cray_major__)
+
230# define COMPILER_VERSION_MINOR DEC(__cray_minor__)
+
231# define COMPILER_VERSION_PATCH DEC(__cray_patchlevel__)
+
232# define COMPILER_VERSION_INTERNAL_STR __clang_version__
+
233
+
234
+
235#elif defined(_CRAYC)
+
236# define COMPILER_ID "Cray"
+
237# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+
238# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
239
+
240#elif defined(__TI_COMPILER_VERSION__)
+
241# define COMPILER_ID "TI"
+
242 /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+
243# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+
244# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+
245# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
246
+
247#elif defined(__CLANG_FUJITSU)
+
248# define COMPILER_ID "FujitsuClang"
+
249# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
+
250# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
+
251# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
+
252# define COMPILER_VERSION_INTERNAL_STR __clang_version__
+
253
+
254
+
255#elif defined(__FUJITSU)
+
256# define COMPILER_ID "Fujitsu"
+
257# if defined(__FCC_version__)
+
258# define COMPILER_VERSION __FCC_version__
+
259# elif defined(__FCC_major__)
+
260# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
+
261# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
+
262# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
+
263# endif
+
264# if defined(__fcc_version)
+
265# define COMPILER_VERSION_INTERNAL DEC(__fcc_version)
+
266# elif defined(__FCC_VERSION)
+
267# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION)
+
268# endif
+
269
+
270
+
271#elif defined(__ghs__)
+
272# define COMPILER_ID "GHS"
+
273/* __GHS_VERSION_NUMBER = VVVVRP */
+
274# ifdef __GHS_VERSION_NUMBER
+
275# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+
276# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+
277# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+
278# endif
+
279
+
280#elif defined(__TASKING__)
+
281# define COMPILER_ID "Tasking"
+
282 # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000)
+
283 # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100)
+
284# define COMPILER_VERSION_INTERNAL DEC(__VERSION__)
+
285
+
286#elif defined(__ORANGEC__)
+
287# define COMPILER_ID "OrangeC"
+
288# define COMPILER_VERSION_MAJOR DEC(__ORANGEC_MAJOR__)
+
289# define COMPILER_VERSION_MINOR DEC(__ORANGEC_MINOR__)
+
290# define COMPILER_VERSION_PATCH DEC(__ORANGEC_PATCHLEVEL__)
+
291
+
292#elif defined(__SCO_VERSION__)
+
293# define COMPILER_ID "SCO"
+
294
+
295#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+
296# define COMPILER_ID "ARMCC"
+
297#if __ARMCC_VERSION >= 1000000
+
298 /* __ARMCC_VERSION = VRRPPPP */
+
299 # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+
300 # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+
301 # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+
302#else
+
303 /* __ARMCC_VERSION = VRPPPP */
+
304 # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+
305 # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+
306 # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+
307#endif
+
308
+
309
+
310#elif defined(__clang__) && defined(__apple_build_version__)
+
311# define COMPILER_ID "AppleClang"
+
312# if defined(_MSC_VER)
+
313# define SIMULATE_ID "MSVC"
+
314# endif
+
315# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+
316# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+
317# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+
318# if defined(_MSC_VER)
+
319 /* _MSC_VER = VVRR */
+
320# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+
321# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+
322# endif
+
323# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
324
+
325#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+
326# define COMPILER_ID "ARMClang"
+
327 # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+
328 # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+
329 # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION/100 % 100)
+
330# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
331
+
332#elif defined(__clang__)
+
333# define COMPILER_ID "Clang"
+
334# if defined(_MSC_VER)
+
335# define SIMULATE_ID "MSVC"
+
336# endif
+
337# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+
338# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+
339# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+
340# if defined(_MSC_VER)
+
341 /* _MSC_VER = VVRR */
+
342# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+
343# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+
344# endif
+
345
+
346#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__))
+
347# define COMPILER_ID "LCC"
+
348# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100)
+
349# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100)
+
350# if defined(__LCC_MINOR__)
+
351# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__)
+
352# endif
+
353# if defined(__GNUC__) && defined(__GNUC_MINOR__)
+
354# define SIMULATE_ID "GNU"
+
355# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+
356# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+
357# if defined(__GNUC_PATCHLEVEL__)
+
358# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+
359# endif
+
360# endif
+
361
+
362#elif defined(__GNUC__) || defined(__GNUG__)
+
363# define COMPILER_ID "GNU"
+
364# if defined(__GNUC__)
+
365# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+
366# else
+
367# define COMPILER_VERSION_MAJOR DEC(__GNUG__)
+
368# endif
+
369# if defined(__GNUC_MINOR__)
+
370# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+
371# endif
+
372# if defined(__GNUC_PATCHLEVEL__)
+
373# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+
374# endif
+
375
+
376#elif defined(_MSC_VER)
+
377# define COMPILER_ID "MSVC"
+
378 /* _MSC_VER = VVRR */
+
379# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+
380# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+
381# if defined(_MSC_FULL_VER)
+
382# if _MSC_VER >= 1400
+
383 /* _MSC_FULL_VER = VVRRPPPPP */
+
384# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+
385# else
+
386 /* _MSC_FULL_VER = VVRRPPPP */
+
387# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+
388# endif
+
389# endif
+
390# if defined(_MSC_BUILD)
+
391# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+
392# endif
+
393
+
394#elif defined(_ADI_COMPILER)
+
395# define COMPILER_ID "ADSP"
+
396#if defined(__VERSIONNUM__)
+
397 /* __VERSIONNUM__ = 0xVVRRPPTT */
+
398# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF)
+
399# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF)
+
400# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF)
+
401# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF)
+
402#endif
+
403
+
404#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+
405# define COMPILER_ID "IAR"
+
406# if defined(__VER__) && defined(__ICCARM__)
+
407# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+
408# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+
409# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+
410# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+
411# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
+
412# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+
413# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+
414# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+
415# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+
416# endif
+
417
+
418
+
419/* These compilers are either not known or too old to define an
+
420 identification macro. Try to identify the platform and guess that
+
421 it is the native compiler. */
+
422#elif defined(__hpux) || defined(__hpua)
+
423# define COMPILER_ID "HP"
+
424
+
425#else /* unknown compiler */
+
426# define COMPILER_ID ""
+
427#endif
+
428
+
429/* Construct the string literal in pieces to prevent the source from
+
430 getting matched. Store it in a pointer rather than an array
+
431 because some compilers will just produce instructions to fill the
+
432 array rather than assigning a pointer to a static array. */
+
433char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+
434#ifdef SIMULATE_ID
+
435char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+
436#endif
+
437
+
438#ifdef __QNXNTO__
+
439char const* qnxnto = "INFO" ":" "qnxnto[]";
+
440#endif
+
441
+
442#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
+
443char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+
444#endif
+
445
+
446#define STRINGIFY_HELPER(X) #X
+
447#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
448
+
449/* Identify known platforms by name. */
+
450#if defined(__linux) || defined(__linux__) || defined(linux)
+
451# define PLATFORM_ID "Linux"
+
452
+
453#elif defined(__MSYS__)
+
454# define PLATFORM_ID "MSYS"
+
455
+
456#elif defined(__CYGWIN__)
+
457# define PLATFORM_ID "Cygwin"
+
458
+
459#elif defined(__MINGW32__)
+
460# define PLATFORM_ID "MinGW"
+
461
+
462#elif defined(__APPLE__)
+
463# define PLATFORM_ID "Darwin"
+
464
+
465#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+
466# define PLATFORM_ID "Windows"
+
467
+
468#elif defined(__FreeBSD__) || defined(__FreeBSD)
+
469# define PLATFORM_ID "FreeBSD"
+
470
+
471#elif defined(__NetBSD__) || defined(__NetBSD)
+
472# define PLATFORM_ID "NetBSD"
+
473
+
474#elif defined(__OpenBSD__) || defined(__OPENBSD)
+
475# define PLATFORM_ID "OpenBSD"
+
476
+
477#elif defined(__sun) || defined(sun)
+
478# define PLATFORM_ID "SunOS"
+
479
+
480#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+
481# define PLATFORM_ID "AIX"
+
482
+
483#elif defined(__hpux) || defined(__hpux__)
+
484# define PLATFORM_ID "HP-UX"
+
485
+
486#elif defined(__HAIKU__)
+
487# define PLATFORM_ID "Haiku"
+
488
+
489#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+
490# define PLATFORM_ID "BeOS"
+
491
+
492#elif defined(__QNX__) || defined(__QNXNTO__)
+
493# define PLATFORM_ID "QNX"
+
494
+
495#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+
496# define PLATFORM_ID "Tru64"
+
497
+
498#elif defined(__riscos) || defined(__riscos__)
+
499# define PLATFORM_ID "RISCos"
+
500
+
501#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+
502# define PLATFORM_ID "SINIX"
+
503
+
504#elif defined(__UNIX_SV__)
+
505# define PLATFORM_ID "UNIX_SV"
+
506
+
507#elif defined(__bsdos__)
+
508# define PLATFORM_ID "BSDOS"
+
509
+
510#elif defined(_MPRAS) || defined(MPRAS)
+
511# define PLATFORM_ID "MP-RAS"
+
512
+
513#elif defined(__osf) || defined(__osf__)
+
514# define PLATFORM_ID "OSF1"
+
515
+
516#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+
517# define PLATFORM_ID "SCO_SV"
+
518
+
519#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+
520# define PLATFORM_ID "ULTRIX"
+
521
+
522#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+
523# define PLATFORM_ID "Xenix"
+
524
+
525#elif defined(__WATCOMC__)
+
526# if defined(__LINUX__)
+
527# define PLATFORM_ID "Linux"
+
528
+
529# elif defined(__DOS__)
+
530# define PLATFORM_ID "DOS"
+
531
+
532# elif defined(__OS2__)
+
533# define PLATFORM_ID "OS2"
+
534
+
535# elif defined(__WINDOWS__)
+
536# define PLATFORM_ID "Windows3x"
+
537
+
538# elif defined(__VXWORKS__)
+
539# define PLATFORM_ID "VxWorks"
+
540
+
541# else /* unknown platform */
+
542# define PLATFORM_ID
+
543# endif
+
544
+
545#elif defined(__INTEGRITY)
+
546# if defined(INT_178B)
+
547# define PLATFORM_ID "Integrity178"
+
548
+
549# else /* regular Integrity */
+
550# define PLATFORM_ID "Integrity"
+
551# endif
+
552
+
553# elif defined(_ADI_COMPILER)
+
554# define PLATFORM_ID "ADSP"
+
555
+
556#else /* unknown platform */
+
557# define PLATFORM_ID
+
558
+
559#endif
+
560
+
561/* For windows compilers MSVC and Intel we can determine
+
562 the architecture of the compiler being used. This is because
+
563 the compilers do not have flags that can change the architecture,
+
564 but rather depend on which compiler is being used
+
565*/
+
566#if defined(_WIN32) && defined(_MSC_VER)
+
567# if defined(_M_IA64)
+
568# define ARCHITECTURE_ID "IA64"
+
569
+
570# elif defined(_M_ARM64EC)
+
571# define ARCHITECTURE_ID "ARM64EC"
+
572
+
573# elif defined(_M_X64) || defined(_M_AMD64)
+
574# define ARCHITECTURE_ID "x64"
+
575
+
576# elif defined(_M_IX86)
+
577# define ARCHITECTURE_ID "X86"
+
578
+
579# elif defined(_M_ARM64)
+
580# define ARCHITECTURE_ID "ARM64"
+
581
+
582# elif defined(_M_ARM)
+
583# if _M_ARM == 4
+
584# define ARCHITECTURE_ID "ARMV4I"
+
585# elif _M_ARM == 5
+
586# define ARCHITECTURE_ID "ARMV5I"
+
587# else
+
588# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+
589# endif
+
590
+
591# elif defined(_M_MIPS)
+
592# define ARCHITECTURE_ID "MIPS"
+
593
+
594# elif defined(_M_SH)
+
595# define ARCHITECTURE_ID "SHx"
+
596
+
597# else /* unknown architecture */
+
598# define ARCHITECTURE_ID ""
+
599# endif
+
600
+
601#elif defined(__WATCOMC__)
+
602# if defined(_M_I86)
+
603# define ARCHITECTURE_ID "I86"
+
604
+
605# elif defined(_M_IX86)
+
606# define ARCHITECTURE_ID "X86"
+
607
+
608# else /* unknown architecture */
+
609# define ARCHITECTURE_ID ""
+
610# endif
+
611
+
612#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+
613# if defined(__ICCARM__)
+
614# define ARCHITECTURE_ID "ARM"
+
615
+
616# elif defined(__ICCRX__)
+
617# define ARCHITECTURE_ID "RX"
+
618
+
619# elif defined(__ICCRH850__)
+
620# define ARCHITECTURE_ID "RH850"
+
621
+
622# elif defined(__ICCRL78__)
+
623# define ARCHITECTURE_ID "RL78"
+
624
+
625# elif defined(__ICCRISCV__)
+
626# define ARCHITECTURE_ID "RISCV"
+
627
+
628# elif defined(__ICCAVR__)
+
629# define ARCHITECTURE_ID "AVR"
+
630
+
631# elif defined(__ICC430__)
+
632# define ARCHITECTURE_ID "MSP430"
+
633
+
634# elif defined(__ICCV850__)
+
635# define ARCHITECTURE_ID "V850"
+
636
+
637# elif defined(__ICC8051__)
+
638# define ARCHITECTURE_ID "8051"
+
639
+
640# elif defined(__ICCSTM8__)
+
641# define ARCHITECTURE_ID "STM8"
+
642
+
643# else /* unknown architecture */
+
644# define ARCHITECTURE_ID ""
+
645# endif
+
646
+
647#elif defined(__ghs__)
+
648# if defined(__PPC64__)
+
649# define ARCHITECTURE_ID "PPC64"
+
650
+
651# elif defined(__ppc__)
+
652# define ARCHITECTURE_ID "PPC"
+
653
+
654# elif defined(__ARM__)
+
655# define ARCHITECTURE_ID "ARM"
+
656
+
657# elif defined(__x86_64__)
+
658# define ARCHITECTURE_ID "x64"
+
659
+
660# elif defined(__i386__)
+
661# define ARCHITECTURE_ID "X86"
+
662
+
663# else /* unknown architecture */
+
664# define ARCHITECTURE_ID ""
+
665# endif
+
666
+
667#elif defined(__TI_COMPILER_VERSION__)
+
668# if defined(__TI_ARM__)
+
669# define ARCHITECTURE_ID "ARM"
+
670
+
671# elif defined(__MSP430__)
+
672# define ARCHITECTURE_ID "MSP430"
+
673
+
674# elif defined(__TMS320C28XX__)
+
675# define ARCHITECTURE_ID "TMS320C28x"
+
676
+
677# elif defined(__TMS320C6X__) || defined(_TMS320C6X)
+
678# define ARCHITECTURE_ID "TMS320C6x"
+
679
+
680# else /* unknown architecture */
+
681# define ARCHITECTURE_ID ""
+
682# endif
+
683
+
684# elif defined(__ADSPSHARC__)
+
685# define ARCHITECTURE_ID "SHARC"
+
686
+
687# elif defined(__ADSPBLACKFIN__)
+
688# define ARCHITECTURE_ID "Blackfin"
+
689
+
690#elif defined(__TASKING__)
+
691
+
692# if defined(__CTC__) || defined(__CPTC__)
+
693# define ARCHITECTURE_ID "TriCore"
+
694
+
695# elif defined(__CMCS__)
+
696# define ARCHITECTURE_ID "MCS"
+
697
+
698# elif defined(__CARM__)
+
699# define ARCHITECTURE_ID "ARM"
+
700
+
701# elif defined(__CARC__)
+
702# define ARCHITECTURE_ID "ARC"
+
703
+
704# elif defined(__C51__)
+
705# define ARCHITECTURE_ID "8051"
+
706
+
707# elif defined(__CPCP__)
+
708# define ARCHITECTURE_ID "PCP"
+
709
+
710# else
+
711# define ARCHITECTURE_ID ""
+
712# endif
+
713
+
714#else
+
715# define ARCHITECTURE_ID
+
716#endif
+
717
+
718/* Convert integer to decimal digit literals. */
+
719#define DEC(n) \
+
720 ('0' + (((n) / 10000000)%10)), \
+
721 ('0' + (((n) / 1000000)%10)), \
+
722 ('0' + (((n) / 100000)%10)), \
+
723 ('0' + (((n) / 10000)%10)), \
+
724 ('0' + (((n) / 1000)%10)), \
+
725 ('0' + (((n) / 100)%10)), \
+
726 ('0' + (((n) / 10)%10)), \
+
727 ('0' + ((n) % 10))
+
728
+
729/* Convert integer to hex digit literals. */
+
730#define HEX(n) \
+
731 ('0' + ((n)>>28 & 0xF)), \
+
732 ('0' + ((n)>>24 & 0xF)), \
+
733 ('0' + ((n)>>20 & 0xF)), \
+
734 ('0' + ((n)>>16 & 0xF)), \
+
735 ('0' + ((n)>>12 & 0xF)), \
+
736 ('0' + ((n)>>8 & 0xF)), \
+
737 ('0' + ((n)>>4 & 0xF)), \
+
738 ('0' + ((n) & 0xF))
+
739
+
740/* Construct a string literal encoding the version number. */
+
741#ifdef COMPILER_VERSION
+
742char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
+
743
+
744/* Construct a string literal encoding the version number components. */
+
745#elif defined(COMPILER_VERSION_MAJOR)
+
746char const info_version[] = {
+
747 'I', 'N', 'F', 'O', ':',
+
748 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+
749 COMPILER_VERSION_MAJOR,
+
750# ifdef COMPILER_VERSION_MINOR
+
751 '.', COMPILER_VERSION_MINOR,
+
752# ifdef COMPILER_VERSION_PATCH
+
753 '.', COMPILER_VERSION_PATCH,
+
754# ifdef COMPILER_VERSION_TWEAK
+
755 '.', COMPILER_VERSION_TWEAK,
+
756# endif
+
757# endif
+
758# endif
+
759 ']','\0'};
+
760#endif
+
761
+
762/* Construct a string literal encoding the internal version number. */
+
763#ifdef COMPILER_VERSION_INTERNAL
+
764char const info_version_internal[] = {
+
765 'I', 'N', 'F', 'O', ':',
+
766 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+
767 'i','n','t','e','r','n','a','l','[',
+
768 COMPILER_VERSION_INTERNAL,']','\0'};
+
769#elif defined(COMPILER_VERSION_INTERNAL_STR)
+
770char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
+
771#endif
+
772
+
773/* Construct a string literal encoding the version number components. */
+
774#ifdef SIMULATE_VERSION_MAJOR
+
775char const info_simulate_version[] = {
+
776 'I', 'N', 'F', 'O', ':',
+
777 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+
778 SIMULATE_VERSION_MAJOR,
+
779# ifdef SIMULATE_VERSION_MINOR
+
780 '.', SIMULATE_VERSION_MINOR,
+
781# ifdef SIMULATE_VERSION_PATCH
+
782 '.', SIMULATE_VERSION_PATCH,
+
783# ifdef SIMULATE_VERSION_TWEAK
+
784 '.', SIMULATE_VERSION_TWEAK,
+
785# endif
+
786# endif
+
787# endif
+
788 ']','\0'};
+
789#endif
+
790
+
791/* Construct the string literal in pieces to prevent the source from
+
792 getting matched. Store it in a pointer rather than an array
+
793 because some compilers will just produce instructions to fill the
+
794 array rather than assigning a pointer to a static array. */
+
795char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+
796char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
797
+
798
+
799
+
800#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L
+
801# if defined(__INTEL_CXX11_MODE__)
+
802# if defined(__cpp_aggregate_nsdmi)
+
803# define CXX_STD 201402L
+
804# else
+
805# define CXX_STD 201103L
+
806# endif
+
807# else
+
808# define CXX_STD 199711L
+
809# endif
+
810#elif defined(_MSC_VER) && defined(_MSVC_LANG)
+
811# define CXX_STD _MSVC_LANG
+
812#else
+
813# define CXX_STD __cplusplus
+
814#endif
+
815
+
816const char* info_language_standard_default = "INFO" ":" "standard_default["
+
817#if CXX_STD > 202002L
+
818 "23"
+
819#elif CXX_STD > 201703L
+
820 "20"
+
821#elif CXX_STD >= 201703L
+
822 "17"
+
823#elif CXX_STD >= 201402L
+
824 "14"
+
825#elif CXX_STD >= 201103L
+
826 "11"
+
827#else
+
828 "98"
+
829#endif
+
830"]";
+
831
+
832const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+
833#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \
+
834 defined(__TI_COMPILER_VERSION__)) && \
+
835 !defined(__STRICT_ANSI__)
+
836 "ON"
+
837#else
+
838 "OFF"
+
839#endif
+
840"]";
+
841
+
842/*--------------------------------------------------------------------------*/
+
843
+
844int main(int argc, char* argv[])
+
845{
+
846 int require = 0;
+
847 require += info_compiler[argc];
+
848 require += info_platform[argc];
+
849 require += info_arch[argc];
+
850#ifdef COMPILER_VERSION_MAJOR
+
851 require += info_version[argc];
+
852#endif
+
853#ifdef COMPILER_VERSION_INTERNAL
+
854 require += info_version_internal[argc];
+
855#endif
+
856#ifdef SIMULATE_ID
+
857 require += info_simulate[argc];
+
858#endif
+
859#ifdef SIMULATE_VERSION_MAJOR
+
860 require += info_simulate_version[argc];
+
861#endif
+
862#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
+
863 require += info_cray[argc];
+
864#endif
+
865 require += info_language_standard_default[argc];
+
866 require += info_language_extensions_default[argc];
+
867 (void)argv;
+
868 return require;
+
869}
+
+
+ + + + diff --git a/doc/html/class_aerial_li_d_a_rcloud.html b/doc/html/class_aerial_li_d_a_rcloud.html index 1f3a9de4d..758757124 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
@@ -2371,10 +2381,13 @@

fileIO.cpp

- -
+ + diff --git a/doc/html/class_aerial_li_d_a_rcloud.js b/doc/html/class_aerial_li_d_a_rcloud.js new file mode 100644 index 000000000..57eec4127 --- /dev/null +++ b/doc/html/class_aerial_li_d_a_rcloud.js @@ -0,0 +1,72 @@ +var class_aerial_li_d_a_rcloud = +[ + [ "AerialLiDARcloud", "class_aerial_li_d_a_rcloud.html#acbcca37e844dc4e5e72c703c619d8962", null ], + [ "~AerialLiDARcloud", "class_aerial_li_d_a_rcloud.html#acdf5d5239f43e8809a615d4c6e1323e3", null ], + [ "addGridToVisualizer", "class_aerial_li_d_a_rcloud.html#afc659e4837184ee76ce5b165ea2515df", null ], + [ "addHitPoint", "class_aerial_li_d_a_rcloud.html#a9ba0abbd9a178fbac01e5fcadfafe2b3", null ], + [ "addHitPoint", "class_aerial_li_d_a_rcloud.html#a8fc59bf1e7995b74ebc260dc31e66edc", null ], + [ "addHitPoint", "class_aerial_li_d_a_rcloud.html#a2de9fafdab55721b424abf420b15c1b2", null ], + [ "addHitPoint", "class_aerial_li_d_a_rcloud.html#a2caa78d1f8a3b4136ae270c9b741eaf7", null ], + [ "addHitPoint", "class_aerial_li_d_a_rcloud.html#a746b984566c871ff37d87cd52ed046a2", null ], + [ "addHitsToVisualizer", "class_aerial_li_d_a_rcloud.html#a2e72b963be7631462f852103f415eeae", null ], + [ "addHitsToVisualizer", "class_aerial_li_d_a_rcloud.html#a36a118297008063457035ef2e281b6cc", null ], + [ "addScan", "class_aerial_li_d_a_rcloud.html#a2912db8a137ffa0add4261e63c6d72c2", null ], + [ "calculateHitGridCell", "class_aerial_li_d_a_rcloud.html#abe3e99a406251c388a3d934a7519ddb2", null ], + [ "calculateLeafAreaGPU", "class_aerial_li_d_a_rcloud.html#a5dd671b27dbc6f27e19c66a5ee15934d", null ], + [ "calculateLeafAreaGPU", "class_aerial_li_d_a_rcloud.html#a2b334f5eb21554cfab456808e669322b", null ], + [ "calculateSyntheticLeafArea", "class_aerial_li_d_a_rcloud.html#ab5fec2c248d5889adf521cac3bb107b3", null ], + [ "deleteHitPoint", "class_aerial_li_d_a_rcloud.html#a9d374100b86e8becf578b65b81f99b67", null ], + [ "disableMessages", "class_aerial_li_d_a_rcloud.html#aae637046290c1276c8f816d975489b86", null ], + [ "distanceFilter", "class_aerial_li_d_a_rcloud.html#acc26240eea9ec98c6b354041cd9b9efc", null ], + [ "doesHitDataExist", "class_aerial_li_d_a_rcloud.html#a9b5aa652c94d4dee19a4f956a62f2ab1", null ], + [ "enableMessages", "class_aerial_li_d_a_rcloud.html#af5a5942d197f59c6f61cde76bb06a1ca", null ], + [ "exportPointCloud", "class_aerial_li_d_a_rcloud.html#a7f0992570b8535f687fd7067eb9f3593", null ], + [ "generateHeightModel", "class_aerial_li_d_a_rcloud.html#afc44503e2a6eb986fa79b5af56069468", null ], + [ "getCellCenter", "class_aerial_li_d_a_rcloud.html#a6e83c157d63d12253af3b81b995e1a33", null ], + [ "getCellCoverFraction", "class_aerial_li_d_a_rcloud.html#ac714e2231b63d1455237662661590b16", null ], + [ "getCellGroundHeight", "class_aerial_li_d_a_rcloud.html#a3b9d9ac013a041c30d58e68e5dc92bee", null ], + [ "getCellLeafArea", "class_aerial_li_d_a_rcloud.html#a9f90891b20b8996e983e66640684b6cc", null ], + [ "getCellLeafAreaDensity", "class_aerial_li_d_a_rcloud.html#a4ca0903b642daffdff27e69a172c96b5", null ], + [ "getCellMaximumHitHeight", "class_aerial_li_d_a_rcloud.html#a00f6479153ac2025031b70bd5637b65b", null ], + [ "getCellRbar", "class_aerial_li_d_a_rcloud.html#ae35261c7fc1553cb15fb318a2b14a3b2", null ], + [ "getCellSize", "class_aerial_li_d_a_rcloud.html#a5bf5379ee229ebb51fdc8195af8cf3e7", null ], + [ "getCellTransmissionProbability", "class_aerial_li_d_a_rcloud.html#a98770b70c510e7611fb171d3fe920554", null ], + [ "getCellVegetationHeight", "class_aerial_li_d_a_rcloud.html#a12fe426a267cbef9982138537198558a", null ], + [ "getGridCenter", "class_aerial_li_d_a_rcloud.html#ad639b0d2337b74b1bd4949cc2aba88e0", null ], + [ "getGridExtent", "class_aerial_li_d_a_rcloud.html#a85ea1ea67ed12f2bbcfc28ef9a78dd77", null ], + [ "getGridResolution", "class_aerial_li_d_a_rcloud.html#ae750e548d565d6305e600c5af8360fdb", null ], + [ "getGridRotation", "class_aerial_li_d_a_rcloud.html#aace3b3baae4a75be461eb31f617ee695", null ], + [ "getHitBoundingBox", "class_aerial_li_d_a_rcloud.html#a74b0e833ecb6ee1b3ce3010f3d38d74d", null ], + [ "getHitColor", "class_aerial_li_d_a_rcloud.html#af8f49444eb1d166837c322d03ea1cbfa", null ], + [ "getHitCount", "class_aerial_li_d_a_rcloud.html#aaf287ef121543f10e9e73579bf77281a", null ], + [ "getHitData", "class_aerial_li_d_a_rcloud.html#a240af79b825bc886e886ff7ff0e0476c", null ], + [ "getHitGridCell", "class_aerial_li_d_a_rcloud.html#a26bc32e67d3195222f11fb72fb7d63da", null ], + [ "getHitRaydir", "class_aerial_li_d_a_rcloud.html#ac0f8ba05e24d146d01ee2af0fb9ece7d", null ], + [ "getHitScanID", "class_aerial_li_d_a_rcloud.html#aaa2bbd15dad66355175fb733630456a4", null ], + [ "getHitXYZ", "class_aerial_li_d_a_rcloud.html#a3363ac3ffff1bbdd164b6074010d75ba", null ], + [ "getScanBeamDivergence", "class_aerial_li_d_a_rcloud.html#a4097c1d3994f57e0f0e2e602c7ca5c04", null ], + [ "getScanBeamExitDiameter", "class_aerial_li_d_a_rcloud.html#ae6cbd6375be39129231233d66061afca", null ], + [ "getScanCenter", "class_aerial_li_d_a_rcloud.html#a1ce1efbe6af71f54dcccd3743918aa72", null ], + [ "getScanConeAngle", "class_aerial_li_d_a_rcloud.html#a0dbf5535304d6d87d67a0d41c5d2310f", null ], + [ "getScanCount", "class_aerial_li_d_a_rcloud.html#ab363717911dada3af4fdafa914532a6a", null ], + [ "getScanDensity", "class_aerial_li_d_a_rcloud.html#a0c4627b15014ebe8c79053ed75f6cfb4", null ], + [ "getScanExtent", "class_aerial_li_d_a_rcloud.html#ad5bd68f06fef597d8c1f1aac3142acc6", null ], + [ "gridijk2index", "class_aerial_li_d_a_rcloud.html#a35c81e8cda423b84c94fc33ee4163d47", null ], + [ "gridindex2ijk", "class_aerial_li_d_a_rcloud.html#add78af9b69161c5c532a23c8df009d2e", null ], + [ "loadXML", "class_aerial_li_d_a_rcloud.html#aa87abfc0d5538d3d8fe28458c7093c2c", null ], + [ "readContextXML", "class_aerial_li_d_a_rcloud.html#a146bfba2241154ce7fa958bf7c797153", null ], + [ "reflectanceFilter", "class_aerial_li_d_a_rcloud.html#ad9b43918cdfd1b4489dca2ac098f9ca9", null ], + [ "scalarFilter", "class_aerial_li_d_a_rcloud.html#a4e1870a07129fc6b64427fd36896cb62", null ], + [ "selfTest", "class_aerial_li_d_a_rcloud.html#a330d36513eee2cc559c09fb71c18f566", null ], + [ "setCellCoverFraction", "class_aerial_li_d_a_rcloud.html#a41adc0bac55f6b4bf6dbf8aa00b87d47", null ], + [ "setCellGroundHeight", "class_aerial_li_d_a_rcloud.html#a7e9921a6fa458f6f9ff71272d81ed711", null ], + [ "setCellLeafArea", "class_aerial_li_d_a_rcloud.html#a789143d75bd6e27e4eecd4af676d03a0", null ], + [ "setCellMaximumHitHeight", "class_aerial_li_d_a_rcloud.html#a5de093096f98d0f7ac30bb17de6f8815", null ], + [ "setCellRbar", "class_aerial_li_d_a_rcloud.html#a0e16c7d7d1c6e876d234e2409f24fafe", null ], + [ "setCellTransmissionProbability", "class_aerial_li_d_a_rcloud.html#a6fae4d874d859d1b09e10eacc23dee7e", null ], + [ "setCellVegetationHeight", "class_aerial_li_d_a_rcloud.html#afa007ec27f0e1b321c522e5ce780d812", null ], + [ "setHitData", "class_aerial_li_d_a_rcloud.html#aba54610f999856adb4ae4ab4b244a553", null ], + [ "setHitGridCell", "class_aerial_li_d_a_rcloud.html#afa9735ddfc392110712a20029cbfd2ed", null ], + [ "syntheticScan", "class_aerial_li_d_a_rcloud.html#a0d56ae98d2ab2ad7008640b0ea4ffaea", null ], + [ "syntheticScan", "class_aerial_li_d_a_rcloud.html#a82abe2d47cc135f9f795ffaa15e4e041", null ] +]; \ No newline at end of file diff --git a/doc/html/class_b_l_conductance_model.html b/doc/html/class_b_l_conductance_model.html index 8a46d3dbb..ae2e18bb6 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
- -
+ + diff --git a/doc/html/class_b_l_conductance_model.js b/doc/html/class_b_l_conductance_model.js new file mode 100644 index 000000000..5b4a80cf7 --- /dev/null +++ b/doc/html/class_b_l_conductance_model.js @@ -0,0 +1,12 @@ +var class_b_l_conductance_model = +[ + [ "BLConductanceModel", "class_b_l_conductance_model.html#af507e5b75f21372ec225d5e5c0c8c97a", null ], + [ "disableMessages", "class_b_l_conductance_model.html#a11bd8193606442d8393bf22131fa0720", null ], + [ "enableMessages", "class_b_l_conductance_model.html#afd2d53808eb3ab1d3b104229c7bf3817", null ], + [ "run", "class_b_l_conductance_model.html#aaa522103af850ee1fff89c0f698ee049", null ], + [ "run", "class_b_l_conductance_model.html#a0b46d5ade5b84be8e8a44723c5dcf720", null ], + [ "selfTest", "class_b_l_conductance_model.html#a6e85abcd1e8544d66af25394cace6ed4", null ], + [ "setBoundaryLayerModel", "class_b_l_conductance_model.html#a601d3eba5024cff7290fa564f619c9df", null ], + [ "setBoundaryLayerModel", "class_b_l_conductance_model.html#a0a9e992d831834b188474e973cd41ee4", null ], + [ "setBoundaryLayerModel", "class_b_l_conductance_model.html#ab07e423e0cbc9a431368b9fddcfd93c7", null ] +]; \ No newline at end of file diff --git a/doc/html/class_canopy_generator.html b/doc/html/class_canopy_generator.html index 02c45916b..81bb0ffcd 100644 --- a/doc/html/class_canopy_generator.html +++ b/doc/html/class_canopy_generator.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
@@ -111,7 +121,7 @@ int selfTest ()  Unit testing routine.
  -template<typename CanopyType , typename... Args> +template<typename CanopyType, typename... Args> void storeCanopyParameters (Args &&... args)  Stores the given canopy parameters.
  @@ -278,7 +288,7 @@

-explicit +explicit

@@ -1517,7 +1527,7 @@

-template<typename CanopyType , typename... Args>
+template<typename CanopyType, typename... Args>
@@ -1678,10 +1688,13 @@

whitespruce.cpp - - + + diff --git a/doc/html/class_canopy_generator.js b/doc/html/class_canopy_generator.js new file mode 100644 index 000000000..f173e88f1 --- /dev/null +++ b/doc/html/class_canopy_generator.js @@ -0,0 +1,52 @@ +var class_canopy_generator = +[ + [ "CanopyGenerator", "class_canopy_generator.html#ac146e7630eb8d80fb91a3795d7b9f9f4", null ], + [ "addGrapeCluster", "class_canopy_generator.html#a6c8cbbd68ca9bd84d42324622cfba0d9", null ], + [ "bean", "class_canopy_generator.html#ad23ee37e5873fe542f6fc799f541384f", null ], + [ "buildCanopies", "class_canopy_generator.html#a7f9ffbcc969d0f50ed12c3de9b3d3b2a", null ], + [ "buildCanopy", "class_canopy_generator.html#adee8550880aaf26ebe1d46cdfcf4e06f", null ], + [ "buildCanopy", "class_canopy_generator.html#ac0a75c0d86d884a5bf5f618e55814ea1", null ], + [ "buildCanopy", "class_canopy_generator.html#a4ac7daae385ca391c756f8c46e7c1b6d", null ], + [ "buildCanopy", "class_canopy_generator.html#a1c7efa40c83c82ec081a7723c9c9ed98", null ], + [ "buildCanopy", "class_canopy_generator.html#a49c39faf194a1c84891001eac5074374", null ], + [ "buildCanopy", "class_canopy_generator.html#a19bdddcfb98212395400598df88f04e1", null ], + [ "buildCanopy", "class_canopy_generator.html#aa2a653e079dccfa1ee9849ef1fb83a51", null ], + [ "buildCanopy", "class_canopy_generator.html#a75022ad53ae8b8a1f631e6e876ee1bea", null ], + [ "buildCanopy", "class_canopy_generator.html#abc8543a9998fa835990580e7e7ded1c0", null ], + [ "buildCanopy", "class_canopy_generator.html#a50fac34470e512a92504c91128d1a437", null ], + [ "buildCanopy", "class_canopy_generator.html#a65a8e9f3edd2d73423cab95ec218a524", null ], + [ "buildCanopy", "class_canopy_generator.html#a5a80279ea1b73ab9c493b8f7819aa50d", null ], + [ "buildCanopy", "class_canopy_generator.html#a589132c50598208a158c21298f11a56c", null ], + [ "buildGround", "class_canopy_generator.html#a5933faa26fa34d44a52ba969d939818b", null ], + [ "buildGround", "class_canopy_generator.html#ab2069cca4af62c08bdf867a91aacf595", null ], + [ "buildIndividualPlants", "class_canopy_generator.html#ad55b3c912c7256b895b55c4dae4c2a5d", null ], + [ "buildIndividualPlants", "class_canopy_generator.html#a5a4d5cac8dff6a4b9a3d80dd87501b55", null ], + [ "createElementLabels", "class_canopy_generator.html#ade5c366887c712553b134ef23509f255", null ], + [ "disableElementLabels", "class_canopy_generator.html#a96b61b2224ca9adb3ccef157447d07c1", null ], + [ "disableMessages", "class_canopy_generator.html#aae25f707aa8f8f0409e497faa127d599", null ], + [ "enableMessages", "class_canopy_generator.html#a42eb441c5fb1f49d5ce758785f1e1700", null ], + [ "getAllUUIDs", "class_canopy_generator.html#a8e395619077d656e206f4159f0bf8d34", null ], + [ "getBranchUUIDs", "class_canopy_generator.html#a7db6f05ab623b77de4e8a81dc132e914", null ], + [ "getBranchUUIDs", "class_canopy_generator.html#ab7115aaa287346b9c8e7854bd66f8b5f", null ], + [ "getFruitUUIDs", "class_canopy_generator.html#abdcc431929f98e57db4b9ed2dc26a616", null ], + [ "getFruitUUIDs", "class_canopy_generator.html#a8ab509f22c4bdffd57b44f67f43ce728", null ], + [ "getGroundUUIDs", "class_canopy_generator.html#a6f0003d6ca29cbb56657442c7a48ad14", null ], + [ "getLeafUUIDs", "class_canopy_generator.html#a73680976a2826f0b5dbf567551fd5593", null ], + [ "getLeafUUIDs", "class_canopy_generator.html#a3509012720b5fd256a14bc2924a3b164", null ], + [ "getPlantCount", "class_canopy_generator.html#aba9e186286ade3cd2ced0be80b3b8b89", null ], + [ "getTrunkUUIDs", "class_canopy_generator.html#a44b2d0846bb08d331281a822df41daa6", null ], + [ "getTrunkUUIDs", "class_canopy_generator.html#aa8e95a610c03588592acebbbba5d638e", null ], + [ "grapevineGoblet", "class_canopy_generator.html#a8f2d498637c464ee852109e6085cde8a", null ], + [ "grapevineSplit", "class_canopy_generator.html#a8747bad1af97214059c38043241f0b47", null ], + [ "grapevineUnilateral", "class_canopy_generator.html#aac9104d7c6565e860737310de06981f8", null ], + [ "grapevineVSP", "class_canopy_generator.html#aaffe5cdb82a779785bc6d5e35e622812", null ], + [ "loadXML", "class_canopy_generator.html#aa481909b393a67953f2366217cf98843", null ], + [ "seedRandomGenerator", "class_canopy_generator.html#ad23ca24fa4ccb033293c8d5118903d16", null ], + [ "selfTest", "class_canopy_generator.html#af7f6d2ec2ee512af381cfaf5c414b505", null ], + [ "sorghum", "class_canopy_generator.html#a1e1b20fe60767277a4440e7a918d507c", null ], + [ "storeCanopyParameters", "class_canopy_generator.html#a1d73a30e5717cdd18a89ff51fe9970e3", null ], + [ "strawberry", "class_canopy_generator.html#a61ad89294ae8c964aff9cd18d273fc10", null ], + [ "tomato", "class_canopy_generator.html#a47b1aef12b71a5a406b6ac1caa7c7363", null ], + [ "walnut", "class_canopy_generator.html#af8b7088179f65a2d3d05a1f21207dd54", null ], + [ "whitespruce", "class_canopy_generator.html#a00d9f2222a38ef4a8494aef9650d11f3", null ] +]; \ No newline at end of file diff --git a/doc/html/class_dummy_model.html b/doc/html/class_dummy_model.html index e51b83989..88930bf8b 100644 --- a/doc/html/class_dummy_model.html +++ b/doc/html/class_dummy_model.html @@ -38,7 +38,7 @@

@@ -46,7 +46,7 @@
void CanopyGenerator::storeCanopyParameters
-
 v1.3.26 +
 v1.3.27

- + +
+
+ +
+
+
+
-
-
@@ -171,10 +181,13 @@

DummyModel.cpp

- -
+ + diff --git a/doc/html/class_dummy_model.js b/doc/html/class_dummy_model.js new file mode 100644 index 000000000..5bcc4bb79 --- /dev/null +++ b/doc/html/class_dummy_model.js @@ -0,0 +1,5 @@ +var class_dummy_model = +[ + [ "DummyModel", "class_dummy_model.html#ae48cd297d1bf8b94c296218e767b9f70", null ], + [ "run", "class_dummy_model.html#aed84f7d16e80cd5a1b6ca01ef45d3842", null ] +]; \ No newline at end of file diff --git a/doc/html/class_energy_balance_model.html b/doc/html/class_energy_balance_model.html index aece19f25..188ccaadd 100644 --- a/doc/html/class_energy_balance_model.html +++ b/doc/html/class_energy_balance_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
- -
+ + diff --git a/doc/html/class_energy_balance_model.js b/doc/html/class_energy_balance_model.js new file mode 100644 index 000000000..270f804bd --- /dev/null +++ b/doc/html/class_energy_balance_model.js @@ -0,0 +1,16 @@ +var class_energy_balance_model = +[ + [ "EnergyBalanceModel", "class_energy_balance_model.html#ad6c6f535390c7fcb4957a33cfc13b140", null ], + [ "addRadiationBand", "class_energy_balance_model.html#a7ce12c9b4baf734d49562fe45e7eb272", null ], + [ "addRadiationBand", "class_energy_balance_model.html#a4de3ab8046e5926fa022d877a11953c3", null ], + [ "disableMessages", "class_energy_balance_model.html#aaee48ad61d28ce32bdc8fb3650471b5b", null ], + [ "enableMessages", "class_energy_balance_model.html#a261480763ea918e133bb594ce9f3e14c", null ], + [ "optionalOutputPrimitiveData", "class_energy_balance_model.html#a8fd349c962047a29384e3f8099f1a054", null ], + [ "printDefaultValueReport", "class_energy_balance_model.html#a058d24583430bffdf78b53a8f9a5a851", null ], + [ "printDefaultValueReport", "class_energy_balance_model.html#aa8f66c144733765289f7748dee193d5e", null ], + [ "run", "class_energy_balance_model.html#aaee8cda49702db14f26e26bddaf3c16a", null ], + [ "run", "class_energy_balance_model.html#a2053c71e6ae107ba6ba612c56b245cf4", null ], + [ "run", "class_energy_balance_model.html#a4accc5ed86460c662db1352ef1857e0c", null ], + [ "run", "class_energy_balance_model.html#a5048dec148d795d76d10d331bdb35156", null ], + [ "selfTest", "class_energy_balance_model.html#ad4a1681ae6edd9f82d23e6a8ef3fc26c", null ] +]; \ No newline at end of file diff --git a/doc/html/class_glyph.html b/doc/html/class_glyph.html index 9977e6ac5..7289cb5ee 100644 --- a/doc/html/class_glyph.html +++ b/doc/html/class_glyph.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Public Member Functions | @@ -199,10 +209,13 @@

Visualizer.h

- -
+ + diff --git a/doc/html/class_hit_table.html b/doc/html/class_hit_table.html index 399db71f5..0a4bc581b 100644 --- a/doc/html/class_hit_table.html +++ b/doc/html/class_hit_table.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
@@ -346,7 +356,7 @@

-template<class datatype >
+template<class datatype>
@@ -364,7 +374,7 @@

-template<class datatype >
+template<class datatype>

uint HitTable< datatype >::Nphi
@@ -380,10 +390,13 @@

LiDAR.h - - + + diff --git a/doc/html/class_leaf_optics.html b/doc/html/class_leaf_optics.html index d727786cd..6ae43c884 100644 --- a/doc/html/class_leaf_optics.html +++ b/doc/html/class_leaf_optics.html @@ -38,7 +38,7 @@

@@ -46,7 +46,7 @@
uint HitTable< datatype >::Ntheta
-
 v1.3.26 +
 v1.3.27

- + +
+
+ +
+
+
+
-
-
- -
+ + diff --git a/doc/html/class_leaf_optics.js b/doc/html/class_leaf_optics.js new file mode 100644 index 000000000..c5865eae4 --- /dev/null +++ b/doc/html/class_leaf_optics.js @@ -0,0 +1,11 @@ +var class_leaf_optics = +[ + [ "LeafOptics", "class_leaf_optics.html#a8f286671c723166c8aae098d0efd9b04", null ], + [ "disableMessages", "class_leaf_optics.html#acc78ee64bd0569888dbaab2b29b4e7d5", null ], + [ "enableMessages", "class_leaf_optics.html#abf74f6bab17e5ef1465efca7803be71a", null ], + [ "getLeafSpectra", "class_leaf_optics.html#a6b9fa9b6fb34fe7738e425b19118005a", null ], + [ "PROSPECT", "class_leaf_optics.html#a8af86e8cce4d721230ddc746580b7dcf", null ], + [ "run", "class_leaf_optics.html#affa921ab4465e6d89cdbe41e15a087ba", null ], + [ "run", "class_leaf_optics.html#a883df20abfc7c37120262108ac056507", null ], + [ "setProperties", "class_leaf_optics.html#ac7a1cfe512d9417c26ad798a94cbdba1", null ] +]; \ No newline at end of file diff --git a/doc/html/class_li_d_a_rcloud.html b/doc/html/class_li_d_a_rcloud.html index 554b36c58..7e27d71b0 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
@@ -251,6 +261,9 @@ void exportTriangleInclinationDistribution (const char *filename, uint Nbins)  Export to file discrete area-weighted inclination angle probability distribution based on the triangulation. Inclination angles are between 0 and 90 degrees. The probability distribution is normalized such that the sine-weighted integral over all angles is 1. The value of each bin is written as a column in the output file; lines correspond to each voxel grid cell.
  +void exportTriangleAzimuthDistribution (const char *filename, uint Nbins) + Export to file discrete azimuthal angle probability distribution based on the triangulation. Azimuthal angles are between 0 and 360 degrees. The probability distribution is normalized such that the integral over all angles is 1. The value of each bin is written as a column in the output file; lines correspond to each voxel grid cell.
+  void exportLeafAreas (const char *filename)  Export to file the leaf area within each grid cell. Lines of the file correspond to each grid cell.
  @@ -438,8 +451,7 @@  Calculate the leaf area for each grid volume using equal weighting method.
  void leafReconstructionAlphaMask (float minimum_leaf_group_area, float maximum_leaf_group_area, float leaf_aspect_ratio, const char *mask_file) - Perform a leaf reconstruction based on texture-masked Patches within each gridcell. The reconstruction produces Patches for each reconstructed leaf surface, with leaf size automatically estimated algorithmically.
-
+ Perform a leaf reconstruction based on texture-masked Patches within each gridcell. The reconstruction produces Patches for each reconstructed leaf surface, with leaf size automatically estimated algorithmically.
  void leafReconstructionAlphaMask (float minimum_leaf_group_area, float maximum_leaf_group_area, float leaf_aspect_ratio, float leaf_length_constant, const char *mask_file)  Perform a leaf reconstruction based on texture-masked Patches within each gridcell. The reconstruction produces Patches for each reconstructed leaf surface, with leaf size set to a constant value.
@@ -1889,7 +1901,7 @@

Definition at line 708 of file fileIO.cpp.

+

Definition at line 780 of file fileIO.cpp.

@@ -1916,7 +1928,7 @@

Definition at line 688 of file fileIO.cpp.

+

Definition at line 760 of file fileIO.cpp.

@@ -1943,7 +1955,7 @@

Definition at line 668 of file fileIO.cpp.

+

Definition at line 740 of file fileIO.cpp.

@@ -1971,7 +1983,7 @@

Note
If there are multiple scans in the point cloud, each scan will be exported to a different file with the scan ID appended to the filename. This is because different scans may have a different column format.
-

Definition at line 728 of file fileIO.cpp.

+

Definition at line 800 of file fileIO.cpp.

@@ -2003,7 +2015,7 @@

Definition at line 756 of file fileIO.cpp.

+

Definition at line 828 of file fileIO.cpp.

@@ -2035,7 +2047,7 @@

Definition at line 843 of file fileIO.cpp.

+

Definition at line 915 of file fileIO.cpp.

@@ -2096,6 +2108,38 @@

Definition at line 584 of file fileIO.cpp.

+ + + +

◆ exportTriangleAzimuthDistribution()

+ +
+
+ + + + + + + + + + + +
void LiDARcloud::exportTriangleAzimuthDistribution (const char * filename,
uint Nbins )
+
+ +

Export to file discrete azimuthal angle probability distribution based on the triangulation. Azimuthal angles are between 0 and 360 degrees. The probability distribution is normalized such that the integral over all angles is 1. The value of each bin is written as a column in the output file; lines correspond to each voxel grid cell.

+
Parameters
+ + + +
[in]filenameName of file
[in]NbinsNumber of bins to use for the histogram
+
+
+ +

Definition at line 671 of file fileIO.cpp.

+
@@ -3136,8 +3180,7 @@

-

Perform a leaf reconstruction based on texture-masked Patches within each gridcell. The reconstruction produces Patches for each reconstructed leaf surface, with leaf size automatically estimated algorithmically.
-

+

Perform a leaf reconstruction based on texture-masked Patches within each gridcell. The reconstruction produces Patches for each reconstructed leaf surface, with leaf size automatically estimated algorithmically.

Parameters
@@ -3996,10 +4039,13 @@

selfTest.cpp - - + + diff --git a/doc/html/class_li_d_a_rcloud.js b/doc/html/class_li_d_a_rcloud.js new file mode 100644 index 000000000..b908700f2 --- /dev/null +++ b/doc/html/class_li_d_a_rcloud.js @@ -0,0 +1,117 @@ +var class_li_d_a_rcloud = +[ + [ "LiDARcloud", "class_li_d_a_rcloud.html#a1c946f80a3431e82e48fc54c611dca2c", null ], + [ "~LiDARcloud", "class_li_d_a_rcloud.html#a849627f4e1cd43c49ab21757e812ca68", null ], + [ "addGrid", "class_li_d_a_rcloud.html#a755ab5b665c80e30a49450ccfa1592d1", null ], + [ "addGridCell", "class_li_d_a_rcloud.html#a60a1e6e5eeb76df93e99c0bbaa971b93", null ], + [ "addGridCell", "class_li_d_a_rcloud.html#ac850f71f86e2872a78d8ff9bc6df6d08", null ], + [ "addGridToVisualizer", "class_li_d_a_rcloud.html#a2b7b76c26d6dd976bf37c0595b761507", null ], + [ "addGridWireFrametoVisualizer", "class_li_d_a_rcloud.html#af8c99daa924206b8172bb3bb1657e251", null ], + [ "addHitPoint", "class_li_d_a_rcloud.html#a244a1de12e8f6a3518b8715086c28e46", null ], + [ "addHitPoint", "class_li_d_a_rcloud.html#a6f01d5c6bdab78ee7bc08c90ba5f2217", null ], + [ "addHitPoint", "class_li_d_a_rcloud.html#ae1955f2181dab90400fcabedb8997c71", null ], + [ "addHitPoint", "class_li_d_a_rcloud.html#a794f9370ba56a29651a95709c528a6a4", null ], + [ "addHitPoint", "class_li_d_a_rcloud.html#aed09112c241e9d60aea781c9684a2633", null ], + [ "addHitsToVisualizer", "class_li_d_a_rcloud.html#a2102dd4711658414cca10fd40a66af18", null ], + [ "addHitsToVisualizer", "class_li_d_a_rcloud.html#a6292d1b6fce7638a256e090608c8c309", null ], + [ "addLeafReconstructionToContext", "class_li_d_a_rcloud.html#aeca8578d8b5ecbc92fa669c612196f8c", null ], + [ "addLeafReconstructionToContext", "class_li_d_a_rcloud.html#ab2b1545809e3537b4e7e803acc8c13c1", null ], + [ "addLeafReconstructionToVisualizer", "class_li_d_a_rcloud.html#a9c9cff3d1f5a68814ff2121d3b12d9b8", null ], + [ "addReconstructedTriangleGroupsToContext", "class_li_d_a_rcloud.html#a503c74fc549e5c3b25a5f5bf2d6a8955", null ], + [ "addScan", "class_li_d_a_rcloud.html#abbe448db446aa64f5ce5a923c597eae8", null ], + [ "addTrianglesToContext", "class_li_d_a_rcloud.html#a65c36191d1f0f82b77ebd2ffa2fe3821", null ], + [ "addTrianglesToVisualizer", "class_li_d_a_rcloud.html#a11d8d20197aa909080d70954c97395e6", null ], + [ "addTrianglesToVisualizer", "class_li_d_a_rcloud.html#a55d1d5c311e4cfa45fa47f36ac875e7f", null ], + [ "addTrunkReconstructionToContext", "class_li_d_a_rcloud.html#a4af78b2f167575f641e867f0f0688dd1", null ], + [ "addTrunkReconstructionToVisualizer", "class_li_d_a_rcloud.html#aa23c198a2c7492b8b6c865a42971a93d", null ], + [ "addTrunkReconstructionToVisualizer", "class_li_d_a_rcloud.html#a9fa20f56e1dbb38de35a48a599cda711", null ], + [ "calculateHitGridCellGPU", "class_li_d_a_rcloud.html#ab16514fff6766e89b91409077daf35fc", null ], + [ "calculateLeafAreaGPU", "class_li_d_a_rcloud.html#aff9aeedaa500516d1c227e5161fb599a", null ], + [ "calculateLeafAreaGPU", "class_li_d_a_rcloud.html#a865b46e46b3f20d879a0122b2ec21b7c", null ], + [ "calculateLeafAreaGPU_equal_weighting", "class_li_d_a_rcloud.html#a7b23ba7fb6a900ff86d7957fcaa89f83", null ], + [ "calculateLeafAreaGPU_equal_weighting", "class_li_d_a_rcloud.html#a5751d6482bc6747b3b0e8d4566b46ca2", null ], + [ "calculateLeafAreaGPU_synthetic", "class_li_d_a_rcloud.html#ac6824b871a54f9a25c0c6d1725cb4ee0", null ], + [ "calculateLeafAreaGPU_testing", "class_li_d_a_rcloud.html#aa6640bd0d26f6cd8e5b8225fe14eaa4d", null ], + [ "calculateSyntheticGtheta", "class_li_d_a_rcloud.html#a94fe14aa32343dc25e366fe2ad7dfdfd", null ], + [ "calculateSyntheticLeafArea", "class_li_d_a_rcloud.html#a22f9c93700be5e5a808b97ecca6752fe", null ], + [ "coordinateRotation", "class_li_d_a_rcloud.html#a263717159dde05f5b98ae4133dec3d5e", null ], + [ "coordinateRotation", "class_li_d_a_rcloud.html#abf2f7677b1a92cba5b51ad0336e3743e", null ], + [ "coordinateRotation", "class_li_d_a_rcloud.html#aeae9aaa404a67082f849e1c8d56579e5", null ], + [ "coordinateShift", "class_li_d_a_rcloud.html#a72bc752975f8783ad8b1710cefa1d2a9", null ], + [ "coordinateShift", "class_li_d_a_rcloud.html#ab37566564d8e421a123c8b1b8cdb2347", null ], + [ "cropBeamsToGridAngleRange", "class_li_d_a_rcloud.html#a85e1a7d8dc2df6eba9b798bb2a456473", null ], + [ "deleteHitPoint", "class_li_d_a_rcloud.html#accf5ec6015b0b68c89716ffff1a016bb", null ], + [ "disableMessages", "class_li_d_a_rcloud.html#af5d0590b160e7069826c52eeeb4e0129", null ], + [ "distanceFilter", "class_li_d_a_rcloud.html#af21b843806f22fb9bc80e7ef370aee1d", null ], + [ "doesHitDataExist", "class_li_d_a_rcloud.html#aabb8d404b7f3fa00d8281cb6b74f90c0", null ], + [ "enableMessages", "class_li_d_a_rcloud.html#a2e87dc18538155b35368ff27ed6a1504", null ], + [ "exportGtheta", "class_li_d_a_rcloud.html#af680cbb9eb0c1ebf49f71f0062d18c0c", null ], + [ "exportLeafAreaDensities", "class_li_d_a_rcloud.html#a6e438fd60af7f54f4d1c09ac64fd7338", null ], + [ "exportLeafAreas", "class_li_d_a_rcloud.html#a8e8bd43bf3b2c107994fee402c41240f", null ], + [ "exportPointCloud", "class_li_d_a_rcloud.html#a2d0c11c6d8001171269232ff5d7f6322", null ], + [ "exportPointCloud", "class_li_d_a_rcloud.html#ae9910fa1aae6b8b077d57417c130e753", null ], + [ "exportPointCloudPTX", "class_li_d_a_rcloud.html#ac48fe9018f26664dd9abd8c100fccaa6", null ], + [ "exportTriangleAreas", "class_li_d_a_rcloud.html#a416638f486c4fd2572a9589b69605fe7", null ], + [ "exportTriangleAreas", "class_li_d_a_rcloud.html#adb93e3a16abc8100b2e5dac956c6cc3e", null ], + [ "exportTriangleAzimuthDistribution", "class_li_d_a_rcloud.html#ab9a33b5d05470e8e0362de352fc09bf1", null ], + [ "exportTriangleInclinationDistribution", "class_li_d_a_rcloud.html#aadeb8297b74a75fd003f6c96fe378043", null ], + [ "exportTriangleNormals", "class_li_d_a_rcloud.html#ad030fdddcfa669d6af513eb66a9cbd1a", null ], + [ "exportTriangleNormals", "class_li_d_a_rcloud.html#aa8376ce652d2e95e886d4d60d321c274", null ], + [ "firstHitFilter", "class_li_d_a_rcloud.html#a869540860f4cace62dbd2fb54353bd33", null ], + [ "gapfillMisses", "class_li_d_a_rcloud.html#a53b80def6bff07231b8d2b10eb3e0330", null ], + [ "gapfillMisses", "class_li_d_a_rcloud.html#a544384a19e7d060c85eb5a8daa1aeef4", null ], + [ "gapfillMisses", "class_li_d_a_rcloud.html#aa70d9c9fb6ca8c20a818c2bc68d39077", null ], + [ "getCellCenter", "class_li_d_a_rcloud.html#a6e2ce01abb33cc0f80b2aa653ac6a445", null ], + [ "getCellGlobalAnchor", "class_li_d_a_rcloud.html#ad1ad4f851b5b7fcbf5b088b161aed83e", null ], + [ "getCellGtheta", "class_li_d_a_rcloud.html#a54351e18e3f4155e9d55eb02bd63c722", null ], + [ "getCellLeafArea", "class_li_d_a_rcloud.html#ac9d20a35bdb7ee2d45490ac1cd520117", null ], + [ "getCellLeafAreaDensity", "class_li_d_a_rcloud.html#a3c1744984481f9629dc1371291fa397e", null ], + [ "getCellRotation", "class_li_d_a_rcloud.html#aa2cba1d0bcd9a2ae35d9a5be03832efc", null ], + [ "getCellSize", "class_li_d_a_rcloud.html#a6662330b95ee7ee77ea6647871695c55", null ], + [ "getGridBoundingBox", "class_li_d_a_rcloud.html#a041ac4ba388c407a35b7f895029038e6", null ], + [ "getGridCellCount", "class_li_d_a_rcloud.html#a28297a71becd69b30820d69b110fcc90", null ], + [ "getHitBoundingBox", "class_li_d_a_rcloud.html#a45bc37a4d26eb74a944c594a7f3cb54b", null ], + [ "getHitColor", "class_li_d_a_rcloud.html#aafafed9102966992d3cfb3772fa2ada1", null ], + [ "getHitCount", "class_li_d_a_rcloud.html#a691fd3bbd1262d80e10a674c82c6f568", null ], + [ "getHitData", "class_li_d_a_rcloud.html#a274ef68850afa3f288bb648d9fd6a59a", null ], + [ "getHitGridCell", "class_li_d_a_rcloud.html#a251c4f3bbefdd07212cd8fe1037dc0d7", null ], + [ "getHitIndex", "class_li_d_a_rcloud.html#a34eee980f365fdd5469a0cc6ee3a36f5", null ], + [ "getHitRaydir", "class_li_d_a_rcloud.html#aa91258bd97d6fcacd3313d8b55cceed4", null ], + [ "getHitScanID", "class_li_d_a_rcloud.html#a5510b2a0d0a878930e9f11331494bf41", null ], + [ "getHitXYZ", "class_li_d_a_rcloud.html#ac5f234b6200419f10fe82c9abe409cbd", null ], + [ "getScanBeamDivergence", "class_li_d_a_rcloud.html#a9d93e6cd9decccf271fbf3fbd5c74a5a", null ], + [ "getScanBeamExitDiameter", "class_li_d_a_rcloud.html#abab6b81a3d96226a766cc2450993407f", null ], + [ "getScanColumnFormat", "class_li_d_a_rcloud.html#abbe892f01508dc69bcc5b28bea5472bf", null ], + [ "getScanCount", "class_li_d_a_rcloud.html#aaa463ea1aaebb03abd8c3ec87091291a", null ], + [ "getScanOrigin", "class_li_d_a_rcloud.html#aa657ed32a8831ebf4f2e4a9203b683ef", null ], + [ "getScanRangePhi", "class_li_d_a_rcloud.html#ab314aac88834eb3938fc2f37e34807e3", null ], + [ "getScanRangeTheta", "class_li_d_a_rcloud.html#a7f0237a83da6997e973fde9939440979", null ], + [ "getScanSizePhi", "class_li_d_a_rcloud.html#aaf04cd04c2b1bc162106a0e47cff6d29", null ], + [ "getScanSizeTheta", "class_li_d_a_rcloud.html#a40809c7a709a6c9ccb4beddca21f8ac9", null ], + [ "getTriangle", "class_li_d_a_rcloud.html#aa1a1af5eea22185e59c267c8e4d94c9e", null ], + [ "getTriangleCount", "class_li_d_a_rcloud.html#abcdbf834959379a189a60efed41f3e52", null ], + [ "lastHitFilter", "class_li_d_a_rcloud.html#ab812d48fd5d81a8cc382bf0d1214496d", null ], + [ "leafReconstructionAlphaMask", "class_li_d_a_rcloud.html#aba102c6c5036ffb99b105fb2b4850935", null ], + [ "leafReconstructionAlphaMask", "class_li_d_a_rcloud.html#a0c80f96188fb83f444e7e08cbf888690", null ], + [ "loadXML", "class_li_d_a_rcloud.html#a6bd7e1839d1a6ecb738233b20b93f1f7", null ], + [ "loadXML", "class_li_d_a_rcloud.html#ac966b0aae37889c288277b950b2fd30a", null ], + [ "maxPulseFilter", "class_li_d_a_rcloud.html#aa5c2bd82b67b3e84069090d75ed2973d", null ], + [ "minPulseFilter", "class_li_d_a_rcloud.html#a530582b532eb13ca938d5e843d902327", null ], + [ "peakFinder", "class_li_d_a_rcloud.html#acffd90677f0584b05b73183747be4e0c", null ], + [ "reflectanceFilter", "class_li_d_a_rcloud.html#adf2d9ef2301fd7fdee97e2adc0947dd3", null ], + [ "scalarFilter", "class_li_d_a_rcloud.html#aa2ea59f063b3c951a1e58af9e4ddfd7e", null ], + [ "selfTest", "class_li_d_a_rcloud.html#aaa2f35f02a65d4a7a731c4989dd9aa36", null ], + [ "setCellGtheta", "class_li_d_a_rcloud.html#a4c8d55452f2423ddf8b77effbf443075", null ], + [ "setCellLeafArea", "class_li_d_a_rcloud.html#a32643f365dda44670b5b132c4eee8442", null ], + [ "setHitData", "class_li_d_a_rcloud.html#a4ad8b12380a24f48ecfbae0ad6b5cfaa", null ], + [ "setHitGridCell", "class_li_d_a_rcloud.html#a122b1716c42af6a07d48ad23b5acb427", null ], + [ "syntheticScan", "class_li_d_a_rcloud.html#aac5cafa2281f9d479f2bb56be0780e31", null ], + [ "syntheticScan", "class_li_d_a_rcloud.html#a027d03054878ad27a705a839c36ba0cf", null ], + [ "syntheticScan", "class_li_d_a_rcloud.html#aca2bef5f45b9c7f65e04952ed1551f25", null ], + [ "syntheticScan", "class_li_d_a_rcloud.html#a0a4118588bb1a17e5d855a18ffbde299", null ], + [ "triangulateHitPoints", "class_li_d_a_rcloud.html#ac495385c9dc7cc7773819ce77175242a", null ], + [ "triangulateHitPoints", "class_li_d_a_rcloud.html#a2e2d9ac728f839b64cedb20582d77d48", null ], + [ "trunkReconstruction", "class_li_d_a_rcloud.html#aa7d6abb997267bce460c48cf02dc3545", null ], + [ "xyzFilter", "class_li_d_a_rcloud.html#ac17ca020e2f2fd4f1ce91ef5101353d0", null ], + [ "xyzFilter", "class_li_d_a_rcloud.html#a56ee72fba222c399c256adf577ae860d", null ] +]; \ No newline at end of file diff --git a/doc/html/class_photosynthesis_model.html b/doc/html/class_photosynthesis_model.html index fff77878e..6c2e7d954 100644 --- a/doc/html/class_photosynthesis_model.html +++ b/doc/html/class_photosynthesis_model.html @@ -38,7 +38,7 @@

@@ -46,7 +46,7 @@
[in]minimum_leaf_group_areaMinimum allowable area of leaf triangular fill groups. Leaf fill groups with total areas less than minimum_leaf_group_area are not considered in the reconstruction.
-
 v1.3.26 +
 v1.3.27
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/class_photosynthesis_model.js b/doc/html/class_photosynthesis_model.js new file mode 100644 index 000000000..9c5d06d03 --- /dev/null +++ b/doc/html/class_photosynthesis_model.js @@ -0,0 +1,23 @@ +var class_photosynthesis_model = +[ + [ "PhotosynthesisModel", "class_photosynthesis_model.html#a2cfdf33f994c6b6cb84432dcb7e57b3b", null ], + [ "disableMessages", "class_photosynthesis_model.html#a53e70a6e8e335d605154d565e283aec1", null ], + [ "enableMessages", "class_photosynthesis_model.html#ade42037f5602cd241150133f496fc1a9", null ], + [ "getEmpiricalModelCoefficients", "class_photosynthesis_model.html#a86094d579852c2dc846acc2a97e6ac44", null ], + [ "getFarquharCoefficientsFromLibrary", "class_photosynthesis_model.html#ae40570ef642d5d4dc070dce9ba093f16", null ], + [ "getFarquharModelCoefficients", "class_photosynthesis_model.html#aeab92cd73298c5f89626b30ce8c41cf9", null ], + [ "optionalOutputPrimitiveData", "class_photosynthesis_model.html#a9ec83db517f4c7d0eb09c20a9f61ef20", null ], + [ "printDefaultValueReport", "class_photosynthesis_model.html#ab4ed6afbb715d143cedf136ff355c1b3", null ], + [ "printDefaultValueReport", "class_photosynthesis_model.html#a5de185fd3e46ef009c362b116e3d7771", null ], + [ "run", "class_photosynthesis_model.html#abb06ce82388d1147e720c3591f9d17b6", null ], + [ "run", "class_photosynthesis_model.html#a837fd2c9c8a84c584e31c5cf3ce7de89", null ], + [ "setFarquharCoefficientsFromLibrary", "class_photosynthesis_model.html#a3e47f7c5fe8100cf93ba9454b911bba4", null ], + [ "setFarquharCoefficientsFromLibrary", "class_photosynthesis_model.html#afc73dbd1a744c6f4aae456349e040b27", null ], + [ "setModelCoefficients", "class_photosynthesis_model.html#a80a8bb51f617da1a7e2d03a67890bf1d", null ], + [ "setModelCoefficients", "class_photosynthesis_model.html#a5a17e8185dd7ad90b4d155bb4f610d85", null ], + [ "setModelCoefficients", "class_photosynthesis_model.html#a394870e63a056a12b7031bfadbf9ae6b", null ], + [ "setModelCoefficients", "class_photosynthesis_model.html#a37ee0175960589edf257726c2a3e0356", null ], + [ "setModelCoefficients", "class_photosynthesis_model.html#ab9ae18a68ca6b3f5639385a7c29076bf", null ], + [ "setModelType_Empirical", "class_photosynthesis_model.html#ae4f1ad6808c1b8ccc28912a4a7dd9363", null ], + [ "setModelType_Farquhar", "class_photosynthesis_model.html#a63e25c843c66fcca47e816a3978e989d", null ] +]; \ No newline at end of file diff --git a/doc/html/class_plant_architecture.html b/doc/html/class_plant_architecture.html index c4e20c297..9ac824d9a 100644 --- a/doc/html/class_plant_architecture.html +++ b/doc/html/class_plant_architecture.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Public Member Functions | @@ -160,6 +170,8 @@ void advanceTime (float time_step_days)  Advance plant growth by a specified time interval for all plants.
  +void accumulateHourlyLeafPhotosynthesis () +  void advanceTime (int time_step_years, float time_step_days)  Advance plant growth by a specified time interval for all plants.
  @@ -199,6 +211,8 @@ void enableGroundClipping (float ground_height=0.f)  Enable automatic removal of organs that are below the ground plane.
  +void initializeCarbohydratePool (float carbohydrate_concentration_molC_m3) +  void initializePlantCarbohydratePool (uint plantID, float carbohydrate_concentration_molC_m3)   void initializeShootCarbohydratePool (uint plantID, uint shootID, float carbohydrate_concentration_molC_m3) @@ -221,6 +235,10 @@   void breakPlantDormancy (uint plantID)   +void pruneBranch (uint plantID, uint shootID, uint node_index) +  +std::string getPlantName (uint plantID) const +  float getPlantAge (uint plantID) const   uint getShootNodeCount (uint plantID, uint shootID) const @@ -232,6 +250,24 @@ float sumPlantLeafArea (uint plantID) const  Sum the one-sided leaf area of all leaves in the plant.
  +float getPlantStemHeight (uint plantID) const + Calculate the height of the last internode on the base stem/shoot.
+  +float getPlantHeight (uint plantID) const + Calculate the height of the highest element in the plant.
+  +std::vector< float > getPlantLeafInclinationAngleDistribution (uint plantID, uint Nbins) const + Calculate the leaf angle distribution of all leaves in the plant.
+  +uint getPlantLeafCount (uint plantID) const + Get the total number of leaves on the plant.
+  +void writePlantMeshVertices (uint plantID, const std::string &filename) const + Write all vertices in the plant to a file for external processing (e.g., bounding volume, convex hull)
+  +std::vector< uint > getAllPlantIDs () const + Get IDs for all plant instances.
+  std::vector< uint > getAllPlantObjectIDs (uint plantID) const  Get object IDs for all organs objects for a given plant.
  @@ -280,6 +316,10 @@ std::vector< uint > getAllObjectIDs () const  Get object IDs for all existing plant compound objects.
  +void enableCarbohydrateModel () +  +void disableCarbohydrateModel () +  std::string getPlantString (uint plantID) const   uint generatePlantFromString (const std::string &generation_string, const PhytomerParameters &phytomer_parameters) @@ -306,7 +346,7 @@

Detailed Description

-

Definition at line 1099 of file PlantArchitecture.h.

+

Definition at line 1113 of file PlantArchitecture.h.

Constructor & Destructor Documentation

◆ PlantArchitecture()

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

-explicit +explicit

@@ -344,6 +384,25 @@

Member Function Documentation

+ +

◆ accumulateHourlyLeafPhotosynthesis()

+ +
+
+ + + + + + + +
void PlantArchitecture::accumulateHourlyLeafPhotosynthesis ()
+
+ +

Definition at line 141 of file CarbohydrateModel.cpp.

+ +
+

◆ addBaseStemShoot()

@@ -415,7 +474,7 @@

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

-

Definition at line 1905 of file PlantArchitecture.cpp.

+

Definition at line 1982 of file PlantArchitecture.cpp.

@@ -508,7 +567,7 @@

Returns
ID of the newly generated shoot.
-

Definition at line 1980 of file PlantArchitecture.cpp.

+

Definition at line 2057 of file PlantArchitecture.cpp.

@@ -595,7 +654,7 @@

Returns
ID of the newly generated shoot.
-

Definition at line 2023 of file PlantArchitecture.cpp.

+

Definition at line 2100 of file PlantArchitecture.cpp.

@@ -628,7 +687,7 @@

Returns
ID of the plant instance.
-

Definition at line 2613 of file PlantArchitecture.cpp.

+

Definition at line 2851 of file PlantArchitecture.cpp.

@@ -655,7 +714,7 @@

Definition at line 2721 of file PlantArchitecture.cpp.

+

Definition at line 2959 of file PlantArchitecture.cpp.

@@ -687,7 +746,7 @@

Definition at line 2729 of file PlantArchitecture.cpp.

+

Definition at line 2967 of file PlantArchitecture.cpp.

@@ -719,7 +778,7 @@

Definition at line 2737 of file PlantArchitecture.cpp.

+

Definition at line 2975 of file PlantArchitecture.cpp.

@@ -782,7 +841,7 @@

Returns
ID of generated phytomer
-

Definition at line 2059 of file PlantArchitecture.cpp.

+

Definition at line 2136 of file PlantArchitecture.cpp.

@@ -863,7 +922,7 @@

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

Definition at line 1936 of file PlantArchitecture.cpp.

+

Definition at line 2013 of file PlantArchitecture.cpp.

@@ -882,7 +941,7 @@

-

Definition at line 2327 of file PlantArchitecture.cpp.

+

Definition at line 2530 of file PlantArchitecture.cpp.

@@ -1025,7 +1084,7 @@

Definition at line 2686 of file PlantArchitecture.cpp.

+

Definition at line 2924 of file PlantArchitecture.cpp.

@@ -1052,7 +1111,26 @@

Definition at line 2676 of file PlantArchitecture.cpp.

+

Definition at line 2914 of file PlantArchitecture.cpp.

+ + + + +

◆ disableCarbohydrateModel()

+ +
+
+ + + + + + + +
void PlantArchitecture::disableCarbohydrateModel ()
+
+ +

Definition at line 2847 of file PlantArchitecture.cpp.

@@ -1073,7 +1151,7 @@

Definition at line 2138 of file PlantArchitecture.cpp.

+

Definition at line 2215 of file PlantArchitecture.cpp.

@@ -1094,7 +1172,7 @@

Definition at line 2146 of file PlantArchitecture.cpp.

+

Definition at line 2223 of file PlantArchitecture.cpp.

@@ -1115,7 +1193,7 @@

Definition at line 2142 of file PlantArchitecture.cpp.

+

Definition at line 2219 of file PlantArchitecture.cpp.

@@ -1134,7 +1212,7 @@

-

Definition at line 2712 of file PlantArchitecture.cpp.

+

Definition at line 2950 of file PlantArchitecture.cpp.

@@ -1178,7 +1256,26 @@

Returns
ID of the new plant instance.
-

Definition at line 2628 of file PlantArchitecture.cpp.

+

Definition at line 2866 of file PlantArchitecture.cpp.

+ + + + +

◆ enableCarbohydrateModel()

+ +
+
+ + + + + + + +
void PlantArchitecture::enableCarbohydrateModel ()
+
+ +

Definition at line 2843 of file PlantArchitecture.cpp.

@@ -1217,7 +1314,7 @@

Definition at line 2124 of file PlantArchitecture.cpp.

+

Definition at line 2201 of file PlantArchitecture.cpp.

@@ -1244,7 +1341,7 @@

Definition at line 2150 of file PlantArchitecture.cpp.

+

Definition at line 2227 of file PlantArchitecture.cpp.

@@ -1312,7 +1409,7 @@

Returns
Vector of UUIDs for all flower primitives.
-

Definition at line 2584 of file PlantArchitecture.cpp.

+

Definition at line 2814 of file PlantArchitecture.cpp.

@@ -1334,7 +1431,7 @@

Returns
Vector of UUIDs for all fruit primitives.
-

Definition at line 2594 of file PlantArchitecture.cpp.

+

Definition at line 2824 of file PlantArchitecture.cpp.

@@ -1356,7 +1453,7 @@

Returns
Vector of UUIDs for all internode primitives.
-

Definition at line 2554 of file PlantArchitecture.cpp.

+

Definition at line 2784 of file PlantArchitecture.cpp.

@@ -1378,7 +1475,7 @@

Returns
Vector of UUIDs for all leaf primitives.
-

Definition at line 2544 of file PlantArchitecture.cpp.

+

Definition at line 2774 of file PlantArchitecture.cpp.

@@ -1400,7 +1497,7 @@

Returns
Vector of object IDs for all plant compound objects.
-

Definition at line 2604 of file PlantArchitecture.cpp.

+

Definition at line 2834 of file PlantArchitecture.cpp.

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

Returns
Vector of UUIDs for all peduncle primitives.
-

Definition at line 2574 of file PlantArchitecture.cpp.

+

Definition at line 2804 of file PlantArchitecture.cpp.

@@ -1444,7 +1541,29 @@

Returns
Vector of UUIDs for all petiole primitives.
-

Definition at line 2564 of file PlantArchitecture.cpp.

+

Definition at line 2794 of file PlantArchitecture.cpp.

+ + + + +

◆ getAllPlantIDs()

+ +
+
+ + + + + + + +
std::vector< uint > PlantArchitecture::getAllPlantIDs () const
+
+ +

Get IDs for all plant instances.

+
Returns
Vector of plant IDs for all plant instances
+ +

Definition at line 2586 of file PlantArchitecture.cpp.

@@ -1472,7 +1591,7 @@

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

Definition at line 2368 of file PlantArchitecture.cpp.

+

Definition at line 2598 of file PlantArchitecture.cpp.

@@ -1500,7 +1619,7 @@

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

Definition at line 2399 of file PlantArchitecture.cpp.

+

Definition at line 2629 of file PlantArchitecture.cpp.

@@ -1522,7 +1641,7 @@

Returns
Vector of UUIDs for all plant primitives.
-

Definition at line 2535 of file PlantArchitecture.cpp.

+

Definition at line 2765 of file PlantArchitecture.cpp.

@@ -1544,7 +1663,7 @@

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

Definition at line 106 of file PlantLibrary.cpp.

+

Definition at line 110 of file PlantLibrary.cpp.

@@ -1566,7 +1685,7 @@

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

Definition at line 99 of file PlantLibrary.cpp.

+

Definition at line 103 of file PlantLibrary.cpp.

@@ -1594,7 +1713,7 @@

Returns
ShootParameters structure for the specified shoot type.
-

Definition at line 90 of file PlantLibrary.cpp.

+

Definition at line 94 of file PlantLibrary.cpp.

@@ -1613,7 +1732,7 @@

-

Definition at line 2259 of file PlantArchitecture.cpp.

+

Definition at line 2462 of file PlantArchitecture.cpp.

@@ -1632,7 +1751,7 @@

-

Definition at line 2229 of file PlantArchitecture.cpp.

+

Definition at line 2306 of file PlantArchitecture.cpp.

@@ -1660,7 +1779,7 @@

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

Definition at line 2485 of file PlantArchitecture.cpp.

+

Definition at line 2715 of file PlantArchitecture.cpp.

@@ -1688,7 +1807,35 @@

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

Definition at line 2510 of file PlantArchitecture.cpp.

+

Definition at line 2740 of file PlantArchitecture.cpp.

+ + + + +

◆ getPlantHeight()

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

Calculate the height of the highest element in the plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Height of the highest element in the plant.
+ +

Definition at line 2368 of file PlantArchitecture.cpp.

@@ -1716,7 +1863,68 @@

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

Definition at line 2403 of file PlantArchitecture.cpp.

+

Definition at line 2633 of file PlantArchitecture.cpp.

+ + + + +

◆ getPlantLeafCount()

+ +
+
+ + + + + + + +
uint PlantArchitecture::getPlantLeafCount (uint plantID) const
+
+ +

Get the total number of leaves on the plant.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Total number of leaves on the plant.
+ +

Definition at line 2414 of file PlantArchitecture.cpp.

+ +
+
+ +

◆ getPlantLeafInclinationAngleDistribution()

+ +
+
+ + + + + + + + + + + +
std::vector< float > PlantArchitecture::getPlantLeafInclinationAngleDistribution (uint plantID,
uint Nbins ) const
+
+ +

Calculate the leaf angle distribution of all leaves in the plant.

+
Parameters
+ + + +
[in]plantIDID of the plant instance.
[in]NbinsNumber of bins for the histogram.
+
+
+
Returns
Histogram of leaf inclination angles. Bins are evenly spaced between 0 and 90 degrees.
+ +

Definition at line 2382 of file PlantArchitecture.cpp.

@@ -1744,7 +1952,26 @@

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

Definition at line 2442 of file PlantArchitecture.cpp.

+

Definition at line 2672 of file PlantArchitecture.cpp.

+ + + + +

◆ getPlantName()

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

Definition at line 2455 of file PlantArchitecture.cpp.

@@ -1772,7 +1999,7 @@

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

Definition at line 2462 of file PlantArchitecture.cpp.

+

Definition at line 2692 of file PlantArchitecture.cpp.

@@ -1800,7 +2027,35 @@

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

Definition at line 2422 of file PlantArchitecture.cpp.

+

Definition at line 2652 of file PlantArchitecture.cpp.

+ + + + +

◆ getPlantStemHeight()

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

Calculate the height of the last internode on the base stem/shoot.

+
Parameters
+ + +
[in]plantIDID of the plant instance.
+
+
+
Returns
Height of the last internode on the base stem/shoot.
+ +

Definition at line 2331 of file PlantArchitecture.cpp.

@@ -1842,7 +2097,7 @@

-

Definition at line 2338 of file PlantArchitecture.cpp.

+

Definition at line 2556 of file PlantArchitecture.cpp.

@@ -1865,7 +2120,7 @@

-

Definition at line 2347 of file PlantArchitecture.cpp.

+

Definition at line 2565 of file PlantArchitecture.cpp.

@@ -1884,7 +2139,7 @@

-

Definition at line 2268 of file PlantArchitecture.cpp.

+

Definition at line 2471 of file PlantArchitecture.cpp.

@@ -1917,7 +2172,26 @@

-

Definition at line 2154 of file PlantArchitecture.cpp.

+

Definition at line 2231 of file PlantArchitecture.cpp.

+ + + + +

◆ initializeCarbohydratePool()

+ +
+
+ + + + + + + +
void PlantArchitecture::initializeCarbohydratePool (float carbohydrate_concentration_molC_m3)
+
+ +

Definition at line 92 of file CarbohydrateModel.cpp.

@@ -1940,7 +2214,7 @@

-

Definition at line 100 of file CarbohydrateModel.cpp.

+

Definition at line 108 of file CarbohydrateModel.cpp.

@@ -1968,7 +2242,7 @@

-

Definition at line 115 of file CarbohydrateModel.cpp.

+

Definition at line 123 of file CarbohydrateModel.cpp.

@@ -2014,7 +2288,7 @@

-

Definition at line 2315 of file PlantArchitecture.cpp.

+

Definition at line 2518 of file PlantArchitecture.cpp.

@@ -2041,7 +2315,7 @@

Definition at line 3139 of file PlantArchitecture.cpp.

+

Definition at line 3383 of file PlantArchitecture.cpp.

@@ -2068,7 +2342,35 @@

Definition at line 3147 of file PlantArchitecture.cpp.

+

Definition at line 3391 of file PlantArchitecture.cpp.

+ + + + +

◆ pruneBranch()

+ +
+
+ + + + + + + + + + + + + + + + +
void PlantArchitecture::pruneBranch (uint plantID,
uint shootID,
uint node_index )
+
+ +

Definition at line 2540 of file PlantArchitecture.cpp.

@@ -2110,7 +2412,7 @@

-

Definition at line 2303 of file PlantArchitecture.cpp.

+

Definition at line 2506 of file PlantArchitecture.cpp.

@@ -2133,7 +2435,7 @@

-

Definition at line 2287 of file PlantArchitecture.cpp.

+

Definition at line 2490 of file PlantArchitecture.cpp.

@@ -2155,7 +2457,7 @@

-static +static @@ -2218,7 +2520,7 @@

-

Definition at line 2254 of file PlantArchitecture.cpp.

+

Definition at line 2450 of file PlantArchitecture.cpp.

@@ -2241,7 +2543,7 @@

-

Definition at line 2215 of file PlantArchitecture.cpp.

+

Definition at line 2292 of file PlantArchitecture.cpp.

@@ -2316,7 +2618,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 2692 of file PlantArchitecture.cpp.

+

Definition at line 2930 of file PlantArchitecture.cpp.

@@ -2344,7 +2646,7 @@

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

Definition at line 2238 of file PlantArchitecture.cpp.

+

Definition at line 2315 of file PlantArchitecture.cpp.

@@ -2373,7 +2675,7 @@

Note
This will overwrite any existing shoot parameter definitions.
-

Definition at line 121 of file PlantLibrary.cpp.

+

Definition at line 125 of file PlantLibrary.cpp.

@@ -2406,7 +2708,39 @@

Note
This will overwrite any existing shoot parameter definitions.
-

Definition at line 117 of file PlantLibrary.cpp.

+

Definition at line 121 of file PlantLibrary.cpp.

+ + + + +

◆ writePlantMeshVertices()

+ +
+
+ + + + + + + + + + + +
void PlantArchitecture::writePlantMeshVertices (uint plantID,
const std::string & filename ) const
+
+ +

Write all vertices in the plant to a file for external processing (e.g., bounding volume, convex hull)

+
Parameters
+ + + +
[in]plantIDID of the plant instance.
[in]filenameName/path of the output file.
+
+
+ +

Definition at line 2424 of file PlantArchitecture.cpp.

@@ -2449,12 +2783,12 @@

-friend +friend @@ -2473,12 +2807,12 @@

-friend +friend @@ -2491,10 +2825,13 @@

selfTest.cpp - - + + diff --git a/doc/html/class_plant_architecture.js b/doc/html/class_plant_architecture.js new file mode 100644 index 000000000..46df51998 --- /dev/null +++ b/doc/html/class_plant_architecture.js @@ -0,0 +1,56 @@ +var class_plant_architecture = +[ + [ "PlantArchitecture", "class_plant_architecture.html#ab55c86604c49abcedde90adb395074e9", null ], + [ "addBaseStemShoot", "class_plant_architecture.html#a32e88ebd4d0bb468f6c0a2655833bff6", null ], + [ "addChildShoot", "class_plant_architecture.html#a0832e7e5e15d64c3ee52ea3d640dee27", null ], + [ "addEpicormicShoot", "class_plant_architecture.html#ade786dc8bb429eb033d29ccf9df6b254", null ], + [ "addPlantInstance", "class_plant_architecture.html#a046541b573d8e03845a2038370cd6665", null ], + [ "advanceTime", "class_plant_architecture.html#a1df979fc7a8523961ae37d934be5bfa7", null ], + [ "advanceTime", "class_plant_architecture.html#a30eb9cf338188dd725852d63919a9aa4", null ], + [ "advanceTime", "class_plant_architecture.html#a48c8a01f66fb38357bddc9eac35173e4", null ], + [ "appendPhytomerToShoot", "class_plant_architecture.html#a122fad48603e2e0f2fe6d870c691bfd1", null ], + [ "appendShoot", "class_plant_architecture.html#a25a69b3eee4eab6501a8bedc777b8c55", null ], + [ "buildPlantCanopyFromLibrary", "class_plant_architecture.html#a9cc3b3b4f6e37fa416c139f6bf1618bd", null ], + [ "buildPlantInstanceFromLibrary", "class_plant_architecture.html#ab98a62363a5e4553c5052a23e39711ba", null ], + [ "defineShootType", "class_plant_architecture.html#a9700f223b8f60bf37852ad87d30e7fc0", null ], + [ "deletePlantInstance", "class_plant_architecture.html#afda177f49619fda164fd0ad6cfe512e9", null ], + [ "deletePlantInstance", "class_plant_architecture.html#a892ccc80c958b43d7528fa07006117e7", null ], + [ "disableInternodeContextBuild", "class_plant_architecture.html#af66af0968daf0fef4135b4434c61dc60", null ], + [ "disablePeduncleContextBuild", "class_plant_architecture.html#a71918ef58e5257e4a8a338dba4f9b328", null ], + [ "disablePetioleContextBuild", "class_plant_architecture.html#ab4ae495e7aebc365826f2a2f02a24338", null ], + [ "duplicatePlantInstance", "class_plant_architecture.html#acd6de0d13dbc534992b94a203a16b76d", null ], + [ "enableEpicormicChildShoots", "class_plant_architecture.html#a8fc29c4a5b44430a34fc780180a01e8b", null ], + [ "enableGroundClipping", "class_plant_architecture.html#a27dd2c46b6bb9f5c922d18acb6d9ba69", null ], + [ "getAllFlowerUUIDs", "class_plant_architecture.html#a056eb82b161cc72288da7844d35f44f5", null ], + [ "getAllFruitUUIDs", "class_plant_architecture.html#aa4da1e4c28959b7f5540aa5ff160b2d1", null ], + [ "getAllInternodeUUIDs", "class_plant_architecture.html#a70553116dc967d84f17063dd9d734db9", null ], + [ "getAllLeafUUIDs", "class_plant_architecture.html#a5431bd0712f4def9fd27cad03065d755", null ], + [ "getAllObjectIDs", "class_plant_architecture.html#a9069b1d637752f0a74ded148ae1706b0", null ], + [ "getAllPeduncleUUIDs", "class_plant_architecture.html#ad46693fc275721338c8f24cb764b2bf1", null ], + [ "getAllPetioleUUIDs", "class_plant_architecture.html#afd1c00e6b5b6aa45e212aeb6b68cb825", null ], + [ "getAllPlantIDs", "class_plant_architecture.html#a73c43e42cc78a343279633842ea0aa07", null ], + [ "getAllPlantObjectIDs", "class_plant_architecture.html#acf9855048c790d30d8d4de7fa1dc3550", null ], + [ "getAllPlantUUIDs", "class_plant_architecture.html#a3bdffb4e53fe0da836a40de80946d31f", null ], + [ "getAllUUIDs", "class_plant_architecture.html#afec06c56ae296984727c90413511cf6a", null ], + [ "getCurrentPhytomerParameters", "class_plant_architecture.html#aaba5ecb6c069be56b3706a4060f5ff49", null ], + [ "getCurrentShootParameters", "class_plant_architecture.html#a190d91f02c5cfcfad036879460b2e495", null ], + [ "getCurrentShootParameters", "class_plant_architecture.html#aa696281e805e8879a78dacdf4354ff38", null ], + [ "getPlantFlowerObjectIDs", "class_plant_architecture.html#a1cb3e4ba93c7a94558c3c07496e550c2", null ], + [ "getPlantFruitObjectIDs", "class_plant_architecture.html#aac602c603ac136c3aaffad052bd844d4", null ], + [ "getPlantHeight", "class_plant_architecture.html#a4d6e2ec9e60b12bc56e2ee753ba9f9cf", null ], + [ "getPlantInternodeObjectIDs", "class_plant_architecture.html#a53967340a1c9b88f4b804522f081ce62", null ], + [ "getPlantLeafCount", "class_plant_architecture.html#a74032e7973d410bf861e0c3448bee3ce", null ], + [ "getPlantLeafInclinationAngleDistribution", "class_plant_architecture.html#a512ba39f59b0ebc35d8f699c136a00fe", null ], + [ "getPlantLeafObjectIDs", "class_plant_architecture.html#afcdea7f14c6ca722d39d94ff19ba87b4", null ], + [ "getPlantPeduncleObjectIDs", "class_plant_architecture.html#af8a9f26212baf6695d71d44b982e6adf", null ], + [ "getPlantPetioleObjectIDs", "class_plant_architecture.html#aee2486b87dca29982dd1b380aa3510fb", null ], + [ "getPlantStemHeight", "class_plant_architecture.html#a7f34d9100299ca2d0d44984e9403915a", null ], + [ "loadPlantModelFromLibrary", "class_plant_architecture.html#adc41de628e65a52f560b4d0685c64c3a", null ], + [ "optionalOutputObjectData", "class_plant_architecture.html#acc53c4a5dd259f25b2b4a26907f8b749", null ], + [ "optionalOutputObjectData", "class_plant_architecture.html#a435b4a07a5ce3ed4e0de58b286c5b883", null ], + [ "setPlantPhenologicalThresholds", "class_plant_architecture.html#a041d11df76990a5b0beb694955788301", null ], + [ "sumPlantLeafArea", "class_plant_architecture.html#ae8be24e5a963c49e7ab9ce5641fddec6", null ], + [ "updateCurrentShootParameters", "class_plant_architecture.html#a4539115c4ba145fa10277d3dcfa63685", null ], + [ "updateCurrentShootParameters", "class_plant_architecture.html#a2074dfe285a623833dd07b4aa0b93a7c", null ], + [ "writePlantMeshVertices", "class_plant_architecture.html#a1314accedeb4c376ee8283aa05c811c5", null ] +]; \ No newline at end of file diff --git a/doc/html/class_radiation_model.html b/doc/html/class_radiation_model.html index 83e9fd772..b2ce26e66 100644 --- a/doc/html/class_radiation_model.html +++ b/doc/html/class_radiation_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- @@ -701,7 +711,7 @@

Definition at line 1203 of file RadiationModel.cpp.

+

Definition at line 1205 of file RadiationModel.cpp.

@@ -1013,7 +1023,7 @@

Returns
Projected area fraction G(theta)
-

Definition at line 4839 of file RadiationModel.cpp.

+

Definition at line 4860 of file RadiationModel.cpp.

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

Definition at line 5652 of file RadiationModel.cpp.

+

Definition at line 5677 of file RadiationModel.cpp.

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

Definition at line 5691 of file RadiationModel.cpp.

+

Definition at line 5716 of file RadiationModel.cpp.

@@ -1482,7 +1492,7 @@

Returns
Vector of strings corresponding to each camera label.
-

Definition at line 1305 of file RadiationModel.cpp.

+

Definition at line 1307 of file RadiationModel.cpp.

@@ -1510,7 +1520,7 @@

Returns
Cartesian coordinate of location camera is pointed toward.
-

Definition at line 1259 of file RadiationModel.cpp.

+

Definition at line 1261 of file RadiationModel.cpp.

@@ -1538,7 +1548,7 @@

Returns
Spherical coordinate defining the orientation of the camera.
-

Definition at line 1282 of file RadiationModel.cpp.

+

Definition at line 1284 of file RadiationModel.cpp.

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

Returns
Cartesian coordinate of camera position.
-

Definition at line 1236 of file RadiationModel.cpp.

+

Definition at line 1238 of file RadiationModel.cpp.

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

Returns
scale factor
-

Definition at line 5070 of file RadiationModel.cpp.

+

Definition at line 5091 of file RadiationModel.cpp.

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

Definition at line 3728 of file RadiationModel.cpp.

+

Definition at line 3749 of file RadiationModel.cpp.

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

Definition at line 3740 of file RadiationModel.cpp.

+

Definition at line 3761 of file RadiationModel.cpp.

@@ -2032,7 +2042,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 3117 of file RadiationModel.cpp.

+

Definition at line 3119 of file RadiationModel.cpp.

@@ -2060,7 +2070,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 3122 of file RadiationModel.cpp.

+

Definition at line 3124 of file RadiationModel.cpp.

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

Definition at line 4985 of file RadiationModel.cpp.

+

Definition at line 5006 of file RadiationModel.cpp.

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

Definition at line 5026 of file RadiationModel.cpp.

+

Definition at line 5047 of file RadiationModel.cpp.

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

-

Definition at line 4863 of file RadiationModel.cpp.

+

Definition at line 4884 of file RadiationModel.cpp.

@@ -2383,7 +2393,7 @@

Definition at line 1246 of file RadiationModel.cpp.

+

Definition at line 1248 of file RadiationModel.cpp.

@@ -2415,7 +2425,7 @@

Definition at line 1292 of file RadiationModel.cpp.

+

Definition at line 1294 of file RadiationModel.cpp.

@@ -2447,7 +2457,7 @@

Definition at line 1269 of file RadiationModel.cpp.

+

Definition at line 1271 of file RadiationModel.cpp.

@@ -2479,7 +2489,7 @@

Definition at line 1221 of file RadiationModel.cpp.

+

Definition at line 1223 of file RadiationModel.cpp.

@@ -2518,7 +2528,7 @@

Note
If global data in the standard camera spectral library is referenced, the library will be automatically loaded.
-

Definition at line 1210 of file RadiationModel.cpp.

+

Definition at line 1212 of file RadiationModel.cpp.

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

Definition at line 5630 of file RadiationModel.cpp.

+

Definition at line 5655 of file RadiationModel.cpp.

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

Definition at line 4868 of file RadiationModel.cpp.

+

Definition at line 4889 of file RadiationModel.cpp.

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

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

Definition at line 1985 of file RadiationModel.cpp.

+

Definition at line 1989 of file RadiationModel.cpp.

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

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

Definition at line 1989 of file RadiationModel.cpp.

+

Definition at line 1993 of file RadiationModel.cpp.

@@ -3498,7 +3508,7 @@

Definition at line 1315 of file RadiationModel.cpp.

+

Definition at line 1317 of file RadiationModel.cpp.

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

Definition at line 1435 of file RadiationModel.cpp.

+

Definition at line 1437 of file RadiationModel.cpp.

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

Definition at line 5276 of file RadiationModel.cpp.

+

Definition at line 5301 of file RadiationModel.cpp.

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

Definition at line 5403 of file RadiationModel.cpp.

+

Definition at line 5428 of file RadiationModel.cpp.

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

Definition at line 5512 of file RadiationModel.cpp.

+

Definition at line 5537 of file RadiationModel.cpp.

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

Definition at line 1401 of file RadiationModel.cpp.

+

Definition at line 1403 of file RadiationModel.cpp.

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

Definition at line 5332 of file RadiationModel.cpp.

+

Definition at line 5357 of file RadiationModel.cpp.

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

Definition at line 5184 of file RadiationModel.cpp.

+

Definition at line 5205 of file RadiationModel.cpp.

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

Definition at line 5093 of file RadiationModel.cpp.

+

Definition at line 5114 of file RadiationModel.cpp.

@@ -3936,10 +3946,13 @@

selfTest.cpp - - + + diff --git a/doc/html/class_radiation_model.js b/doc/html/class_radiation_model.js new file mode 100644 index 000000000..01321b5ee --- /dev/null +++ b/doc/html/class_radiation_model.js @@ -0,0 +1,102 @@ +var class_radiation_model = +[ + [ "RadiationModel", "class_radiation_model.html#acfcbd32e59e2b2728dabde1c7fa74329", null ], + [ "~RadiationModel", "class_radiation_model.html#aeae03b4de9b9c57ac987407fdfd6afa4", null ], + [ "addCollimatedRadiationSource", "class_radiation_model.html#adea522844d6fe85df2f1dc3b78f514eb", null ], + [ "addCollimatedRadiationSource", "class_radiation_model.html#aaa7660215edce07be51d4dae3cf4ffb1", null ], + [ "addCollimatedRadiationSource", "class_radiation_model.html#a768434aa4802835d706a07e29f8500fd", null ], + [ "addDiskRadiationSource", "class_radiation_model.html#a8ef94c0bf6286d3e64d7d8c8b96f33bc", null ], + [ "addRadiationBand", "class_radiation_model.html#ad0a4554dfa67054804de534229805054", null ], + [ "addRadiationBand", "class_radiation_model.html#a066dd10dcf1ebd8902b197bb6812b5e1", null ], + [ "addRadiationCamera", "class_radiation_model.html#ab4509110acf603466cbed2ad05fcc1a3", null ], + [ "addRadiationCamera", "class_radiation_model.html#aedf80552eaf2bf6a8544dcb2c72cb331", null ], + [ "addRectangleRadiationSource", "class_radiation_model.html#abb39d616c6b37bd56b2ea3014a19c6bf", null ], + [ "addSphereRadiationSource", "class_radiation_model.html#a44fbd20dd6ee50666f8d693dbba89822", null ], + [ "addSunSphereRadiationSource", "class_radiation_model.html#a8edb972e53fecddc21f0c23d08e355d0", null ], + [ "addSunSphereRadiationSource", "class_radiation_model.html#ab6220aa1f1e5ad425df93c9abdef3d07", null ], + [ "addSunSphereRadiationSource", "class_radiation_model.html#a5ffce4db04c85848d55c895f9aedc5f5", null ], + [ "blendSpectra", "class_radiation_model.html#a43a328dde4dd5f1a431afe9dc5e8664e", null ], + [ "blendSpectraRandomly", "class_radiation_model.html#a3f52651f2144aaca702824028964a076", null ], + [ "calculateGtheta", "class_radiation_model.html#a12d9870f22e5f3719baa7fde8e07fb0a", null ], + [ "calibrateCamera", "class_radiation_model.html#ab04cda35cd54937070cb63344630ada8", null ], + [ "calibrateCamera", "class_radiation_model.html#a1da3d8b0b1654693cb1261e909612997", null ], + [ "copyRadiationBand", "class_radiation_model.html#a516dafe4d898ad38af6f5bc23bdfb4d8", null ], + [ "copyRadiationBand", "class_radiation_model.html#ab0e729819054765ad2c40d30fd56c7a6", null ], + [ "deleteRadiationSource", "class_radiation_model.html#a1078def47ddf309e01c908a775c1ecd4", null ], + [ "disableCameraModelVisualization", "class_radiation_model.html#a697a43f3706fe60094dab0e525b370f8", null ], + [ "disableEmission", "class_radiation_model.html#a764f6cfd8e79569cc7a110fccd36857b", null ], + [ "disableLightModelVisualization", "class_radiation_model.html#abe728e1b9804571c0125ad92659d6a9e", null ], + [ "disableMessages", "class_radiation_model.html#a173a9cb77b4dfda7a008267d6331b7b7", null ], + [ "doesBandExist", "class_radiation_model.html#a966780925811e3a710a6d91f4ac852fb", null ], + [ "enableCameraModelVisualization", "class_radiation_model.html#ad4236469b34bcb4b216a78c96872b760", null ], + [ "enableEmission", "class_radiation_model.html#a7ac4bd9e9cf3ff4252818d984b782e79", null ], + [ "enableLightModelVisualization", "class_radiation_model.html#a5a4c7643cb05be9f7f893d65dee33dc2", null ], + [ "enableMessages", "class_radiation_model.html#abd5d02245b9dbd9401e2a7a65b37c95c", null ], + [ "enforcePeriodicBoundary", "class_radiation_model.html#a46c60b11342d10feed8f3a431df415bd", null ], + [ "getAllCameraLabels", "class_radiation_model.html#a4719caf3bacb35b9d58dc853b56d6a0b", null ], + [ "getCameraLookat", "class_radiation_model.html#a68c8736e58c7daf440ff9c93bb00522d", null ], + [ "getCameraOrientation", "class_radiation_model.html#a0b67b056aa1f2b5e6c42a06e358f4eb8", null ], + [ "getCameraPosition", "class_radiation_model.html#a6785deae272a9464920030fc3f124bc3", null ], + [ "getCameraResponseScale", "class_radiation_model.html#adb5a74547d51a18018d3daeba0ec5f3c", null ], + [ "getDiffuseFlux", "class_radiation_model.html#af8450f2308aee38272b4aef87f0c547b", null ], + [ "getSkyEnergy", "class_radiation_model.html#a9c9a5f6cb6b0ba6e3780aba8a4da8a0d", null ], + [ "getSourceFlux", "class_radiation_model.html#a9d4ea3e08514b90e617695ab2ee2fbf8", null ], + [ "getSourcePosition", "class_radiation_model.html#ab8ec35514a0e4b53ce8a64d3f390427c", null ], + [ "getTotalAbsorbedFlux", "class_radiation_model.html#a5e95e775550a2000798a97b00857bdd2", null ], + [ "integrateSourceSpectrum", "class_radiation_model.html#afadd1370bef086ee0e69c3d0469c5941", null ], + [ "integrateSpectrum", "class_radiation_model.html#ab6be78d097793b7738daeb95f5cd3fda", null ], + [ "integrateSpectrum", "class_radiation_model.html#ab688ee5e6d5997711ca4ae24151148d7", null ], + [ "integrateSpectrum", "class_radiation_model.html#a47c0fce1e3ee937cd53f7380b6002c69", null ], + [ "integrateSpectrum", "class_radiation_model.html#a98d3a2322d58841f001c5dfccbf03391", null ], + [ "integrateSpectrum", "class_radiation_model.html#a355137712ebe1c4025db448d7b5e58fb", null ], + [ "optionalOutputPrimitiveData", "class_radiation_model.html#ac42245154cfb4f125cfe1ef4671ca19f", null ], + [ "runBand", "class_radiation_model.html#a7d803f2b67bc4d0d89b2dc98a58d9ff1", null ], + [ "runBand", "class_radiation_model.html#a19c42659077eb909a6dc7fa137459b69", null ], + [ "runRadiationImaging", "class_radiation_model.html#a728c89b679cfcb957567b43e52023baf", null ], + [ "runRadiationImaging", "class_radiation_model.html#a63f23da646aac79163c8154ef3a6e93e", null ], + [ "scaleSpectrum", "class_radiation_model.html#a32496f56edc4837c7cc2b28d154a108f", null ], + [ "scaleSpectrum", "class_radiation_model.html#abfd1f6bc9d59a09ff3baab866c0b124c", null ], + [ "scaleSpectrumRandomly", "class_radiation_model.html#ac292f5d218647fc7cbb0a58bc3d284ae", null ], + [ "selfTest", "class_radiation_model.html#a4c9038e22b7457bc0eae2ef0ffed25ad", null ], + [ "setCameraLookat", "class_radiation_model.html#a8560b5c278ae279e0a2bf78ec33409bf", null ], + [ "setCameraOrientation", "class_radiation_model.html#aa8e73030b94c82fc52635affca88ebf9", null ], + [ "setCameraOrientation", "class_radiation_model.html#a2fb90fb962f16b13e4afc020ecb74b31", null ], + [ "setCameraPosition", "class_radiation_model.html#a9ec01ae743b29b5a0e9da04b24a7b230", null ], + [ "setCameraSpectralResponse", "class_radiation_model.html#a1ea2acedb464217f1acc38f0e05d353f", null ], + [ "setDiffuseRadiationExtinctionCoeff", "class_radiation_model.html#a11255a6b9afa49a30b164d0eb9640767", null ], + [ "setDiffuseRadiationExtinctionCoeff", "class_radiation_model.html#ac85aa79af6c1b3b50081216c6c257225", null ], + [ "setDiffuseRadiationFlux", "class_radiation_model.html#aa976502e7f722222399fbfe4f25dbe05", null ], + [ "setDiffuseRayCount", "class_radiation_model.html#ab279259e3c925d3213d8bf097156fd02", null ], + [ "setDiffuseSpectrum", "class_radiation_model.html#a1b1ae98cd2ba54fb8d1da8d434014e3d", null ], + [ "setDiffuseSpectrum", "class_radiation_model.html#af698122e4c9cb2855cca5e54037c985d", null ], + [ "setDiffuseSpectrumIntegral", "class_radiation_model.html#a5469495a0aee0e2d9f29100fa5d8683e", null ], + [ "setDiffuseSpectrumIntegral", "class_radiation_model.html#a278b621362ef2fdb528f0669a6cd0224", null ], + [ "setDiffuseSpectrumIntegral", "class_radiation_model.html#a6b733f931af8bed3bf13452d971d5c29", null ], + [ "setDiffuseSpectrumIntegral", "class_radiation_model.html#afa3b8ade09099752b11e5249b975a6c6", null ], + [ "setDirectRayCount", "class_radiation_model.html#a48c6ea6e90806e3c4942348996c29391", null ], + [ "setMinScatterEnergy", "class_radiation_model.html#a68adae041b6d017cc640ff90a2648f02", null ], + [ "setPadValue", "class_radiation_model.html#a73fac0b01c685471de95cd7bdfb5ef7b", null ], + [ "setScatteringDepth", "class_radiation_model.html#a6d2c7374b0de7f50b1857b95c606182f", null ], + [ "setSourceFlux", "class_radiation_model.html#a85a5126035acb66aeea93886255dca47", null ], + [ "setSourceFlux", "class_radiation_model.html#a2fa24d994612857ddc889e705b0444b1", null ], + [ "setSourcePosition", "class_radiation_model.html#a9ccfc277d9f9f38c29b7cb4cbb8e98f1", null ], + [ "setSourcePosition", "class_radiation_model.html#aa25715f947c98e00efebb1cc96af7071", null ], + [ "setSourceSpectrum", "class_radiation_model.html#a04c39684e5ac12c403f6dc68cec06877", null ], + [ "setSourceSpectrum", "class_radiation_model.html#a88b8a77a11c6aa1caf6ef931c39710c2", null ], + [ "setSourceSpectrum", "class_radiation_model.html#ab99467c6cee84a59d6b4df6b34f0fba7", null ], + [ "setSourceSpectrum", "class_radiation_model.html#a790ce56ed07f2f40b80be9676fa02c05", null ], + [ "setSourceSpectrumIntegral", "class_radiation_model.html#a0d07935957cc6651d38a621513581189", null ], + [ "setSourceSpectrumIntegral", "class_radiation_model.html#af39f938b1c2bde9af59d0d96311c8d9a", null ], + [ "updateCameraResponse", "class_radiation_model.html#afabb4e1a6c8c67ccc9c68aab7dfd07e3", null ], + [ "updateGeometry", "class_radiation_model.html#acf5fe304146a9270bf0e841f59e51934", null ], + [ "updateGeometry", "class_radiation_model.html#a28ab342e5959369755037fa5ec039e70", null ], + [ "writeCameraImage", "class_radiation_model.html#aa30ec7ec3b6c3b109e9a9544b890e8de", null ], + [ "writeCameraImageData", "class_radiation_model.html#a546c959be8d158f17ab1cb9ada0ebe6d", null ], + [ "writeDepthImageData", "class_radiation_model.html#ad495efb7a88df316cc8117e1d181d104", null ], + [ "writeImageBoundingBoxes", "class_radiation_model.html#a59db63fb5cf7d82ab641f636378923fd", null ], + [ "writeImageBoundingBoxes_ObjectData", "class_radiation_model.html#ac78340f2c7f5cf9089e26d15ea5dc41b", null ], + [ "writeNormCameraImage", "class_radiation_model.html#a61abdff90fd75f3ebebc6b8f189cdac9", null ], + [ "writeNormDepthImage", "class_radiation_model.html#a633d84a823ad4cd99495a06afc13d7a3", null ], + [ "writeObjectDataLabelMap", "class_radiation_model.html#afdbe940b3c4ae5855a0fcbe5b0b7f708", null ], + [ "writePrimitiveDataLabelMap", "class_radiation_model.html#a771c53fe19d75303c3f60017db8a2b50", null ] +]; \ No newline at end of file diff --git a/doc/html/class_solar_position.html b/doc/html/class_solar_position.html index 15a1f19c4..f6a321858 100644 --- a/doc/html/class_solar_position.html +++ b/doc/html/class_solar_position.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/class_solar_position.js b/doc/html/class_solar_position.js new file mode 100644 index 000000000..d65d690b6 --- /dev/null +++ b/doc/html/class_solar_position.js @@ -0,0 +1,22 @@ +var class_solar_position = +[ + [ "SolarPosition", "class_solar_position.html#a25fa8345e4101fa2d63757ca1bc9fe10", null ], + [ "SolarPosition", "class_solar_position.html#aad8b52cdec7e725441001f99dce4316f", null ], + [ "calibrateTurbidityFromTimeseries", "class_solar_position.html#aeefa73ede0d1797f94fd4ca2739f7f3e", null ], + [ "disableCloudCalibration", "class_solar_position.html#a282ed51f351684b847255212dcd53869", null ], + [ "enableCloudCalibration", "class_solar_position.html#abee2003c22cbbffb671e8e6a9305b66f", null ], + [ "getAmbientLongwaveFlux", "class_solar_position.html#a30ee555eedece8b7e19855877a74da71", null ], + [ "getDiffuseFraction", "class_solar_position.html#af8dbd15453ce775dab5b2c5a49b1c93b", null ], + [ "getSolarFlux", "class_solar_position.html#a9701cb29a0336a11c445d285405b6956", null ], + [ "getSolarFluxNIR", "class_solar_position.html#a611461f700df9efa7c56b6f4ee7712b7", null ], + [ "getSolarFluxPAR", "class_solar_position.html#a5c6635160944b5b8202ea9965da6de9d", null ], + [ "getSunAzimuth", "class_solar_position.html#a2b736578f75ecb8532556931b8263dc4", null ], + [ "getSunDirectionSpherical", "class_solar_position.html#adad5310db742ef9f2754e75095aeea92", null ], + [ "getSunDirectionVector", "class_solar_position.html#af889756d5b3d7d3c366887fae1fb86ab", null ], + [ "getSunElevation", "class_solar_position.html#a307e963d840abb9ee7867579fec69fa2", null ], + [ "getSunriseTime", "class_solar_position.html#a2d15fe2ca0d29adf33971916b1d8cd83", null ], + [ "getSunsetTime", "class_solar_position.html#a4c58aa642b4fc2300d1c1447388bc0d8", null ], + [ "getSunZenith", "class_solar_position.html#a4c4ba4931d13c6cc2ad69e8eab90ac14", null ], + [ "selfTest", "class_solar_position.html#aced032bb94f6fcff47e66747f7547396", null ], + [ "setSunDirection", "class_solar_position.html#af52dad396956d1699fb08ceed6f9a29e", null ] +]; \ No newline at end of file diff --git a/doc/html/class_stomatal_conductance_model.html b/doc/html/class_stomatal_conductance_model.html index 3696d1a17..81a9d6418 100644 --- a/doc/html/class_stomatal_conductance_model.html +++ b/doc/html/class_stomatal_conductance_model.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/class_stomatal_conductance_model.js b/doc/html/class_stomatal_conductance_model.js new file mode 100644 index 000000000..5fb09c4ff --- /dev/null +++ b/doc/html/class_stomatal_conductance_model.js @@ -0,0 +1,30 @@ +var class_stomatal_conductance_model = +[ + [ "StomatalConductanceModel", "class_stomatal_conductance_model.html#a8d0993a2649b696c37c2f24799b1b545", null ], + [ "disableMessages", "class_stomatal_conductance_model.html#a1ec3059345b100a8d9df83b36e1c821d", null ], + [ "enableMessages", "class_stomatal_conductance_model.html#a8cb0e8867b0c74c2777fd6c5f0b0b200", null ], + [ "getBMFCoefficientsFromLibrary", "class_stomatal_conductance_model.html#ada09940a1cc67dbfc0192f6e0a50c967", null ], + [ "optionalOutputPrimitiveData", "class_stomatal_conductance_model.html#a9618e00c9b4649c289debff2a4a1cfd4", null ], + [ "printDefaultValueReport", "class_stomatal_conductance_model.html#a66e680118d189c0ed79ca45636262a35", null ], + [ "printDefaultValueReport", "class_stomatal_conductance_model.html#a28c60dbd86a0aa2c3b8a90704205abde", null ], + [ "run", "class_stomatal_conductance_model.html#acb041e756e00d5ced85b03905a97f5c6", null ], + [ "run", "class_stomatal_conductance_model.html#ae08af8bff0c6924133948c7459baf91f", null ], + [ "run", "class_stomatal_conductance_model.html#ab3cf7261085bc4f5292a5340285a75ec", null ], + [ "run", "class_stomatal_conductance_model.html#ab83b66067cdd933ec48ee1c75cbfe1b7", null ], + [ "selfTest", "class_stomatal_conductance_model.html#aa32dad6bf0ee3ecb37b02957ebea0e3d", null ], + [ "setBMFCoefficientsFromLibrary", "class_stomatal_conductance_model.html#a67b1af836d98f934a9e4ba1390523413", null ], + [ "setBMFCoefficientsFromLibrary", "class_stomatal_conductance_model.html#abca589232617a8543feff66ca10d5d79", null ], + [ "setDynamicTimeConstants", "class_stomatal_conductance_model.html#a045fd837e2328617901dfd4e15f1da29", null ], + [ "setDynamicTimeConstants", "class_stomatal_conductance_model.html#a317e6d8d262ddffb5e66839ee987a067", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a07294b1dfa951bcdf2fb1608959607c4", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a29e691b7d3fa4348b8a5ef859483ed91", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a37d7b81a2082a09d351bea4590d3eadb", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a48b91aeb301f53d13656d0a6f1d16fe7", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a97e78eaec6ca94159c55499a40bc7807", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a1b6ffb0b1beef707d77b273b9cc7f9c9", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#afbbb0af7d8b3c7966058dbb1289dca13", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#ae0ce3cb199ab635b5563ec2added7ae8", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a24ba00d45416d57afe43628712a32fc3", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a17211c4b6d87e120f182de8cc3cc7aa7", null ], + [ "setModelCoefficients", "class_stomatal_conductance_model.html#a5939354a840f4a2199ad6610b22e4d89", null ] +]; \ No newline at end of file diff --git a/doc/html/class_synthetic_annotation.html b/doc/html/class_synthetic_annotation.html index 73ff8fa5b..e94503c34 100644 --- a/doc/html/class_synthetic_annotation.html +++ b/doc/html/class_synthetic_annotation.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/class_synthetic_annotation.js b/doc/html/class_synthetic_annotation.js new file mode 100644 index 000000000..cb28de51b --- /dev/null +++ b/doc/html/class_synthetic_annotation.js @@ -0,0 +1,12 @@ +var class_synthetic_annotation = +[ + [ "SyntheticAnnotation", "class_synthetic_annotation.html#a4a5fa05deea2f4a9ce20f7b941c23725", null ], + [ "disableInstanceSegmentation", "class_synthetic_annotation.html#a04117857ddc185b3b3595fcc2cfa97ae", null ], + [ "disableObjectDetection", "class_synthetic_annotation.html#a482f3217d844ba462f3640c07902ea58", null ], + [ "disableSemanticSegmentation", "class_synthetic_annotation.html#aaacbec2f1a8da152494b802d98f54cde", null ], + [ "enableInstanceSegmentation", "class_synthetic_annotation.html#af2bc966a2a1074b763c8bbd5d81eda37", null ], + [ "enableObjectDetection", "class_synthetic_annotation.html#a999f1f8f6e0135c20af979044668abb2", null ], + [ "enableSemanticSegmentation", "class_synthetic_annotation.html#abd40e35ef90be948265ef8b0d08206e1", null ], + [ "render", "class_synthetic_annotation.html#ab217bc96eaee704af3fd032eb0f999fc", null ], + [ "selfTest", "class_synthetic_annotation.html#a8ed7db69b40f2b0c49da32a87d5ef34e", null ] +]; \ No newline at end of file diff --git a/doc/html/class_visualizer.html b/doc/html/class_visualizer.html index 1145f96dd..c750a24e0 100644 --- a/doc/html/class_visualizer.html +++ b/doc/html/class_visualizer.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
@@ -691,7 +701,7 @@

Definition at line 2520 of file Visualizer.cpp.

+

Definition at line 2521 of file Visualizer.cpp.

@@ -894,7 +904,7 @@

Definition at line 2558 of file Visualizer.cpp.

+

Definition at line 2559 of file Visualizer.cpp.

@@ -2256,7 +2266,7 @@

Definition at line 2705 of file Visualizer.cpp.

+

Definition at line 2706 of file Visualizer.cpp.

@@ -2288,7 +2298,7 @@

Definition at line 2710 of file Visualizer.cpp.

+

Definition at line 2711 of file Visualizer.cpp.

@@ -2352,7 +2362,7 @@

Note
Useful for visualizing individual objects
-

Definition at line 3276 of file Visualizer.cpp.

+

Definition at line 3277 of file Visualizer.cpp.

@@ -2374,7 +2384,7 @@

Note
Useful for visualizing individual objects
-

Definition at line 3260 of file Visualizer.cpp.

+

Definition at line 3261 of file Visualizer.cpp.

@@ -2402,7 +2412,7 @@

Note
If the data value does not exist for a certain primitive, a value of 0 is assumed.
-

Definition at line 3173 of file Visualizer.cpp.

+

Definition at line 3174 of file Visualizer.cpp.

@@ -2435,7 +2445,7 @@

Note
If the data value does not exist for a certain primitive, a value of 0 is assumed.
-

Definition at line 3184 of file Visualizer.cpp.

+

Definition at line 3185 of file Visualizer.cpp.

@@ -2463,7 +2473,7 @@

Note
If the data value does not exist for a certain primitive, a value of 0 is assumed.
-

Definition at line 3195 of file Visualizer.cpp.

+

Definition at line 3196 of file Visualizer.cpp.

@@ -2496,7 +2506,7 @@

Note
If the data value does not exist for a certain primitive, a value of 0 is assumed.
-

Definition at line 3206 of file Visualizer.cpp.

+

Definition at line 3207 of file Visualizer.cpp.

@@ -2518,7 +2528,7 @@

Note
Useful for visualizing individual primitives that are part of compound objects
-

Definition at line 3238 of file Visualizer.cpp.

+

Definition at line 3239 of file Visualizer.cpp.

@@ -2546,7 +2556,7 @@

Note
Useful for visualizing individual primitives that are part of compound objects
-

Definition at line 3217 of file Visualizer.cpp.

+

Definition at line 3218 of file Visualizer.cpp.

@@ -2587,7 +2597,7 @@

Definition at line 2598 of file Visualizer.cpp.

+

Definition at line 2599 of file Visualizer.cpp.

@@ -2629,7 +2639,7 @@

Definition at line 2594 of file Visualizer.cpp.

+

Definition at line 2595 of file Visualizer.cpp.

@@ -2671,7 +2681,7 @@

Definition at line 2701 of file Visualizer.cpp.

+

Definition at line 2702 of file Visualizer.cpp.

@@ -2883,7 +2893,7 @@

Definition at line 3733 of file Visualizer.cpp.

+

Definition at line 3734 of file Visualizer.cpp.

@@ -2904,7 +2914,7 @@

Definition at line 3306 of file Visualizer.cpp.

+

Definition at line 3307 of file Visualizer.cpp.

@@ -2925,7 +2935,7 @@

Definition at line 3589 of file Visualizer.cpp.

+

Definition at line 3590 of file Visualizer.cpp.

@@ -2952,7 +2962,7 @@

Definition at line 3593 of file Visualizer.cpp.

+

Definition at line 3594 of file Visualizer.cpp.

@@ -3168,7 +3178,7 @@

Definition at line 2665 of file Visualizer.cpp.

+

Definition at line 2666 of file Visualizer.cpp.

@@ -3195,7 +3205,7 @@

Definition at line 2658 of file Visualizer.cpp.

+

Definition at line 2659 of file Visualizer.cpp.

@@ -3222,7 +3232,7 @@

Definition at line 2602 of file Visualizer.cpp.

+

Definition at line 2603 of file Visualizer.cpp.

@@ -3254,7 +3264,7 @@

Definition at line 2616 of file Visualizer.cpp.

+

Definition at line 2617 of file Visualizer.cpp.

@@ -3281,7 +3291,7 @@

Definition at line 2609 of file Visualizer.cpp.

+

Definition at line 2610 of file Visualizer.cpp.

@@ -3309,7 +3319,7 @@

Note
If tick values are outside of the colorbar range (see setColorBarRange()), the colorbar will be automatically expanded to fit the tick values.
-

Definition at line 2625 of file Visualizer.cpp.

+

Definition at line 2626 of file Visualizer.cpp.

@@ -3336,7 +3346,7 @@

Definition at line 2654 of file Visualizer.cpp.

+

Definition at line 2655 of file Visualizer.cpp.

@@ -3368,7 +3378,7 @@

Definition at line 2689 of file Visualizer.cpp.

+

Definition at line 2690 of file Visualizer.cpp.

@@ -3396,7 +3406,7 @@

Note
Valid colormaps are "COLORMAP_HOT", "COLORMAP_COOL", "COLORMAP_LAVA", "COLORMAP_RAINBOW", "COLORMAP_PARULA", "COLORMAP_GRAY".
-

Definition at line 2669 of file Visualizer.cpp.

+

Definition at line 2670 of file Visualizer.cpp.

@@ -3508,10 +3518,13 @@

Visualizer.cpp - - + + diff --git a/doc/html/class_visualizer.js b/doc/html/class_visualizer.js new file mode 100644 index 000000000..bcc50c0eb --- /dev/null +++ b/doc/html/class_visualizer.js @@ -0,0 +1,106 @@ +var class_visualizer = +[ + [ "CoordinateSystem", "class_visualizer.html#a084713b3d4d0720dcc1ee44d270b42e3", [ + [ "COORDINATES_WINDOW_NORMALIZED", "class_visualizer.html#a084713b3d4d0720dcc1ee44d270b42e3a9392af82f887f2fc1982a8315bcc95f5", null ], + [ "COORDINATES_CARTESIAN", "class_visualizer.html#a084713b3d4d0720dcc1ee44d270b42e3a83efc5e87fcf84a8c3d646e77adf53d4", null ] + ] ], + [ "Ctable", "class_visualizer.html#a0af839aae42fd7086643608a6cbd194b", [ + [ "COLORMAP_HOT", "class_visualizer.html#a0af839aae42fd7086643608a6cbd194ba50215b5b3fb3a48fc83d7b4670da2026", null ], + [ "COLORMAP_COOL", "class_visualizer.html#a0af839aae42fd7086643608a6cbd194ba65fd6eb9eefd4fbd10caa6ccceb689f5", null ], + [ "COLORMAP_RAINBOW", "class_visualizer.html#a0af839aae42fd7086643608a6cbd194baae019baa3e114715bf2a8feab826608d", null ], + [ "COLORMAP_LAVA", "class_visualizer.html#a0af839aae42fd7086643608a6cbd194baae3d180822a9415592cd938ef445e128", null ], + [ "COLORMAP_PARULA", "class_visualizer.html#a0af839aae42fd7086643608a6cbd194ba9a15b906eca8c544a6b83f885877fbe7", null ], + [ "COLORMAP_GRAY", "class_visualizer.html#a0af839aae42fd7086643608a6cbd194ba9902d02656030da0e50afae4ac10ab58", null ], + [ "COLORMAP_CUSTOM", "class_visualizer.html#a0af839aae42fd7086643608a6cbd194ba915aba9d8ae7c0796d8ed705671003a7", null ] + ] ], + [ "LightingModel", "class_visualizer.html#a580a78fe3e25c423e2d13aebc1b54573", [ + [ "LIGHTING_NONE", "class_visualizer.html#a580a78fe3e25c423e2d13aebc1b54573ac864e3d3a92a93d2d070faee3a6b4789", null ], + [ "LIGHTING_PHONG", "class_visualizer.html#a580a78fe3e25c423e2d13aebc1b54573adce805e52c5b47950ecc3cfdddd2160c", null ], + [ "LIGHTING_PHONG_SHADOWED", "class_visualizer.html#a580a78fe3e25c423e2d13aebc1b54573afe63a1dd4fcd9bbf57ad0dc2c168c864", null ] + ] ], + [ "Visualizer", "class_visualizer.html#a9277e99596d46d77d31a2249a1406983", null ], + [ "Visualizer", "class_visualizer.html#ac39e631c7d248c0e0f4f9ebba58a6dc4", null ], + [ "Visualizer", "class_visualizer.html#a9c6edf93389fa78548f2024aec944b82", null ], + [ "addCoordinateAxes", "class_visualizer.html#a831a69f2320707924c582e27d29a0ee5", null ], + [ "addCoordinateAxes", "class_visualizer.html#a309ce95c73229321d06d52f219b30510", null ], + [ "addDiskByCenter", "class_visualizer.html#a2886b6f91cd376bd83a945bc1b551f01", null ], + [ "addDiskByCenter", "class_visualizer.html#a1f4ef2ddcab0f1ed6bc1b4378b25e2df", null ], + [ "addDiskByCenter", "class_visualizer.html#acd7256a79fdfe2b37f270bec45bb3568", null ], + [ "addGridWireFrame", "class_visualizer.html#a6cbeaf6c6b6e877106173bc42a018d10", null ], + [ "addLine", "class_visualizer.html#ae287d6fdfab2cac58d0c1be890eff057", null ], + [ "addLine", "class_visualizer.html#a48a8390c82a8ee31172827b9aa378eb3", null ], + [ "addPoint", "class_visualizer.html#a4767d80ec00f90b36b9547da4bcc3d77", null ], + [ "addPoint", "class_visualizer.html#a228b710936fbf5e2bda8701c717b4019", null ], + [ "addRectangleByCenter", "class_visualizer.html#af86d3df98bbfa845e9c6bb4d8945429d", null ], + [ "addRectangleByCenter", "class_visualizer.html#a48e6d180f3751da810b8ff1ec02a4cfe", null ], + [ "addRectangleByCenter", "class_visualizer.html#a8ca1611eccfefb20cdfb2a686a78bd00", null ], + [ "addRectangleByCenter", "class_visualizer.html#af0d855cd55a8ae6f9734ddaf7c02ef24", null ], + [ "addRectangleByCenter", "class_visualizer.html#acd331a705d12dcec86131612cf433e88", null ], + [ "addRectangleByVertices", "class_visualizer.html#afe1be9b4d0cfa14298e162d59f5749bf", null ], + [ "addRectangleByVertices", "class_visualizer.html#a28ed082b9f1dea0e81e28535a23b1521", null ], + [ "addRectangleByVertices", "class_visualizer.html#af11f22cfc12cf5abad785bc0b8d875d2", null ], + [ "addRectangleByVertices", "class_visualizer.html#a342a0315efa1aaf7844f704fed0244bd", null ], + [ "addRectangleByVertices", "class_visualizer.html#acbcf904d891cc28d56a12cb9672c6893", null ], + [ "addRectangleByVertices", "class_visualizer.html#a546e454af8cdfee4db207ddbc3abcd7e", null ], + [ "addRectangleByVertices", "class_visualizer.html#a7ff15e66eb2ef54b7cc0c03deda255fe", null ], + [ "addRectangleByVertices", "class_visualizer.html#ac778d07346ddf94b7341181ed4640e28", null ], + [ "addSkyDomeByCenter", "class_visualizer.html#abc14ae2206a8b46c9724cc6aac06b44b", null ], + [ "addSphereByCenter", "class_visualizer.html#aff40781cf9b38f2f23e7fc998351105a", null ], + [ "addSphereByCenter", "class_visualizer.html#a6ce8c982a4576eb8d8fd5dc9be3a8ddf", null ], + [ "addTextboxByCenter", "class_visualizer.html#a2e139e1e6446b90f29d9e280fe3111db", null ], + [ "addTriangle", "class_visualizer.html#acc411df8e5d30efd31e69c46b4ce9875", null ], + [ "addTriangle", "class_visualizer.html#a0b45fc611a368a72d7f62e27aa4d4bfa", null ], + [ "addTriangle", "class_visualizer.html#a7c57ae2c58acb076e43848d650912733", null ], + [ "addTriangle", "class_visualizer.html#a30fa7fb8430e7e8e93e283710ea26a37", null ], + [ "addVoxelByCenter", "class_visualizer.html#a2c289bcb13fa935f78f2d032fa852b90", null ], + [ "addVoxelByCenter", "class_visualizer.html#a4b814571e4dccc0e550d3f184a48fab8", null ], + [ "buildContextGeometry", "class_visualizer.html#a4834cddbcc01696bf0b1ef1b0a2cde0c", null ], + [ "buildContextGeometry", "class_visualizer.html#ada78ef51373f63718a95841f564a83ef", null ], + [ "clearGeometry", "class_visualizer.html#a6ed171a1cff8b411bc45d097a38cd81b", null ], + [ "closeWindow", "class_visualizer.html#a6b7be76387563b2981bba995a7578d78", null ], + [ "colorContextObjectsRandomly", "class_visualizer.html#a16770662445e4a697353871a370174cb", null ], + [ "colorContextObjectsRandomly", "class_visualizer.html#a1eeba834ac28642f0e884ce68160d644", null ], + [ "colorContextPrimitivesByData", "class_visualizer.html#a0c75972b0cc0300a4fa0139af6a32234", null ], + [ "colorContextPrimitivesByData", "class_visualizer.html#ac9b9fb0076f62a9a06542d876db34563", null ], + [ "colorContextPrimitivesByObjectData", "class_visualizer.html#ad6479e1f6bb7f0f06d0c83b0351b4424", null ], + [ "colorContextPrimitivesByObjectData", "class_visualizer.html#af221d03db54adff2d38f8a938a1512b7", null ], + [ "colorContextPrimitivesRandomly", "class_visualizer.html#ac82b9c5274ec13dae412a9972fe2a080", null ], + [ "colorContextPrimitivesRandomly", "class_visualizer.html#afb87c8a06744966e4e02b61cf011ea79", null ], + [ "DEPRECATED", "class_visualizer.html#a66b16cf0e4d56836fad694658ccb7931", null ], + [ "disableColorbar", "class_visualizer.html#a3580188fe9f0daf71e1c434fe7f14103", null ], + [ "disableMessages", "class_visualizer.html#ab095acf8151f5825077b2ff36846c7df", null ], + [ "enableColorbar", "class_visualizer.html#a050807f8462ca95bde2fd737b26830c4", null ], + [ "enableMessages", "class_visualizer.html#aaf6a79caee464bfe52cb4fd34d3882d2", null ], + [ "getCurrentColormap", "class_visualizer.html#ae2bba6102a283a31ec4f5780817a15da", null ], + [ "getDepthMap", "class_visualizer.html#a7c6362d7dc0f0bd4bba53195ce92b84e", null ], + [ "getDomainBoundingBox", "class_visualizer.html#ae9c98dee278e9bcd5f85b871ff8ddfe5", null ], + [ "getDomainBoundingRadius", "class_visualizer.html#a783739e072baeafc943a077dcb1cc3d5", null ], + [ "getFramebufferSize", "class_visualizer.html#ab3b0261a21e7f552d55e4d2fda55f94f", null ], + [ "getWindowPixelsRGB", "class_visualizer.html#a15828ea9966b9729b56c9ddfccd4c117", null ], + [ "getWindowSize", "class_visualizer.html#ae6b83402c798f56334851f77b898de52", null ], + [ "hideWatermark", "class_visualizer.html#a90d0c5630620d30d062c0af4bace0a99", null ], + [ "plotDepthMap", "class_visualizer.html#a133187767033ad1f89c312a2d6f4a533", null ], + [ "plotInteractive", "class_visualizer.html#ab4858ed12fa78fe451569f4bbc27cd7c", null ], + [ "plotUpdate", "class_visualizer.html#aa87c684dd84db8d1ae0d12872b1dda22", null ], + [ "plotUpdate", "class_visualizer.html#a0c0af4bbebf814a6220f8876f5b13fc3", null ], + [ "printWindow", "class_visualizer.html#a2db00c518bf610fdcb70e0ec5a5a0e32", null ], + [ "printWindow", "class_visualizer.html#a1840b4285caa645e6b8b28144478cfe1", null ], + [ "selfTest", "class_visualizer.html#a1dc0a74852187800f44d2eaba4154650", null ], + [ "setBackgroundColor", "class_visualizer.html#a6e54e59d971acaadbf4cef72a28585ce", null ], + [ "setCameraFieldOfView", "class_visualizer.html#a4b92cdf1bb8f0c5411f9834839c3def4", null ], + [ "setCameraPosition", "class_visualizer.html#a7dd09cda5b3865b9ca5799560bf3e008", null ], + [ "setCameraPosition", "class_visualizer.html#ac6af1cee39fc442f47548e0dd69ebb1c", null ], + [ "setColorbarFontColor", "class_visualizer.html#a452fa37af4c7294b8b631ee83c6fe46c", null ], + [ "setColorbarFontSize", "class_visualizer.html#a40280c3f96152de174a4d9b26cc58c9d", null ], + [ "setColorbarPosition", "class_visualizer.html#ad0a19f3097299a4407919d6fd9c5fefe", null ], + [ "setColorbarRange", "class_visualizer.html#ac41ea2148985f9797ca84a3affa35da9", null ], + [ "setColorbarSize", "class_visualizer.html#a7efb1e8bc6de19f885781b564573066f", null ], + [ "setColorbarTicks", "class_visualizer.html#aabe4913f9a3444a5fea906382eeb6037", null ], + [ "setColorbarTitle", "class_visualizer.html#ae30cb19cb7d003ebbc0851c51c45d8a8", null ], + [ "setColormap", "class_visualizer.html#a9ec2fbf7ed0518b053dc831574dd9446", null ], + [ "setColormap", "class_visualizer.html#a992f636c4c406bbfc3f29add1fa3a278", null ], + [ "setLightDirection", "class_visualizer.html#a492533fe226fa92d08b010dc9a3f6e93", null ], + [ "setLightingModel", "class_visualizer.html#afc496b8bd99bbb786d553c4b3e8dfded", null ], + [ "setLightIntensityFactor", "class_visualizer.html#ae2227bdf3b92fb67bcad6acf7e9279b0", null ], + [ "showWatermark", "class_visualizer.html#a2f5e413bb5e48d98f061845065dfb830", null ] +]; \ No newline at end of file diff --git a/doc/html/class_voxel_intersection.html b/doc/html/class_voxel_intersection.html index 4e6405a5b..6dca802ef 100644 --- a/doc/html/class_voxel_intersection.html +++ b/doc/html/class_voxel_intersection.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
- -
+ + diff --git a/doc/html/class_voxel_intersection.js b/doc/html/class_voxel_intersection.js new file mode 100644 index 000000000..30fa9e01d --- /dev/null +++ b/doc/html/class_voxel_intersection.js @@ -0,0 +1,16 @@ +var class_voxel_intersection = +[ + [ "VoxelIntersection", "class_voxel_intersection.html#a45bf9a3a44c9373452753480c8e47c72", null ], + [ "approxSame", "class_voxel_intersection.html#a7b67a822c84c1086e3d0a8e05114c4bc", null ], + [ "approxSame", "class_voxel_intersection.html#af78fea330c0c2e38e3a02db732ed7dd7", null ], + [ "calculatePrimitiveVoxelIntersection", "class_voxel_intersection.html#ab8514a6e5868e77b6074bcd15bda831f", null ], + [ "calculatePrimitiveVoxelIntersection", "class_voxel_intersection.html#a11089d71d85cd247bd281edd664052fb", null ], + [ "disableMessages", "class_voxel_intersection.html#a899b91a48fbd227ff96b233c90709e74", null ], + [ "enableMessages", "class_voxel_intersection.html#a203e5402eba704b3e403ba7974cceaf3", null ], + [ "getCellPrimitives", "class_voxel_intersection.html#a7d50123db71cf5cd7c7cc4582abd5cb2", null ], + [ "interpolate_texture_UV_to_slice_point", "class_voxel_intersection.html#aba4e8fce246ada7df4f9975bc7b9624f", null ], + [ "linesIntersection", "class_voxel_intersection.html#a69cda90cd28f478ae007a88615994df2", null ], + [ "selfTest", "class_voxel_intersection.html#a320f16f7b1ee5c32b35c91331b426221", null ], + [ "slicePrimitive", "class_voxel_intersection.html#a31bb0e73e1018d371b8927c10fb415cb", null ], + [ "slicePrimitivesUsingGrid", "class_voxel_intersection.html#a03d0dcdbf67ada3ba0d99b0e3754ef61", null ] +]; \ No newline at end of file diff --git a/doc/html/class_weber_penn_tree.html b/doc/html/class_weber_penn_tree.html index 353e7af38..546ad0c81 100644 --- a/doc/html/class_weber_penn_tree.html +++ b/doc/html/class_weber_penn_tree.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
- -
+ + diff --git a/doc/html/class_weber_penn_tree.js b/doc/html/class_weber_penn_tree.js new file mode 100644 index 000000000..b3d0127c2 --- /dev/null +++ b/doc/html/class_weber_penn_tree.js @@ -0,0 +1,20 @@ +var class_weber_penn_tree = +[ + [ "WeberPennTree", "class_weber_penn_tree.html#a5b949a2008b9e4817f2df4b5861c49b5", null ], + [ "buildTree", "class_weber_penn_tree.html#a49f706c54cbf91ea5c40fb247d4e3559", null ], + [ "buildTree", "class_weber_penn_tree.html#af1dc9499df0c1cc26f3d0c5782da10bd", null ], + [ "getAllUUIDs", "class_weber_penn_tree.html#a19e16f9a51493680afebc38f3c434400", null ], + [ "getBranchUUIDs", "class_weber_penn_tree.html#a813cb8959272b535050dc97aa49d3ed3", null ], + [ "getLeafUUIDs", "class_weber_penn_tree.html#af4368c1f900503f6d72f0c0e569fe8e5", null ], + [ "getTreeParameters", "class_weber_penn_tree.html#aac5619ac480517f8f01cb465d0dc4a6f", null ], + [ "getTrunkUUIDs", "class_weber_penn_tree.html#ab247d9368368263dfdded18a43917f98", null ], + [ "loadXML", "class_weber_penn_tree.html#a3cc9a0c0b3039e5fa44fc77a117a72dc", null ], + [ "optionalOutputPrimitiveData", "class_weber_penn_tree.html#adb6095aad4b1dd1da8adc15fbd295775", null ], + [ "seedRandomGenerator", "class_weber_penn_tree.html#a8a9df18ae61815739063b0baff142f9d", null ], + [ "selfTest", "class_weber_penn_tree.html#a9fc96eafd81b0aa3ca628e25abbda28b", null ], + [ "setBranchRecursionLevel", "class_weber_penn_tree.html#a7aee9ed5ca2f7696179029b0c3ec5522", null ], + [ "setBranchSegmentResolution", "class_weber_penn_tree.html#a8b39281ab94cb9d77bcc4aa67a226796", null ], + [ "setLeafSubdivisions", "class_weber_penn_tree.html#a085a56d129e306469147762509fa7378", null ], + [ "setTreeParameters", "class_weber_penn_tree.html#a43a71d285a4dba83a6afc3870847e8eb", null ], + [ "setTrunkSegmentResolution", "class_weber_penn_tree.html#ab7ee7dfc8e8d599ea6875203af7ec002", null ] +]; \ No newline at end of file diff --git a/doc/html/classes.html b/doc/html/classes.html index b66391e61..efc870269 100644 --- a/doc/html/classes.html +++ b/doc/html/classes.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
XMLparser (helios)
- -
+ + diff --git a/doc/html/classhelios_1_1_box.html b/doc/html/classhelios_1_1_box.html index c566b0893..d248bcbe0 100644 --- a/doc/html/classhelios_1_1_box.html +++ b/doc/html/classhelios_1_1_box.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Public Member Functions | @@ -351,7 +357,7 @@

Detailed Description

Box compound object class.

-

Definition at line 759 of file Context.h.

+

Definition at line 765 of file Context.h.

Constructor & Destructor Documentation

◆ Box()

@@ -389,7 +395,7 @@

Definition at line 3941 of file Context.cpp.

+

Definition at line 3968 of file Context.cpp.

@@ -411,7 +417,7 @@

Definition at line 3980 of file Context.cpp.

+

Definition at line 4007 of file Context.cpp.

@@ -432,7 +438,7 @@

Definition at line 3961 of file Context.cpp.

+

Definition at line 3988 of file Context.cpp.

@@ -453,7 +459,7 @@

Definition at line 3996 of file Context.cpp.

+

Definition at line 4023 of file Context.cpp.

@@ -474,7 +480,7 @@

Definition at line 4004 of file Context.cpp.

+

Definition at line 4031 of file Context.cpp.

@@ -501,7 +507,7 @@

Definition at line 4000 of file Context.cpp.

+

Definition at line 4027 of file Context.cpp.

@@ -521,12 +527,12 @@

-friend +friend
-

Definition at line 790 of file Context.h.

+

Definition at line 796 of file Context.h.

@@ -535,10 +541,13 @@

Context.cpp - - + + diff --git a/doc/html/classhelios_1_1_box.js b/doc/html/classhelios_1_1_box.js new file mode 100644 index 000000000..ed672130d --- /dev/null +++ b/doc/html/classhelios_1_1_box.js @@ -0,0 +1,10 @@ +var classhelios_1_1_box = +[ + [ "Box", "classhelios_1_1_box.html#ab93cb2d8f6948617f67d236d85b3682a", null ], + [ "~Box", "classhelios_1_1_box.html#ab040ad0ee078cb1c9b4fc3c29ec3688d", null ], + [ "getCenter", "classhelios_1_1_box.html#a96e72a40ff113d6a6b463fe8c60b672a", null ], + [ "getSize", "classhelios_1_1_box.html#afd79ee17402ab6367896fe8278800f34", null ], + [ "getSubdivisionCount", "classhelios_1_1_box.html#a6f25b211d8740257329f841cda737a4f", null ], + [ "getVolume", "classhelios_1_1_box.html#a3d3d0b20e22aff306fde02bd7e2a4f84", null ], + [ "setSubdivisionCount", "classhelios_1_1_box.html#a4659cc09d90d34f4d993c107612ac6aa", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_compound_object.html b/doc/html/classhelios_1_1_compound_object.html index 1a7b6f45c..66c24e103 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
- -
+ + diff --git a/doc/html/classhelios_1_1_compound_object.js b/doc/html/classhelios_1_1_compound_object.js new file mode 100644 index 000000000..2771d7596 --- /dev/null +++ b/doc/html/classhelios_1_1_compound_object.js @@ -0,0 +1,68 @@ +var classhelios_1_1_compound_object = +[ + [ "arePrimitivesComplete", "classhelios_1_1_compound_object.html#a74e4a36175853a8e14153678c035accb", null ], + [ "clearObjectData", "classhelios_1_1_compound_object.html#abc9415005f1f45902b6834cb9d5aa987", null ], + [ "deleteChildPrimitive", "classhelios_1_1_compound_object.html#a4b8f242ec7d96ef82bd9d49658fb605f", null ], + [ "deleteChildPrimitive", "classhelios_1_1_compound_object.html#a5448b4bd356d7f772b8a0c7a848cfb89", null ], + [ "doesObjectContainPrimitive", "classhelios_1_1_compound_object.html#ae06ed1275c9ba5ed5ed59b08bdfd1216", null ], + [ "doesObjectDataExist", "classhelios_1_1_compound_object.html#aac66c9dbdba0e7418051a9eb9c688618", null ], + [ "getArea", "classhelios_1_1_compound_object.html#a8bb518f6166e2a2831a68a7626787ac1", null ], + [ "getObjectCenter", "classhelios_1_1_compound_object.html#aff66ca85a22d7f8a2501039e2e7183a7", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a6d99ef1cacec7471bb79b57601a7a6ee", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#ac222719662ca008014cdd045bedd3d96", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#ac91c73ac495bc4a93cc9a89d0eb58f47", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a768a439ecb0d6e8449b31cd137317168", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a95f20aead49e80032b0673273de436f2", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a2c0dcefe9e05ec04b001ad94f475f34c", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#afa77a9712c207752cd56522f2dbca52b", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#ac7af8838d7132683dd9fdbffd1288579", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#ac128057ff1d7cabb9dfbfb33216cb0c5", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#aed77927b3d3fe0ea7ea674b20a8acce1", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#af4d1accb01b8dd2f968296c43dfb6d97", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a6cb032fa5f5b6de86f234eb237980586", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#aba75ef4dd5b01b02fc99f9a1d957d70b", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#adfd1f35dc8785f223c02cc940360e6a5", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a7be991a83ada928f25c23cf7ca3b1822", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#af7574c29395681941d4d875e304b93de", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a797a5fd8f08ff7220b15ae1d5accb6cd", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a15ef0fda0196b4de933e4379d5f8234f", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#ac91bb0e57aa261b003de76b3e008a762", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#aef1aadca9de0e9a66500ca5879ab3755", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#acea74a2c138c1e5d832df864a231e486", null ], + [ "getObjectData", "classhelios_1_1_compound_object.html#a52661efba4b57415b073fcf839069623", null ], + [ "getObjectDataSize", "classhelios_1_1_compound_object.html#a03b2516f8e7e8ae921ea61e4f571eb1d", null ], + [ "getObjectDataType", "classhelios_1_1_compound_object.html#abbcfd5c545991ee59cf3f77acf300b1e", null ], + [ "getObjectID", "classhelios_1_1_compound_object.html#a28c85b0cf4dee51dd7997b7b78e4f442", null ], + [ "getObjectType", "classhelios_1_1_compound_object.html#ab07473392ca1e4c439c909c83cc9730b", null ], + [ "getPrimitiveCount", "classhelios_1_1_compound_object.html#a0eb06d37710a7dc9f5b915fc33f191a0", null ], + [ "getPrimitiveUUIDs", "classhelios_1_1_compound_object.html#ab3973a7c8ccb1aa0ce3f21ffe461ef7b", null ], + [ "getTextureFile", "classhelios_1_1_compound_object.html#a3e43ebd386e7a6663fa877613b9d27fa", null ], + [ "getTransformationMatrix", "classhelios_1_1_compound_object.html#ac1e98d4f8098dadda345f9dc6dae73ca", null ], + [ "hasTexture", "classhelios_1_1_compound_object.html#a547a3a56f24fdaf541d12dc74776318e", null ], + [ "listObjectData", "classhelios_1_1_compound_object.html#a4750278bd9c519d57c3f27891dcf666d", null ], + [ "overrideTextureColor", "classhelios_1_1_compound_object.html#a247e9f55e89ce5bb4621cc395069a20d", null ], + [ "rotate", "classhelios_1_1_compound_object.html#a06cb565db4569677cdfde7d0bb33c61e", null ], + [ "rotate", "classhelios_1_1_compound_object.html#ab09695c9859a79b17806f7a4a18b56f4", null ], + [ "rotate", "classhelios_1_1_compound_object.html#a7a4ab077211799f617a423bf05282aee", null ], + [ "scale", "classhelios_1_1_compound_object.html#a4b2124d89efe900244fb51426ab1f4ce", null ], + [ "scaleAboutCenter", "classhelios_1_1_compound_object.html#a63e491c5eed7b39ef26a67718da2a10f", null ], + [ "scaleAboutPoint", "classhelios_1_1_compound_object.html#a6e3b6e95498c551dc124b2653603e10f", null ], + [ "setColor", "classhelios_1_1_compound_object.html#a2c652ccbd87bd8308706a2ed0989e32b", null ], + [ "setColor", "classhelios_1_1_compound_object.html#acc54a3160aa1bc81789d627a108e61bb", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#a316d892dd85e920bfb964d3017dc25c4", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#ac657af83b036f3c886d2f64d0697378f", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#ae19d6e464af601cea45a1c631c8f44b2", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#a48d6781ec37e21f405cf368f854ef19a", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#a3b03b96096e7618e7a3865225413b7b9", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#a6442aef7859238fc3a49cb9187548c7c", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#af93de91ec2dc1cdeca58c09d6f1febb1", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#ac7815b7cda94f76a87e564f9d9b05a3c", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#acf473c0595a525618fc6a5e39fca40e6", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#a3369928e9718d521cf135051a3f60e81", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#a5730d9c317726f1a0ed3a396575a0957", null ], + [ "setObjectData", "classhelios_1_1_compound_object.html#a93395e379a6266f31364ea1cd7f65cea", null ], + [ "setPrimitiveUUIDs", "classhelios_1_1_compound_object.html#a0b00455ff0bab50e012bd6e7b5a54a51", null ], + [ "setTransformationMatrix", "classhelios_1_1_compound_object.html#a55a1ebd9699cb1c9ae0ca39b3db8f9b4", null ], + [ "translate", "classhelios_1_1_compound_object.html#aa16f6ad8ec100173147c89bb2c5e0446", null ], + [ "useTextureColor", "classhelios_1_1_compound_object.html#ad40fa98ddefc9ba9d24cd45ca0df44d5", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_cone.html b/doc/html/classhelios_1_1_cone.html index aaa8eb52a..40db2d1a2 100644 --- a/doc/html/classhelios_1_1_cone.html +++ b/doc/html/classhelios_1_1_cone.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Public Member Functions | @@ -369,7 +375,7 @@

Detailed Description

Cone compound object class.

-

Definition at line 847 of file Context.h.

+

Definition at line 853 of file Context.h.

Constructor & Destructor Documentation

◆ Cone()

@@ -427,7 +433,7 @@

Definition at line 4107 of file Context.cpp.

+

Definition at line 4134 of file Context.cpp.

@@ -449,7 +455,7 @@

Definition at line 4179 of file Context.cpp.

+

Definition at line 4206 of file Context.cpp.

@@ -470,7 +476,7 @@

Definition at line 4197 of file Context.cpp.

+

Definition at line 4224 of file Context.cpp.

@@ -498,7 +504,7 @@

Returns
Cartesian coordinate of the cone node center.
-

Definition at line 4144 of file Context.cpp.

+

Definition at line 4171 of file Context.cpp.

@@ -520,7 +526,7 @@

Returns
Vector of Cartesian coordinates of cone object nodes (length = 2).
-

Definition at line 4130 of file Context.cpp.

+

Definition at line 4157 of file Context.cpp.

@@ -542,7 +548,7 @@

Returns
Vector of radii at cone object nodes (length = 2).
-

Definition at line 4159 of file Context.cpp.

+

Definition at line 4186 of file Context.cpp.

@@ -570,7 +576,7 @@

Returns
Radius of the cone node.
-

Definition at line 4163 of file Context.cpp.

+

Definition at line 4190 of file Context.cpp.

@@ -591,7 +597,7 @@

Definition at line 4171 of file Context.cpp.

+

Definition at line 4198 of file Context.cpp.

@@ -612,7 +618,7 @@

Definition at line 4302 of file Context.cpp.

+

Definition at line 4329 of file Context.cpp.

@@ -639,7 +645,7 @@

Definition at line 4261 of file Context.cpp.

+

Definition at line 4288 of file Context.cpp.

@@ -666,7 +672,7 @@

Definition at line 4212 of file Context.cpp.

+

Definition at line 4239 of file Context.cpp.

@@ -693,7 +699,7 @@

Definition at line 4175 of file Context.cpp.

+

Definition at line 4202 of file Context.cpp.

@@ -713,12 +719,12 @@

-friend +friend
-

Definition at line 919 of file Context.h.

+

Definition at line 925 of file Context.h.

@@ -727,10 +733,13 @@

Context.cpp - - + + diff --git a/doc/html/classhelios_1_1_cone.js b/doc/html/classhelios_1_1_cone.js new file mode 100644 index 000000000..05005cfff --- /dev/null +++ b/doc/html/classhelios_1_1_cone.js @@ -0,0 +1,16 @@ +var classhelios_1_1_cone = +[ + [ "Cone", "classhelios_1_1_cone.html#a1812816ea32de6d7a28fae76ebd66f80", null ], + [ "~Cone", "classhelios_1_1_cone.html#ac4f380f30c6bb1dbdf2e8c215c05677c", null ], + [ "getAxisUnitVector", "classhelios_1_1_cone.html#a60fc92fbb15149017956449123c0e4d0", null ], + [ "getLength", "classhelios_1_1_cone.html#ada36b3fe4850f16c4dfa58c38a8da80c", null ], + [ "getNodeCoordinate", "classhelios_1_1_cone.html#a4f6ddd7fd23d61528ada9df1e333ad17", null ], + [ "getNodeCoordinates", "classhelios_1_1_cone.html#a9eaab4331e325c85ce9f4c101135c966", null ], + [ "getNodeRadii", "classhelios_1_1_cone.html#adc5370734810e4b526bf0d42e143ecf8", null ], + [ "getNodeRadius", "classhelios_1_1_cone.html#a2334ca87f6bb556b411c8a51476b523c", null ], + [ "getSubdivisionCount", "classhelios_1_1_cone.html#a051a2c5760d53a6c0b95f66cab9cbf73", null ], + [ "getVolume", "classhelios_1_1_cone.html#aff2cb2fc89c68b75a038a9604ce73cd0", null ], + [ "scaleGirth", "classhelios_1_1_cone.html#ad40b7cda9baac86be967058736b2bb78", null ], + [ "scaleLength", "classhelios_1_1_cone.html#aaefa3caee5b8e46ca46650031d0bee0a", null ], + [ "setSubdivisionCount", "classhelios_1_1_cone.html#a44fce4adcb863c4049640d4e8757563f", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_context.html b/doc/html/classhelios_1_1_context.html index 024ec1463..712f48df8 100644 --- a/doc/html/classhelios_1_1_context.html +++ b/doc/html/classhelios_1_1_context.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Public Member Functions | @@ -1218,6 +1224,9 @@ void scaleTubeLength (uint ObjID, float scale_factor)  Scale the length of a tube object by an arbitrary factor for all tube nodes.
  +void pruneTubeNodes (uint ObjID, uint node_index) + Remove a portion of the tube downstream of a specified node.
+  void setTubeNodes (uint ObjID, const std::vector< helios::vec3 > &node_xyz)  Set tube vertex coordinates at each segment node.
  @@ -1755,10 +1764,9 @@

Detailed Description

Stores the state associated with simulation.

-

The Context provides an interface to global information about the application environment. It allows access to application-level operations such as adding geometry, running models, and visualization. After creation, the Context must first be initialized via a call to initializeContext(), after which geometry and models can be added and simulated.
-

+

The Context provides an interface to global information about the application environment. It allows access to application-level operations such as adding geometry, running models, and visualization. After creation, the Context must first be initialized via a call to initializeContext(), after which geometry and models can be added and simulated.

-

Definition at line 1882 of file Context.h.

+

Definition at line 1888 of file Context.h.

Constructor & Destructor Documentation

◆ Context()

@@ -1798,7 +1806,7 @@

Context destructor.

-

Definition at line 6970 of file Context.cpp.

+

Definition at line 6997 of file Context.cpp.

@@ -2107,7 +2115,7 @@

Definition at line 8187 of file Context.cpp.

+

Definition at line 8214 of file Context.cpp.

@@ -2151,7 +2159,7 @@

Definition at line 8180 of file Context.cpp.

+

Definition at line 8207 of file Context.cpp.

@@ -3303,7 +3311,7 @@

Definition at line 6666 of file Context.cpp.

+

Definition at line 6693 of file Context.cpp.

@@ -3359,7 +3367,7 @@

Definition at line 6672 of file Context.cpp.

+

Definition at line 6699 of file Context.cpp.

@@ -3866,7 +3874,7 @@

Definition at line 7974 of file Context.cpp.

+

Definition at line 8001 of file Context.cpp.

@@ -4715,7 +4723,7 @@

Definition at line 8222 of file Context.cpp.

+

Definition at line 8256 of file Context.cpp.

@@ -4742,7 +4750,7 @@

Definition at line 3954 of file Context.cpp.

+

Definition at line 3981 of file Context.cpp.

@@ -4769,7 +4777,7 @@

Definition at line 8226 of file Context.cpp.

+

Definition at line 8260 of file Context.cpp.

@@ -4796,7 +4804,7 @@

Definition at line 8230 of file Context.cpp.

+

Definition at line 8264 of file Context.cpp.

@@ -4823,7 +4831,7 @@

Definition at line 8234 of file Context.cpp.

+

Definition at line 8268 of file Context.cpp.

@@ -4850,7 +4858,7 @@

Definition at line 8270 of file Context.cpp.

+

Definition at line 8304 of file Context.cpp.

@@ -4878,7 +4886,7 @@

Returns
Dimension of cone object in the axial direction
-

Definition at line 8274 of file Context.cpp.

+

Definition at line 8308 of file Context.cpp.

@@ -4909,7 +4917,7 @@

Definition at line 8262 of file Context.cpp.

+

Definition at line 8296 of file Context.cpp.

@@ -4936,7 +4944,7 @@

Definition at line 8258 of file Context.cpp.

+

Definition at line 8292 of file Context.cpp.

@@ -4967,7 +4975,7 @@

Definition at line 8266 of file Context.cpp.

+

Definition at line 8300 of file Context.cpp.

@@ -4994,7 +5002,7 @@

Definition at line 8254 of file Context.cpp.

+

Definition at line 8288 of file Context.cpp.

@@ -5021,7 +5029,7 @@

Definition at line 4123 of file Context.cpp.

+

Definition at line 4150 of file Context.cpp.

@@ -5048,7 +5056,7 @@

Definition at line 8250 of file Context.cpp.

+

Definition at line 8284 of file Context.cpp.

@@ -5075,7 +5083,7 @@

Definition at line 8278 of file Context.cpp.

+

Definition at line 8312 of file Context.cpp.

@@ -5125,7 +5133,7 @@

Definition at line 8238 of file Context.cpp.

+

Definition at line 8272 of file Context.cpp.

@@ -5152,7 +5160,7 @@

Definition at line 4022 of file Context.cpp.

+

Definition at line 4049 of file Context.cpp.

@@ -5179,7 +5187,7 @@

Definition at line 8242 of file Context.cpp.

+

Definition at line 8276 of file Context.cpp.

@@ -5206,7 +5214,7 @@

Definition at line 8246 of file Context.cpp.

+

Definition at line 8280 of file Context.cpp.

@@ -6238,7 +6246,7 @@

Definition at line 7920 of file Context.cpp.

+

Definition at line 7947 of file Context.cpp.

@@ -6276,7 +6284,7 @@

Definition at line 8003 of file Context.cpp.

+

Definition at line 8030 of file Context.cpp.

@@ -6314,7 +6322,7 @@

Definition at line 7998 of file Context.cpp.

+

Definition at line 8025 of file Context.cpp.

@@ -6341,7 +6349,7 @@

Definition at line 7928 of file Context.cpp.

+

Definition at line 7955 of file Context.cpp.

@@ -7320,7 +7328,7 @@

Definition at line 7924 of file Context.cpp.

+

Definition at line 7951 of file Context.cpp.

@@ -7428,7 +7436,7 @@

Definition at line 7932 of file Context.cpp.

+

Definition at line 7959 of file Context.cpp.

@@ -7460,7 +7468,7 @@

Definition at line 7936 of file Context.cpp.

+

Definition at line 7963 of file Context.cpp.

@@ -7572,7 +7580,7 @@

Definition at line 4081 of file Context.cpp.

+

Definition at line 4108 of file Context.cpp.

@@ -7599,7 +7607,7 @@

Definition at line 8282 of file Context.cpp.

+

Definition at line 8316 of file Context.cpp.

@@ -7626,7 +7634,7 @@

Definition at line 7053 of file Context.cpp.

+

Definition at line 7080 of file Context.cpp.

@@ -7664,7 +7672,7 @@

Definition at line 7062 of file Context.cpp.

+

Definition at line 7089 of file Context.cpp.

@@ -7702,7 +7710,7 @@

Definition at line 7057 of file Context.cpp.

+

Definition at line 7084 of file Context.cpp.

@@ -7729,7 +7737,7 @@

Definition at line 7127 of file Context.cpp.

+

Definition at line 7154 of file Context.cpp.

@@ -7756,7 +7764,7 @@

Definition at line 7131 of file Context.cpp.

+

Definition at line 7158 of file Context.cpp.

@@ -7783,7 +7791,7 @@

Definition at line 7135 of file Context.cpp.

+

Definition at line 7162 of file Context.cpp.

@@ -8713,7 +8721,7 @@

Definition at line 7104 of file Context.cpp.

+

Definition at line 7131 of file Context.cpp.

@@ -8740,7 +8748,7 @@

Definition at line 7017 of file Context.cpp.

+

Definition at line 7044 of file Context.cpp.

@@ -8768,7 +8776,7 @@

Returns
Fraction of non-transparent area (=1 if primitive does not have a semi-transparent texture).
-

Definition at line 7221 of file Context.cpp.

+

Definition at line 7248 of file Context.cpp.

@@ -8796,7 +8804,7 @@

Returns
Path to texture map file.
-

Definition at line 7159 of file Context.cpp.

+

Definition at line 7186 of file Context.cpp.

@@ -8824,7 +8832,7 @@

Returns
Texture image resolution (columns x rows).
-

Definition at line 7167 of file Context.cpp.

+

Definition at line 7194 of file Context.cpp.

@@ -8852,7 +8860,7 @@

Returns
Transparency value (0 or 1) for each pixel in primitive texture map.
-

Definition at line 7187 of file Context.cpp.

+

Definition at line 7214 of file Context.cpp.

@@ -8879,7 +8887,7 @@

Definition at line 7175 of file Context.cpp.

+

Definition at line 7202 of file Context.cpp.

@@ -8911,7 +8919,7 @@

Definition at line 7108 of file Context.cpp.

+

Definition at line 7135 of file Context.cpp.

@@ -8938,7 +8946,7 @@

Definition at line 6984 of file Context.cpp.

+

Definition at line 7011 of file Context.cpp.

@@ -8965,7 +8973,7 @@

Definition at line 7122 of file Context.cpp.

+

Definition at line 7149 of file Context.cpp.

@@ -9014,7 +9022,7 @@

Definition at line 8140 of file Context.cpp.

+

Definition at line 8167 of file Context.cpp.

@@ -9068,7 +9076,7 @@

Definition at line 8144 of file Context.cpp.

+

Definition at line 8171 of file Context.cpp.

@@ -9095,7 +9103,7 @@

Definition at line 8148 of file Context.cpp.

+

Definition at line 8175 of file Context.cpp.

@@ -9122,7 +9130,7 @@

Definition at line 8152 of file Context.cpp.

+

Definition at line 8179 of file Context.cpp.

@@ -9205,7 +9213,7 @@

Returns
Center position of a Tile Object.
Note
If the ObjID passed to this method does not correspond to a Tile Object, an error will be thrown.
-

Definition at line 8116 of file Context.cpp.

+

Definition at line 8143 of file Context.cpp.

@@ -9232,7 +9240,7 @@

Definition at line 8128 of file Context.cpp.

+

Definition at line 8155 of file Context.cpp.

@@ -9286,7 +9294,7 @@

Definition at line 8120 of file Context.cpp.

+

Definition at line 8147 of file Context.cpp.

@@ -9313,7 +9321,7 @@

Definition at line 8124 of file Context.cpp.

+

Definition at line 8151 of file Context.cpp.

@@ -9340,7 +9348,7 @@

Definition at line 8132 of file Context.cpp.

+

Definition at line 8159 of file Context.cpp.

@@ -9367,7 +9375,7 @@

Definition at line 8136 of file Context.cpp.

+

Definition at line 8163 of file Context.cpp.

@@ -9451,7 +9459,7 @@

Definition at line 8168 of file Context.cpp.

+

Definition at line 8195 of file Context.cpp.

@@ -9478,7 +9486,7 @@

Definition at line 8164 of file Context.cpp.

+

Definition at line 8191 of file Context.cpp.

@@ -9505,7 +9513,7 @@

Definition at line 8160 of file Context.cpp.

+

Definition at line 8187 of file Context.cpp.

@@ -9564,7 +9572,7 @@

Definition at line 8176 of file Context.cpp.

+

Definition at line 8203 of file Context.cpp.

@@ -9591,7 +9599,7 @@

Definition at line 8156 of file Context.cpp.

+

Definition at line 8183 of file Context.cpp.

@@ -9618,7 +9626,7 @@

Definition at line 8172 of file Context.cpp.

+

Definition at line 8199 of file Context.cpp.

@@ -9645,7 +9653,7 @@

Definition at line 7022 of file Context.cpp.

+

Definition at line 7049 of file Context.cpp.

@@ -9676,7 +9684,7 @@

Definition at line 7027 of file Context.cpp.

+

Definition at line 7054 of file Context.cpp.

@@ -9761,7 +9769,7 @@

Definition at line 7901 of file Context.cpp.

+

Definition at line 7928 of file Context.cpp.

@@ -10128,7 +10136,7 @@

Returns
True if the object is hidden, false otherwise.
-

Definition at line 7913 of file Context.cpp.

+

Definition at line 7940 of file Context.cpp.

@@ -10183,7 +10191,7 @@

Definition at line 7217 of file Context.cpp.

+

Definition at line 7244 of file Context.cpp.

@@ -10896,7 +10904,7 @@

Definition at line 7950 of file Context.cpp.

+

Definition at line 7977 of file Context.cpp.

@@ -10923,7 +10931,7 @@

Definition at line 7982 of file Context.cpp.

+

Definition at line 8009 of file Context.cpp.

@@ -10950,7 +10958,7 @@

Definition at line 7978 of file Context.cpp.

+

Definition at line 8005 of file Context.cpp.

@@ -10977,7 +10985,7 @@

Definition at line 7201 of file Context.cpp.

+

Definition at line 7228 of file Context.cpp.

@@ -11004,7 +11012,7 @@

Definition at line 7197 of file Context.cpp.

+

Definition at line 7224 of file Context.cpp.

@@ -11032,7 +11040,7 @@

Returns
True if transparency channel data exists, false otherwise
-

Definition at line 7179 of file Context.cpp.

+

Definition at line 7206 of file Context.cpp.

@@ -11059,7 +11067,7 @@

Definition at line 7499 of file Context.cpp.

+

Definition at line 7526 of file Context.cpp.

@@ -11086,7 +11094,39 @@

Definition at line 7225 of file Context.cpp.

+

Definition at line 7252 of file Context.cpp.

+ + + + +

◆ pruneTubeNodes()

+ +
+
+ + + + + + + + + + + +
void Context::pruneTubeNodes (uint ObjID,
uint node_index )
+
+ +

Remove a portion of the tube downstream of a specified node.

+
Parameters
+ + + +
[in]ObjIDobject ID of the Tube object
[in]node_indexIndex of the tube segment node beyond which will be removed
+
+
+ +

Definition at line 8242 of file Context.cpp.

@@ -12264,7 +12304,7 @@

Definition at line 8194 of file Context.cpp.

+

Definition at line 8221 of file Context.cpp.

@@ -12296,7 +12336,7 @@

Definition at line 8208 of file Context.cpp.

+

Definition at line 8235 of file Context.cpp.

@@ -12327,7 +12367,7 @@

-static +static @@ -12986,7 +13026,7 @@

Definition at line 7958 of file Context.cpp.

+

Definition at line 7985 of file Context.cpp.

@@ -13018,7 +13058,7 @@

Definition at line 7964 of file Context.cpp.

+

Definition at line 7991 of file Context.cpp.

@@ -13050,7 +13090,7 @@

Definition at line 7954 of file Context.cpp.

+

Definition at line 7981 of file Context.cpp.

@@ -14800,7 +14840,7 @@

Definition at line 7944 of file Context.cpp.

+

Definition at line 7971 of file Context.cpp.

@@ -14832,7 +14872,7 @@

Definition at line 7940 of file Context.cpp.

+

Definition at line 7967 of file Context.cpp.

@@ -14864,7 +14904,7 @@

Definition at line 7153 of file Context.cpp.

+

Definition at line 7180 of file Context.cpp.

@@ -14896,7 +14936,7 @@

Definition at line 7143 of file Context.cpp.

+

Definition at line 7170 of file Context.cpp.

@@ -14928,7 +14968,7 @@

Definition at line 7149 of file Context.cpp.

+

Definition at line 7176 of file Context.cpp.

@@ -14960,7 +15000,7 @@

Definition at line 7139 of file Context.cpp.

+

Definition at line 7166 of file Context.cpp.

@@ -16710,7 +16750,7 @@

Definition at line 7011 of file Context.cpp.

+

Definition at line 7038 of file Context.cpp.

@@ -16742,7 +16782,7 @@

Definition at line 6988 of file Context.cpp.

+

Definition at line 7015 of file Context.cpp.

@@ -16774,7 +16814,7 @@

Definition at line 7163 of file Context.cpp.

+

Definition at line 7190 of file Context.cpp.

@@ -16806,7 +16846,7 @@

Definition at line 7116 of file Context.cpp.

+

Definition at line 7143 of file Context.cpp.

@@ -16838,7 +16878,7 @@

Definition at line 7112 of file Context.cpp.

+

Definition at line 7139 of file Context.cpp.

@@ -17084,7 +17124,7 @@

Definition at line 8215 of file Context.cpp.

+

Definition at line 8249 of file Context.cpp.

@@ -17116,7 +17156,7 @@

Definition at line 8201 of file Context.cpp.

+

Definition at line 8228 of file Context.cpp.

@@ -17299,7 +17339,7 @@

Definition at line 7992 of file Context.cpp.

+

Definition at line 8019 of file Context.cpp.

@@ -17326,7 +17366,7 @@

Definition at line 7988 of file Context.cpp.

+

Definition at line 8015 of file Context.cpp.

@@ -17353,7 +17393,7 @@

Definition at line 7211 of file Context.cpp.

+

Definition at line 7238 of file Context.cpp.

@@ -17380,7 +17420,7 @@

Definition at line 7207 of file Context.cpp.

+

Definition at line 7234 of file Context.cpp.

@@ -17706,10 +17746,13 @@

selfTest.cpp - - + + diff --git a/doc/html/classhelios_1_1_context.js b/doc/html/classhelios_1_1_context.js new file mode 100644 index 000000000..917fc4f3d --- /dev/null +++ b/doc/html/classhelios_1_1_context.js @@ -0,0 +1,546 @@ +var classhelios_1_1_context = +[ + [ "Context", "classhelios_1_1_context.html#a652cdcd2eedc8dbd9110bd284c5d5cf0", null ], + [ "~Context", "classhelios_1_1_context.html#a2d34e4556448e40693f61d15e091b604", null ], + [ "Context", "classhelios_1_1_context.html#a859979bfe3d7d03b07d3c640ccbc0efa", null ], + [ "addBox", "group__compoundobjects.html#gaad6b1c9613d3e1e70519e145166c8879", null ], + [ "addBox", "group__compoundobjects.html#gac9d9b47750abac76a5630d2218db5861", null ], + [ "addBox", "group__compoundobjects.html#ga8d7f04707bc24f049cb60212c3ba29d2", null ], + [ "addBox", "group__compoundobjects.html#ga9a00c2f632e5625524dc8cd7587b771e", null ], + [ "addBox", "group__compoundobjects.html#ga73e5eea0a4841336b41ed2848327c12a", null ], + [ "addBoxObject", "group__compoundobjects.html#gab2549ca65442372287b30c874b0c2b1c", null ], + [ "addBoxObject", "group__compoundobjects.html#ga23b4391b46d9c4b8f9452fc7a0812ce2", null ], + [ "addBoxObject", "group__compoundobjects.html#ga71aa11aa723683d18807fda36397f7e3", null ], + [ "addBoxObject", "group__compoundobjects.html#gac29332e0332233ea902a94e4822f739f", null ], + [ "addBoxObject", "group__compoundobjects.html#gab3b99bd7bee16911a3f47173dba06cbc", null ], + [ "addCone", "group__compoundobjects.html#gae6dfe37103da5348a8e09541e6832579", null ], + [ "addCone", "group__compoundobjects.html#gadaded2acc62c6bf577b840097cf63715", null ], + [ "addCone", "group__compoundobjects.html#gaa90786c814a02a713c73e3f2063f7b15", null ], + [ "addConeObject", "group__compoundobjects.html#ga91e46b44e9d7ece5a7e75e739cac4610", null ], + [ "addConeObject", "group__compoundobjects.html#gaff21895b974a64df8fd78b3604d7c404", null ], + [ "addConeObject", "group__compoundobjects.html#ga5dfcb74a1406d4a2ee15c251dedcd744", null ], + [ "addDisk", "group__compoundobjects.html#gacb1267c95cec56efb0150e292c12f24c", null ], + [ "addDisk", "group__compoundobjects.html#ga9e43e2dc65df7b0aa93e140881fd2bfa", null ], + [ "addDisk", "group__compoundobjects.html#gac196d3c8356561ef33b6e41c80cf8b4a", null ], + [ "addDisk", "group__compoundobjects.html#gaad3d5c21579728fa839c6a95514991bb", null ], + [ "addDisk", "group__compoundobjects.html#ga3c0d84f0ade9148214d0a7ec5e574aeb", null ], + [ "addDisk", "group__compoundobjects.html#gaee1c741715ce7367c8198e573b9684ec", null ], + [ "addDisk", "group__compoundobjects.html#gaf323d883bfc3392b3817fce85a5205ae", null ], + [ "addDisk", "group__compoundobjects.html#gac774b33822ae284009dc761146e37670", null ], + [ "addDiskObject", "group__compoundobjects.html#ga9edafbc21c49d4f76294279a2818cfb4", null ], + [ "addDiskObject", "group__compoundobjects.html#ga259d1db05876a3dbf7a37ac5612935c4", null ], + [ "addDiskObject", "group__compoundobjects.html#ga8b77c42881f1b6d4a6abb712256a87cd", null ], + [ "addDiskObject", "group__compoundobjects.html#ga064d0343ca8556d8a6a00c7cdce3bf0d", null ], + [ "addDiskObject", "group__compoundobjects.html#ga826e790ed5999e168c22ddcc7e57e514", null ], + [ "addDiskObject", "group__compoundobjects.html#ga4fb358731a06c9eafc267e9e6f522577", null ], + [ "addDiskObject", "group__compoundobjects.html#gaed3cc3a47ff86ea9dfcf70cd9b295b23", null ], + [ "addDiskObject", "group__compoundobjects.html#gadcc9c858b2c3afe1430ff4013f69b780", null ], + [ "addPatch", "group__primitives.html#gaf4aec42f3f104b7c71150577ef129659", null ], + [ "addPatch", "group__primitives.html#gafaae593d52d284c5aab98e29cee0cd76", null ], + [ "addPatch", "group__primitives.html#ga148090c69c7b04bbfbae4eed2443a235", null ], + [ "addPatch", "group__primitives.html#ga953a329d019e3c91948b139215c748af", null ], + [ "addPatch", "group__primitives.html#ga542e67cc428fb707452c216091a7f24f", null ], + [ "addPatch", "classhelios_1_1_context.html#a5118575675393453c5d927e66d59293e", null ], + [ "addPatch", "classhelios_1_1_context.html#a7ead8162aab12a399925aa89a6f9007c", null ], + [ "addPolymeshObject", "group__compoundobjects.html#gababf99153757527880fe3866cc23fd1b", null ], + [ "addSphere", "group__compoundobjects.html#gac5df0d862dd8d6783edc037804c452bf", null ], + [ "addSphere", "group__compoundobjects.html#ga2b10346e874dd539c742102b385c9370", null ], + [ "addSphere", "group__compoundobjects.html#ga645ee8b5e829c08e8e3549eceea815cc", null ], + [ "addSphereObject", "group__compoundobjects.html#gac1787b97a96f2c4d21d13ed130b263d0", null ], + [ "addSphereObject", "group__compoundobjects.html#gaa0f43d59a2c0341dfe3ab97814c37962", null ], + [ "addSphereObject", "group__compoundobjects.html#ga2b30de9aefefbbac2400f79dfc7c74fb", null ], + [ "addSphereObject", "group__compoundobjects.html#gae7cb6682b28087b6d1d68c12d6814a23", null ], + [ "addSphereObject", "group__compoundobjects.html#ga6c66a36c17dbf43376909fdc1f4df826", null ], + [ "addSphereObject", "group__compoundobjects.html#gac0836f609016ffc2726788a252832003", null ], + [ "addTile", "group__compoundobjects.html#gae15ba3f5741d27c52c43a35eec6c866b", null ], + [ "addTile", "group__compoundobjects.html#ga8d8cdafde1ebfaebf8edd27aa36ae82b", null ], + [ "addTile", "group__compoundobjects.html#ga48feb2165a7adfbb11cb402c7db56d4b", null ], + [ "addTileObject", "group__compoundobjects.html#gae5c1fa3bae1ff170c14a4378fb8abd95", null ], + [ "addTileObject", "group__compoundobjects.html#gad5c5cd832ce014a4862d72ccf52e2100", null ], + [ "addTileObject", "group__compoundobjects.html#gae846d22b6cba8b50582ace8509c16e12", null ], + [ "addTimeseriesData", "group__timeseries.html#gab4e83017576a164eaa7c61cd0812d8a2", null ], + [ "addTriangle", "group__primitives.html#ga2a78a464a4c7ef3375a0ced2f1005b77", null ], + [ "addTriangle", "group__primitives.html#ga6d8025b542a52a8683f76ae292934c76", null ], + [ "addTriangle", "group__primitives.html#ga6c541321006498aa976afd7a1a65cafb", null ], + [ "addTriangle", "group__primitives.html#gafedf69d3c13704eac0b1cdbaedfc2f5c", null ], + [ "addTube", "group__compoundobjects.html#gad1d3bab869a03fe7c35d33cf8a03841a", null ], + [ "addTube", "group__compoundobjects.html#ga90ce3e295347f72bbd84322e491f7626", null ], + [ "addTube", "group__compoundobjects.html#ga622745a32ac6545e607b2dc18812dba9", null ], + [ "addTubeObject", "group__compoundobjects.html#ga51f79fece15fee384255237359563a18", null ], + [ "addTubeObject", "group__compoundobjects.html#gac244937b4bb6a2e57e6c2b25e59a741f", null ], + [ "addTubeObject", "group__compoundobjects.html#gad109dcdc4ae24e03945a8d39c0dc7cc5", null ], + [ "addTubeObject", "group__compoundobjects.html#ga0bb97aacf2830f27c1ad9b35609477c9", null ], + [ "addVoxel", "group__primitives.html#ga5c3476d33e4c6125276bcae114b49b10", null ], + [ "addVoxel", "group__primitives.html#gab03110bd9b0a7d4bdfedfe1e7881b6b0", null ], + [ "addVoxel", "classhelios_1_1_context.html#a16ca40cdd79ff77f7fab6506f0e06895", null ], + [ "addVoxel", "classhelios_1_1_context.html#a722c6b3018a5a4cd7a1ccdb06fe21c4b", null ], + [ "aggregatePrimitiveDataProduct", "classhelios_1_1_context.html#a66b69dc68ed0a21353485eff97257047", null ], + [ "aggregatePrimitiveDataSum", "classhelios_1_1_context.html#aad6f828c598f574cab637a263562bea2", null ], + [ "appendTubeSegment", "classhelios_1_1_context.html#a9d097ed9d14b9d575e494bf000ce33ec", null ], + [ "appendTubeSegment", "classhelios_1_1_context.html#a646f6a5449870a191fe3d60db849b190", null ], + [ "areObjectPrimitivesComplete", "classhelios_1_1_context.html#ad1ad7d600c2d436ae48d218c1aa19668", null ], + [ "calculatePrimitiveDataAreaWeightedMean", "classhelios_1_1_context.html#a57646963eb21eed16ced61fad28d176d", null ], + [ "calculatePrimitiveDataAreaWeightedMean", "classhelios_1_1_context.html#acbc8e2f6b09248ef0e1b4039ae49dc3f", null ], + [ "calculatePrimitiveDataAreaWeightedMean", "classhelios_1_1_context.html#a1aded7761f3571d8b162521308b6982a", null ], + [ "calculatePrimitiveDataAreaWeightedMean", "classhelios_1_1_context.html#af0ac56f7ead05e93c49ca64364e1de94", null ], + [ "calculatePrimitiveDataAreaWeightedMean", "classhelios_1_1_context.html#a8ecb78b9926d1a41b0d05ddc63de89cf", null ], + [ "calculatePrimitiveDataAreaWeightedSum", "classhelios_1_1_context.html#a074b0b3ba7069e416206ab3c84138b93", null ], + [ "calculatePrimitiveDataAreaWeightedSum", "classhelios_1_1_context.html#ac3f0cb99c782cc18b34c1565d83ea754", null ], + [ "calculatePrimitiveDataAreaWeightedSum", "classhelios_1_1_context.html#a715cddf9567a06b1f6a61fa10f08c145", null ], + [ "calculatePrimitiveDataAreaWeightedSum", "classhelios_1_1_context.html#af7b74178a6b1c7baa3efd06656a287d8", null ], + [ "calculatePrimitiveDataAreaWeightedSum", "classhelios_1_1_context.html#a8c269c7aafedc057c4cdbbfbb0ae050c", null ], + [ "calculatePrimitiveDataMean", "classhelios_1_1_context.html#a7ae0ab4e81a6359e4e5c290211869028", null ], + [ "calculatePrimitiveDataMean", "classhelios_1_1_context.html#a915ef6fe6a947427508e75a584150290", null ], + [ "calculatePrimitiveDataMean", "classhelios_1_1_context.html#acea0629aca8ecead44f6801ed8760e98", null ], + [ "calculatePrimitiveDataMean", "classhelios_1_1_context.html#a019706d872616a6ee74de1c763055b58", null ], + [ "calculatePrimitiveDataMean", "classhelios_1_1_context.html#a6ccd7935e4e453ae32bbd8ba704dbdd6", null ], + [ "calculatePrimitiveDataSum", "classhelios_1_1_context.html#a8da7a17942e11fa41938f022f9827cb8", null ], + [ "calculatePrimitiveDataSum", "classhelios_1_1_context.html#a4d5c413fd13de34ccbf63db430b84747", null ], + [ "calculatePrimitiveDataSum", "classhelios_1_1_context.html#a2166638f224b3d8c78c92699d1d6be06", null ], + [ "calculatePrimitiveDataSum", "classhelios_1_1_context.html#a0525d3480cc5136811cb779b81915db1", null ], + [ "calculatePrimitiveDataSum", "classhelios_1_1_context.html#a275251f326d7b04887307991fa7ec122", null ], + [ "cleanDeletedObjectIDs", "classhelios_1_1_context.html#a82d9c7f1149b51645f34b87f1d5e8b32", null ], + [ "cleanDeletedObjectIDs", "classhelios_1_1_context.html#a1bd5d91491521ff07c7d96e20349e21d", null ], + [ "cleanDeletedObjectIDs", "classhelios_1_1_context.html#af62f212e01997e02b9e6650984441c81", null ], + [ "cleanDeletedUUIDs", "classhelios_1_1_context.html#a2957986f92393ef6d429daa4927551dc", null ], + [ "cleanDeletedUUIDs", "classhelios_1_1_context.html#a13b8a75c8986e5461e26f559dc6e1675", null ], + [ "cleanDeletedUUIDs", "classhelios_1_1_context.html#a1f8686dea9f4b1029e1a13034492e725", null ], + [ "clearGlobalData", "classhelios_1_1_context.html#aa2facabc7384ac82a0e51acd59486ae8", null ], + [ "clearObjectData", "classhelios_1_1_context.html#abde8caac74d1da85a5f9503aba64be48", null ], + [ "clearObjectData", "classhelios_1_1_context.html#a6c96c0f3fbb3c31ae9aad750d647903b", null ], + [ "clearPrimitiveData", "classhelios_1_1_context.html#ab4cc7c915a03f7eb5dbbce24bbbc6903", null ], + [ "clearPrimitiveData", "classhelios_1_1_context.html#ac6ef3bc00a8d091f9408033af63f162b", null ], + [ "colorPrimitiveByDataPseudocolor", "classhelios_1_1_context.html#a77832cbf16fff127553ea797db74caa1", null ], + [ "colorPrimitiveByDataPseudocolor", "classhelios_1_1_context.html#a1a6a0cf71941e344dc086a13e49ddb78", null ], + [ "copyObject", "classhelios_1_1_context.html#a293850533a36a27b1403bbf1ae0da67d", null ], + [ "copyObject", "classhelios_1_1_context.html#a14f83860167c061e537f29f7754c12c3", null ], + [ "copyObjectData", "classhelios_1_1_context.html#ae36135cf1bcbbe48d170012e47818752", null ], + [ "copyPrimitive", "classhelios_1_1_context.html#a33af572acef6f81e93fe723cdc4eb501", null ], + [ "copyPrimitive", "classhelios_1_1_context.html#a7eb6409748de787c4a8f2cc10c290144", null ], + [ "copyPrimitiveData", "classhelios_1_1_context.html#a001b487c911a93940aa4d4621eda0053", null ], + [ "cropDomain", "classhelios_1_1_context.html#a646610820710e8012084aeb0fe0ec0f1", null ], + [ "cropDomain", "classhelios_1_1_context.html#aea4ea9dfed93b6e75cdc49ab3a94b023", null ], + [ "cropDomainX", "classhelios_1_1_context.html#a5a9ae91eb630bf727ce994e7d1c0fb40", null ], + [ "cropDomainY", "classhelios_1_1_context.html#a743a39dcf2a6688cc8aeabf79f6bc0b6", null ], + [ "cropDomainZ", "classhelios_1_1_context.html#a574cfb5f54a48a49d3a9f2b292f65786", null ], + [ "deleteObject", "classhelios_1_1_context.html#a690553ff4b945d117782addb96c5add0", null ], + [ "deleteObject", "classhelios_1_1_context.html#aaae58688c97d14257223911be4bb13e6", null ], + [ "deletePrimitive", "classhelios_1_1_context.html#a06b7dc6a572fcf33f499f249ea44db5a", null ], + [ "deletePrimitive", "classhelios_1_1_context.html#a24324ccb5318cb103846a71d44dda23e", null ], + [ "doesGlobalDataExist", "classhelios_1_1_context.html#a65ad9cb057b0cb2be3ef2734847608cc", null ], + [ "doesObjectContainPrimitive", "classhelios_1_1_context.html#a60b571dd1cfd525caedcfd725162721e", null ], + [ "doesObjectDataExist", "classhelios_1_1_context.html#a2834b9a6eee49d644f201f696ae5a4d5", null ], + [ "doesObjectExist", "classhelios_1_1_context.html#a9b410e55075482b8cbc549f9bf571541", null ], + [ "doesPrimitiveDataExist", "classhelios_1_1_context.html#a780d83edd66f25cd38b5059359b48a7b", null ], + [ "doesPrimitiveExist", "classhelios_1_1_context.html#a0c478e8ce47bfad4db16829f76305946", null ], + [ "doesPrimitiveExist", "classhelios_1_1_context.html#acf4a7fa9ba97f03d0a9218e5c4b7bc66", null ], + [ "doesTimeseriesVariableExist", "group__timeseries.html#ga8beaa8454ad248064b74698f7f0534a2", null ], + [ "duplicateGlobalData", "classhelios_1_1_context.html#ae89abaa03d7585e7f3abc6c5f16a0223", null ], + [ "duplicateObjectData", "classhelios_1_1_context.html#a613366ab9fdbfd69428535d5c1867b73", null ], + [ "duplicatePrimitiveData", "classhelios_1_1_context.html#a3796eae362aec38408e40a3a83b3d8a4", null ], + [ "duplicatePrimitiveData", "classhelios_1_1_context.html#a86be37149a98b13141175da5793d053e", null ], + [ "filterObjectsByData", "classhelios_1_1_context.html#a6263c6f3b15c1e66f7bd902f1da6d8a8", null ], + [ "filterObjectsByData", "classhelios_1_1_context.html#a05ee48c5e13900f8c9815954bb4c7b06", null ], + [ "filterObjectsByData", "classhelios_1_1_context.html#aaf93fbdf1f58127a5af34cc166247649", null ], + [ "filterObjectsByData", "classhelios_1_1_context.html#a6c14f758352ebe13c74ec4ebcb1d29a9", null ], + [ "filterObjectsByData", "classhelios_1_1_context.html#ac677208cd4aca4855e6681bff3a430b8", null ], + [ "filterObjectsByData", "classhelios_1_1_context.html#af5740b7d57d1b7fe2c7e699b498c66f0", null ], + [ "filterPrimitivesByData", "classhelios_1_1_context.html#a622fabc835cfed565c78fa6db6a34535", null ], + [ "filterPrimitivesByData", "classhelios_1_1_context.html#a93513af810192e6802d20a7e5579b005", null ], + [ "filterPrimitivesByData", "classhelios_1_1_context.html#a416b75bbf3ddf4ca0184df35651f41b7", null ], + [ "filterPrimitivesByData", "classhelios_1_1_context.html#a271237c1395c7460e89fcd25452d6d68", null ], + [ "filterPrimitivesByData", "classhelios_1_1_context.html#ad37d63ef2955fcef29ddcc6908055c1b", null ], + [ "getAllObjectIDs", "classhelios_1_1_context.html#a2ef355a3298b21313700acec64232e22", null ], + [ "getAllUUIDs", "classhelios_1_1_context.html#a98516632daccf958cca6b5b6582310bb", null ], + [ "getBoxObjectCenter", "classhelios_1_1_context.html#af73c44dace71ec805136b7d6ad6095a9", null ], + [ "getBoxObjectPointer", "classhelios_1_1_context.html#a1ecbb5a8cfa6764bade6e0650d2f6990", null ], + [ "getBoxObjectSize", "classhelios_1_1_context.html#a4e5799ba4b6a0a889f446bef9e4d3dc0", null ], + [ "getBoxObjectSubdivisionCount", "classhelios_1_1_context.html#a258f524d38cdeb5f6c83a7f387608490", null ], + [ "getBoxObjectVolume", "classhelios_1_1_context.html#ae31cc8855aacb6380a288a4b7fa8db82", null ], + [ "getConeObjectAxisUnitVector", "classhelios_1_1_context.html#acaa3fb162b17cb7f912162f5d4be894e", null ], + [ "getConeObjectLength", "classhelios_1_1_context.html#ad2b045f361aa8e8596bcf325c1707a25", null ], + [ "getConeObjectNode", "classhelios_1_1_context.html#a54e9f0b7c5014a37cd9d5bf74e7d5935", null ], + [ "getConeObjectNodeRadii", "classhelios_1_1_context.html#ade2608274b311c809d46bb13943b9e4e", null ], + [ "getConeObjectNodeRadius", "classhelios_1_1_context.html#af5acc5647e6bf9cd1649da1dec677110", null ], + [ "getConeObjectNodes", "classhelios_1_1_context.html#a8c4ec2d90ccd3d44a97597ecd80d78b6", null ], + [ "getConeObjectPointer", "classhelios_1_1_context.html#a3221051ea9c1025e8fb00d9dec01839f", null ], + [ "getConeObjectSubdivisionCount", "classhelios_1_1_context.html#a1ff97eb95d5896e096156320f5bd5ff0", null ], + [ "getConeObjectVolume", "classhelios_1_1_context.html#af6c1c571171be2604822a8df44d2349c", null ], + [ "getDate", "classhelios_1_1_context.html#a95dd5bc221cd8bcb4efabd0122d59b4f", null ], + [ "getDiskObjectCenter", "classhelios_1_1_context.html#a213aea1539e0bb38965cf2953b1831df", null ], + [ "getDiskObjectPointer", "classhelios_1_1_context.html#a17c1256a1f57fbae1f34e04b66b76ca8", null ], + [ "getDiskObjectSize", "classhelios_1_1_context.html#acee51918d3ee1d9892e5a51106a625d9", null ], + [ "getDiskObjectSubdivisionCount", "classhelios_1_1_context.html#a86ffc9a6cdcd3851231c64dcc152123c", null ], + [ "getDomainBoundingBox", "classhelios_1_1_context.html#ad4ac166bb01547d1cefb1ace7a9b966d", null ], + [ "getDomainBoundingBox", "classhelios_1_1_context.html#a8690412a63d1eff69e679e48d03c9838", null ], + [ "getDomainBoundingSphere", "classhelios_1_1_context.html#af3e048e969f06e3a0cf36ed3d76766ca", null ], + [ "getDomainBoundingSphere", "classhelios_1_1_context.html#a3a6b0d25c5d9febb17787982c9f09d63", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a8ec49c820f10831b4b27059d4d1749d6", null ], + [ "getGlobalData", "classhelios_1_1_context.html#ac1f5f6c3f24577cd5c4657c441483425", null ], + [ "getGlobalData", "classhelios_1_1_context.html#aea16d4845e23fe44ae1da4c032ea57e3", null ], + [ "getGlobalData", "classhelios_1_1_context.html#aba7c4fe63193509f40ca6682cddfa9a3", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a2b2f0570e50711f34bb24dc01c8a7b43", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a6f4d6971c05d78aff30b92d277014b9f", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a990fdccf51979e235a1acba08e54583b", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a3f621b536c3585d7f808698e2f0cd826", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a972fa4a45b2775f6047d41b88dc69d03", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a890583b0897bfcd730d137838fa7e155", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a66e7d689b62d9ad47fb85ad45664c97f", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a863264ab1339ba35c3754bfbf4c69eec", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a609563835616233b15fd263bb2e8857d", null ], + [ "getGlobalData", "classhelios_1_1_context.html#abbc6d463f6d722fca56ad219c8278c16", null ], + [ "getGlobalData", "classhelios_1_1_context.html#ad08d9d2bea2c93b14ae2b3678aea2e29", null ], + [ "getGlobalData", "classhelios_1_1_context.html#afc90a3d0143273e436541fc3bc9c5554", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a0376e2dc456e481bd055d5a84b7785f2", null ], + [ "getGlobalData", "classhelios_1_1_context.html#ab0f329c8584b002dda2d77719073bf5d", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a175d9a1955f428b0f2d6b11ab3b17659", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a0572c1557ec60ae7389072e8ab3c2113", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a931a92ba7e9916c64d164bc1f29ff754", null ], + [ "getGlobalData", "classhelios_1_1_context.html#a98cbb0d37dc9fafaad14184cb889534f", null ], + [ "getGlobalDataSize", "classhelios_1_1_context.html#a96d1060d1329dc467380ce2e5eafd559", null ], + [ "getGlobalDataType", "classhelios_1_1_context.html#a94bf0b919e5e6034fa45fbae2f575947", null ], + [ "getJulianDate", "classhelios_1_1_context.html#a23f2611ed71eeefe8cf772cab98de4d4", null ], + [ "getLoadedXMLFiles", "classhelios_1_1_context.html#a48a8a843b99c36ad357dba13ee6f1774", null ], + [ "getLocation", "classhelios_1_1_context.html#af4b1fa52419259a0c8a2faeb7484a439", null ], + [ "getMonthString", "classhelios_1_1_context.html#a6189f6ab35669f4fefde571ec362247c", null ], + [ "getObjectArea", "classhelios_1_1_context.html#aac46a608ec7719e4702cd861667925f1", null ], + [ "getObjectBoundingBox", "classhelios_1_1_context.html#ab5aef932bd4b64b1cee932423172ab6f", null ], + [ "getObjectBoundingBox", "classhelios_1_1_context.html#a1b9871bf670404adc1d952e59429ec38", null ], + [ "getObjectCenter", "classhelios_1_1_context.html#a4fe8ddd10f0d34bfe0b2a4aea648442a", null ], + [ "getObjectCount", "classhelios_1_1_context.html#a54b9c5503ad33d1dcc8f6a5c74f7ea76", null ], + [ "getObjectData", "classhelios_1_1_context.html#ae222f3351535f3aea35e76cbe2ca2d67", null ], + [ "getObjectData", "classhelios_1_1_context.html#a8935a9cdf6e34e72bcb636a97043a474", null ], + [ "getObjectData", "classhelios_1_1_context.html#a3511ff568337b501ca878c99d97c9b52", null ], + [ "getObjectData", "classhelios_1_1_context.html#ae56639e95fae8796545efde94fa84bcc", null ], + [ "getObjectData", "classhelios_1_1_context.html#ac58fc8f10c12dc54265491576650a0c6", null ], + [ "getObjectData", "classhelios_1_1_context.html#aa393d7b0f24855b2e54480be71c09ad2", null ], + [ "getObjectData", "classhelios_1_1_context.html#a1eae737b91ec70ae6490a8c403936975", null ], + [ "getObjectData", "classhelios_1_1_context.html#acda7f75e833791bcbd74ca8b37272a8b", null ], + [ "getObjectData", "classhelios_1_1_context.html#a293d899bb22cae1db8cf6c2cc813055d", null ], + [ "getObjectData", "classhelios_1_1_context.html#ae75ddc9a945ec876533211f52b8cd22e", null ], + [ "getObjectData", "classhelios_1_1_context.html#a39b169b41cf94516afd863f580c2b772", null ], + [ "getObjectData", "classhelios_1_1_context.html#ac097e42620523f2d57d28eecd02954a4", null ], + [ "getObjectData", "classhelios_1_1_context.html#a7ca032799776268d30fe185a76100e0e", null ], + [ "getObjectData", "classhelios_1_1_context.html#a158215e07c921d11e495b3805823b725", null ], + [ "getObjectData", "classhelios_1_1_context.html#a22d510fad177ca319bdac0a94ee8f069", null ], + [ "getObjectData", "classhelios_1_1_context.html#a2e691b7f0b630792f50b5423e23ebab1", null ], + [ "getObjectData", "classhelios_1_1_context.html#a6606603899859e211de9f56cd49bf92d", null ], + [ "getObjectData", "classhelios_1_1_context.html#ace5025b962226a75c4984ee6ecc21356", null ], + [ "getObjectData", "classhelios_1_1_context.html#abbd59cc4e7bcad35b43ea7240c4d5558", null ], + [ "getObjectData", "classhelios_1_1_context.html#af8fa05c716517966f7abcc2f4019c709", null ], + [ "getObjectData", "classhelios_1_1_context.html#a628cf051625e33549044cd20656519ac", null ], + [ "getObjectData", "classhelios_1_1_context.html#ac2b7e667ec37c88868ba0752919da1c9", null ], + [ "getObjectDataSize", "classhelios_1_1_context.html#ac251e9be64f3a35b6d2e6441c2a46f40", null ], + [ "getObjectDataType", "classhelios_1_1_context.html#af77ff3ea4a7668d2b5cb03bc6fc5f5b6", null ], + [ "getObjectPointer", "classhelios_1_1_context.html#a3d9493949db2c5d8ddeef30afd2a9a0a", null ], + [ "getObjectPrimitiveCount", "classhelios_1_1_context.html#a457ccd0bcf9870aef138b22c4a160aeb", null ], + [ "getObjectPrimitiveUUIDs", "classhelios_1_1_context.html#a266fba7ca4a0a1536c49f1e3ce918b1e", null ], + [ "getObjectPrimitiveUUIDs", "classhelios_1_1_context.html#a09e60fbbd3c4be1f8345a9de3695ccdd", null ], + [ "getObjectPrimitiveUUIDs", "classhelios_1_1_context.html#a7d0b3a6ca36b02702b06208a735a3b03", null ], + [ "getObjectTextureFile", "classhelios_1_1_context.html#aacd4cff3b170281516dcafb3fa83b84a", null ], + [ "getObjectTransformationMatrix", "classhelios_1_1_context.html#af9e972c138b0626cece9eea5f018b418", null ], + [ "getObjectType", "classhelios_1_1_context.html#a75ae3ee4580c4420059fe95755dc22d2", null ], + [ "getPatchCenter", "classhelios_1_1_context.html#a4165df43e5ab752e81bc2b7d7caf19d5", null ], + [ "getPatchSize", "classhelios_1_1_context.html#ab3f802aca8dd1930127d9f76358e71cf", null ], + [ "getPolymeshObjectPointer", "classhelios_1_1_context.html#a5a10781f6c1e24b226a32b1e1369f5c1", null ], + [ "getPolymeshObjectVolume", "classhelios_1_1_context.html#aad71b3e493ab0e47c6d4496d14e89803", null ], + [ "getPrimitiveArea", "classhelios_1_1_context.html#a1dafe58b3251d2ef9d09112258b2e85d", null ], + [ "getPrimitiveBoundingBox", "classhelios_1_1_context.html#a808527f76dec2683cbc168250c4f69be", null ], + [ "getPrimitiveBoundingBox", "classhelios_1_1_context.html#abf2e26ac2b32556878be6626a8876569", null ], + [ "getPrimitiveColor", "classhelios_1_1_context.html#a1223205f1080b0b7024b8f97950779b8", null ], + [ "getPrimitiveColorRGB", "classhelios_1_1_context.html#a8550633570ee91e4f09ec1464810bd7b", null ], + [ "getPrimitiveColorRGBA", "classhelios_1_1_context.html#a4e29adcb908d55172efd239f294b49e5", null ], + [ "getPrimitiveCount", "group__primitives.html#ga4d3447fb04c25e685bcc82599e2b173d", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a802b10b84762052e52b9ff1861604c58", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#aa54fb6e8a942845010ae669505adc2e8", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a2144eea981e4030c973287ce2c38315e", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a72ee49f503ff0c4937d9aa81b72689ed", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a18f0ede968126842068551834391e3ad", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#afe292fdf1d3c7983427c699e4a2eca3a", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#ad1a2ca668fb5f5043f23f7a50c22483f", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a65d1918df796575a5e5bc8c470ff3201", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a466dea76918a4bd02e4a355ab70f161b", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#ad1f6453da61e8e64ba91f589b7cc4eb0", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#ae76119a1083016c2cffed9eb443aaa62", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a5c37491d4bc0a1d69ffcaf214e6c2fe7", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a8ebaded3f143fc9c673765ab3fda5366", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a1d8cd543d68c2bc3b7ef876421284f15", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#add62ecdb7cc13510670c9c45bc8725a3", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#ab0fb70ff8b6e81901df14efe07ae7ff4", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a83619185959d1dae4570674a3855f808", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a29fed63e84bf5b5111b0e98f499da56e", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a420487af4a23ed5b527069c6471efd93", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a2ac5198c45a57b7926f4dbd9129fcad5", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#abbe503b705cfdeb903becdb7fb082dae", null ], + [ "getPrimitiveData", "classhelios_1_1_context.html#a0e62c9bb97e4cbbcd56518b060e9cae5", null ], + [ "getPrimitiveDataSize", "classhelios_1_1_context.html#a4b64585d356463ac759472f099660eca", null ], + [ "getPrimitiveDataType", "classhelios_1_1_context.html#a9c894ecd12e0d893c53ffcfa9e90c0b6", null ], + [ "getPrimitiveNormal", "classhelios_1_1_context.html#abfeadf8e6a35eb97da1439abc21c434e", null ], + [ "getPrimitiveParentObjectID", "classhelios_1_1_context.html#a2d3e254d04f913e590a645b54886436e", null ], + [ "getPrimitiveSolidFraction", "classhelios_1_1_context.html#a6e8a5e2044331158d69d6f9bd88fc0f7", null ], + [ "getPrimitiveTextureFile", "classhelios_1_1_context.html#a4fffad72d1ebb517d9c41837e448d4f5", null ], + [ "getPrimitiveTextureSize", "classhelios_1_1_context.html#a7fec62cbf2c2d56603b2750cbb4a4d9f", null ], + [ "getPrimitiveTextureTransparencyData", "classhelios_1_1_context.html#a98ad773979fff9efda47b44d71ac8e06", null ], + [ "getPrimitiveTextureUV", "classhelios_1_1_context.html#a5702f94aaba15bf6757aeb4d72d7774d", null ], + [ "getPrimitiveTransformationMatrix", "classhelios_1_1_context.html#a046e855d15fa88088be01adea38a67fd", null ], + [ "getPrimitiveType", "classhelios_1_1_context.html#a67bfd66f0a445f6485f1099f9eadc949", null ], + [ "getPrimitiveVertices", "classhelios_1_1_context.html#ae8542fd1452150d3302675a0a3d991ed", null ], + [ "getRandomGenerator", "classhelios_1_1_context.html#a96a928fa28d3d771ba310f798b56bd63", null ], + [ "getSphereObjectCenter", "classhelios_1_1_context.html#a4f75af0785498d14eb3f5a3539cb16b1", null ], + [ "getSphereObjectPointer", "classhelios_1_1_context.html#a8ed7580efa323c0f5e53e97d00e16c85", null ], + [ "getSphereObjectRadius", "classhelios_1_1_context.html#a5afb4fd92e9a726fb396779d1f2ae92b", null ], + [ "getSphereObjectSubdivisionCount", "classhelios_1_1_context.html#adadbc5a5378a874cd6705ed681fb9e6a", null ], + [ "getSphereObjectVolume", "classhelios_1_1_context.html#ae92df5975ec7fa257e7633d6551e2a87", null ], + [ "getTileObjectAreaRatio", "classhelios_1_1_context.html#afdebad3fd25bb8b9fa228020c3b11329", null ], + [ "getTileObjectAreaRatio", "classhelios_1_1_context.html#a9943834b21ccfb9ac1c519e47f959c92", null ], + [ "getTileObjectCenter", "classhelios_1_1_context.html#aa60f87c9bc771e613f60db73188a149d", null ], + [ "getTileObjectNormal", "classhelios_1_1_context.html#a64f4bcadff461357aa390d7f5dad2ba7", null ], + [ "getTileObjectPointer", "classhelios_1_1_context.html#ad2b762dd7b31126150c6e6dc350a3914", null ], + [ "getTileObjectSize", "classhelios_1_1_context.html#a457654b4a1f96a4979f83299dd9752df", null ], + [ "getTileObjectSubdivisionCount", "classhelios_1_1_context.html#a9320e4577eb131e7efe05677d30591b3", null ], + [ "getTileObjectTextureUV", "classhelios_1_1_context.html#a00718598a9c308dabe8fc24f85683210", null ], + [ "getTileObjectVertices", "classhelios_1_1_context.html#ab77b708ac6b39c1c5e8ecaa4988403b0", null ], + [ "getTime", "classhelios_1_1_context.html#a847ecbb2297e60220a23b67c39b0f6e2", null ], + [ "getTimeseriesLength", "group__timeseries.html#ga56d13f8c949e68137581a3c974790892", null ], + [ "getTriangleVertex", "classhelios_1_1_context.html#a846f93175f8b45f44237e88155af8fde", null ], + [ "getTubeObjectNodeColors", "classhelios_1_1_context.html#a7ad271dabb4291067f9a39d4c92e6ffd", null ], + [ "getTubeObjectNodeRadii", "classhelios_1_1_context.html#a6a58d8f1a8446a213d9a21e67ae8ed97", null ], + [ "getTubeObjectNodes", "classhelios_1_1_context.html#aa4650e7a0a16be12615870ff9a567ae3", null ], + [ "getTubeObjectPointer", "classhelios_1_1_context.html#ab26f963c75aa99d797a43860479910b0", null ], + [ "getTubeObjectSegmentVolume", "classhelios_1_1_context.html#a10928031db222e77e93ac8088f4b001d", null ], + [ "getTubeObjectSubdivisionCount", "classhelios_1_1_context.html#a272ba030971b86c7d3da57ff90784e0f", null ], + [ "getTubeObjectVolume", "classhelios_1_1_context.html#a56b82c3f009084451225003b2b461b6f", null ], + [ "getUniquePrimitiveParentObjectIDs", "classhelios_1_1_context.html#a18a276db8d3c1d754bbd1ca475deec82", null ], + [ "getUniquePrimitiveParentObjectIDs", "classhelios_1_1_context.html#a1f50af8c859a5b2ee0973c9ed5c10284", null ], + [ "getVoxelCenter", "classhelios_1_1_context.html#acadf5206cbfed7b8eaa2835702349cd9", null ], + [ "getVoxelSize", "classhelios_1_1_context.html#a6a3f85d4f29f8f7432b6ef605172a1cb", null ], + [ "hideObject", "classhelios_1_1_context.html#a983606fef144a460d4b987032a8ad005", null ], + [ "hidePrimitive", "classhelios_1_1_context.html#a8c68c830335865618227463fbb9d2663", null ], + [ "incrementGlobalData", "classhelios_1_1_context.html#a65bade6c654b836ff0c097b728a45dd4", null ], + [ "incrementGlobalData", "classhelios_1_1_context.html#a1c3d180b9f658fe61e2ae7aad2dac96f", null ], + [ "incrementGlobalData", "classhelios_1_1_context.html#ac5b4311cbca56d1d7f0d605d19adf6f9", null ], + [ "incrementGlobalData", "classhelios_1_1_context.html#ac09c095f00af2544ac74f5b18a7f6e9a", null ], + [ "incrementPrimitiveData", "classhelios_1_1_context.html#aa58aeb5e56184e6f0c696922d99ba4cc", null ], + [ "incrementPrimitiveData", "classhelios_1_1_context.html#a83fcbc3d3debc230c0a8df670d88b60c", null ], + [ "incrementPrimitiveData", "classhelios_1_1_context.html#a4fe0481b73bf5f6225b4b8a5a6c52d8e", null ], + [ "incrementPrimitiveData", "classhelios_1_1_context.html#aa1b4c2cd46df6941caf1e95e8c6876bb", null ], + [ "isGeometryDirty", "classhelios_1_1_context.html#a64f402ff71dd246be8c1b06699c05e26", null ], + [ "isObjectHidden", "classhelios_1_1_context.html#a084b7fb6ef0cec4a83207ce3c7f70843", null ], + [ "isPrimitiveHidden", "classhelios_1_1_context.html#a94d5c318d9f7edaf1f5410ad8b17e141", null ], + [ "isPrimitiveTextureColorOverridden", "classhelios_1_1_context.html#aaaa6de8a55765b258d6e65c52bf5df69", null ], + [ "listGlobalData", "classhelios_1_1_context.html#adf9a2febe48629536b06cdaa9903dbe3", null ], + [ "listObjectData", "classhelios_1_1_context.html#adc44dfce7e5dc7deaa42139795eee942", null ], + [ "listPrimitiveData", "classhelios_1_1_context.html#a7cb64e054e6dacbab27f31cd73852cc3", null ], + [ "listTimeseriesVariables", "classhelios_1_1_context.html#a0850fc1a35fd563e4008a4a152105307", null ], + [ "loadOBJ", "classhelios_1_1_context.html#a8657240a0b2926e8c73b083f0fdc339d", null ], + [ "loadOBJ", "classhelios_1_1_context.html#a7455810db826dfed35a36eb452e817a9", null ], + [ "loadOBJ", "classhelios_1_1_context.html#a90fd1a67dd60550207b1f29bfcd385ca", null ], + [ "loadOBJ", "classhelios_1_1_context.html#ae3014d59a9e1668cb84725a30fd8ef68", null ], + [ "loadPLY", "classhelios_1_1_context.html#a116724929091eabd6324047ed66cef85", null ], + [ "loadPLY", "classhelios_1_1_context.html#a8f1777b7f07ddfedaafac1c6d781c1d0", null ], + [ "loadPLY", "classhelios_1_1_context.html#a7965b2ac5e884fbbf067a2355aca497e", null ], + [ "loadPLY", "classhelios_1_1_context.html#a2748413487ea587e30b9d7be3ef61350", null ], + [ "loadPLY", "classhelios_1_1_context.html#a99cda26e82d56d9241b10346ce097010", null ], + [ "loadTabularTimeseriesData", "classhelios_1_1_context.html#a1dc9a0f79be2477c4873755586744e51", null ], + [ "loadXML", "classhelios_1_1_context.html#a129516a8fce035705a541e7b877eba2f", null ], + [ "markGeometryClean", "classhelios_1_1_context.html#a368852580048c62c2b16ebec000b35ed", null ], + [ "markGeometryDirty", "classhelios_1_1_context.html#aba4b1c6f469953791017770fd8c18fa1", null ], + [ "objectHasTexture", "classhelios_1_1_context.html#afbdf67c60f6a4efc93cd9526151d5d89", null ], + [ "operator=", "classhelios_1_1_context.html#aef8acffd049cf98f2544143188c164e2", null ], + [ "overrideObjectTextureColor", "classhelios_1_1_context.html#afe34537e4079b477f2eaf2b0e2e0d8a9", null ], + [ "overrideObjectTextureColor", "classhelios_1_1_context.html#a17e6824df31545c92187c6529122aada", null ], + [ "overridePrimitiveTextureColor", "classhelios_1_1_context.html#a7173c1deabbe8dd57791ff94bcdf0621", null ], + [ "overridePrimitiveTextureColor", "classhelios_1_1_context.html#a90df70161f5ded2f8a79e995464598e0", null ], + [ "primitiveTextureHasTransparencyChannel", "classhelios_1_1_context.html#a5e10a8afe134f4a55f65c81a9398c69c", null ], + [ "printObjectInfo", "classhelios_1_1_context.html#a963fbdd1d4c3d270d2eb8f49a22b274a", null ], + [ "printPrimitiveInfo", "classhelios_1_1_context.html#a355617da1f3faa4d01ca4d95425e9c0b", null ], + [ "pruneTubeNodes", "classhelios_1_1_context.html#a7e47d13895d9e65ae719e2afce8d1d54", null ], + [ "queryTimeseriesData", "group__timeseries.html#gab52bde84b96d02a4d928a610794ab146", null ], + [ "queryTimeseriesData", "group__timeseries.html#ga8845155a8f5df1e6db968b78f5a5fb18", null ], + [ "queryTimeseriesData", "group__timeseries.html#gadffd45c3717c9255d035ce098349ca74", null ], + [ "queryTimeseriesDate", "group__timeseries.html#gae15d53565b2a699d212de636318290b8", null ], + [ "queryTimeseriesTime", "group__timeseries.html#ga520b33fad86d1514ceb5eeafa52c81ef", null ], + [ "randn", "classhelios_1_1_context.html#a1792e2ad0a31efec76fecd1554e0aa07", null ], + [ "randn", "classhelios_1_1_context.html#a903aa1e3e016c522cac528c0377c0fe4", null ], + [ "randu", "classhelios_1_1_context.html#a4caa001e21890bca8bb952e1206153dc", null ], + [ "randu", "classhelios_1_1_context.html#a2f7842a2902bce8a8978a19aa9862a70", null ], + [ "randu", "classhelios_1_1_context.html#a4dfca3b6d71d2016661da51c38cac565", null ], + [ "renameGlobalData", "classhelios_1_1_context.html#a842cfdcdce20fb9fef8dc8703f12f1fa", null ], + [ "renameObjectData", "classhelios_1_1_context.html#aa34c4f240d760708cf845546cb6bdb93", null ], + [ "renamePrimitiveData", "classhelios_1_1_context.html#a5c76017adb8c397c3b2398861ee23c7d", null ], + [ "rotateObject", "classhelios_1_1_context.html#a54589e1ad3210184bde2c0f84df193c2", null ], + [ "rotateObject", "classhelios_1_1_context.html#a1a18c9a548406cbb4490e4ca7b75399b", null ], + [ "rotateObject", "classhelios_1_1_context.html#ae7904c86f3479719ed6f7da045546d29", null ], + [ "rotateObject", "classhelios_1_1_context.html#a3b4ffa6ef56001319b2b63703b9f2acd", null ], + [ "rotateObject", "classhelios_1_1_context.html#a7e40a23540dccd04d111b523759789e5", null ], + [ "rotateObject", "classhelios_1_1_context.html#a6b9587a6ccab5dd8aac367bf19a939d8", null ], + [ "rotatePrimitive", "classhelios_1_1_context.html#a236cf95ad565a77338bd45fe098e9b83", null ], + [ "rotatePrimitive", "classhelios_1_1_context.html#ae32a831a933122e64bc2bca4d23d3777", null ], + [ "rotatePrimitive", "classhelios_1_1_context.html#aca6e120f1607b07c71c4da83ab449813", null ], + [ "rotatePrimitive", "classhelios_1_1_context.html#a5e5dd3ef9b56a0bf148ed9d315422fe7", null ], + [ "rotatePrimitive", "classhelios_1_1_context.html#a55a61fb7f4a3829b04680dabb9a0276a", null ], + [ "rotatePrimitive", "classhelios_1_1_context.html#ac325bb44ad539aac6ce37d03ff51de3c", null ], + [ "scaleObject", "classhelios_1_1_context.html#a781c1e297264aa37c92f4b72eb5277c9", null ], + [ "scaleObject", "classhelios_1_1_context.html#afe9817e155de4a39bc82b000c5d0e888", null ], + [ "scaleObjectAboutCenter", "classhelios_1_1_context.html#a6f6e1b33ed92d3b852301a2ddef531d7", null ], + [ "scaleObjectAboutCenter", "classhelios_1_1_context.html#a72ccb742cc258704655c7fda792e58eb", null ], + [ "scaleObjectAboutPoint", "classhelios_1_1_context.html#ab5b5b78157ccf325cf3924630833c0e1", null ], + [ "scaleObjectAboutPoint", "classhelios_1_1_context.html#a0c84572898729e1a1d40415ad633066d", null ], + [ "scalePrimitive", "classhelios_1_1_context.html#a04cb06f3f2db846e6fbf725a0980259a", null ], + [ "scalePrimitive", "classhelios_1_1_context.html#aaeafd65954d09be5773fbdaba35c694e", null ], + [ "scalePrimitiveAboutPoint", "classhelios_1_1_context.html#aa5cc5ee1ba536b5b7565b780a272d6b4", null ], + [ "scalePrimitiveAboutPoint", "classhelios_1_1_context.html#ad510492e34ffad178aa3a47e7932093e", null ], + [ "scalePrimitiveData", "classhelios_1_1_context.html#ad307d199229f2fd1b36ad7efb4450696", null ], + [ "scalePrimitiveData", "classhelios_1_1_context.html#a0860253c22d51b274a8f63b806ff08c7", null ], + [ "scaleTubeGirth", "classhelios_1_1_context.html#aa77f3e51de5230a69bdd70c26c7173e6", null ], + [ "scaleTubeLength", "classhelios_1_1_context.html#a049755c6b0b7a3affa2c8dcdd0623935", null ], + [ "seedRandomGenerator", "classhelios_1_1_context.html#a337936c3123ff382da12cb37725170c1", null ], + [ "setCurrentTimeseriesPoint", "group__timeseries.html#ga3ca2e5c0a2c1983d552fd7ee57d04997", null ], + [ "setDate", "classhelios_1_1_context.html#a76a34480ca16cfde5e940d07235fcbbb", null ], + [ "setDate", "classhelios_1_1_context.html#a5b9565e477a321ec7b7b9b62d43b2139", null ], + [ "setDate", "classhelios_1_1_context.html#a810169fc94d22368ff83c357e13b0a61", null ], + [ "setGlobalData", "classhelios_1_1_context.html#a86ae444d6a565d3a53b40ab86d90e31f", null ], + [ "setGlobalData", "classhelios_1_1_context.html#a0cb1f9f692d9e2f225f148eedc180c3f", null ], + [ "setGlobalData", "classhelios_1_1_context.html#ae13ebc953481eb686436ad5c0ec0feef", null ], + [ "setGlobalData", "classhelios_1_1_context.html#a6244085c9792f55eecd47fcb1139d716", null ], + [ "setGlobalData", "classhelios_1_1_context.html#ad7503da3c31420ba92d4a4e2bec76ff9", null ], + [ "setGlobalData", "classhelios_1_1_context.html#a843249de363a1fff0ce37175c4731ac0", null ], + [ "setGlobalData", "classhelios_1_1_context.html#aede18efe430ee34910042933d8ed3810", null ], + [ "setGlobalData", "classhelios_1_1_context.html#a6dcd5f1df0ee040046f68cd1be8f05a1", null ], + [ "setGlobalData", "classhelios_1_1_context.html#aa92b28a9c26bbff7e5621e1c9dd48086", null ], + [ "setGlobalData", "classhelios_1_1_context.html#a526467937f59154a0c9a2915c5153d1e", null ], + [ "setGlobalData", "classhelios_1_1_context.html#a4218481857cdd07cae78f2b7808534b0", null ], + [ "setGlobalData", "classhelios_1_1_context.html#a05f1b6122de12b60a94ad9d8ad673ee7", null ], + [ "setLocation", "classhelios_1_1_context.html#adb901722158039153a7556ef06827e21", null ], + [ "setObjectColor", "classhelios_1_1_context.html#a53a30c9a819df9153025ef3b7e89c536", null ], + [ "setObjectColor", "classhelios_1_1_context.html#a41e1e95cb347f0ad25008f4fd128b0ff", null ], + [ "setObjectColor", "classhelios_1_1_context.html#a0c9146e4df91eeed82989fd89a436dcf", null ], + [ "setObjectColor", "classhelios_1_1_context.html#a62bdd296ce410e272e6f82a41c27935d", null ], + [ "setObjectData", "classhelios_1_1_context.html#aa4d8933f40fc51cab3abe9cfcdb34e7d", null ], + [ "setObjectData", "classhelios_1_1_context.html#add1f2dff968114e12cc8f2a8f7b364d9", null ], + [ "setObjectData", "classhelios_1_1_context.html#aeec21f6416d64e7a5b7dddbe3a07372a", null ], + [ "setObjectData", "classhelios_1_1_context.html#a80cc9fac3b3411d1470e8b7a37a9f867", null ], + [ "setObjectData", "classhelios_1_1_context.html#add40dc92c4e4d0fb1f7a2fc10da5214e", null ], + [ "setObjectData", "classhelios_1_1_context.html#af321368266e6b84665817b875deb530b", null ], + [ "setObjectData", "classhelios_1_1_context.html#aac050e413c74fc286f57a077ace9ad8a", null ], + [ "setObjectData", "classhelios_1_1_context.html#af85ecaf6d6d040258e66758e30739324", null ], + [ "setObjectData", "classhelios_1_1_context.html#aee97bd83087427bd59fcb287f5dc3531", null ], + [ "setObjectData", "classhelios_1_1_context.html#a638267ca0da2ad2070da281eaf34f04a", null ], + [ "setObjectData", "classhelios_1_1_context.html#a61b179ccebf291849bc79ac76de78940", null ], + [ "setObjectData", "classhelios_1_1_context.html#a80d2bd91fc42731a50b091b96c610660", null ], + [ "setObjectData", "classhelios_1_1_context.html#a11bc2418b81e2e771fdbb0cacde189ae", null ], + [ "setObjectData", "classhelios_1_1_context.html#ab30e197faaa31bc942ca6519d9212e64", null ], + [ "setObjectData", "classhelios_1_1_context.html#a410b495a7408fda18da26a815b76889d", null ], + [ "setObjectData", "classhelios_1_1_context.html#a503793f406ad42ab94e23cf890f6dd0b", null ], + [ "setObjectData", "classhelios_1_1_context.html#a01a97d15d63268ac511ca8859b4c68f8", null ], + [ "setObjectData", "classhelios_1_1_context.html#a33eb32f1916ccb4aa920d8e6adc3ae81", null ], + [ "setObjectData", "classhelios_1_1_context.html#a667a87b0fdd41ce1d01fe01e97b12d8d", null ], + [ "setObjectData", "classhelios_1_1_context.html#a86111a5ee990e7d4fd0cf45ba676d776", null ], + [ "setObjectData", "classhelios_1_1_context.html#a4a90397534b17c91d2a5897c0fa4e110", null ], + [ "setObjectData", "classhelios_1_1_context.html#ac35897c934684bf6bc274b06d67dc10c", null ], + [ "setObjectData", "classhelios_1_1_context.html#ab023969f177745818be2bb909fbf97c0", null ], + [ "setObjectData", "classhelios_1_1_context.html#a8423c26081c83aeaf24e9d3002449450", null ], + [ "setObjectData", "classhelios_1_1_context.html#aacd2386732ad774427ea7e034bf5642b", null ], + [ "setObjectData", "classhelios_1_1_context.html#a6d12369392b2092af37bd64b904021f6", null ], + [ "setObjectData", "classhelios_1_1_context.html#aaf0447235525b6f26c706b06f159446e", null ], + [ "setObjectData", "classhelios_1_1_context.html#a55584d6bd6e20c67375cf91c6d56ec91", null ], + [ "setObjectData", "classhelios_1_1_context.html#ac97287d999956f8e689ea6df0d035516", null ], + [ "setObjectData", "classhelios_1_1_context.html#a05b21f0772970223c636f32ab2cd51ec", null ], + [ "setObjectData", "classhelios_1_1_context.html#af1cfa4877dd8e1ecc1dca0e819378ff6", null ], + [ "setObjectData", "classhelios_1_1_context.html#a2e2a4371cd1af5af7ee256db1c5f3f94", null ], + [ "setObjectData", "classhelios_1_1_context.html#af2f608a87e8b8552e9cb3632a24c3ab9", null ], + [ "setObjectData", "classhelios_1_1_context.html#a65866490e5eca5169c8865038bbad7a0", null ], + [ "setObjectData", "classhelios_1_1_context.html#a43a3a8d47b237941ff8cb5a8e37bec0c", null ], + [ "setObjectData", "classhelios_1_1_context.html#a862846ca49277adcee6350e598999743", null ], + [ "setObjectData", "classhelios_1_1_context.html#ac20d7c0ffe64e39835be77b4d0932a1b", null ], + [ "setObjectData", "classhelios_1_1_context.html#a0345eb747604912fe02af987e0b5950a", null ], + [ "setObjectData", "classhelios_1_1_context.html#a476c80474522dfa1b1e24e7ea2aaba41", null ], + [ "setObjectData", "classhelios_1_1_context.html#a2513df3e1520fde62df047d62d7e6645", null ], + [ "setObjectData", "classhelios_1_1_context.html#a9fe071caed6756577d147c130e10f6aa", null ], + [ "setObjectData", "classhelios_1_1_context.html#a6ad7971a0c42fcf3b185d92354cb95b2", null ], + [ "setObjectData", "classhelios_1_1_context.html#ace339d1e727d6aa4308e9153ea0df480", null ], + [ "setObjectData", "classhelios_1_1_context.html#a13c69bf3d81189d4a0c93409ba0d9207", null ], + [ "setObjectData", "classhelios_1_1_context.html#ab25c2b85edded276a5e100702c63c07e", null ], + [ "setObjectTransformationMatrix", "classhelios_1_1_context.html#a31d7cc0676201cf2513e7c4c87ed7481", null ], + [ "setObjectTransformationMatrix", "classhelios_1_1_context.html#ae9627595f57c55b4c540d239fa7889e1", null ], + [ "setPrimitiveColor", "classhelios_1_1_context.html#aa4e3d7f71aaa0823edd9341b3c2d786c", null ], + [ "setPrimitiveColor", "classhelios_1_1_context.html#af445c8f33a279ce7374d1b2691ef1f1c", null ], + [ "setPrimitiveColor", "classhelios_1_1_context.html#a22dce781917215d2e80784ae5eb78d60", null ], + [ "setPrimitiveColor", "classhelios_1_1_context.html#a029f95ee0056f027866f8bad2fe9e48e", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a67cd49500d77ca6308b9d78a19bf88e1", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#aae92b01f3ddb4cc429201690915d40d1", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a1f4e4e874b0aa4419616044086267d65", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#aaeb1ac9f83289382d93f7f928678e43d", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a2eb91839363153ca1f35feabf41043eb", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a1804c156ced6f5170c2598a08bcef591", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a952aab995b6549ebd30204c84666f315", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#aa8b86ea5363d7a88b7954385320f72d3", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a9c4326dc8d8c8b7e195b9a1ba76ac59f", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a9e9465353484026f03c8b1bf531a5258", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#af083c0cb69b3d9550848a9995b8feb18", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#aace047cba0c9e4c1eff9576d972c1911", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#ae93791b3c29ac4879451bcbe16d76956", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a0ae4cb43e3ef7a1e2de9471480549252", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a86baeff8b954def960e6c99ebbb10c86", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#acd544b707254a434620527f7df1014a5", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a2704360051e07066eff51e8056b4aa46", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a6af8952525fc82f010e800fa36a67719", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a7eac4377c1c06b4967f0817386ff0b4f", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a0946dae4ec20fe3ea42ad8e5bec56767", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a6ff3779ada111fc103a7ecefa6a8a736", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a643cfcaed693097e98c340c6c9e8d5d2", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#accd3e2ac5a3d87d6232fc22b83bcda12", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a075ecb2de0d5239188a643b1bd937396", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a28ab165fde1de4555e832ec7dd6bfcbb", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#af54a5f531284ea6b04be4cfb99db7d06", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a0293ea9fb3750432f27f716d46d61f7b", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a5cc520e5d9325eca45103430dc5c93be", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a8ad05382759041555c89c26069f30e48", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a7a8797c39a45b7e265edd7741b2510e5", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#acff5da084e7c9d2c90c73edca24c07d3", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#aaf69d2f0621b95dfadcccae2594c5645", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#aa3a6f6eae58a58be9d212b0c3956eaf9", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a16457aac3e2c40890c2d05bbf4d36e3d", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a5271a627fdfd0731cfde8016fbc42652", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#ad87da629799dd7cd5469676675145f37", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a9d7bc32ca67260588402ca9999326ecb", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a135888cd244b54848cc6117613e0bf5d", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a480acac6101b32110856aabe4c674ad1", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a9512442e3771220e49946af21db01b9b", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#aaae3a5abba76fd76b37f3488522a9ef2", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#ac7677094a3bbcb62506ce461d982af1d", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a8002c535b841c78d0ec9430362186c9e", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a62ee96ec6df77c6451a6c67efd4d67da", null ], + [ "setPrimitiveData", "classhelios_1_1_context.html#a866183b15bb63a464a7de9de0faef0f4", null ], + [ "setPrimitiveParentObjectID", "classhelios_1_1_context.html#ac97ab81d1324437cadae575a76f5ef80", null ], + [ "setPrimitiveParentObjectID", "classhelios_1_1_context.html#a5d7974e92bd4ac128ffae0c36cfad85d", null ], + [ "setPrimitiveTextureFile", "classhelios_1_1_context.html#a89466d607b5499cbee7614c425270570", null ], + [ "setPrimitiveTransformationMatrix", "classhelios_1_1_context.html#a9447c0c5ad7f1f19d606f227d164f679", null ], + [ "setPrimitiveTransformationMatrix", "classhelios_1_1_context.html#af7d8333251195bcc4788792d9aa6f37c", null ], + [ "setTileObjectSubdivisionCount", "classhelios_1_1_context.html#a01957c516d832789a0fe613accc71f72", null ], + [ "setTileObjectSubdivisionCount", "classhelios_1_1_context.html#a14626fb1701c57a683418b9b9d442913", null ], + [ "setTime", "classhelios_1_1_context.html#ad40aa40adbee471a588a1e32eb721db4", null ], + [ "setTime", "classhelios_1_1_context.html#ae3d9e19581787775556b8dd7dc1ac845", null ], + [ "setTime", "classhelios_1_1_context.html#a940a77e10a3210bcf3b292e029cc3fda", null ], + [ "setTriangleVertices", "classhelios_1_1_context.html#a639c36e288b6a154ee6a827a9e497351", null ], + [ "setTubeNodes", "classhelios_1_1_context.html#af3076c6a493bb0b888882adee34d039e", null ], + [ "setTubeRadii", "classhelios_1_1_context.html#afbbb8692fb22c4c7475738556af0ec6a", null ], + [ "sumPrimitiveSurfaceArea", "classhelios_1_1_context.html#af7fae7c44d5608b23016300d8a917d9a", null ], + [ "translateObject", "classhelios_1_1_context.html#a886b95e094bc80e95c602e9e81b568ad", null ], + [ "translateObject", "classhelios_1_1_context.html#a70805980c2c201082507dcfdde4399d1", null ], + [ "translatePrimitive", "classhelios_1_1_context.html#a1e98dca73f3e6282b2d1c3a0458b14a4", null ], + [ "translatePrimitive", "classhelios_1_1_context.html#a1ae827c4e0c90a883430bd1db95993e1", null ], + [ "useObjectTextureColor", "classhelios_1_1_context.html#a92457a1277ce0e5918e20007193001bf", null ], + [ "useObjectTextureColor", "classhelios_1_1_context.html#ad58362537512f6df9028a60181d88af0", null ], + [ "usePrimitiveTextureColor", "classhelios_1_1_context.html#a563083497cce82f251e0eaf238cb3600", null ], + [ "usePrimitiveTextureColor", "classhelios_1_1_context.html#a60aaa1a72ff6ebcd28c48b7dfbc3ca7c", null ], + [ "writeOBJ", "classhelios_1_1_context.html#a8249b03fa781c9382863b7cf2caf0dd8", null ], + [ "writeOBJ", "classhelios_1_1_context.html#a8a5040ff4aaa061eddabe881ac668a01", null ], + [ "writeOBJ", "classhelios_1_1_context.html#ae976f6626930c925c8fdacb543e1e923", null ], + [ "writePLY", "classhelios_1_1_context.html#aa47b8b6f8cefb3c9d55a3cda10d851d7", null ], + [ "writePrimitiveData", "classhelios_1_1_context.html#ab643fc787ea7b1a215605c369f446844", null ], + [ "writePrimitiveData", "classhelios_1_1_context.html#a97378b12bfaf42c2052960c54ff096d4", null ], + [ "writeXML", "classhelios_1_1_context.html#abfcac5a56c13e86298609ed3fccf354d", null ], + [ "writeXML", "classhelios_1_1_context.html#a499545512efe3645e2085e4815dcb94e", null ], + [ "writeXML_byobject", "classhelios_1_1_context.html#ae2ada2bfdce5226cd970a6e6fa0ccc88", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_disk.html b/doc/html/classhelios_1_1_disk.html index f096342f1..ce102e1f7 100644 --- a/doc/html/classhelios_1_1_disk.html +++ b/doc/html/classhelios_1_1_disk.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Public Member Functions | @@ -348,7 +354,7 @@

Detailed Description

Disk compound object class.

-

Definition at line 795 of file Context.h.

+

Definition at line 801 of file Context.h.

Constructor & Destructor Documentation

◆ Disk()

@@ -386,7 +392,7 @@

Definition at line 4009 of file Context.cpp.

+

Definition at line 4036 of file Context.cpp.

@@ -408,7 +414,7 @@

Definition at line 4045 of file Context.cpp.

+

Definition at line 4072 of file Context.cpp.

@@ -429,7 +435,7 @@

Definition at line 4029 of file Context.cpp.

+

Definition at line 4056 of file Context.cpp.

@@ -450,7 +456,7 @@

Definition at line 4061 of file Context.cpp.

+

Definition at line 4088 of file Context.cpp.

@@ -477,7 +483,7 @@

Definition at line 4065 of file Context.cpp.

+

Definition at line 4092 of file Context.cpp.

@@ -497,12 +503,12 @@

-friend +friend
-

Definition at line 823 of file Context.h.

+

Definition at line 829 of file Context.h.

@@ -511,10 +517,13 @@

Context.cpp - - + + diff --git a/doc/html/classhelios_1_1_disk.js b/doc/html/classhelios_1_1_disk.js new file mode 100644 index 000000000..cdaba48a4 --- /dev/null +++ b/doc/html/classhelios_1_1_disk.js @@ -0,0 +1,9 @@ +var classhelios_1_1_disk = +[ + [ "Disk", "classhelios_1_1_disk.html#aedc5a15466aa7b07a76605473a00ba15", null ], + [ "~Disk", "classhelios_1_1_disk.html#aa670ffa43a0cf0570ea1d789cb8653a5", null ], + [ "getCenter", "classhelios_1_1_disk.html#ae8ed884a95cbfa2440e3bd9f8e3e4057", null ], + [ "getSize", "classhelios_1_1_disk.html#a23c03df1f2e351659a08420a41a74eb5", null ], + [ "getSubdivisionCount", "classhelios_1_1_disk.html#a8dc2a195735ee3321b274274e7e0352e", null ], + [ "setSubdivisionCount", "classhelios_1_1_disk.html#af3481e8589adbf120be158a591b0acda", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_polymesh.html b/doc/html/classhelios_1_1_polymesh.html index fd8440fca..6860a8e7b 100644 --- a/doc/html/classhelios_1_1_polymesh.html +++ b/doc/html/classhelios_1_1_polymesh.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Public Member Functions | @@ -339,7 +345,7 @@

Detailed Description

Polymesh compound object class.

-

Definition at line 828 of file Context.h.

+

Definition at line 834 of file Context.h.

Constructor & Destructor Documentation

◆ Polymesh()

@@ -372,7 +378,7 @@

Definition at line 4069 of file Context.cpp.

+

Definition at line 4096 of file Context.cpp.

@@ -394,7 +400,7 @@

Definition at line 4088 of file Context.cpp.

+

Definition at line 4115 of file Context.cpp.

@@ -414,12 +420,12 @@

-friend +friend
-

Definition at line 842 of file Context.h.

+

Definition at line 848 of file Context.h.

@@ -428,10 +434,13 @@

Context.cpp - - + + diff --git a/doc/html/classhelios_1_1_polymesh.js b/doc/html/classhelios_1_1_polymesh.js new file mode 100644 index 000000000..3f7e86e1b --- /dev/null +++ b/doc/html/classhelios_1_1_polymesh.js @@ -0,0 +1,6 @@ +var classhelios_1_1_polymesh = +[ + [ "Polymesh", "classhelios_1_1_polymesh.html#a4a3c02f97dac295f584090ccd622cb94", null ], + [ "~Polymesh", "classhelios_1_1_polymesh.html#a19617972bebd43a3bff944250fc7ddb1", null ], + [ "getVolume", "classhelios_1_1_polymesh.html#ad901c4de0e202f44c16fc9af29481538", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_sphere.html b/doc/html/classhelios_1_1_sphere.html index f1db431fa..9468d339b 100644 --- a/doc/html/classhelios_1_1_sphere.html +++ b/doc/html/classhelios_1_1_sphere.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
- -
+ + diff --git a/doc/html/classhelios_1_1_sphere.js b/doc/html/classhelios_1_1_sphere.js new file mode 100644 index 000000000..f55e557cc --- /dev/null +++ b/doc/html/classhelios_1_1_sphere.js @@ -0,0 +1,10 @@ +var classhelios_1_1_sphere = +[ + [ "Sphere", "classhelios_1_1_sphere.html#a4b215db8d3d2c52925b5bdd8b5b02eae", null ], + [ "~Sphere", "classhelios_1_1_sphere.html#ae7e8121c9a60f9c4e4efa853fd2cee59", null ], + [ "getCenter", "classhelios_1_1_sphere.html#a48eada17c3dab899a91158f1424518d6", null ], + [ "getRadius", "classhelios_1_1_sphere.html#a38cf8b6959d22577a1a2f9a6c675bc8b", null ], + [ "getSubdivisionCount", "classhelios_1_1_sphere.html#a152107e463d6765ba27ff8f3ab737711", null ], + [ "getVolume", "classhelios_1_1_sphere.html#a3d6a8e9f8c0daee1e093593d6006c906", null ], + [ "setSubdivisionCount", "classhelios_1_1_sphere.html#a7e215edcae37bcd70051deea1bfb59eb", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_texture.html b/doc/html/classhelios_1_1_texture.html index ac3125636..ef0257dbc 100644 --- a/doc/html/classhelios_1_1_texture.html +++ b/doc/html/classhelios_1_1_texture.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
- + + diff --git a/doc/html/classhelios_1_1_texture.js b/doc/html/classhelios_1_1_texture.js new file mode 100644 index 000000000..893e2c74d --- /dev/null +++ b/doc/html/classhelios_1_1_texture.js @@ -0,0 +1,9 @@ +var classhelios_1_1_texture = +[ + [ "Texture", "classhelios_1_1_texture.html#a219d0c23431e27022fbac3c0b38befd6", null ], + [ "getImageResolution", "classhelios_1_1_texture.html#a4e106c0c80f0c4c065e5ff71193aaeab", null ], + [ "getSolidFraction", "classhelios_1_1_texture.html#a685024e8394b49433f26a0dcd6665d86", null ], + [ "getTextureFile", "classhelios_1_1_texture.html#a0371473a81deb9bb19b8274109b75ef8", null ], + [ "getTransparencyData", "classhelios_1_1_texture.html#a798c3a24b21fc853db299d1f1f84a61c", null ], + [ "hasTransparencyChannel", "classhelios_1_1_texture.html#a44d0d36861494725a85bfbc100f398da", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_tile.html b/doc/html/classhelios_1_1_tile.html index 4da934211..ec2de556d 100644 --- a/doc/html/classhelios_1_1_tile.html +++ b/doc/html/classhelios_1_1_tile.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
- -
+ + diff --git a/doc/html/classhelios_1_1_tile.js b/doc/html/classhelios_1_1_tile.js new file mode 100644 index 000000000..fb61e30f5 --- /dev/null +++ b/doc/html/classhelios_1_1_tile.js @@ -0,0 +1,12 @@ +var classhelios_1_1_tile = +[ + [ "Tile", "classhelios_1_1_tile.html#ae7a684eae38bd9f5b3397962cd1a2774", null ], + [ "~Tile", "classhelios_1_1_tile.html#a001e45730aa531c75c90a599b5524956", null ], + [ "getCenter", "classhelios_1_1_tile.html#a18178d0280f8ecc1149663558947ca06", null ], + [ "getNormal", "classhelios_1_1_tile.html#ab8c70daf8c14bc60caf499b5adce301c", null ], + [ "getSize", "classhelios_1_1_tile.html#aa8daadd99bd57f647837e26890fcfeac", null ], + [ "getSubdivisionCount", "classhelios_1_1_tile.html#a4f4198becfe3cafd989b5aa6cd21d5cf", null ], + [ "getTextureUV", "classhelios_1_1_tile.html#a94deb25ac31abc1eb02dfe6913b4546f", null ], + [ "getVertices", "classhelios_1_1_tile.html#aaea21403039646db33792c95be929afd", null ], + [ "setSubdivisionCount", "classhelios_1_1_tile.html#a8d9bd065c9607ccb2ac0b20e945fb51f", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_tube.html b/doc/html/classhelios_1_1_tube.html index b33088db5..ea238b890 100644 --- a/doc/html/classhelios_1_1_tube.html +++ b/doc/html/classhelios_1_1_tube.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Public Member Functions | @@ -173,6 +179,9 @@ void setTubeNodes (const std::vector< helios::vec3 > &node_xyz)  Set tube vertex coordinates at each segment node.
  +void pruneTubeNodes (uint node_index) + Remove a portion of the tube downstream of a specified node.
- Public Member Functions inherited from helios::CompoundObject uint getObjectID () const  Get the unique identifier for the object.
@@ -695,6 +704,33 @@

Definition at line 3547 of file Context.cpp.

+

+
+ +

◆ pruneTubeNodes()

+ +
+
+ + + + + + + +
void Tube::pruneTubeNodes (uint node_index)
+
+ +

Remove a portion of the tube downstream of a specified node.

+
Parameters
+ + +
[in]node_indexIndex of the tube segment node beyond which will be removed
+
+
+ +

Definition at line 3916 of file Context.cpp.

+
@@ -821,12 +857,12 @@

-friend +friend

-

Definition at line 754 of file Context.h.

+

Definition at line 760 of file Context.h.

@@ -835,10 +871,13 @@

Context.cpp - - + + diff --git a/doc/html/classhelios_1_1_tube.js b/doc/html/classhelios_1_1_tube.js new file mode 100644 index 000000000..2353f0b00 --- /dev/null +++ b/doc/html/classhelios_1_1_tube.js @@ -0,0 +1,20 @@ +var classhelios_1_1_tube = +[ + [ "Tube", "classhelios_1_1_tube.html#a10d74e5d06813e05c2b188ee170339c9", null ], + [ "~Tube", "classhelios_1_1_tube.html#a15d0248cb525ce91129abcb398f728e8", null ], + [ "appendTubeSegment", "classhelios_1_1_tube.html#a7cb8cf830e6017d29c7396c28846f83b", null ], + [ "appendTubeSegment", "classhelios_1_1_tube.html#aac259b1a564be7ac9cc11bd14ab8cf82", null ], + [ "getLength", "classhelios_1_1_tube.html#ad3c194a0f9977e212ac425aefe4032bf", null ], + [ "getNodeColors", "classhelios_1_1_tube.html#aae753418cb304e97c296240dc9919388", null ], + [ "getNodeRadii", "classhelios_1_1_tube.html#a29823b956371d22b35add97fc6831cab", null ], + [ "getNodes", "classhelios_1_1_tube.html#ab55e8f7d7a948941027f169d714e365b", null ], + [ "getSegmentVolume", "classhelios_1_1_tube.html#a2966ff764897904282082f23a76756b8", null ], + [ "getSubdivisionCount", "classhelios_1_1_tube.html#abf9bb1153b3607a5d616aafeee06e43e", null ], + [ "getTriangleVertices", "classhelios_1_1_tube.html#a6aedd14e533981bd79497ba13b33f2c9", null ], + [ "getVolume", "classhelios_1_1_tube.html#aaa11cc27d6f704a989c3e5b0fe1b8055", null ], + [ "pruneTubeNodes", "classhelios_1_1_tube.html#a4d8bc6d05dab160f3e0fbee48ad3fd2c", null ], + [ "scaleTubeGirth", "classhelios_1_1_tube.html#a3fafe2daf9caaf3590e2c3fe2cecc914", null ], + [ "scaleTubeLength", "classhelios_1_1_tube.html#aceabd5281c442abf90725bb3728caf8b", null ], + [ "setTubeNodes", "classhelios_1_1_tube.html#ae11824e0497c6a97e912e341da388a7d", null ], + [ "setTubeRadii", "classhelios_1_1_tube.html#a50362d071c320d6ec8d5aa9b26c5570f", null ] +]; \ No newline at end of file diff --git a/doc/html/classhelios_1_1_x_m_lparser.html b/doc/html/classhelios_1_1_x_m_lparser.html index c8887b2ff..8f8c09116 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
- + + diff --git a/doc/html/clipboard.js b/doc/html/clipboard.js index 42c1fb0e0..9da9f3ca4 100644 --- a/doc/html/clipboard.js +++ b/doc/html/clipboard.js @@ -28,8 +28,8 @@ SOFTWARE. */ let clipboard_title = "Copy to clipboard" -let clipboard_icon = `` -let clipboard_successIcon = `` +let clipboard_icon = `` +let clipboard_successIcon = `` let clipboard_successDuration = 1000 $(function() { diff --git a/doc/html/cmake-build-release_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html b/doc/html/cmake-build-release_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html new file mode 100644 index 000000000..5ad64e76f --- /dev/null +++ b/doc/html/cmake-build-release_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html @@ -0,0 +1,992 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
CMakeCXXCompilerId.cpp
+
+
+
1/* This source file must have a .cpp extension so that all C++ compilers
+
2 recognize the extension without flags. Borland does not know .cxx for
+
3 example. */
+
4#ifndef __cplusplus
+
5# error "A C compiler has been selected for C++."
+
6#endif
+
7
+
8#if !defined(__has_include)
+
9/* If the compiler does not have __has_include, pretend the answer is
+
10 always no. */
+
11# define __has_include(x) 0
+
12#endif
+
13
+
14
+
15/* Version number components: V=Version, R=Revision, P=Patch
+
16 Version date components: YYYY=Year, MM=Month, DD=Day */
+
17
+
18#if defined(__COMO__)
+
19# define COMPILER_ID "Comeau"
+
20 /* __COMO_VERSION__ = VRR */
+
21# define COMPILER_VERSION_MAJOR DEC(__COMO_VERSION__ / 100)
+
22# define COMPILER_VERSION_MINOR DEC(__COMO_VERSION__ % 100)
+
23
+
24#elif defined(__INTEL_COMPILER) || defined(__ICC)
+
25# define COMPILER_ID "Intel"
+
26# if defined(_MSC_VER)
+
27# define SIMULATE_ID "MSVC"
+
28# endif
+
29# if defined(__GNUC__)
+
30# define SIMULATE_ID "GNU"
+
31# endif
+
32 /* __INTEL_COMPILER = VRP prior to 2021, and then VVVV for 2021 and later,
+
33 except that a few beta releases use the old format with V=2021. */
+
34# if __INTEL_COMPILER < 2021 || __INTEL_COMPILER == 202110 || __INTEL_COMPILER == 202111
+
35# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100)
+
36# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10)
+
37# if defined(__INTEL_COMPILER_UPDATE)
+
38# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER_UPDATE)
+
39# else
+
40# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10)
+
41# endif
+
42# else
+
43# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER)
+
44# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER_UPDATE)
+
45 /* The third version component from --version is an update index,
+
46 but no macro is provided for it. */
+
47# define COMPILER_VERSION_PATCH DEC(0)
+
48# endif
+
49# if defined(__INTEL_COMPILER_BUILD_DATE)
+
50 /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */
+
51# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE)
+
52# endif
+
53# if defined(_MSC_VER)
+
54 /* _MSC_VER = VVRR */
+
55# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+
56# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+
57# endif
+
58# if defined(__GNUC__)
+
59# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+
60# elif defined(__GNUG__)
+
61# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+
62# endif
+
63# if defined(__GNUC_MINOR__)
+
64# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+
65# endif
+
66# if defined(__GNUC_PATCHLEVEL__)
+
67# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+
68# endif
+
69
+
70#elif (defined(__clang__) && defined(__INTEL_CLANG_COMPILER)) || defined(__INTEL_LLVM_COMPILER)
+
71# define COMPILER_ID "IntelLLVM"
+
72#if defined(_MSC_VER)
+
73# define SIMULATE_ID "MSVC"
+
74#endif
+
75#if defined(__GNUC__)
+
76# define SIMULATE_ID "GNU"
+
77#endif
+
78/* __INTEL_LLVM_COMPILER = VVVVRP prior to 2021.2.0, VVVVRRPP for 2021.2.0 and
+
79 * later. Look for 6 digit vs. 8 digit version number to decide encoding.
+
80 * VVVV is no smaller than the current year when a version is released.
+
81 */
+
82#if __INTEL_LLVM_COMPILER < 1000000L
+
83# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/100)
+
84# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/10 % 10)
+
85# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 10)
+
86#else
+
87# define COMPILER_VERSION_MAJOR DEC(__INTEL_LLVM_COMPILER/10000)
+
88# define COMPILER_VERSION_MINOR DEC(__INTEL_LLVM_COMPILER/100 % 100)
+
89# define COMPILER_VERSION_PATCH DEC(__INTEL_LLVM_COMPILER % 100)
+
90#endif
+
91#if defined(_MSC_VER)
+
92 /* _MSC_VER = VVRR */
+
93# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+
94# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+
95#endif
+
96#if defined(__GNUC__)
+
97# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+
98#elif defined(__GNUG__)
+
99# define SIMULATE_VERSION_MAJOR DEC(__GNUG__)
+
100#endif
+
101#if defined(__GNUC_MINOR__)
+
102# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+
103#endif
+
104#if defined(__GNUC_PATCHLEVEL__)
+
105# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+
106#endif
+
107
+
108#elif defined(__PATHCC__)
+
109# define COMPILER_ID "PathScale"
+
110# define COMPILER_VERSION_MAJOR DEC(__PATHCC__)
+
111# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__)
+
112# if defined(__PATHCC_PATCHLEVEL__)
+
113# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__)
+
114# endif
+
115
+
116#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__)
+
117# define COMPILER_ID "Embarcadero"
+
118# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF)
+
119# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF)
+
120# define COMPILER_VERSION_PATCH DEC(__CODEGEARC_VERSION__ & 0xFFFF)
+
121
+
122#elif defined(__BORLANDC__)
+
123# define COMPILER_ID "Borland"
+
124 /* __BORLANDC__ = 0xVRR */
+
125# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8)
+
126# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF)
+
127
+
128#elif defined(__WATCOMC__) && __WATCOMC__ < 1200
+
129# define COMPILER_ID "Watcom"
+
130 /* __WATCOMC__ = VVRR */
+
131# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100)
+
132# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+
133# if (__WATCOMC__ % 10) > 0
+
134# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+
135# endif
+
136
+
137#elif defined(__WATCOMC__)
+
138# define COMPILER_ID "OpenWatcom"
+
139 /* __WATCOMC__ = VVRP + 1100 */
+
140# define COMPILER_VERSION_MAJOR DEC((__WATCOMC__ - 1100) / 100)
+
141# define COMPILER_VERSION_MINOR DEC((__WATCOMC__ / 10) % 10)
+
142# if (__WATCOMC__ % 10) > 0
+
143# define COMPILER_VERSION_PATCH DEC(__WATCOMC__ % 10)
+
144# endif
+
145
+
146#elif defined(__SUNPRO_CC)
+
147# define COMPILER_ID "SunPro"
+
148# if __SUNPRO_CC >= 0x5100
+
149 /* __SUNPRO_CC = 0xVRRP */
+
150# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12)
+
151# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF)
+
152# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+
153# else
+
154 /* __SUNPRO_CC = 0xVRP */
+
155# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8)
+
156# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF)
+
157# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF)
+
158# endif
+
159
+
160#elif defined(__HP_aCC)
+
161# define COMPILER_ID "HP"
+
162 /* __HP_aCC = VVRRPP */
+
163# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000)
+
164# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100)
+
165# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100)
+
166
+
167#elif defined(__DECCXX)
+
168# define COMPILER_ID "Compaq"
+
169 /* __DECCXX_VER = VVRRTPPPP */
+
170# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000)
+
171# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100)
+
172# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000)
+
173
+
174#elif defined(__IBMCPP__) && defined(__COMPILER_VER__)
+
175# define COMPILER_ID "zOS"
+
176 /* __IBMCPP__ = VRP */
+
177# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+
178# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+
179# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
180
+
181#elif defined(__open_xl__) && defined(__clang__)
+
182# define COMPILER_ID "IBMClang"
+
183# define COMPILER_VERSION_MAJOR DEC(__open_xl_version__)
+
184# define COMPILER_VERSION_MINOR DEC(__open_xl_release__)
+
185# define COMPILER_VERSION_PATCH DEC(__open_xl_modification__)
+
186# define COMPILER_VERSION_TWEAK DEC(__open_xl_ptf_fix_level__)
+
187
+
188
+
189#elif defined(__ibmxl__) && defined(__clang__)
+
190# define COMPILER_ID "XLClang"
+
191# define COMPILER_VERSION_MAJOR DEC(__ibmxl_version__)
+
192# define COMPILER_VERSION_MINOR DEC(__ibmxl_release__)
+
193# define COMPILER_VERSION_PATCH DEC(__ibmxl_modification__)
+
194# define COMPILER_VERSION_TWEAK DEC(__ibmxl_ptf_fix_level__)
+
195
+
196
+
197#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ >= 800
+
198# define COMPILER_ID "XL"
+
199 /* __IBMCPP__ = VRP */
+
200# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+
201# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+
202# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
203
+
204#elif defined(__IBMCPP__) && !defined(__COMPILER_VER__) && __IBMCPP__ < 800
+
205# define COMPILER_ID "VisualAge"
+
206 /* __IBMCPP__ = VRP */
+
207# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100)
+
208# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10)
+
209# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10)
+
210
+
211#elif defined(__NVCOMPILER)
+
212# define COMPILER_ID "NVHPC"
+
213# define COMPILER_VERSION_MAJOR DEC(__NVCOMPILER_MAJOR__)
+
214# define COMPILER_VERSION_MINOR DEC(__NVCOMPILER_MINOR__)
+
215# if defined(__NVCOMPILER_PATCHLEVEL__)
+
216# define COMPILER_VERSION_PATCH DEC(__NVCOMPILER_PATCHLEVEL__)
+
217# endif
+
218
+
219#elif defined(__PGI)
+
220# define COMPILER_ID "PGI"
+
221# define COMPILER_VERSION_MAJOR DEC(__PGIC__)
+
222# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__)
+
223# if defined(__PGIC_PATCHLEVEL__)
+
224# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__)
+
225# endif
+
226
+
227#elif defined(__clang__) && defined(__cray__)
+
228# define COMPILER_ID "CrayClang"
+
229# define COMPILER_VERSION_MAJOR DEC(__cray_major__)
+
230# define COMPILER_VERSION_MINOR DEC(__cray_minor__)
+
231# define COMPILER_VERSION_PATCH DEC(__cray_patchlevel__)
+
232# define COMPILER_VERSION_INTERNAL_STR __clang_version__
+
233
+
234
+
235#elif defined(_CRAYC)
+
236# define COMPILER_ID "Cray"
+
237# define COMPILER_VERSION_MAJOR DEC(_RELEASE_MAJOR)
+
238# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR)
+
239
+
240#elif defined(__TI_COMPILER_VERSION__)
+
241# define COMPILER_ID "TI"
+
242 /* __TI_COMPILER_VERSION__ = VVVRRRPPP */
+
243# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000)
+
244# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000)
+
245# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000)
+
246
+
247#elif defined(__CLANG_FUJITSU)
+
248# define COMPILER_ID "FujitsuClang"
+
249# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
+
250# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
+
251# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
+
252# define COMPILER_VERSION_INTERNAL_STR __clang_version__
+
253
+
254
+
255#elif defined(__FUJITSU)
+
256# define COMPILER_ID "Fujitsu"
+
257# if defined(__FCC_version__)
+
258# define COMPILER_VERSION __FCC_version__
+
259# elif defined(__FCC_major__)
+
260# define COMPILER_VERSION_MAJOR DEC(__FCC_major__)
+
261# define COMPILER_VERSION_MINOR DEC(__FCC_minor__)
+
262# define COMPILER_VERSION_PATCH DEC(__FCC_patchlevel__)
+
263# endif
+
264# if defined(__fcc_version)
+
265# define COMPILER_VERSION_INTERNAL DEC(__fcc_version)
+
266# elif defined(__FCC_VERSION)
+
267# define COMPILER_VERSION_INTERNAL DEC(__FCC_VERSION)
+
268# endif
+
269
+
270
+
271#elif defined(__ghs__)
+
272# define COMPILER_ID "GHS"
+
273/* __GHS_VERSION_NUMBER = VVVVRP */
+
274# ifdef __GHS_VERSION_NUMBER
+
275# define COMPILER_VERSION_MAJOR DEC(__GHS_VERSION_NUMBER / 100)
+
276# define COMPILER_VERSION_MINOR DEC(__GHS_VERSION_NUMBER / 10 % 10)
+
277# define COMPILER_VERSION_PATCH DEC(__GHS_VERSION_NUMBER % 10)
+
278# endif
+
279
+
280#elif defined(__TASKING__)
+
281# define COMPILER_ID "Tasking"
+
282 # define COMPILER_VERSION_MAJOR DEC(__VERSION__/1000)
+
283 # define COMPILER_VERSION_MINOR DEC(__VERSION__ % 100)
+
284# define COMPILER_VERSION_INTERNAL DEC(__VERSION__)
+
285
+
286#elif defined(__ORANGEC__)
+
287# define COMPILER_ID "OrangeC"
+
288# define COMPILER_VERSION_MAJOR DEC(__ORANGEC_MAJOR__)
+
289# define COMPILER_VERSION_MINOR DEC(__ORANGEC_MINOR__)
+
290# define COMPILER_VERSION_PATCH DEC(__ORANGEC_PATCHLEVEL__)
+
291
+
292#elif defined(__SCO_VERSION__)
+
293# define COMPILER_ID "SCO"
+
294
+
295#elif defined(__ARMCC_VERSION) && !defined(__clang__)
+
296# define COMPILER_ID "ARMCC"
+
297#if __ARMCC_VERSION >= 1000000
+
298 /* __ARMCC_VERSION = VRRPPPP */
+
299 # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/1000000)
+
300 # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 100)
+
301 # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+
302#else
+
303 /* __ARMCC_VERSION = VRPPPP */
+
304 # define COMPILER_VERSION_MAJOR DEC(__ARMCC_VERSION/100000)
+
305 # define COMPILER_VERSION_MINOR DEC(__ARMCC_VERSION/10000 % 10)
+
306 # define COMPILER_VERSION_PATCH DEC(__ARMCC_VERSION % 10000)
+
307#endif
+
308
+
309
+
310#elif defined(__clang__) && defined(__apple_build_version__)
+
311# define COMPILER_ID "AppleClang"
+
312# if defined(_MSC_VER)
+
313# define SIMULATE_ID "MSVC"
+
314# endif
+
315# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+
316# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+
317# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+
318# if defined(_MSC_VER)
+
319 /* _MSC_VER = VVRR */
+
320# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+
321# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+
322# endif
+
323# define COMPILER_VERSION_TWEAK DEC(__apple_build_version__)
+
324
+
325#elif defined(__clang__) && defined(__ARMCOMPILER_VERSION)
+
326# define COMPILER_ID "ARMClang"
+
327 # define COMPILER_VERSION_MAJOR DEC(__ARMCOMPILER_VERSION/1000000)
+
328 # define COMPILER_VERSION_MINOR DEC(__ARMCOMPILER_VERSION/10000 % 100)
+
329 # define COMPILER_VERSION_PATCH DEC(__ARMCOMPILER_VERSION/100 % 100)
+
330# define COMPILER_VERSION_INTERNAL DEC(__ARMCOMPILER_VERSION)
+
331
+
332#elif defined(__clang__)
+
333# define COMPILER_ID "Clang"
+
334# if defined(_MSC_VER)
+
335# define SIMULATE_ID "MSVC"
+
336# endif
+
337# define COMPILER_VERSION_MAJOR DEC(__clang_major__)
+
338# define COMPILER_VERSION_MINOR DEC(__clang_minor__)
+
339# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__)
+
340# if defined(_MSC_VER)
+
341 /* _MSC_VER = VVRR */
+
342# define SIMULATE_VERSION_MAJOR DEC(_MSC_VER / 100)
+
343# define SIMULATE_VERSION_MINOR DEC(_MSC_VER % 100)
+
344# endif
+
345
+
346#elif defined(__LCC__) && (defined(__GNUC__) || defined(__GNUG__) || defined(__MCST__))
+
347# define COMPILER_ID "LCC"
+
348# define COMPILER_VERSION_MAJOR DEC(__LCC__ / 100)
+
349# define COMPILER_VERSION_MINOR DEC(__LCC__ % 100)
+
350# if defined(__LCC_MINOR__)
+
351# define COMPILER_VERSION_PATCH DEC(__LCC_MINOR__)
+
352# endif
+
353# if defined(__GNUC__) && defined(__GNUC_MINOR__)
+
354# define SIMULATE_ID "GNU"
+
355# define SIMULATE_VERSION_MAJOR DEC(__GNUC__)
+
356# define SIMULATE_VERSION_MINOR DEC(__GNUC_MINOR__)
+
357# if defined(__GNUC_PATCHLEVEL__)
+
358# define SIMULATE_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+
359# endif
+
360# endif
+
361
+
362#elif defined(__GNUC__) || defined(__GNUG__)
+
363# define COMPILER_ID "GNU"
+
364# if defined(__GNUC__)
+
365# define COMPILER_VERSION_MAJOR DEC(__GNUC__)
+
366# else
+
367# define COMPILER_VERSION_MAJOR DEC(__GNUG__)
+
368# endif
+
369# if defined(__GNUC_MINOR__)
+
370# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__)
+
371# endif
+
372# if defined(__GNUC_PATCHLEVEL__)
+
373# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__)
+
374# endif
+
375
+
376#elif defined(_MSC_VER)
+
377# define COMPILER_ID "MSVC"
+
378 /* _MSC_VER = VVRR */
+
379# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100)
+
380# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100)
+
381# if defined(_MSC_FULL_VER)
+
382# if _MSC_VER >= 1400
+
383 /* _MSC_FULL_VER = VVRRPPPPP */
+
384# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000)
+
385# else
+
386 /* _MSC_FULL_VER = VVRRPPPP */
+
387# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000)
+
388# endif
+
389# endif
+
390# if defined(_MSC_BUILD)
+
391# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD)
+
392# endif
+
393
+
394#elif defined(_ADI_COMPILER)
+
395# define COMPILER_ID "ADSP"
+
396#if defined(__VERSIONNUM__)
+
397 /* __VERSIONNUM__ = 0xVVRRPPTT */
+
398# define COMPILER_VERSION_MAJOR DEC(__VERSIONNUM__ >> 24 & 0xFF)
+
399# define COMPILER_VERSION_MINOR DEC(__VERSIONNUM__ >> 16 & 0xFF)
+
400# define COMPILER_VERSION_PATCH DEC(__VERSIONNUM__ >> 8 & 0xFF)
+
401# define COMPILER_VERSION_TWEAK DEC(__VERSIONNUM__ & 0xFF)
+
402#endif
+
403
+
404#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+
405# define COMPILER_ID "IAR"
+
406# if defined(__VER__) && defined(__ICCARM__)
+
407# define COMPILER_VERSION_MAJOR DEC((__VER__) / 1000000)
+
408# define COMPILER_VERSION_MINOR DEC(((__VER__) / 1000) % 1000)
+
409# define COMPILER_VERSION_PATCH DEC((__VER__) % 1000)
+
410# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+
411# elif defined(__VER__) && (defined(__ICCAVR__) || defined(__ICCRX__) || defined(__ICCRH850__) || defined(__ICCRL78__) || defined(__ICC430__) || defined(__ICCRISCV__) || defined(__ICCV850__) || defined(__ICC8051__) || defined(__ICCSTM8__))
+
412# define COMPILER_VERSION_MAJOR DEC((__VER__) / 100)
+
413# define COMPILER_VERSION_MINOR DEC((__VER__) - (((__VER__) / 100)*100))
+
414# define COMPILER_VERSION_PATCH DEC(__SUBVERSION__)
+
415# define COMPILER_VERSION_INTERNAL DEC(__IAR_SYSTEMS_ICC__)
+
416# endif
+
417
+
418
+
419/* These compilers are either not known or too old to define an
+
420 identification macro. Try to identify the platform and guess that
+
421 it is the native compiler. */
+
422#elif defined(__hpux) || defined(__hpua)
+
423# define COMPILER_ID "HP"
+
424
+
425#else /* unknown compiler */
+
426# define COMPILER_ID ""
+
427#endif
+
428
+
429/* Construct the string literal in pieces to prevent the source from
+
430 getting matched. Store it in a pointer rather than an array
+
431 because some compilers will just produce instructions to fill the
+
432 array rather than assigning a pointer to a static array. */
+
433char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]";
+
434#ifdef SIMULATE_ID
+
435char const* info_simulate = "INFO" ":" "simulate[" SIMULATE_ID "]";
+
436#endif
+
437
+
438#ifdef __QNXNTO__
+
439char const* qnxnto = "INFO" ":" "qnxnto[]";
+
440#endif
+
441
+
442#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
+
443char const *info_cray = "INFO" ":" "compiler_wrapper[CrayPrgEnv]";
+
444#endif
+
445
+
446#define STRINGIFY_HELPER(X) #X
+
447#define STRINGIFY(X) STRINGIFY_HELPER(X)
+
448
+
449/* Identify known platforms by name. */
+
450#if defined(__linux) || defined(__linux__) || defined(linux)
+
451# define PLATFORM_ID "Linux"
+
452
+
453#elif defined(__MSYS__)
+
454# define PLATFORM_ID "MSYS"
+
455
+
456#elif defined(__CYGWIN__)
+
457# define PLATFORM_ID "Cygwin"
+
458
+
459#elif defined(__MINGW32__)
+
460# define PLATFORM_ID "MinGW"
+
461
+
462#elif defined(__APPLE__)
+
463# define PLATFORM_ID "Darwin"
+
464
+
465#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32)
+
466# define PLATFORM_ID "Windows"
+
467
+
468#elif defined(__FreeBSD__) || defined(__FreeBSD)
+
469# define PLATFORM_ID "FreeBSD"
+
470
+
471#elif defined(__NetBSD__) || defined(__NetBSD)
+
472# define PLATFORM_ID "NetBSD"
+
473
+
474#elif defined(__OpenBSD__) || defined(__OPENBSD)
+
475# define PLATFORM_ID "OpenBSD"
+
476
+
477#elif defined(__sun) || defined(sun)
+
478# define PLATFORM_ID "SunOS"
+
479
+
480#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__)
+
481# define PLATFORM_ID "AIX"
+
482
+
483#elif defined(__hpux) || defined(__hpux__)
+
484# define PLATFORM_ID "HP-UX"
+
485
+
486#elif defined(__HAIKU__)
+
487# define PLATFORM_ID "Haiku"
+
488
+
489#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS)
+
490# define PLATFORM_ID "BeOS"
+
491
+
492#elif defined(__QNX__) || defined(__QNXNTO__)
+
493# define PLATFORM_ID "QNX"
+
494
+
495#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__)
+
496# define PLATFORM_ID "Tru64"
+
497
+
498#elif defined(__riscos) || defined(__riscos__)
+
499# define PLATFORM_ID "RISCos"
+
500
+
501#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__)
+
502# define PLATFORM_ID "SINIX"
+
503
+
504#elif defined(__UNIX_SV__)
+
505# define PLATFORM_ID "UNIX_SV"
+
506
+
507#elif defined(__bsdos__)
+
508# define PLATFORM_ID "BSDOS"
+
509
+
510#elif defined(_MPRAS) || defined(MPRAS)
+
511# define PLATFORM_ID "MP-RAS"
+
512
+
513#elif defined(__osf) || defined(__osf__)
+
514# define PLATFORM_ID "OSF1"
+
515
+
516#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv)
+
517# define PLATFORM_ID "SCO_SV"
+
518
+
519#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX)
+
520# define PLATFORM_ID "ULTRIX"
+
521
+
522#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX)
+
523# define PLATFORM_ID "Xenix"
+
524
+
525#elif defined(__WATCOMC__)
+
526# if defined(__LINUX__)
+
527# define PLATFORM_ID "Linux"
+
528
+
529# elif defined(__DOS__)
+
530# define PLATFORM_ID "DOS"
+
531
+
532# elif defined(__OS2__)
+
533# define PLATFORM_ID "OS2"
+
534
+
535# elif defined(__WINDOWS__)
+
536# define PLATFORM_ID "Windows3x"
+
537
+
538# elif defined(__VXWORKS__)
+
539# define PLATFORM_ID "VxWorks"
+
540
+
541# else /* unknown platform */
+
542# define PLATFORM_ID
+
543# endif
+
544
+
545#elif defined(__INTEGRITY)
+
546# if defined(INT_178B)
+
547# define PLATFORM_ID "Integrity178"
+
548
+
549# else /* regular Integrity */
+
550# define PLATFORM_ID "Integrity"
+
551# endif
+
552
+
553# elif defined(_ADI_COMPILER)
+
554# define PLATFORM_ID "ADSP"
+
555
+
556#else /* unknown platform */
+
557# define PLATFORM_ID
+
558
+
559#endif
+
560
+
561/* For windows compilers MSVC and Intel we can determine
+
562 the architecture of the compiler being used. This is because
+
563 the compilers do not have flags that can change the architecture,
+
564 but rather depend on which compiler is being used
+
565*/
+
566#if defined(_WIN32) && defined(_MSC_VER)
+
567# if defined(_M_IA64)
+
568# define ARCHITECTURE_ID "IA64"
+
569
+
570# elif defined(_M_ARM64EC)
+
571# define ARCHITECTURE_ID "ARM64EC"
+
572
+
573# elif defined(_M_X64) || defined(_M_AMD64)
+
574# define ARCHITECTURE_ID "x64"
+
575
+
576# elif defined(_M_IX86)
+
577# define ARCHITECTURE_ID "X86"
+
578
+
579# elif defined(_M_ARM64)
+
580# define ARCHITECTURE_ID "ARM64"
+
581
+
582# elif defined(_M_ARM)
+
583# if _M_ARM == 4
+
584# define ARCHITECTURE_ID "ARMV4I"
+
585# elif _M_ARM == 5
+
586# define ARCHITECTURE_ID "ARMV5I"
+
587# else
+
588# define ARCHITECTURE_ID "ARMV" STRINGIFY(_M_ARM)
+
589# endif
+
590
+
591# elif defined(_M_MIPS)
+
592# define ARCHITECTURE_ID "MIPS"
+
593
+
594# elif defined(_M_SH)
+
595# define ARCHITECTURE_ID "SHx"
+
596
+
597# else /* unknown architecture */
+
598# define ARCHITECTURE_ID ""
+
599# endif
+
600
+
601#elif defined(__WATCOMC__)
+
602# if defined(_M_I86)
+
603# define ARCHITECTURE_ID "I86"
+
604
+
605# elif defined(_M_IX86)
+
606# define ARCHITECTURE_ID "X86"
+
607
+
608# else /* unknown architecture */
+
609# define ARCHITECTURE_ID ""
+
610# endif
+
611
+
612#elif defined(__IAR_SYSTEMS_ICC__) || defined(__IAR_SYSTEMS_ICC)
+
613# if defined(__ICCARM__)
+
614# define ARCHITECTURE_ID "ARM"
+
615
+
616# elif defined(__ICCRX__)
+
617# define ARCHITECTURE_ID "RX"
+
618
+
619# elif defined(__ICCRH850__)
+
620# define ARCHITECTURE_ID "RH850"
+
621
+
622# elif defined(__ICCRL78__)
+
623# define ARCHITECTURE_ID "RL78"
+
624
+
625# elif defined(__ICCRISCV__)
+
626# define ARCHITECTURE_ID "RISCV"
+
627
+
628# elif defined(__ICCAVR__)
+
629# define ARCHITECTURE_ID "AVR"
+
630
+
631# elif defined(__ICC430__)
+
632# define ARCHITECTURE_ID "MSP430"
+
633
+
634# elif defined(__ICCV850__)
+
635# define ARCHITECTURE_ID "V850"
+
636
+
637# elif defined(__ICC8051__)
+
638# define ARCHITECTURE_ID "8051"
+
639
+
640# elif defined(__ICCSTM8__)
+
641# define ARCHITECTURE_ID "STM8"
+
642
+
643# else /* unknown architecture */
+
644# define ARCHITECTURE_ID ""
+
645# endif
+
646
+
647#elif defined(__ghs__)
+
648# if defined(__PPC64__)
+
649# define ARCHITECTURE_ID "PPC64"
+
650
+
651# elif defined(__ppc__)
+
652# define ARCHITECTURE_ID "PPC"
+
653
+
654# elif defined(__ARM__)
+
655# define ARCHITECTURE_ID "ARM"
+
656
+
657# elif defined(__x86_64__)
+
658# define ARCHITECTURE_ID "x64"
+
659
+
660# elif defined(__i386__)
+
661# define ARCHITECTURE_ID "X86"
+
662
+
663# else /* unknown architecture */
+
664# define ARCHITECTURE_ID ""
+
665# endif
+
666
+
667#elif defined(__TI_COMPILER_VERSION__)
+
668# if defined(__TI_ARM__)
+
669# define ARCHITECTURE_ID "ARM"
+
670
+
671# elif defined(__MSP430__)
+
672# define ARCHITECTURE_ID "MSP430"
+
673
+
674# elif defined(__TMS320C28XX__)
+
675# define ARCHITECTURE_ID "TMS320C28x"
+
676
+
677# elif defined(__TMS320C6X__) || defined(_TMS320C6X)
+
678# define ARCHITECTURE_ID "TMS320C6x"
+
679
+
680# else /* unknown architecture */
+
681# define ARCHITECTURE_ID ""
+
682# endif
+
683
+
684# elif defined(__ADSPSHARC__)
+
685# define ARCHITECTURE_ID "SHARC"
+
686
+
687# elif defined(__ADSPBLACKFIN__)
+
688# define ARCHITECTURE_ID "Blackfin"
+
689
+
690#elif defined(__TASKING__)
+
691
+
692# if defined(__CTC__) || defined(__CPTC__)
+
693# define ARCHITECTURE_ID "TriCore"
+
694
+
695# elif defined(__CMCS__)
+
696# define ARCHITECTURE_ID "MCS"
+
697
+
698# elif defined(__CARM__)
+
699# define ARCHITECTURE_ID "ARM"
+
700
+
701# elif defined(__CARC__)
+
702# define ARCHITECTURE_ID "ARC"
+
703
+
704# elif defined(__C51__)
+
705# define ARCHITECTURE_ID "8051"
+
706
+
707# elif defined(__CPCP__)
+
708# define ARCHITECTURE_ID "PCP"
+
709
+
710# else
+
711# define ARCHITECTURE_ID ""
+
712# endif
+
713
+
714#else
+
715# define ARCHITECTURE_ID
+
716#endif
+
717
+
718/* Convert integer to decimal digit literals. */
+
719#define DEC(n) \
+
720 ('0' + (((n) / 10000000)%10)), \
+
721 ('0' + (((n) / 1000000)%10)), \
+
722 ('0' + (((n) / 100000)%10)), \
+
723 ('0' + (((n) / 10000)%10)), \
+
724 ('0' + (((n) / 1000)%10)), \
+
725 ('0' + (((n) / 100)%10)), \
+
726 ('0' + (((n) / 10)%10)), \
+
727 ('0' + ((n) % 10))
+
728
+
729/* Convert integer to hex digit literals. */
+
730#define HEX(n) \
+
731 ('0' + ((n)>>28 & 0xF)), \
+
732 ('0' + ((n)>>24 & 0xF)), \
+
733 ('0' + ((n)>>20 & 0xF)), \
+
734 ('0' + ((n)>>16 & 0xF)), \
+
735 ('0' + ((n)>>12 & 0xF)), \
+
736 ('0' + ((n)>>8 & 0xF)), \
+
737 ('0' + ((n)>>4 & 0xF)), \
+
738 ('0' + ((n) & 0xF))
+
739
+
740/* Construct a string literal encoding the version number. */
+
741#ifdef COMPILER_VERSION
+
742char const* info_version = "INFO" ":" "compiler_version[" COMPILER_VERSION "]";
+
743
+
744/* Construct a string literal encoding the version number components. */
+
745#elif defined(COMPILER_VERSION_MAJOR)
+
746char const info_version[] = {
+
747 'I', 'N', 'F', 'O', ':',
+
748 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[',
+
749 COMPILER_VERSION_MAJOR,
+
750# ifdef COMPILER_VERSION_MINOR
+
751 '.', COMPILER_VERSION_MINOR,
+
752# ifdef COMPILER_VERSION_PATCH
+
753 '.', COMPILER_VERSION_PATCH,
+
754# ifdef COMPILER_VERSION_TWEAK
+
755 '.', COMPILER_VERSION_TWEAK,
+
756# endif
+
757# endif
+
758# endif
+
759 ']','\0'};
+
760#endif
+
761
+
762/* Construct a string literal encoding the internal version number. */
+
763#ifdef COMPILER_VERSION_INTERNAL
+
764char const info_version_internal[] = {
+
765 'I', 'N', 'F', 'O', ':',
+
766 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','_',
+
767 'i','n','t','e','r','n','a','l','[',
+
768 COMPILER_VERSION_INTERNAL,']','\0'};
+
769#elif defined(COMPILER_VERSION_INTERNAL_STR)
+
770char const* info_version_internal = "INFO" ":" "compiler_version_internal[" COMPILER_VERSION_INTERNAL_STR "]";
+
771#endif
+
772
+
773/* Construct a string literal encoding the version number components. */
+
774#ifdef SIMULATE_VERSION_MAJOR
+
775char const info_simulate_version[] = {
+
776 'I', 'N', 'F', 'O', ':',
+
777 's','i','m','u','l','a','t','e','_','v','e','r','s','i','o','n','[',
+
778 SIMULATE_VERSION_MAJOR,
+
779# ifdef SIMULATE_VERSION_MINOR
+
780 '.', SIMULATE_VERSION_MINOR,
+
781# ifdef SIMULATE_VERSION_PATCH
+
782 '.', SIMULATE_VERSION_PATCH,
+
783# ifdef SIMULATE_VERSION_TWEAK
+
784 '.', SIMULATE_VERSION_TWEAK,
+
785# endif
+
786# endif
+
787# endif
+
788 ']','\0'};
+
789#endif
+
790
+
791/* Construct the string literal in pieces to prevent the source from
+
792 getting matched. Store it in a pointer rather than an array
+
793 because some compilers will just produce instructions to fill the
+
794 array rather than assigning a pointer to a static array. */
+
795char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]";
+
796char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]";
+
797
+
798
+
799
+
800#if defined(__INTEL_COMPILER) && defined(_MSVC_LANG) && _MSVC_LANG < 201403L
+
801# if defined(__INTEL_CXX11_MODE__)
+
802# if defined(__cpp_aggregate_nsdmi)
+
803# define CXX_STD 201402L
+
804# else
+
805# define CXX_STD 201103L
+
806# endif
+
807# else
+
808# define CXX_STD 199711L
+
809# endif
+
810#elif defined(_MSC_VER) && defined(_MSVC_LANG)
+
811# define CXX_STD _MSVC_LANG
+
812#else
+
813# define CXX_STD __cplusplus
+
814#endif
+
815
+
816const char* info_language_standard_default = "INFO" ":" "standard_default["
+
817#if CXX_STD > 202002L
+
818 "23"
+
819#elif CXX_STD > 201703L
+
820 "20"
+
821#elif CXX_STD >= 201703L
+
822 "17"
+
823#elif CXX_STD >= 201402L
+
824 "14"
+
825#elif CXX_STD >= 201103L
+
826 "11"
+
827#else
+
828 "98"
+
829#endif
+
830"]";
+
831
+
832const char* info_language_extensions_default = "INFO" ":" "extensions_default["
+
833#if (defined(__clang__) || defined(__GNUC__) || defined(__xlC__) || \
+
834 defined(__TI_COMPILER_VERSION__)) && \
+
835 !defined(__STRICT_ANSI__)
+
836 "ON"
+
837#else
+
838 "OFF"
+
839#endif
+
840"]";
+
841
+
842/*--------------------------------------------------------------------------*/
+
843
+
844int main(int argc, char* argv[])
+
845{
+
846 int require = 0;
+
847 require += info_compiler[argc];
+
848 require += info_platform[argc];
+
849 require += info_arch[argc];
+
850#ifdef COMPILER_VERSION_MAJOR
+
851 require += info_version[argc];
+
852#endif
+
853#ifdef COMPILER_VERSION_INTERNAL
+
854 require += info_version_internal[argc];
+
855#endif
+
856#ifdef SIMULATE_ID
+
857 require += info_simulate[argc];
+
858#endif
+
859#ifdef SIMULATE_VERSION_MAJOR
+
860 require += info_simulate_version[argc];
+
861#endif
+
862#if defined(__CRAYXT_COMPUTE_LINUX_TARGET)
+
863 require += info_cray[argc];
+
864#endif
+
865 require += info_language_standard_default[argc];
+
866 require += info_language_extensions_default[argc];
+
867 (void)argv;
+
868 return require;
+
869}
+
+
+ + + + diff --git a/doc/html/context_globaldata.html b/doc/html/context_globaldata.html index aaa9917ae..fc0447a26 100644 --- a/doc/html/context_globaldata.html +++ b/doc/html/context_globaldata.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Tutorial 6: Global Data
@@ -171,10 +177,13 @@

}

- - + + diff --git a/doc/html/context_primdata.html b/doc/html/context_primdata.html index 1db1cf7e1..2159de7ec 100644 --- a/doc/html/context_primdata.html +++ b/doc/html/context_primdata.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Tutorial 5: Primitive Data
@@ -218,10 +224,13 @@

}

- - + + diff --git a/doc/html/context_primitives.html b/doc/html/context_primitives.html index 66eb2b9fb..4b166b1dd 100644 --- a/doc/html/context_primitives.html +++ b/doc/html/context_primitives.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Tutorial 2: Working with Context Geometry
@@ -178,10 +184,13 @@

}

- - + + diff --git a/doc/html/context_selftest.html b/doc/html/context_selftest.html index 148947fba..447a249d8 100644 --- a/doc/html/context_selftest.html +++ b/doc/html/context_selftest.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Tutorial 0: Context Self-Test Tutorial
@@ -166,10 +172,13 @@

Notice the line where we have set the name of the executable to "context_selftest", which we could change to any name. Notice also just below where we specify the name of the source code file ("main.cpp"). It is important to note that the path to the source files is relative to the directory where the CMakeLists.txt file is located.

- - + + diff --git a/doc/html/context_vectors.html b/doc/html/context_vectors.html index 2c3840cae..831ea397d 100644 --- a/doc/html/context_vectors.html +++ b/doc/html/context_vectors.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Tutorial 1: Helios Vector Types Tutorial
@@ -240,10 +246,13 @@

}

- - + + diff --git a/doc/html/core_2src_2self_test_8cpp.html b/doc/html/core_2src_2self_test_8cpp.html index f324ceb0c..8b00cfe51 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
selfTest.cpp File Reference
@@ -108,17 +114,20 @@

Go to the source code of this file.

Detailed Description

-

Context selfTest() function.

+

Context selfTest() function.

Copyright (C) 2016-2025 Brian Bailey

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

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

Definition in file selfTest.cpp.

- - + + diff --git a/doc/html/core_2src_2self_test_8cpp_source.html b/doc/html/core_2src_2self_test_8cpp_source.html index caa0ceabb..b2488d463 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
selfTest.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "Context.h"
17
18using namespace helios;
@@ -114,7 +121,7 @@
21
22 std::cout << "Running Context self-test..." << std::flush;
23
-
24 Context context_test;
+
24 Context context_test;
25
26 uint error_count=0;
27
@@ -878,7 +885,7 @@
785
786 //-------- Timeseries -----------//
787
-
788 Context context_ts;
+
788 Context context_ts;
789
790 Date date_ts( 12, 3, 2010 );
791 context_ts.setDate( date_ts );
@@ -961,7 +968,7 @@
868
869 context_ts.queryTimeseriesData( "timeseries", date_ts, make_Time(time0_ts.hour,time0_ts.minute,time0_ts.second+10) );
870
-
871 Context context_ts2;
+
871 Context context_ts2;
872
873 context_ts2.loadTabularTimeseriesData("lib/testdata/weather_data.csv", {"date", "hour", "temperature"}, ",", "MMDDYYYY", 1);
874
@@ -987,7 +994,7 @@
894
895 //------- XML I/O --------//
896
-
897 Context context_io;
+
897 Context context_io;
898
899 RGBcolor color_io = RGB::red;
900
@@ -1050,7 +1057,7 @@
957
958 context_io.writeXML( "xmltest_io.xml", true );
959
-
960 Context context_oi;
+
960 Context context_oi;
961
962 context_oi.loadXML( "xmltest_io.xml", true );
963
@@ -1084,7 +1091,7 @@
991
992 //------- setTileObjectSubdivisionCount, getTileObjectAreaRatio, cropDomain & writeXML & loadXML for compound objects --------//
993
-
994 Context context_to;
+
994 Context context_to;
995
996 //non-textured tile object single subpatch
997 uint to1 = context_to.addTileObject(make_vec3(0,0,0), make_vec2(1,0.3), make_SphericalCoord(float(M_PI)*0.25, float(M_PI)*0.75), make_int2(1,1));
@@ -1164,7 +1171,7 @@
1071
1072 //------------ writeXML & loadXML for compound objects --------------//
1073
-
1074 Context context_to2;
+
1074 Context context_to2;
1075 context_to2.loadXML("xmltest_to.xml", true );
1076 uint context_to2_PrimitiveCount = context_to2.getPrimitiveCount();
1077 uint context_to2_ObjectCount = context_to2.getObjectCount();
@@ -1185,7 +1192,7 @@
1092 // CASE # 1 Changing Object ID of one object primitive
1093 // Would expect a single object to remain containing one primitive and a separate non-object primitive
1094
-
1095 Context context_dzpo;
+
1095 Context context_dzpo;
1096 context_dzpo.addTileObject(make_vec3(0,0,0), make_vec2(1,1), nullrotation, make_int2(1,2));
1097
1098 //set primitive parent object ID to zero
@@ -1199,7 +1206,7 @@
1106 }
1107 context_dzpo.writeXML("./dzpo_case1.xml", true );
1108
-
1109 Context context_dzpo_load;
+
1109 Context context_dzpo_load;
1110 context_dzpo_load.loadXML("./dzpo_case1.xml", true);
1111 std::vector<uint> opi_load = context_dzpo_load.getObjectPrimitiveUUIDs(1);
1112 if(opi_load.size() != 1)
@@ -1211,7 +1218,7 @@
1118 //CASE # 2 Changing Object ID of one object primitive and deleting it
1119 //Would expect a single object to remain containing one primitive
1120
-
1121 Context context_dzpo2;
+
1121 Context context_dzpo2;
1122 context_dzpo2.addTileObject(make_vec3(0,0,0), make_vec2(1,1), nullrotation, make_int2(1,2));
1123
1124 //set one primitive parent object ID to zero
@@ -1221,7 +1228,7 @@
1128
1129 context_dzpo2.writeXML("./dzpo_case2.xml", true);
1130
-
1131 Context context_dzpo2_load;
+
1131 Context context_dzpo2_load;
1132 context_dzpo2_load.loadXML("./dzpo_case2.xml", true);
1133 uint opi_load2 = context_dzpo2_load.getObjectPrimitiveUUIDs(1).size();
1134 uint n_prim2 = context_dzpo2_load.getAllUUIDs().size();
@@ -1236,7 +1243,7 @@
1143
1144 //CASE #3 Changing Object ID of one object primitive and deleting the other object primitive
1145 //Would expect the object to be deleted since it has no primitives
-
1146 Context context_dzpo3;
+
1146 Context context_dzpo3;
1147 context_dzpo3.addTileObject(make_vec3(0,0,0), make_vec2(1,1), nullrotation, make_int2(1,2));
1148
1149 //set one primitive parent object ID to zero
@@ -1246,7 +1253,7 @@
1153
1154 context_dzpo3.writeXML("./dzpo_case3.xml", true);
1155
-
1156 Context context_dzpo3_load;
+
1156 Context context_dzpo3_load;
1157 context_dzpo3_load.loadXML("./dzpo_case3.xml", true);
1158 uint n_prim3 = context_dzpo3_load.getAllUUIDs().size();
1159 uint n_obj3 = context_dzpo3_load.getAllObjectIDs().size();
@@ -1358,37 +1365,37 @@
void translate(const helios::vec3 &shift)
Method to translate/shift a Compound Object.
Definition Context.cpp:2353
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
void getObjectData(const char *label, int &data) const
Get data associated with a object element (integer scalar)
-
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4130
-
void scaleLength(float S)
Method to scale the length of the cone.
Definition Context.cpp:4212
-
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition Context.cpp:4261
-
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4159
-
Stores the state associated with simulation.
Definition Context.h:1882
+
std::vector< helios::vec3 > getNodeCoordinates() const
Get the Cartesian coordinates of each of the cone object nodes.
Definition Context.cpp:4157
+
void scaleLength(float S)
Method to scale the length of the cone.
Definition Context.cpp:4239
+
void scaleGirth(float S)
Method to scale the girth of the cone.
Definition Context.cpp:4288
+
std::vector< float > getNodeRadii() const
Get the radius at each of the cone object nodes.
Definition Context.cpp:4186
void setTileObjectSubdivisionCount(const std::vector< uint > &ObjectIDs, const int2 &new_subdiv)
Change the subdivision count of a tile object.
Definition Context.cpp:2982
-
helios::RGBcolor getPrimitiveColor(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7127
+
helios::RGBcolor getPrimitiveColor(uint UUID) const
Method to return the diffuse color of a Primitive.
Definition Context.cpp:7154
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:1406
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
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:1536
-
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
+
bool doesObjectDataExist(uint objID, const char *label) const
Check if primitive data 'label' exists.
std::vector< uint > getAllObjectIDs() const
Get the IDs for all Compound Objects in the Context.
Definition Context.cpp:2589
-
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4123
+
Cone * getConeObjectPointer(uint ObjID) const
Get a pointer to a Cone Compound Object.
Definition Context.cpp:4150
void getObjectData(uint objID, const char *label, int &data) const
Get data associated with a compound object.
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
helios::vec3 getPatchCenter(uint UUID) const
Get the Cartesian (x,y,z) center position of a patch element.
Definition Context.cpp:1693
std::vector< uint > filterPrimitivesByData(const std::vector< uint > &UUIDs, const std::string &primitive_data_label, float filter_value, const std::string &comparator)
Filter a set of primitives based on their primitive data and a condition and float value.
void calculatePrimitiveDataSum(const std::vector< uint > &UUIDs, const std::string &label, float &sum) const
Calculate sum of primitive data values (float) for a subset of primitives.
-
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7159
+
std::string getPrimitiveTextureFile(uint UUID) const
Get the path to texture map file for primitive. If primitive does not have a texture map,...
Definition Context.cpp:7186
uint getObjectCount() const
Get the total number of objects that have been created in the Context.
Definition Context.cpp:2581
-
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7175
+
std::vector< vec2 > getPrimitiveTextureUV(uint UUID) const
Get u-v texture coordinates at primitive vertices.
Definition Context.cpp:7202
void setDate(int day, int month, int year)
Set simulation date by day, month, year.
Definition Context.cpp:1059
-
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:6988
-
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
-
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:6984
+
void setPrimitiveParentObjectID(uint UUID, uint objID)
Method to set the ID of the parent object the primitive belongs to (default is object 0)
Definition Context.cpp:7015
+
Context()
Context default constructor.
Definition Context.cpp:20
+
bool doesGlobalDataExist(const char *label) const
Check if global data 'label' exists.
+
PrimitiveType getPrimitiveType(uint UUID) const
Method to get the Primitive type.
Definition Context.cpp:7011
void setObjectData(uint objID, const char *label, const int &data)
Add data value (int) associated with a compound object.
-
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7221
-
bool doesPrimitiveDataExist(uint UUID, const char *label) const
Check if primitive data 'label' exists.
+
float getPrimitiveSolidFraction(uint UUID) const
Get fraction of primitive surface area that is non-transparent.
Definition Context.cpp:7248
+
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:2907
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
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...
@@ -1399,16 +1406,16 @@
void setGlobalData(const char *label, const int &data)
Add global data value (int)
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1491
helios::vec2 getPatchSize(uint UUID) const
Get the size of a patch element.
Definition Context.cpp:1684
-
void getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single primitive.
Definition Context.cpp:7057
+
void getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const
Get the axis-aligned bounding box for a single primitive.
Definition Context.cpp:7084
void writeXML(const char *filename, bool quiet=false) const
Write Context geometry and data to XML file for all UUIDs in the context.
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7104
+
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7131
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
void calculatePrimitiveDataAreaWeightedMean(const std::vector< uint > &UUIDs, const std::string &label, float &awt_mean) const
Calculate mean of primitive data values (float) for a subset of primitives, where each value in the m...
bool doesPrimitiveExist(uint UUID) const
Check if primitive exists for a given UUID.
Definition Context.cpp:1659
Tile * getTileObjectPointer(uint ObjID) const
Get a pointer to a Tile Compound Object.
Definition Context.cpp:3312
-
float getBoxObjectVolume(uint ObjID) const
get the volume of a Box object from the context
Definition Context.cpp:8234
+
float getBoxObjectVolume(uint ObjID) const
get the volume of a Box object from the context
Definition Context.cpp:8268
void setTime(int minute, int hour)
Set simulation time.
Definition Context.cpp:1136
-
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:7122
+
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:7149
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:3075
std::string getFileName(const std::string &filepath)
Parse a file string to get the filename including extension.
Definition global.cpp:3085
@@ -1416,12 +1423,12 @@
std::string getFileStem(const std::string &filepath)
Parse a file string to get the filename without extension.
Definition global.cpp:3080
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:3090
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:5256
-
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:4728
-
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5426
-
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5000
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
-
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4310
+
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:5283
+
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:4755
+
uint addConeObject(uint Ndivs, const vec3 &node0, const vec3 &node1, float radius0, float radius1)
Add a 3D cone compound object to the Context.
Definition Context.cpp:5453
+
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5027
+
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4577
+
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4337
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
helios::vec3 spline_interp3(float u, const vec3 &x_start, const vec3 &tan_start, const vec3 &x_end, const vec3 &tan_end)
Function to perform cubic Hermite spline interpolation.
Definition global.cpp:2768
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
@@ -1461,22 +1468,25 @@
int second
Second of minute.
int hour
Hour of day.
int minute
Minute of hour.
-
Vector of two elements of type 'int'.
-
Vector of three elements of type 'int'.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'int'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
float magnitude() const
Compute the vector magnitude.
- -
+ + diff --git a/doc/html/dir_000a2e4fe776603f09c56917fe929269.html b/doc/html/dir_000a2e4fe776603f09c56917fe929269.html index f05690dfc..38511d1a3 100644 --- a/doc/html/dir_000a2e4fe776603f09c56917fe929269.html +++ b/doc/html/dir_000a2e4fe776603f09c56917fe929269.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
src Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_000a2e4fe776603f09c56917fe929269.js b/doc/html/dir_000a2e4fe776603f09c56917fe929269.js new file mode 100644 index 000000000..2f99a5ec6 --- /dev/null +++ b/doc/html/dir_000a2e4fe776603f09c56917fe929269.js @@ -0,0 +1,5 @@ +var dir_000a2e4fe776603f09c56917fe929269 = +[ + [ "EnergyBalanceModel.cpp", "_energy_balance_model_8cpp.html", null ], + [ "EnergyBalanceModel.cu", "_energy_balance_model_8cu.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_01af3122a6d2fc081d545f111575c8ac.html b/doc/html/dir_01af3122a6d2fc081d545f111575c8ac.html index 7e09ca23f..339fa5158 100644 --- a/doc/html/dir_01af3122a6d2fc081d545f111575c8ac.html +++ b/doc/html/dir_01af3122a6d2fc081d545f111575c8ac.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_0581b1fc91af6cc2594fe789a424270d.html b/doc/html/dir_0581b1fc91af6cc2594fe789a424270d.html index d01ee4c5a..4030ab4a2 100644 --- a/doc/html/dir_0581b1fc91af6cc2594fe789a424270d.html +++ b/doc/html/dir_0581b1fc91af6cc2594fe789a424270d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.html b/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.html index b56a7f42d..603b107f6 100644 --- a/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.html +++ b/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.js b/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.js new file mode 100644 index 000000000..a97ce9823 --- /dev/null +++ b/doc/html/dir_09ba98b3b490a60de71fb62d89fe47cd.js @@ -0,0 +1,4 @@ +var dir_09ba98b3b490a60de71fb62d89fe47cd = +[ + [ "LeafOptics.cpp", "_leaf_optics_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.html b/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.html index 24bad547c..99c48e02e 100644 --- a/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.html +++ b/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.js b/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.js new file mode 100644 index 000000000..880f10a06 --- /dev/null +++ b/doc/html/dir_0b377c449e87c33e20eed98f7cc3a6cc.js @@ -0,0 +1,4 @@ +var dir_0b377c449e87c33e20eed98f7cc3a6cc = +[ + [ "Visualizer.h", "_visualizer_8h.html", "_visualizer_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_0ed0e5ef04d2b4b7edd36da5802052a6.html b/doc/html/dir_0ed0e5ef04d2b4b7edd36da5802052a6.html index ebe6cc69d..20dc5affa 100644 --- a/doc/html/dir_0ed0e5ef04d2b4b7edd36da5802052a6.html +++ b/doc/html/dir_0ed0e5ef04d2b4b7edd36da5802052a6.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.html b/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.html index cf0e3b477..8ed9cf63f 100644 --- a/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.html +++ b/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.js b/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.js new file mode 100644 index 000000000..e07085a7b --- /dev/null +++ b/doc/html/dir_10651e710c37b90bb60afaa4d2c6a975.js @@ -0,0 +1,5 @@ +var dir_10651e710c37b90bb60afaa4d2c6a975 = +[ + [ "Assets.h", "_assets_8h_source.html", null ], + [ "PlantArchitecture.h", "_plant_architecture_8h.html", "_plant_architecture_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.html b/doc/html/dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.html new file mode 100644 index 000000000..fe9199878 --- /dev/null +++ b/doc/html/dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.html @@ -0,0 +1,129 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
3.28.1 Directory Reference
+
+
+ + + + +

+Directories

 CompilerIdCXX
 
+
+
+ + + + diff --git a/doc/html/dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.js b/doc/html/dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.js new file mode 100644 index 000000000..638ad72f9 --- /dev/null +++ b/doc/html/dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.js @@ -0,0 +1,4 @@ +var dir_171367d4bb2d5d4c1b7aef91f5e5cf6e = +[ + [ "CompilerIdCXX", "dir_f34af3b1f7257ff6e74b73055c589954.html", "dir_f34af3b1f7257ff6e74b73055c589954" ] +]; \ No newline at end of file diff --git a/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html b/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html index 8d677e856..6664d381d 100644 --- a/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html +++ b/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -121,10 +127,13 @@  
- - + + diff --git a/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.js b/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.js new file mode 100644 index 000000000..230014c4a --- /dev/null +++ b/doc/html/dir_1736472fec890ec3b25c5f707a1ad41b.js @@ -0,0 +1,9 @@ +var dir_1736472fec890ec3b25c5f707a1ad41b = +[ + [ "CameraCalibration.cpp", "_camera_calibration_8cpp.html", null ], + [ "primitiveIntersection.cu", "primitive_intersection_8cu.html", "primitive_intersection_8cu" ], + [ "RadiationModel.cpp", "_radiation_model_8cpp.html", null ], + [ "rayGeneration.cu", "ray_generation_8cu.html", null ], + [ "rayHit.cu", "ray_hit_8cu.html", null ], + [ "selfTest.cpp", "plugins_2radiation_2src_2self_test_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.html b/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.html index eeed8a288..bcd634564 100644 --- a/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.html +++ b/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.js b/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.js new file mode 100644 index 000000000..30cd26330 --- /dev/null +++ b/doc/html/dir_1b48a9a5d33ab4b7862a4538757abad5.js @@ -0,0 +1,4 @@ +var dir_1b48a9a5d33ab4b7862a4538757abad5 = +[ + [ "Visualizer.cpp", "_visualizer_8cpp.html", "_visualizer_8cpp" ] +]; \ No newline at end of file diff --git a/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.html b/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.html index 8be027d2c..33a138ae9 100644 --- a/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.html +++ b/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.js b/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.js new file mode 100644 index 000000000..9bfadc249 --- /dev/null +++ b/doc/html/dir_1c54673618a694dbf6d60994b9e4cd26.js @@ -0,0 +1,5 @@ +var dir_1c54673618a694dbf6d60994b9e4cd26 = +[ + [ "selfTest.cpp", "plugins_2solarposition_2src_2self_test_8cpp_source.html", null ], + [ "SolarPosition.cpp", "_solar_position_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html b/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html index 42dcd59eb..d310c8edd 100644 --- a/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html +++ b/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -121,10 +127,13 @@  
- - + + diff --git a/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.js b/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.js new file mode 100644 index 000000000..b18ba7bc5 --- /dev/null +++ b/doc/html/dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.js @@ -0,0 +1,9 @@ +var dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3 = +[ + [ "Assets.cpp", "_assets_8cpp.html", null ], + [ "CarbohydrateModel.cpp", "_carbohydrate_model_8cpp.html", null ], + [ "InputOutput.cpp", "_input_output_8cpp.html", null ], + [ "PlantArchitecture.cpp", "_plant_architecture_8cpp.html", "_plant_architecture_8cpp" ], + [ "PlantLibrary.cpp", "_plant_library_8cpp.html", null ], + [ "selfTest.cpp", "plugins_2plantarchitecture_2src_2self_test_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html b/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html index f07907a5d..ffb509632 100644 --- a/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html +++ b/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
include Directory Reference
@@ -115,10 +121,13 @@  
- - + + diff --git a/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.js b/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.js new file mode 100644 index 000000000..9eec34a1b --- /dev/null +++ b/doc/html/dir_24d671cfcbc5d5238a6bd565a49d198f.js @@ -0,0 +1,6 @@ +var dir_24d671cfcbc5d5238a6bd565a49d198f = +[ + [ "Context.h", "_context_8h.html", "_context_8h" ], + [ "global.h", "global_8h.html", "global_8h" ], + [ "helios_vector_types.h", "helios__vector__types_8h.html", "helios__vector__types_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.html b/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.html index f1dc38652..f1ff41e89 100644 --- a/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.html +++ b/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
solarposition Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.js b/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.js new file mode 100644 index 000000000..1517bcc21 --- /dev/null +++ b/doc/html/dir_2dbe15cacd8389cc56dad1ecef740014.js @@ -0,0 +1,5 @@ +var dir_2dbe15cacd8389cc56dad1ecef740014 = +[ + [ "include", "dir_d6ff66ea9f957e81b4485948f070bc7c.html", "dir_d6ff66ea9f957e81b4485948f070bc7c" ], + [ "src", "dir_1c54673618a694dbf6d60994b9e4cd26.html", "dir_1c54673618a694dbf6d60994b9e4cd26" ] +]; \ No newline at end of file diff --git a/doc/html/dir_311a8078924eda44cf0bc3884606fa36.html b/doc/html/dir_311a8078924eda44cf0bc3884606fa36.html index d8177d6e1..26e58b858 100644 --- a/doc/html/dir_311a8078924eda44cf0bc3884606fa36.html +++ b/doc/html/dir_311a8078924eda44cf0bc3884606fa36.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
aeriallidar Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_311a8078924eda44cf0bc3884606fa36.js b/doc/html/dir_311a8078924eda44cf0bc3884606fa36.js new file mode 100644 index 000000000..e1a59d07a --- /dev/null +++ b/doc/html/dir_311a8078924eda44cf0bc3884606fa36.js @@ -0,0 +1,5 @@ +var dir_311a8078924eda44cf0bc3884606fa36 = +[ + [ "include", "dir_98f1c86a7f536ff9d6c61df9d8c64baa.html", "dir_98f1c86a7f536ff9d6c61df9d8c64baa" ], + [ "src", "dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html", "dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5" ] +]; \ No newline at end of file diff --git a/doc/html/dir_324b51d306f9962e8d7b85b82cd2c869.html b/doc/html/dir_324b51d306f9962e8d7b85b82cd2c869.html index 63f2ae665..b1fe3d5c6 100644 --- a/doc/html/dir_324b51d306f9962e8d7b85b82cd2c869.html +++ b/doc/html/dir_324b51d306f9962e8d7b85b82cd2c869.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.html b/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.html index 6f38654a3..07933d88a 100644 --- a/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.html +++ b/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
TutorialVideos Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.js b/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.js new file mode 100644 index 000000000..e4e856f71 --- /dev/null +++ b/doc/html/dir_3771cc92d713de3e5272f9ad4d0b1912.js @@ -0,0 +1,4 @@ +var dir_3771cc92d713de3e5272f9ad4d0b1912 = +[ + [ "RadiationModelPt2", "dir_d346877beec799c6cac1a2fc56d1c290.html", "dir_d346877beec799c6cac1a2fc56d1c290" ] +]; \ No newline at end of file diff --git a/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.html b/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.html index 15a6bd654..9bb44d97d 100644 --- a/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.html +++ b/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
plugins Directory Reference
- -
+ + diff --git a/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.js b/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.js new file mode 100644 index 000000000..e6d72e641 --- /dev/null +++ b/doc/html/dir_38c8d24aef3972a7f87b834274e76e31.js @@ -0,0 +1,19 @@ +var dir_38c8d24aef3972a7f87b834274e76e31 = +[ + [ "aeriallidar", "dir_311a8078924eda44cf0bc3884606fa36.html", "dir_311a8078924eda44cf0bc3884606fa36" ], + [ "boundarylayerconductance", "dir_bc56ed6b0b97565306d951dc61815da9.html", "dir_bc56ed6b0b97565306d951dc61815da9" ], + [ "canopygenerator", "dir_615177bc4a60bdbaf2db637460677b64.html", "dir_615177bc4a60bdbaf2db637460677b64" ], + [ "dummy", "dir_a4ee10e64f839049093220f98040855a.html", "dir_a4ee10e64f839049093220f98040855a" ], + [ "energybalance", "dir_53e799243804d32eb30709605e43a53b.html", "dir_53e799243804d32eb30709605e43a53b" ], + [ "leafoptics", "dir_b867f472847a1f099af0eb422541f49e.html", "dir_b867f472847a1f099af0eb422541f49e" ], + [ "lidar", "dir_9a3b5787d2329f793333f6962c777986.html", "dir_9a3b5787d2329f793333f6962c777986" ], + [ "photosynthesis", "dir_f93a58e1b1064abf3e9af98b74e2f5d5.html", "dir_f93a58e1b1064abf3e9af98b74e2f5d5" ], + [ "plantarchitecture", "dir_6d823072f66bbcb32b0d3acc588685b0.html", "dir_6d823072f66bbcb32b0d3acc588685b0" ], + [ "radiation", "dir_676c0954ed84853013df50d94356577b.html", "dir_676c0954ed84853013df50d94356577b" ], + [ "solarposition", "dir_2dbe15cacd8389cc56dad1ecef740014.html", "dir_2dbe15cacd8389cc56dad1ecef740014" ], + [ "stomatalconductance", "dir_a2b45ea1295f1e42b26af05f3b546a5b.html", "dir_a2b45ea1295f1e42b26af05f3b546a5b" ], + [ "syntheticannotation", "dir_daed1286feb5181d9374e50e34ff739d.html", "dir_daed1286feb5181d9374e50e34ff739d" ], + [ "visualizer", "dir_f54e10c7807847345da870f7da42cdf0.html", "dir_f54e10c7807847345da870f7da42cdf0" ], + [ "voxelintersection", "dir_3b948ba013618d5b0560477725ec43e1.html", "dir_3b948ba013618d5b0560477725ec43e1" ], + [ "weberpenntree", "dir_ee14773baee519b082f78b85b263aa48.html", "dir_ee14773baee519b082f78b85b263aa48" ] +]; \ No newline at end of file diff --git a/doc/html/dir_3b948ba013618d5b0560477725ec43e1.html b/doc/html/dir_3b948ba013618d5b0560477725ec43e1.html index b70894b6f..ea20712e1 100644 --- a/doc/html/dir_3b948ba013618d5b0560477725ec43e1.html +++ b/doc/html/dir_3b948ba013618d5b0560477725ec43e1.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
voxelintersection Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_3b948ba013618d5b0560477725ec43e1.js b/doc/html/dir_3b948ba013618d5b0560477725ec43e1.js new file mode 100644 index 000000000..d2872188f --- /dev/null +++ b/doc/html/dir_3b948ba013618d5b0560477725ec43e1.js @@ -0,0 +1,5 @@ +var dir_3b948ba013618d5b0560477725ec43e1 = +[ + [ "include", "dir_7b945ff507247f5bd903b50b5c416c04.html", "dir_7b945ff507247f5bd903b50b5c416c04" ], + [ "src", "dir_4942485e7dfd848fb997bfbb4ff4feb4.html", "dir_4942485e7dfd848fb997bfbb4ff4feb4" ] +]; \ No newline at end of file diff --git a/doc/html/dir_3d4da5c581737ecd0f864ccf0711fd92.html b/doc/html/dir_3d4da5c581737ecd0f864ccf0711fd92.html index 2faada944..ccbe3a068 100644 --- a/doc/html/dir_3d4da5c581737ecd0f864ccf0711fd92.html +++ b/doc/html/dir_3d4da5c581737ecd0f864ccf0711fd92.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.html b/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.html index 6d8d3ea8f..8d5c36dcf 100644 --- a/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.html +++ b/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.js b/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.js new file mode 100644 index 000000000..789b6edc6 --- /dev/null +++ b/doc/html/dir_3d6a603070d279a42ac417e5c8a6aba1.js @@ -0,0 +1,4 @@ +var dir_3d6a603070d279a42ac417e5c8a6aba1 = +[ + [ "LeafOptics.h", "_leaf_optics_8h.html", "_leaf_optics_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.html b/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.html index 0594d4134..a2cb0e544 100644 --- a/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.html +++ b/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -117,10 +123,13 @@  
- - + + diff --git a/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.js b/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.js new file mode 100644 index 000000000..0d4f71cf3 --- /dev/null +++ b/doc/html/dir_40ea2a4aa4adfc7dc77aa13d0834001b.js @@ -0,0 +1,7 @@ +var dir_40ea2a4aa4adfc7dc77aa13d0834001b = +[ + [ "CameraCalibration.h", "_camera_calibration_8h.html", "_camera_calibration_8h" ], + [ "RadiationModel.h", "_radiation_model_8h.html", "_radiation_model_8h" ], + [ "random.h", "radiation_2include_2random_8h_source.html", null ], + [ "RayTracing.cu.h", "_ray_tracing_8cu_8h.html", "_ray_tracing_8cu_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.html b/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.html index b5e1c243b..2662f13c8 100644 --- a/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.html +++ b/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.js b/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.js new file mode 100644 index 000000000..f3487da91 --- /dev/null +++ b/doc/html/dir_418637634c2136ee3716f84b17e3fdeb.js @@ -0,0 +1,4 @@ +var dir_418637634c2136ee3716f84b17e3fdeb = +[ + [ "PhotosynthesisModel.h", "_photosynthesis_model_8h.html", "_photosynthesis_model_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.html b/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.html index 6de653628..bac5295b2 100644 --- a/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.html +++ b/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
core Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.js b/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.js new file mode 100644 index 000000000..c3a0cdc1c --- /dev/null +++ b/doc/html/dir_4270bfced15e0e73154b13468c7c9ad9.js @@ -0,0 +1,7 @@ +var dir_4270bfced15e0e73154b13468c7c9ad9 = +[ + [ "build", "dir_d1ae8b435665c605bb4d6dbecb12be83.html", "dir_d1ae8b435665c605bb4d6dbecb12be83" ], + [ "cmake-build-release", "dir_ffb82276458c900659fd697987337356.html", "dir_ffb82276458c900659fd697987337356" ], + [ "include", "dir_24d671cfcbc5d5238a6bd565a49d198f.html", "dir_24d671cfcbc5d5238a6bd565a49d198f" ], + [ "src", "dir_90fd98a0ba30abf7a6068a44995d2d6b.html", "dir_90fd98a0ba30abf7a6068a44995d2d6b" ] +]; \ No newline at end of file diff --git a/doc/html/dir_4821d91ccf02e9e7895ac63900918c57.html b/doc/html/dir_4821d91ccf02e9e7895ac63900918c57.html new file mode 100644 index 000000000..736aa7eaf --- /dev/null +++ b/doc/html/dir_4821d91ccf02e9e7895ac63900918c57.html @@ -0,0 +1,123 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
CMakeFiles Directory Reference
+
+
+
+
+ + + + diff --git a/doc/html/dir_4821d91ccf02e9e7895ac63900918c57.js b/doc/html/dir_4821d91ccf02e9e7895ac63900918c57.js new file mode 100644 index 000000000..e46645b32 --- /dev/null +++ b/doc/html/dir_4821d91ccf02e9e7895ac63900918c57.js @@ -0,0 +1,4 @@ +var dir_4821d91ccf02e9e7895ac63900918c57 = +[ + [ "3.28.1", "dir_171367d4bb2d5d4c1b7aef91f5e5cf6e.html", "dir_171367d4bb2d5d4c1b7aef91f5e5cf6e" ] +]; \ No newline at end of file diff --git a/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.html b/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.html index b9fbbb7ed..363bf048b 100644 --- a/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.html +++ b/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.js b/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.js new file mode 100644 index 000000000..d307b2768 --- /dev/null +++ b/doc/html/dir_4942485e7dfd848fb997bfbb4ff4feb4.js @@ -0,0 +1,5 @@ +var dir_4942485e7dfd848fb997bfbb4ff4feb4 = +[ + [ "VoxelIntersection.cpp", "_voxel_intersection_8cpp.html", null ], + [ "VoxelIntersection.cu", "_voxel_intersection_8cu.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_4bc526d9ea56fd6bbf4f8bb7e1833918.html b/doc/html/dir_4bc526d9ea56fd6bbf4f8bb7e1833918.html new file mode 100644 index 000000000..a2c60759a --- /dev/null +++ b/doc/html/dir_4bc526d9ea56fd6bbf4f8bb7e1833918.html @@ -0,0 +1,123 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
CMakeFiles Directory Reference
+
+
+
+
+ + + + diff --git a/doc/html/dir_4bc526d9ea56fd6bbf4f8bb7e1833918.js b/doc/html/dir_4bc526d9ea56fd6bbf4f8bb7e1833918.js new file mode 100644 index 000000000..52be0f915 --- /dev/null +++ b/doc/html/dir_4bc526d9ea56fd6bbf4f8bb7e1833918.js @@ -0,0 +1,4 @@ +var dir_4bc526d9ea56fd6bbf4f8bb7e1833918 = +[ + [ "3.28.1", "dir_7b776a486e9f6b66ded8f2e7f8d3acb3.html", "dir_7b776a486e9f6b66ded8f2e7f8d3acb3" ] +]; \ No newline at end of file diff --git a/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.html b/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.html index e72d0b119..727b6f100 100644 --- a/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.html +++ b/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.js b/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.js new file mode 100644 index 000000000..3512f3a46 --- /dev/null +++ b/doc/html/dir_4ccbab8385dcba906f6a2cce80a3b511.js @@ -0,0 +1,4 @@ +var dir_4ccbab8385dcba906f6a2cce80a3b511 = +[ + [ "PhotosynthesisModel.cpp", "_photosynthesis_model_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.html b/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.html index b08fbd6c0..7df552987 100644 --- a/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.html +++ b/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.js b/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.js new file mode 100644 index 000000000..cc253a7fc --- /dev/null +++ b/doc/html/dir_51eab06546c34d501c6cf953a16a9cc5.js @@ -0,0 +1,4 @@ +var dir_51eab06546c34d501c6cf953a16a9cc5 = +[ + [ "StomatalConductanceModel.cpp", "_stomatal_conductance_model_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_53e799243804d32eb30709605e43a53b.html b/doc/html/dir_53e799243804d32eb30709605e43a53b.html index 4922df8c6..523182c6f 100644 --- a/doc/html/dir_53e799243804d32eb30709605e43a53b.html +++ b/doc/html/dir_53e799243804d32eb30709605e43a53b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
energybalance Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_53e799243804d32eb30709605e43a53b.js b/doc/html/dir_53e799243804d32eb30709605e43a53b.js new file mode 100644 index 000000000..586664ace --- /dev/null +++ b/doc/html/dir_53e799243804d32eb30709605e43a53b.js @@ -0,0 +1,5 @@ +var dir_53e799243804d32eb30709605e43a53b = +[ + [ "include", "dir_6252300d35bf0f8a4d6b5ccb98672957.html", "dir_6252300d35bf0f8a4d6b5ccb98672957" ], + [ "src", "dir_000a2e4fe776603f09c56917fe929269.html", "dir_000a2e4fe776603f09c56917fe929269" ] +]; \ No newline at end of file diff --git a/doc/html/dir_562cb346de9113a49164a1513c42aa1c.html b/doc/html/dir_562cb346de9113a49164a1513c42aa1c.html index c7a1d8b38..8ab93be14 100644 --- a/doc/html/dir_562cb346de9113a49164a1513c42aa1c.html +++ b/doc/html/dir_562cb346de9113a49164a1513c42aa1c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_562cb346de9113a49164a1513c42aa1c.js b/doc/html/dir_562cb346de9113a49164a1513c42aa1c.js new file mode 100644 index 000000000..de0cb46f7 --- /dev/null +++ b/doc/html/dir_562cb346de9113a49164a1513c42aa1c.js @@ -0,0 +1,4 @@ +var dir_562cb346de9113a49164a1513c42aa1c = +[ + [ "SyntheticAnnotation.cpp", "_synthetic_annotation_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.html b/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.html index eb6f20452..440cabdd1 100644 --- a/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.html +++ b/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.js b/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.js new file mode 100644 index 000000000..9b8bf93f8 --- /dev/null +++ b/doc/html/dir_577e0cdb3e2614f5a260ea490887b143.js @@ -0,0 +1,4 @@ +var dir_577e0cdb3e2614f5a260ea490887b143 = +[ + [ "DummyModel.h", "_dummy_model_8h.html", "_dummy_model_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.html b/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.html index 11841bbe7..4a4ab8751 100644 --- a/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.html +++ b/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -125,10 +131,13 @@  
- - + + diff --git a/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.js b/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.js new file mode 100644 index 000000000..26d963dac --- /dev/null +++ b/doc/html/dir_58badfc9ced8151ac5118cd2e12bebf1.js @@ -0,0 +1,11 @@ +var dir_58badfc9ced8151ac5118cd2e12bebf1 = +[ + [ "bean.cpp", "bean_8cpp_source.html", null ], + [ "CanopyGenerator.cpp", "_canopy_generator_8cpp.html", "_canopy_generator_8cpp" ], + [ "grapevine.cpp", "grapevine_8cpp.html", null ], + [ "sorghum.cpp", "sorghum_8cpp_source.html", null ], + [ "strawberry.cpp", "strawberry_8cpp_source.html", null ], + [ "tomato.cpp", "tomato_8cpp_source.html", null ], + [ "walnut.cpp", "walnut_8cpp_source.html", null ], + [ "whitespruce.cpp", "whitespruce_8cpp_source.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.html b/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.html index 1e9442550..160533c1d 100644 --- a/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.html +++ b/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.js b/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.js new file mode 100644 index 000000000..0aa5b27fe --- /dev/null +++ b/doc/html/dir_594f7d9c1b5f727f933fa022588b0b7d.js @@ -0,0 +1,4 @@ +var dir_594f7d9c1b5f727f933fa022588b0b7d = +[ + [ "StomatalConductanceModel.h", "_stomatal_conductance_model_8h.html", "_stomatal_conductance_model_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.html b/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.html index 72d5d86ad..84513a7f3 100644 --- a/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.html +++ b/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.js b/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.js new file mode 100644 index 000000000..d969df3aa --- /dev/null +++ b/doc/html/dir_59c6a555a98729b3f6a8f77608cc74a4.js @@ -0,0 +1,4 @@ +var dir_59c6a555a98729b3f6a8f77608cc74a4 = +[ + [ "CanopyGenerator.h", "_canopy_generator_8h.html", "_canopy_generator_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_615177bc4a60bdbaf2db637460677b64.html b/doc/html/dir_615177bc4a60bdbaf2db637460677b64.html index 268933000..2ceb50250 100644 --- a/doc/html/dir_615177bc4a60bdbaf2db637460677b64.html +++ b/doc/html/dir_615177bc4a60bdbaf2db637460677b64.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
canopygenerator Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_615177bc4a60bdbaf2db637460677b64.js b/doc/html/dir_615177bc4a60bdbaf2db637460677b64.js new file mode 100644 index 000000000..a6a3e8e87 --- /dev/null +++ b/doc/html/dir_615177bc4a60bdbaf2db637460677b64.js @@ -0,0 +1,5 @@ +var dir_615177bc4a60bdbaf2db637460677b64 = +[ + [ "include", "dir_59c6a555a98729b3f6a8f77608cc74a4.html", "dir_59c6a555a98729b3f6a8f77608cc74a4" ], + [ "src", "dir_58badfc9ced8151ac5118cd2e12bebf1.html", "dir_58badfc9ced8151ac5118cd2e12bebf1" ] +]; \ No newline at end of file diff --git a/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.html b/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.html index 67fb05f85..9ac86490f 100644 --- a/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.html +++ b/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.js b/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.js new file mode 100644 index 000000000..12eab16b5 --- /dev/null +++ b/doc/html/dir_6252300d35bf0f8a4d6b5ccb98672957.js @@ -0,0 +1,4 @@ +var dir_6252300d35bf0f8a4d6b5ccb98672957 = +[ + [ "EnergyBalanceModel.h", "_energy_balance_model_8h.html", "_energy_balance_model_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_6576ef5c45e1ae696f88b82c16a4c6c0.html b/doc/html/dir_6576ef5c45e1ae696f88b82c16a4c6c0.html index 6b4840e63..5944b34cf 100644 --- a/doc/html/dir_6576ef5c45e1ae696f88b82c16a4c6c0.html +++ b/doc/html/dir_6576ef5c45e1ae696f88b82c16a4c6c0.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_676c0954ed84853013df50d94356577b.html b/doc/html/dir_676c0954ed84853013df50d94356577b.html index 1f191e585..35514476c 100644 --- a/doc/html/dir_676c0954ed84853013df50d94356577b.html +++ b/doc/html/dir_676c0954ed84853013df50d94356577b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
radiation Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_676c0954ed84853013df50d94356577b.js b/doc/html/dir_676c0954ed84853013df50d94356577b.js new file mode 100644 index 000000000..13b91c1cd --- /dev/null +++ b/doc/html/dir_676c0954ed84853013df50d94356577b.js @@ -0,0 +1,5 @@ +var dir_676c0954ed84853013df50d94356577b = +[ + [ "include", "dir_40ea2a4aa4adfc7dc77aa13d0834001b.html", "dir_40ea2a4aa4adfc7dc77aa13d0834001b" ], + [ "src", "dir_1736472fec890ec3b25c5f707a1ad41b.html", "dir_1736472fec890ec3b25c5f707a1ad41b" ] +]; \ No newline at end of file diff --git a/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.html b/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.html index 595e69cfc..036aecd8f 100644 --- a/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.html +++ b/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.js b/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.js new file mode 100644 index 000000000..ad05ec9ad --- /dev/null +++ b/doc/html/dir_67ef339cfff2cfda5a7b1755578ee854.js @@ -0,0 +1,4 @@ +var dir_67ef339cfff2cfda5a7b1755578ee854 = +[ + [ "WeberPennTree.h", "_weber_penn_tree_8h.html", "_weber_penn_tree_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.html b/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.html index acfd1a386..3d4cf7b8f 100644 --- a/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.html +++ b/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
plantarchitecture Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.js b/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.js new file mode 100644 index 000000000..cf27ccb86 --- /dev/null +++ b/doc/html/dir_6d823072f66bbcb32b0d3acc588685b0.js @@ -0,0 +1,5 @@ +var dir_6d823072f66bbcb32b0d3acc588685b0 = +[ + [ "include", "dir_10651e710c37b90bb60afaa4d2c6a975.html", "dir_10651e710c37b90bb60afaa4d2c6a975" ], + [ "src", "dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3.html", "dir_1f4a8e9b5fbfec7b9342d55d1c70b0d3" ] +]; \ No newline at end of file diff --git a/doc/html/dir_7b776a486e9f6b66ded8f2e7f8d3acb3.html b/doc/html/dir_7b776a486e9f6b66ded8f2e7f8d3acb3.html new file mode 100644 index 000000000..7754592b1 --- /dev/null +++ b/doc/html/dir_7b776a486e9f6b66ded8f2e7f8d3acb3.html @@ -0,0 +1,129 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
3.28.1 Directory Reference
+
+
+ + + + +

+Directories

 CompilerIdCXX
 
+
+
+ + + + diff --git a/doc/html/dir_7b776a486e9f6b66ded8f2e7f8d3acb3.js b/doc/html/dir_7b776a486e9f6b66ded8f2e7f8d3acb3.js new file mode 100644 index 000000000..963d391ff --- /dev/null +++ b/doc/html/dir_7b776a486e9f6b66ded8f2e7f8d3acb3.js @@ -0,0 +1,4 @@ +var dir_7b776a486e9f6b66ded8f2e7f8d3acb3 = +[ + [ "CompilerIdCXX", "dir_ff579404bf421b82abd301ebf28d9c70.html", "dir_ff579404bf421b82abd301ebf28d9c70" ] +]; \ No newline at end of file diff --git a/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html b/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html index 7a1f58aaf..2efb45f11 100644 --- a/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html +++ b/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.js b/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.js new file mode 100644 index 000000000..f94544f3a --- /dev/null +++ b/doc/html/dir_7b945ff507247f5bd903b50b5c416c04.js @@ -0,0 +1,4 @@ +var dir_7b945ff507247f5bd903b50b5c416c04 = +[ + [ "VoxelIntersection.h", "_voxel_intersection_8h.html", "_voxel_intersection_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.html b/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.html index ee050317c..41dbfb47d 100644 --- a/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.html +++ b/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
src Directory Reference
@@ -117,10 +123,13 @@  
- - + + diff --git a/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.js b/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.js new file mode 100644 index 000000000..0df637cdc --- /dev/null +++ b/doc/html/dir_7f186228a2612084b0fc24dff2e535bf.js @@ -0,0 +1,7 @@ +var dir_7f186228a2612084b0fc24dff2e535bf = +[ + [ "fileIO.cpp", "lidar_2src_2file_i_o_8cpp.html", null ], + [ "LiDAR.cpp", "_li_d_a_r_8cpp.html", null ], + [ "LiDAR.cu", "_li_d_a_r_8cu.html", null ], + [ "selfTest.cpp", "plugins_2lidar_2src_2self_test_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_8a62bca5fa5119ede20b35462196f194.html b/doc/html/dir_8a62bca5fa5119ede20b35462196f194.html index b7fba3fe3..534ed28b6 100644 --- a/doc/html/dir_8a62bca5fa5119ede20b35462196f194.html +++ b/doc/html/dir_8a62bca5fa5119ede20b35462196f194.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
src Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_8a62bca5fa5119ede20b35462196f194.js b/doc/html/dir_8a62bca5fa5119ede20b35462196f194.js new file mode 100644 index 000000000..05e5e8294 --- /dev/null +++ b/doc/html/dir_8a62bca5fa5119ede20b35462196f194.js @@ -0,0 +1,4 @@ +var dir_8a62bca5fa5119ede20b35462196f194 = +[ + [ "DummyModel.cpp", "_dummy_model_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_8add51f561986f34dfac90d296d2ac1f.html b/doc/html/dir_8add51f561986f34dfac90d296d2ac1f.html index 8599bb94b..ea8fe6c67 100644 --- a/doc/html/dir_8add51f561986f34dfac90d296d2ac1f.html +++ b/doc/html/dir_8add51f561986f34dfac90d296d2ac1f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.html b/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.html index 9f0beeef1..8327ce8f8 100644 --- a/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.html +++ b/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.js b/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.js new file mode 100644 index 000000000..36125a7c9 --- /dev/null +++ b/doc/html/dir_9018c8dc5d181eb1cb047286a97fa87b.js @@ -0,0 +1,4 @@ +var dir_9018c8dc5d181eb1cb047286a97fa87b = +[ + [ "BoundaryLayerConductanceModel.h", "_boundary_layer_conductance_model_8h.html", "_boundary_layer_conductance_model_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.html b/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.html index 7932d6405..10f8e4f66 100644 --- a/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.html +++ b/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
src Directory Reference
@@ -119,10 +125,13 @@  
- - + + diff --git a/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.js b/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.js new file mode 100644 index 000000000..2ec5df352 --- /dev/null +++ b/doc/html/dir_90fd98a0ba30abf7a6068a44995d2d6b.js @@ -0,0 +1,8 @@ +var dir_90fd98a0ba30abf7a6068a44995d2d6b = +[ + [ "Context.cpp", "_context_8cpp.html", null ], + [ "Context_data.cpp", "_context__data_8cpp.html", null ], + [ "Context_fileIO.cpp", "_context__file_i_o_8cpp.html", null ], + [ "global.cpp", "global_8cpp.html", "global_8cpp" ], + [ "selfTest.cpp", "core_2src_2self_test_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.html b/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.html index 3a106f04d..1c2d4b154 100644 --- a/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.html +++ b/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.js b/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.js new file mode 100644 index 000000000..d36943d33 --- /dev/null +++ b/doc/html/dir_98f1c86a7f536ff9d6c61df9d8c64baa.js @@ -0,0 +1,5 @@ +var dir_98f1c86a7f536ff9d6c61df9d8c64baa = +[ + [ "AerialLiDAR.h", "_aerial_li_d_a_r_8h.html", "_aerial_li_d_a_r_8h" ], + [ "random.h", "aeriallidar_2include_2random_8h_source.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_9a3b5787d2329f793333f6962c777986.html b/doc/html/dir_9a3b5787d2329f793333f6962c777986.html index 1ab00a269..b1fc42728 100644 --- a/doc/html/dir_9a3b5787d2329f793333f6962c777986.html +++ b/doc/html/dir_9a3b5787d2329f793333f6962c777986.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
lidar Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_9a3b5787d2329f793333f6962c777986.js b/doc/html/dir_9a3b5787d2329f793333f6962c777986.js new file mode 100644 index 000000000..b70d1ef4a --- /dev/null +++ b/doc/html/dir_9a3b5787d2329f793333f6962c777986.js @@ -0,0 +1,5 @@ +var dir_9a3b5787d2329f793333f6962c777986 = +[ + [ "include", "dir_a8babb820ec20ecec6aebc09dbfb576c.html", "dir_a8babb820ec20ecec6aebc09dbfb576c" ], + [ "src", "dir_7f186228a2612084b0fc24dff2e535bf.html", "dir_7f186228a2612084b0fc24dff2e535bf" ] +]; \ No newline at end of file diff --git a/doc/html/dir_9a6cc15fde559dad335c1dc145a826ea.html b/doc/html/dir_9a6cc15fde559dad335c1dc145a826ea.html index 6b4b3149e..c434784f1 100644 --- a/doc/html/dir_9a6cc15fde559dad335c1dc145a826ea.html +++ b/doc/html/dir_9a6cc15fde559dad335c1dc145a826ea.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.html b/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.html index b74383572..af1694ba7 100644 --- a/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.html +++ b/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
stomatalconductance Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.js b/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.js new file mode 100644 index 000000000..d372fba0f --- /dev/null +++ b/doc/html/dir_a2b45ea1295f1e42b26af05f3b546a5b.js @@ -0,0 +1,5 @@ +var dir_a2b45ea1295f1e42b26af05f3b546a5b = +[ + [ "include", "dir_594f7d9c1b5f727f933fa022588b0b7d.html", "dir_594f7d9c1b5f727f933fa022588b0b7d" ], + [ "src", "dir_51eab06546c34d501c6cf953a16a9cc5.html", "dir_51eab06546c34d501c6cf953a16a9cc5" ] +]; \ No newline at end of file diff --git a/doc/html/dir_a4ee10e64f839049093220f98040855a.html b/doc/html/dir_a4ee10e64f839049093220f98040855a.html index 827d4f560..1f1abd46c 100644 --- a/doc/html/dir_a4ee10e64f839049093220f98040855a.html +++ b/doc/html/dir_a4ee10e64f839049093220f98040855a.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
dummy Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_a4ee10e64f839049093220f98040855a.js b/doc/html/dir_a4ee10e64f839049093220f98040855a.js new file mode 100644 index 000000000..8f2b97498 --- /dev/null +++ b/doc/html/dir_a4ee10e64f839049093220f98040855a.js @@ -0,0 +1,5 @@ +var dir_a4ee10e64f839049093220f98040855a = +[ + [ "include", "dir_577e0cdb3e2614f5a260ea490887b143.html", "dir_577e0cdb3e2614f5a260ea490887b143" ], + [ "src", "dir_8a62bca5fa5119ede20b35462196f194.html", "dir_8a62bca5fa5119ede20b35462196f194" ] +]; \ No newline at end of file diff --git a/doc/html/dir_a604905e97bad612ecdda55ac09d6396.html b/doc/html/dir_a604905e97bad612ecdda55ac09d6396.html index 852aa2c7b..ddc4ea5ac 100644 --- a/doc/html/dir_a604905e97bad612ecdda55ac09d6396.html +++ b/doc/html/dir_a604905e97bad612ecdda55ac09d6396.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_a604905e97bad612ecdda55ac09d6396.js b/doc/html/dir_a604905e97bad612ecdda55ac09d6396.js new file mode 100644 index 000000000..52ce49335 --- /dev/null +++ b/doc/html/dir_a604905e97bad612ecdda55ac09d6396.js @@ -0,0 +1,4 @@ +var dir_a604905e97bad612ecdda55ac09d6396 = +[ + [ "SyntheticAnnotation.h", "_synthetic_annotation_8h.html", "_synthetic_annotation_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.html b/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.html index 3295cdbb8..0f6451cca 100644 --- a/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.html +++ b/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -115,10 +121,13 @@  
- - + + diff --git a/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.js b/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.js new file mode 100644 index 000000000..557f217e9 --- /dev/null +++ b/doc/html/dir_a8babb820ec20ecec6aebc09dbfb576c.js @@ -0,0 +1,6 @@ +var dir_a8babb820ec20ecec6aebc09dbfb576c = +[ + [ "LiDAR.h", "_li_d_a_r_8h.html", "_li_d_a_r_8h" ], + [ "random.h", "lidar_2include_2random_8h_source.html", null ], + [ "s_hull_pro.h", "s__hull__pro_8h_source.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_b81f286eb903e0c3ba53b620487c01ae.html b/doc/html/dir_b81f286eb903e0c3ba53b620487c01ae.html index ff81f7738..ae0882b38 100644 --- a/doc/html/dir_b81f286eb903e0c3ba53b620487c01ae.html +++ b/doc/html/dir_b81f286eb903e0c3ba53b620487c01ae.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_b867f472847a1f099af0eb422541f49e.html b/doc/html/dir_b867f472847a1f099af0eb422541f49e.html index c3b1be2a7..92e3d3904 100644 --- a/doc/html/dir_b867f472847a1f099af0eb422541f49e.html +++ b/doc/html/dir_b867f472847a1f099af0eb422541f49e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
leafoptics Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_b867f472847a1f099af0eb422541f49e.js b/doc/html/dir_b867f472847a1f099af0eb422541f49e.js new file mode 100644 index 000000000..291de8ea0 --- /dev/null +++ b/doc/html/dir_b867f472847a1f099af0eb422541f49e.js @@ -0,0 +1,5 @@ +var dir_b867f472847a1f099af0eb422541f49e = +[ + [ "include", "dir_3d6a603070d279a42ac417e5c8a6aba1.html", "dir_3d6a603070d279a42ac417e5c8a6aba1" ], + [ "src", "dir_09ba98b3b490a60de71fb62d89fe47cd.html", "dir_09ba98b3b490a60de71fb62d89fe47cd" ] +]; \ No newline at end of file diff --git a/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.html b/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.html index 5081551f7..d35615a30 100644 --- a/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.html +++ b/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
boundarylayerconductance Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.js b/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.js new file mode 100644 index 000000000..1cdb2a1fc --- /dev/null +++ b/doc/html/dir_bc56ed6b0b97565306d951dc61815da9.js @@ -0,0 +1,5 @@ +var dir_bc56ed6b0b97565306d951dc61815da9 = +[ + [ "include", "dir_9018c8dc5d181eb1cb047286a97fa87b.html", "dir_9018c8dc5d181eb1cb047286a97fa87b" ], + [ "src", "dir_fceca22ca0920a3e9321d273c935ca85.html", "dir_fceca22ca0920a3e9321d273c935ca85" ] +]; \ No newline at end of file diff --git a/doc/html/dir_c2e785b0428381d295aba3d86e865907.html b/doc/html/dir_c2e785b0428381d295aba3d86e865907.html index 96ce138b7..d39d5b51d 100644 --- a/doc/html/dir_c2e785b0428381d295aba3d86e865907.html +++ b/doc/html/dir_c2e785b0428381d295aba3d86e865907.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.html b/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.html index 47b469fc7..ef2ad5f76 100644 --- a/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.html +++ b/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.js b/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.js new file mode 100644 index 000000000..1ed42373a --- /dev/null +++ b/doc/html/dir_d11e5a89bd40b12607fdeb823ca30c1a.js @@ -0,0 +1,4 @@ +var dir_d11e5a89bd40b12607fdeb823ca30c1a = +[ + [ "WeberPennTree.cpp", "_weber_penn_tree_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_d1ae8b435665c605bb4d6dbecb12be83.html b/doc/html/dir_d1ae8b435665c605bb4d6dbecb12be83.html new file mode 100644 index 000000000..550690d08 --- /dev/null +++ b/doc/html/dir_d1ae8b435665c605bb4d6dbecb12be83.html @@ -0,0 +1,123 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
build Directory Reference
+
+
+
+
+ + + + diff --git a/doc/html/dir_d1ae8b435665c605bb4d6dbecb12be83.js b/doc/html/dir_d1ae8b435665c605bb4d6dbecb12be83.js new file mode 100644 index 000000000..9f64b6acd --- /dev/null +++ b/doc/html/dir_d1ae8b435665c605bb4d6dbecb12be83.js @@ -0,0 +1,4 @@ +var dir_d1ae8b435665c605bb4d6dbecb12be83 = +[ + [ "CMakeFiles", "dir_4bc526d9ea56fd6bbf4f8bb7e1833918.html", "dir_4bc526d9ea56fd6bbf4f8bb7e1833918" ] +]; \ No newline at end of file diff --git a/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.html b/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.html index 4d50380c6..e1516020c 100644 --- a/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.html +++ b/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
RadiationModelPt2 Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.js b/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.js new file mode 100644 index 000000000..3874e8106 --- /dev/null +++ b/doc/html/dir_d346877beec799c6cac1a2fc56d1c290.js @@ -0,0 +1,4 @@ +var dir_d346877beec799c6cac1a2fc56d1c290 = +[ + [ "main.cpp", "main_8cpp_source.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_d39c4dd70ac914a319fbf3979f3cb0cd.html b/doc/html/dir_d39c4dd70ac914a319fbf3979f3cb0cd.html index d79e50970..05b28f45b 100644 --- a/doc/html/dir_d39c4dd70ac914a319fbf3979f3cb0cd.html +++ b/doc/html/dir_d39c4dd70ac914a319fbf3979f3cb0cd.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_d684e7c998fb76edbfb655ffd4cf6611.html b/doc/html/dir_d684e7c998fb76edbfb655ffd4cf6611.html index 2aed2c5ca..c77446876 100644 --- a/doc/html/dir_d684e7c998fb76edbfb655ffd4cf6611.html +++ b/doc/html/dir_d684e7c998fb76edbfb655ffd4cf6611.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.html b/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.html index e202e70c2..d22ced1e2 100644 --- a/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.html +++ b/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
include Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.js b/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.js new file mode 100644 index 000000000..ff3920a13 --- /dev/null +++ b/doc/html/dir_d6ff66ea9f957e81b4485948f070bc7c.js @@ -0,0 +1,4 @@ +var dir_d6ff66ea9f957e81b4485948f070bc7c = +[ + [ "SolarPosition.h", "_solar_position_8h.html", "_solar_position_8h" ] +]; \ No newline at end of file diff --git a/doc/html/dir_daed1286feb5181d9374e50e34ff739d.html b/doc/html/dir_daed1286feb5181d9374e50e34ff739d.html index 152376d28..f4adab29b 100644 --- a/doc/html/dir_daed1286feb5181d9374e50e34ff739d.html +++ b/doc/html/dir_daed1286feb5181d9374e50e34ff739d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
syntheticannotation Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_daed1286feb5181d9374e50e34ff739d.js b/doc/html/dir_daed1286feb5181d9374e50e34ff739d.js new file mode 100644 index 000000000..09a9a1779 --- /dev/null +++ b/doc/html/dir_daed1286feb5181d9374e50e34ff739d.js @@ -0,0 +1,5 @@ +var dir_daed1286feb5181d9374e50e34ff739d = +[ + [ "include", "dir_a604905e97bad612ecdda55ac09d6396.html", "dir_a604905e97bad612ecdda55ac09d6396" ], + [ "src", "dir_562cb346de9113a49164a1513c42aa1c.html", "dir_562cb346de9113a49164a1513c42aa1c" ] +]; \ No newline at end of file diff --git a/doc/html/dir_e68e8157741866f444e17edd764ebbae.html b/doc/html/dir_e68e8157741866f444e17edd764ebbae.html index 73c060bc1..a7af616d0 100644 --- a/doc/html/dir_e68e8157741866f444e17edd764ebbae.html +++ b/doc/html/dir_e68e8157741866f444e17edd764ebbae.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_e68e8157741866f444e17edd764ebbae.js b/doc/html/dir_e68e8157741866f444e17edd764ebbae.js new file mode 100644 index 000000000..5fe400cab --- /dev/null +++ b/doc/html/dir_e68e8157741866f444e17edd764ebbae.js @@ -0,0 +1,4 @@ +var dir_e68e8157741866f444e17edd764ebbae = +[ + [ "TutorialVideos", "dir_3771cc92d713de3e5272f9ad4d0b1912.html", "dir_3771cc92d713de3e5272f9ad4d0b1912" ] +]; \ No newline at end of file diff --git a/doc/html/dir_e725f6d562ac5b3216da834679296cd3.html b/doc/html/dir_e725f6d562ac5b3216da834679296cd3.html index 3a8d0fae9..286844582 100644 --- a/doc/html/dir_e725f6d562ac5b3216da834679296cd3.html +++ b/doc/html/dir_e725f6d562ac5b3216da834679296cd3.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_e771e57a540d4f14ef5ec2c81b56a7b6.html b/doc/html/dir_e771e57a540d4f14ef5ec2c81b56a7b6.html index cb290c790..e7e53b7f0 100644 --- a/doc/html/dir_e771e57a540d4f14ef5ec2c81b56a7b6.html +++ b/doc/html/dir_e771e57a540d4f14ef5ec2c81b56a7b6.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
doc Directory Reference
- -
+ + diff --git a/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html b/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html index d34193581..c509a0105 100644 --- a/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html +++ b/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -115,10 +121,13 @@  
- - + + diff --git a/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.js b/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.js new file mode 100644 index 000000000..f626e43ba --- /dev/null +++ b/doc/html/dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5.js @@ -0,0 +1,6 @@ +var dir_e8ed08f2d5f8ac3e3b5447bfe7f0fce5 = +[ + [ "AerialLiDAR.cpp", "_aerial_li_d_a_r_8cpp.html", null ], + [ "AerialLiDAR.cu", "_aerial_li_d_a_r_8cu.html", null ], + [ "fileIO.cpp", "aeriallidar_2src_2file_i_o_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_ee14773baee519b082f78b85b263aa48.html b/doc/html/dir_ee14773baee519b082f78b85b263aa48.html index df7ffb9eb..8477380fe 100644 --- a/doc/html/dir_ee14773baee519b082f78b85b263aa48.html +++ b/doc/html/dir_ee14773baee519b082f78b85b263aa48.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
weberpenntree Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_ee14773baee519b082f78b85b263aa48.js b/doc/html/dir_ee14773baee519b082f78b85b263aa48.js new file mode 100644 index 000000000..cfb8bf947 --- /dev/null +++ b/doc/html/dir_ee14773baee519b082f78b85b263aa48.js @@ -0,0 +1,5 @@ +var dir_ee14773baee519b082f78b85b263aa48 = +[ + [ "include", "dir_67ef339cfff2cfda5a7b1755578ee854.html", "dir_67ef339cfff2cfda5a7b1755578ee854" ], + [ "src", "dir_d11e5a89bd40b12607fdeb823ca30c1a.html", "dir_d11e5a89bd40b12607fdeb823ca30c1a" ] +]; \ No newline at end of file diff --git a/doc/html/dir_f34af3b1f7257ff6e74b73055c589954.html b/doc/html/dir_f34af3b1f7257ff6e74b73055c589954.html new file mode 100644 index 000000000..2340b959b --- /dev/null +++ b/doc/html/dir_f34af3b1f7257ff6e74b73055c589954.html @@ -0,0 +1,129 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
CompilerIdCXX Directory Reference
+
+
+ + + + +

+Files

 CMakeCXXCompilerId.cpp
 
+
+
+ + + + diff --git a/doc/html/dir_f34af3b1f7257ff6e74b73055c589954.js b/doc/html/dir_f34af3b1f7257ff6e74b73055c589954.js new file mode 100644 index 000000000..d013d53bc --- /dev/null +++ b/doc/html/dir_f34af3b1f7257ff6e74b73055c589954.js @@ -0,0 +1,4 @@ +var dir_f34af3b1f7257ff6e74b73055c589954 = +[ + [ "CMakeCXXCompilerId.cpp", "cmake-build-release_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_f54e10c7807847345da870f7da42cdf0.html b/doc/html/dir_f54e10c7807847345da870f7da42cdf0.html index c2510d943..4a3e03be0 100644 --- a/doc/html/dir_f54e10c7807847345da870f7da42cdf0.html +++ b/doc/html/dir_f54e10c7807847345da870f7da42cdf0.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
visualizer Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_f54e10c7807847345da870f7da42cdf0.js b/doc/html/dir_f54e10c7807847345da870f7da42cdf0.js new file mode 100644 index 000000000..5200d36ec --- /dev/null +++ b/doc/html/dir_f54e10c7807847345da870f7da42cdf0.js @@ -0,0 +1,5 @@ +var dir_f54e10c7807847345da870f7da42cdf0 = +[ + [ "include", "dir_0b377c449e87c33e20eed98f7cc3a6cc.html", "dir_0b377c449e87c33e20eed98f7cc3a6cc" ], + [ "src", "dir_1b48a9a5d33ab4b7862a4538757abad5.html", "dir_1b48a9a5d33ab4b7862a4538757abad5" ] +]; \ No newline at end of file diff --git a/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.html b/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.html index ba0ef78c1..528e39ac7 100644 --- a/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.html +++ b/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
photosynthesis Directory Reference
@@ -113,10 +119,13 @@  
- - + + diff --git a/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.js b/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.js new file mode 100644 index 000000000..dd30bad28 --- /dev/null +++ b/doc/html/dir_f93a58e1b1064abf3e9af98b74e2f5d5.js @@ -0,0 +1,5 @@ +var dir_f93a58e1b1064abf3e9af98b74e2f5d5 = +[ + [ "include", "dir_418637634c2136ee3716f84b17e3fdeb.html", "dir_418637634c2136ee3716f84b17e3fdeb" ], + [ "src", "dir_4ccbab8385dcba906f6a2cce80a3b511.html", "dir_4ccbab8385dcba906f6a2cce80a3b511" ] +]; \ No newline at end of file diff --git a/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.html b/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.html index 88575fe2c..958591276 100644 --- a/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.html +++ b/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
src Directory Reference
@@ -111,10 +117,13 @@  
- - + + diff --git a/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.js b/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.js new file mode 100644 index 000000000..975ce91ce --- /dev/null +++ b/doc/html/dir_fceca22ca0920a3e9321d273c935ca85.js @@ -0,0 +1,4 @@ +var dir_fceca22ca0920a3e9321d273c935ca85 = +[ + [ "BoundaryLayerConductanceModel.cpp", "_boundary_layer_conductance_model_8cpp.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_ff579404bf421b82abd301ebf28d9c70.html b/doc/html/dir_ff579404bf421b82abd301ebf28d9c70.html new file mode 100644 index 000000000..fdd15844b --- /dev/null +++ b/doc/html/dir_ff579404bf421b82abd301ebf28d9c70.html @@ -0,0 +1,129 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
CompilerIdCXX Directory Reference
+
+
+ + + + +

+Files

 CMakeCXXCompilerId.cpp
 
+
+
+ + + + diff --git a/doc/html/dir_ff579404bf421b82abd301ebf28d9c70.js b/doc/html/dir_ff579404bf421b82abd301ebf28d9c70.js new file mode 100644 index 000000000..ed4cbe9d6 --- /dev/null +++ b/doc/html/dir_ff579404bf421b82abd301ebf28d9c70.js @@ -0,0 +1,4 @@ +var dir_ff579404bf421b82abd301ebf28d9c70 = +[ + [ "CMakeCXXCompilerId.cpp", "build_2_c_make_files_23_828_81_2_compiler_id_c_x_x_2_c_make_c_x_x_compiler_id_8cpp_source.html", null ] +]; \ No newline at end of file diff --git a/doc/html/dir_ffb82276458c900659fd697987337356.html b/doc/html/dir_ffb82276458c900659fd697987337356.html new file mode 100644 index 000000000..f5a908f03 --- /dev/null +++ b/doc/html/dir_ffb82276458c900659fd697987337356.html @@ -0,0 +1,123 @@ + + + + + + + +.: Helios Documentation + + + + + + + + + + + + + + + +
+
+ + + + + + + +
+
 v1.3.27 +
+
+
+ + + + + + + + +
+
+ +
+
+
+ +
+ +
+
+ + +
+
+
+
+
+
Loading...
+
Searching...
+
No Matches
+
+
+
+
+ +
+
cmake-build-release Directory Reference
+
+
+
+
+ + + + diff --git a/doc/html/dir_ffb82276458c900659fd697987337356.js b/doc/html/dir_ffb82276458c900659fd697987337356.js new file mode 100644 index 000000000..1a4e7615d --- /dev/null +++ b/doc/html/dir_ffb82276458c900659fd697987337356.js @@ -0,0 +1,4 @@ +var dir_ffb82276458c900659fd697987337356 = +[ + [ "CMakeFiles", "dir_4821d91ccf02e9e7895ac63900918c57.html", "dir_4821d91ccf02e9e7895ac63900918c57" ] +]; \ No newline at end of file diff --git a/doc/html/doxygen-awesome-darkmode-toggle.js b/doc/html/doxygen-awesome-darkmode-toggle.js new file mode 100644 index 000000000..40fe2d38e --- /dev/null +++ b/doc/html/doxygen-awesome-darkmode-toggle.js @@ -0,0 +1,157 @@ +/** + +Doxygen Awesome +https://github.com/jothepro/doxygen-awesome-css + +MIT License + +Copyright (c) 2021 - 2023 jothepro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +*/ + +class DoxygenAwesomeDarkModeToggle extends HTMLElement { + // SVG icons from https://fonts.google.com/icons + // Licensed under the Apache 2.0 license: + // https://www.apache.org/licenses/LICENSE-2.0.html + static lightModeIcon = `` + static darkModeIcon = `` + static title = "Toggle Light/Dark Mode" + + static prefersLightModeInDarkModeKey = "prefers-light-mode-in-dark-mode" + static prefersDarkModeInLightModeKey = "prefers-dark-mode-in-light-mode" + + static _staticConstructor = function() { + DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.userPreference) + // Update the color scheme when the browsers preference changes + // without user interaction on the website. + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { + DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() + }) + // Update the color scheme when the tab is made visible again. + // It is possible that the appearance was changed in another tab + // while this tab was in the background. + document.addEventListener("visibilitychange", visibilityState => { + if (document.visibilityState === 'visible') { + DoxygenAwesomeDarkModeToggle.onSystemPreferenceChanged() + } + }); + }() + + static init() { + $(function() { + $(document).ready(function() { + const toggleButton = document.createElement('doxygen-awesome-dark-mode-toggle') + toggleButton.title = DoxygenAwesomeDarkModeToggle.title + toggleButton.updateIcon() + + window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', event => { + toggleButton.updateIcon() + }) + document.addEventListener("visibilitychange", visibilityState => { + if (document.visibilityState === 'visible') { + toggleButton.updateIcon() + } + }); + + $(document).ready(function(){ + document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) + }) + $(window).resize(function(){ + document.getElementById("MSearchBox").parentNode.appendChild(toggleButton) + }) + }) + }) + } + + constructor() { + super(); + this.onclick=this.toggleDarkMode + } + + /** + * @returns `true` for dark-mode, `false` for light-mode system preference + */ + static get systemPreference() { + return window.matchMedia('(prefers-color-scheme: dark)').matches + } + + /** + * @returns `true` for dark-mode, `false` for light-mode user preference + */ + static get userPreference() { + return (!DoxygenAwesomeDarkModeToggle.systemPreference && localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey)) || + (DoxygenAwesomeDarkModeToggle.systemPreference && !localStorage.getItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey)) + } + + static set userPreference(userPreference) { + DoxygenAwesomeDarkModeToggle.darkModeEnabled = userPreference + if(!userPreference) { + if(DoxygenAwesomeDarkModeToggle.systemPreference) { + localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey, true) + } else { + localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey) + } + } else { + if(!DoxygenAwesomeDarkModeToggle.systemPreference) { + localStorage.setItem(DoxygenAwesomeDarkModeToggle.prefersDarkModeInLightModeKey, true) + } else { + localStorage.removeItem(DoxygenAwesomeDarkModeToggle.prefersLightModeInDarkModeKey) + } + } + DoxygenAwesomeDarkModeToggle.onUserPreferenceChanged() + } + + static enableDarkMode(enable) { + if(enable) { + DoxygenAwesomeDarkModeToggle.darkModeEnabled = true + document.documentElement.classList.add("dark-mode") + document.documentElement.classList.remove("light-mode") + } else { + DoxygenAwesomeDarkModeToggle.darkModeEnabled = false + document.documentElement.classList.remove("dark-mode") + document.documentElement.classList.add("light-mode") + } + } + + static onSystemPreferenceChanged() { + DoxygenAwesomeDarkModeToggle.darkModeEnabled = DoxygenAwesomeDarkModeToggle.userPreference + DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) + } + + static onUserPreferenceChanged() { + DoxygenAwesomeDarkModeToggle.enableDarkMode(DoxygenAwesomeDarkModeToggle.darkModeEnabled) + } + + toggleDarkMode() { + DoxygenAwesomeDarkModeToggle.userPreference = !DoxygenAwesomeDarkModeToggle.userPreference + this.updateIcon() + } + + updateIcon() { + if(DoxygenAwesomeDarkModeToggle.darkModeEnabled) { + this.innerHTML = DoxygenAwesomeDarkModeToggle.darkModeIcon + } else { + this.innerHTML = DoxygenAwesomeDarkModeToggle.lightModeIcon + } + } +} + +customElements.define("doxygen-awesome-dark-mode-toggle", DoxygenAwesomeDarkModeToggle); diff --git a/doc/html/doxygen.css b/doc/html/doxygen.css index 4da4d34c0..fc0ce33c8 100644 --- a/doc/html/doxygen.css +++ b/doc/html/doxygen.css @@ -1,4 +1,4 @@ -/* The standard CSS for doxygen 1.12.0*/ +/* The standard CSS for doxygen 1.13.2*/ body { background-color: white; @@ -338,8 +338,7 @@ pre.fragment { opacity: 0; position: absolute; display: inline; - overflow: auto; - fill: black; + overflow: hidden; justify-content: center; align-items: center; cursor: pointer; @@ -351,7 +350,7 @@ pre.fragment { } .fragment:hover .clipboard, .clipboard.success { - opacity: .28; + opacity: .4; } .clipboard:hover, .clipboard.success { @@ -1422,6 +1421,11 @@ dl.invariant dt, dl.pre dt, dl.post dt { padding: 2px 0px; } +#side-nav #projectname +{ + font-size: 130%; +} + #projectbrief { font-size: 90%; @@ -1809,10 +1813,14 @@ th.markdownTableHeadCenter, td.markdownTableBodyCenter { text-align: center } -tt, code, kbd, samp +tt, code, kbd { display: inline-block; } +tt, code, kbd +{ + vertical-align: top; +} /* @end */ u { diff --git a/doc/html/doxygen_crawl.html b/doc/html/doxygen_crawl.html index 168a9e3d3..375de6713 100644 --- a/doc/html/doxygen_crawl.html +++ b/doc/html/doxygen_crawl.html @@ -4,461 +4,10 @@ Validator / crawler helper - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -492,8 +41,11 @@ + + + @@ -510,6 +62,7 @@ + @@ -528,7 +81,9 @@ + + @@ -536,7 +91,9 @@ + + @@ -544,6 +101,7 @@ + @@ -551,6 +109,7 @@ + @@ -572,10 +131,12 @@ + + @@ -601,8 +162,11 @@ + + + @@ -623,7 +187,9 @@ + + @@ -641,8 +207,11 @@ + + + @@ -657,11 +226,17 @@ + + + + + + @@ -724,12 +299,16 @@ + + + + @@ -771,6 +350,7 @@ + @@ -811,6 +391,7 @@ + @@ -818,13 +399,17 @@ + + + + @@ -839,7 +424,9 @@ + + @@ -855,7 +442,9 @@ + + @@ -869,6 +458,7 @@ + @@ -877,6 +467,7 @@ + @@ -901,8 +492,11 @@ + + + @@ -927,11 +521,15 @@ + + + + @@ -1174,6 +772,7 @@ + @@ -1232,6 +831,7 @@ + @@ -1244,11 +844,16 @@ + + + + + @@ -1885,6 +1490,7 @@ + @@ -2166,6 +1772,7 @@ + @@ -2200,6 +1807,7 @@ + @@ -2222,10 +1830,15 @@ + + + + + @@ -2233,14 +1846,18 @@ + + + + @@ -2251,32 +1868,47 @@ + + + + + + + + + + + + + + + @@ -2354,6 +1986,7 @@ + @@ -2408,91 +2041,12 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + @@ -2669,9 +2223,7 @@ - - @@ -2691,124 +2243,20 @@ - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + @@ -2823,6 +2271,7 @@ + @@ -2840,7 +2289,9 @@ + + diff --git a/doc/html/files.html b/doc/html/files.html index 322b19566..fbff78b0c 100644 --- a/doc/html/files.html +++ b/doc/html/files.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
+ + diff --git a/doc/html/files_dup.js b/doc/html/files_dup.js new file mode 100644 index 000000000..19c0f7474 --- /dev/null +++ b/doc/html/files_dup.js @@ -0,0 +1,6 @@ +var files_dup = +[ + [ "core", "dir_4270bfced15e0e73154b13468c7c9ad9.html", "dir_4270bfced15e0e73154b13468c7c9ad9" ], + [ "doc", "dir_e68e8157741866f444e17edd764ebbae.html", "dir_e68e8157741866f444e17edd764ebbae" ], + [ "plugins", "dir_38c8d24aef3972a7f87b834274e76e31.html", "dir_38c8d24aef3972a7f87b834274e76e31" ] +]; \ No newline at end of file diff --git a/doc/html/form_0.png b/doc/html/form_0.png index 287285b2f6b4ebdb523c58e4bff6b9783e9799d3..415fbe39b5803dfb0cc5ddb1cfb77236ef073ccd 100644 GIT binary patch delta 18 acmeyW`c-v86}yR^!G^0d)^2Pp5dr{E-w0X& delta 18 ZcmeyW`c-v86}yq1;oAwHq57838?l2QB~r delta 18 ZcmZo-X=0gB#crf$csTw_=f=iHMgTj92I2q! diff --git a/doc/html/form_10.png b/doc/html/form_10.png index fdafa165391eaadc73ded3d2436945cd6e5098cf..481837a4355644311ba1967788005680d84ffc0d 100644 GIT binary patch delta 18 ZcmeBT?P8r!#crZ!u;J>AwHq5bnE*Y*2FU;b delta 18 ZcmeBT?P8r!#crf$csTw_=f*}(CICCg27Lek diff --git a/doc/html/form_100.png b/doc/html/form_100.png index 1d4643777eedca0797d2c9e209105f531d122c85..96bd17befd18c7005615c6ae18dca42636e7ba21 100644 GIT binary patch delta 18 acmaDM{z8006}yR^!G^0d)^2P}=LP^xLAwHq55`2at!2JHX< delta 18 ZcmZpYZIYc(#crf$csTw_=f*}xJ^($m2B81| diff --git a/doc/html/form_105.png b/doc/html/form_105.png index 271d0ea86727e08ec65a588455c649e1dd8a3bf6..eb2b863d5c9c7a8d80d992660b39cc8d20cbb0b6 100644 GIT binary patch delta 18 acmX@abBJd`6}yR^!G^0d)^2P($O-^Qh6n-x delta 18 acmX@abBJd`6}yq1;oAwHq55nE^cH2DShI delta 18 ZcmZo-Z(^TN#crf$csTw_=f*}xW&k?r25JBR diff --git a/doc/html/form_107.png b/doc/html/form_107.png index 04373b923f8da4d6c00917e1d0178f5137ae8b5b..197ea60300a709591a2f392ba82485bd49ff4148 100644 GIT binary patch delta 18 acmX@ke4Keg6}yR^!G^0d)^2QcV*~(376*F( delta 18 ZcmX@ke4Keg6}yq1;ok-`zz6yO diff --git a/doc/html/form_109.png b/doc/html/form_109.png index 0edd0ae6c535562db928156faac49d400357edf4..482b9106f1f1ace1a9d60fe697be940f4d07ddfa 100644 GIT binary patch delta 18 acmbQIIZty!6}yR^!G^0d)^2Q+6#)Q6B?n&s delta 18 ZcmbQIIZty!6}yq1;o diff --git a/doc/html/form_111.png b/doc/html/form_111.png index f94515c6ab7846ca7c12cba84aa2917bd187b0c8..e78bc7e11929a930ee231781fdee61dc5c6e04e3 100644 GIT binary patch delta 18 acmX?5dZ2Vd6}yR^!G^0d)^2RHw*mlDlL&(V delta 18 ZcmX?5dZ2Vd6}yq1;oXKmk1gF delta 18 acmX@lcAjlQ6}yq1;o6}yR^!G^0d)^2Rv%LD*MGY97Y delta 18 acmdnTwvTN>6}yq1;ol2$$#crZ!u;J>AwHq6Ixd1_X2Y&zn delta 18 ZcmeAZ>l2$$#crf$csTw_=f=ifE&xA(2QvTw diff --git a/doc/html/form_120.png b/doc/html/form_120.png index 5aa88da4f110821a8cb71f32aca382460783dfba..ac6abb4b2c75cc611dbc8a064b7474b7aca7d150 100644 GIT binary patch delta 18 ZcmeC=>g1YG#crZ!u;J>AwHq5dSO7mk2T}k4 delta 18 ZcmeC=>g1YG#crf$csTw_=f=hk763g)2L=ED diff --git a/doc/html/form_121.png b/doc/html/form_121.png index f0821db79e1cb29bd6998cfc8e367dbb71148c56..1689c5dbb86d4fc39de50124e13f94d7ccfce126 100644 GIT binary patch delta 18 ZcmeBW>1CNv#crZ!u;J>AwHq6I7y&;H2TuS1 delta 18 ZcmeBW>1CNv#crf$csTw_=f=h!MgTn%2Lk{A diff --git a/doc/html/form_122.png b/doc/html/form_122.png index 647a17c45594256dbc194f74dba4694383b69d68..d3646fcde075110ad8f4085a52cbe3bc77215ea4 100644 GIT binary patch delta 18 acmX@ZeujNQ6}yR^!G^0d)^2R{W(EL9Ob3(z delta 18 ZcmX@ZeujNQ6}yq1;ou>b%>P6wO- diff --git a/doc/html/form_127.png b/doc/html/form_127.png index 2d439e7cac0e78dc86ef407288e0e7d05a0283a4..3a884dd87689a6ffc277626ed8eef57037d33ef6 100644 GIT binary patch delta 18 acmaFQ@t$Ks6}yR^!G^0d)^2Qk#|!{XSO|Xr delta 18 acmaFQ@t$Ks6}yq1;oAwHq6`m;gQJ2Fw5e delta 18 ZcmeBX?Pi@&#crf$csTw_=f*}ZCICC^27mwn diff --git a/doc/html/form_130.png b/doc/html/form_130.png index c8a269c65b96013d21c6f7615bc25c09a5ebe9ce..2f45c42fdc6452b68c985cec3dd2f8ef0f734511 100644 GIT binary patch delta 18 ZcmZqTY2uks#crZ!u;J>AwHq57SphzV2SNY< delta 18 ZcmZqTY2uks#crf$csTw_=f=iHRscMU2KE2| diff --git a/doc/html/form_131.png b/doc/html/form_131.png index 277d7eed6407de6f453b604c2646ac50450bd847..37fd41417503c6d7678c62f40a886fc2ba5d7d86 100644 GIT binary patch delta 18 acmey${grz{6}yR^!G^0d)^2PpVFdt9k_Z_9 delta 18 Zcmey${grz{6}yq1;o3kOyJ diff --git a/doc/html/form_133.png b/doc/html/form_133.png index 6082a2915f63b79e99c324cc64c158966f0d95cc..edb0cb58ccdc2787847c350cb53ee02a2d0b83be 100644 GIT binary patch delta 18 acmey*^`C1(6}yR^!G^0d)^2S4#{vLP*$A`% delta 18 acmey*^`C1(6}yq1;ob%~-Uw&_ diff --git a/doc/html/form_134.png b/doc/html/form_134.png index 3d55d6a6fdaf984803f02c25a57eed01aa03999f..cbeb428c02056cc77cff3d9675e8049863bdf585 100644 GIT binary patch delta 18 acmeyt^@D3d6}yR^!G^0d)^2S4&H?~V-3Xrm delta 18 acmeyt^@D3d6}yq1;oIVw| delta 18 ZcmbQuJ)3(%6}yq1;oGg2F?Hg diff --git a/doc/html/form_14.png b/doc/html/form_14.png index 1c19648bcf3b94b15e13dcce3d7944097aff7ba8..18936672628195f19718dbc778b61ad1da70a571 100644 GIT binary patch delta 18 acmX@ZafV|;6}yR^!G^0d)^2P(%?toYYzP(r delta 18 acmX@ZafV|;6}yq1;o6}yR^!G^0d)^2PxX9563I|ow$ delta 18 ZcmdnNx`TB>6}yq1;oAwHq7R838>y2EG6Q delta 18 ZcmeBR?qHr!#crf$csTw_=f*~MMgTiM266xZ diff --git a/doc/html/form_155.png b/doc/html/form_155.png index ec80fc40bdaf7e4dca45e0f52be9b6b786a7ff3d..f0ec8c85c638aff4d34edd67a1ce2e6484d30cf5 100644 GIT binary patch delta 18 acmZ3*v5I3t6}yR^!G^0d)^2QE$qWEPqzAA7 delta 18 acmZ3*v5I3t6}yq1;o6}yR^!G^0d)^2Rv#RvdJh6mXI delta 18 acmdnZvYTZ>6}yq1;oF#-TXiwBJW diff --git a/doc/html/form_158.png b/doc/html/form_158.png index faac15c71d03c19bfb4ecb8fb69fc7411b19c242..93536998a80c85c0d1ac2d2b6ae8b15578b95639 100644 GIT binary patch delta 18 acmdnVwv%l_6}yR^!G^0d)^2Rv!2|$Be+SqA delta 18 acmdnVwv%l_6}yq1;oFaZEVga?cO diff --git a/doc/html/form_159.png b/doc/html/form_159.png index e55911232cb187e817f1643458b7b7daa3f190e8..8103e8fb0a4440e3bee697aeb85a2d6962015d9e 100644 GIT binary patch delta 18 acmdnZyqkGK6}yR^!G^0d)^2RHVgvw0W(QXQ delta 18 ZcmdnZyqkGK6}yq1;oAwHq6mSpYq42EhOT delta 18 ZcmZqSY~h?x#crf$csTw_=f*~6763bP26X@c diff --git a/doc/html/form_160.png b/doc/html/form_160.png index 8627b151a74ab4da37aa84b2f82599cd4b553b64..f1672535ba8f3c1106a0e37d854134fadfe6b2e9 100644 GIT binary patch delta 18 acmdnax}9}G6}yR^!G^0d)^2PxV*&s~7Y9%P delta 18 Zcmdnax}9}G6}yq1;o6}yR^!G^0d)^2P}Vgdk4M+ejZ delta 18 ZcmaFN`j~Y>6}yq1;otLHu#crZ!u;J>AwHq7TnE*bU2Soq? delta 18 ZcmeBR>tLHu#crf$csTw_=f=i%CICF32KfL0 diff --git a/doc/html/form_17.png b/doc/html/form_17.png index 12629b85a822ce456486520c88a1883b2b6c115d..58b828cd73e2f3db5d77b3ab517648068b3a2848 100644 GIT binary patch delta 18 acmZ3_zMg$T6}yR^!G^0d)^2RnV+H_2I0rod delta 18 ZcmZ3_zMg$T6}yq1;o<{`>IdWi diff --git a/doc/html/form_171.png b/doc/html/form_171.png index 7ada8254e9d2f29ee953208737167ed3ae465987..36054bb55cc91c24566376c2c2353c9e94ac9454 100644 GIT binary patch delta 18 acmeyz_K$5s6}yR^!G^0d)^2S4%LD*VGYF>u delta 18 acmeyz_K$5s6}yq1;oAwHq7R838>y2EG6Q delta 18 ZcmeBR?qHr!#crf$csTw_=f*~MMgTiM266xZ diff --git a/doc/html/form_173.png b/doc/html/form_173.png index f9dda5304c887a0d21f16ac1f73ee762e10d3239..88a39edb3fc90c4ae7e661c46b8da0dce6d7d945 100644 GIT binary patch delta 18 acmX>sd028n6}yR^!G^0d)^2Qc;sF3iQ3s{~ delta 18 ZcmX>sd028n6}yq1;oGXelZuLqC- diff --git a/doc/html/form_175.png b/doc/html/form_175.png index 80d9ea979b6f30eb14780fe3e6a0738d0744980d..602763f4a045fbc4cedb7b6c175d76d33ccf5cd0 100644 GIT binary patch delta 18 ZcmZqWYUP?x#crZ!u;J>AwHq5-SO7k;2Sxw@ delta 18 ZcmZqWYUP?x#crf$csTw_=f=hs763f92KoR1 diff --git a/doc/html/form_176.png b/doc/html/form_176.png index 7f6f961334be8197d6e34ae2d4f46fbbee677dad..1eee60cff70efbd733e881fa1bed15b0dae9cdd7 100644 GIT binary patch delta 18 acmey$_LXfy6}yR^!G^0d)^2S4!UO)2QD+mz) delta 18 acmX@Zc7|<26}yq1;oAwHq5*m;gNw2D$(M delta 18 ZcmZo=ZDpNM#crf$csTw_=f*}BCICAW25tZV diff --git a/doc/html/form_18.png b/doc/html/form_18.png index d41e9c816c8f73990461c754aa8a357c84f9a54b..a7e021aa1ac5510132a14b16e1cdf4d7a932d820 100644 GIT binary patch delta 18 acmcc5cAsrR6}yR^!G^0d)^2RP#{>XM*9b}g delta 18 acmcc5cAsrR6}yq1;o<9<| delta 18 acmdlbu}fk?6}yq1;oasvQG@dvyB diff --git a/doc/html/form_181.png b/doc/html/form_181.png index ff74fffb34a471f595a94166f11d8af723b77ef4..4e0605308d311063955ed4b663cbf30c2a700a1d 100644 GIT binary patch delta 18 acmbOwJWF^&6}yR^!G^0d)^2Q+AwHq7%GXelUS_i5C delta 18 ZcmZo*ZD5^H#crf$csTw_=f=kWi~u}e2VMXG diff --git a/doc/html/form_184.png b/doc/html/form_184.png index 9e6ee5c75186343ca7ac2b65e06250902a8ed6d9..c1b8597595f90760b78d278e4886282b1f2414cb 100644 GIT binary patch delta 18 acmbQpK9PMw6}yR^!G^0d)^2PRU^K6}yR^!G^0d)^2R{W&{96$_I)7 delta 18 ZcmX@Ze1>^K6}yq1;oww7%|6}yR^!G^0d)^2QE!vp|B&j+*s delta 18 acmZ3>ww7%|6}yq1;o6}yR^!G^0d)^2RfU<3e4-Us0T delta 18 ZcmaFK{E~S>6}yq1;oAwHq55nE*Va2C)DD delta 18 ZcmZo-ZDO5J#crf$csTw_=f*}xCIC9924w&M diff --git a/doc/html/form_191.png b/doc/html/form_191.png index 09b8b3b314f437a577ac6477511f8c115a373b0b..c52fea79b983efb5a2f653b80ef9bf557cc88eca 100644 GIT binary patch delta 18 acmca2c13JL6}yR^!G^0d)^2RP%mn~TQwUK2 delta 18 acmca2c13JL6}yq1;ojeMWjh6}yR^!G^0d)^2R{<^=#r)(6G_ delta 18 ZcmX>jeMWjh6}yq1;ozb;2YLVi diff --git a/doc/html/form_196.png b/doc/html/form_196.png index 7b1dad023015f7db5a4ae80a361ff66419438ec8..7174f8d507602afbcfd9bb32e66f6e02e3567436 100644 GIT binary patch delta 18 acmbOrJ3)3r6}yR^!G^0d)^2R%=K}yirw11R delta 18 ZcmbOrJ3)3r6}yq1;ojNC>w8 delta 18 acmaE^@mym<6}yq1;ofoAC#crZ!u;J>AwHq7TSpYvB2TuS1 delta 18 ZcmeC+>foAC#crf$csTw_=f=i%763gW2Lk{A diff --git a/doc/html/form_202.png b/doc/html/form_202.png index 8a9ecebcba7413bf52216473f273c0830c4e221a..d3fb0ee886523f443797ef806d00c6eb210740ce 100644 GIT binary patch delta 18 acmcc3b(?EK6}yR^!G^0d)^2RP#R33I$p}aQ delta 18 acmcc3b(?EK6}yq1;ob%_&IkMe diff --git a/doc/html/form_203.png b/doc/html/form_203.png index 84b7bc0998ddcdfc42de91bbf2db83b700349e24..4c42ed6380a3aba27ce9de186a762f4182bb2cc4 100644 GIT binary patch delta 18 acmew=_f>8}6}yR^!G^0d)^2S4!Uq6Q`v}MY delta 18 acmew=_f>8}6}yq1;ol2HOAt diff --git a/doc/html/form_205.png b/doc/html/form_205.png index 084f8488ed6aa046882fffc2a5104bcae49d3b55..a7713a8b447e75b615c651e3b85cabf84a049dff 100644 GIT binary patch delta 18 acmey)^POix6}yR^!G^0d)^2S4#tHyV`Us%_ delta 18 acmey)^POix6}yq1;ot^0{|Hq8 diff --git a/doc/html/form_206.png b/doc/html/form_206.png index c0c91169b8e477ffda15a89328df992ec5be02ed..e2fc768b4c9a01800a344c2e0ac3f5cf8e123320 100644 GIT binary patch delta 18 ZcmeC->*1SF#crZ!u;J>AwHq6|*#JN<2W0>N delta 18 ZcmeC->*1SF#crf$csTw_=f=ivHUK^}2N?hW diff --git a/doc/html/form_207.png b/doc/html/form_207.png index bd998b9bfc23c7f5f4b4979d7d0242b513de9124..6ac865a0c5f14e10157fe43a02ca71c3af69968e 100644 GIT binary patch delta 18 acmaFG`HFKw6}yR^!G^0d)^2RfWB~w6#Ru~M delta 18 ZcmaFG`HFKw6}yq1;oAwHq6G7y&)*2F(Bf delta 18 ZcmeBW?q!}(#crf$csTw_=f*}JMgTkW27v$o diff --git a/doc/html/form_210.png b/doc/html/form_210.png index b678c605ed360efff697b9459d8fc2256dbec080..9872b2ff259142b98c922d4008a028baf7a79f8d 100644 GIT binary patch delta 18 acmdn4uw7w76}yR^!G^0d)^2Rv#t#5Uga{J= delta 18 acmdn4uw7w76}yq1;o)6}yR^!G^0d)^2RvzzP6GA_va^ delta 18 acmdnUvyo>)6}yq1;oCkKN7 diff --git a/doc/html/form_212.png b/doc/html/form_212.png index 4c625c6135077f6e2d106f3caa13844273b31d1a..245b8118e24fb5c06e392b76a32e9d0685b1b2b7 100644 GIT binary patch delta 18 acmX>pby8|V6}yR^!G^0d)^2P(!2pby8|V6}yq1;osc35me6}yR^!G^0d)^2P(#03CI?+6|M delta 18 acmX>sc35me6}yq1;oS=6}yR^!G^0d)^2R9VFCb6?+79Q delta 18 Zcmey%`j>S=6}yq1;oAwHq57m;gPW2QUBt delta 18 ZcmZoAwHq7RSpYr#2F(Bf delta 18 ZcmeC+?BJYG#crf$csTw_=f*~M763c~27v$o diff --git a/doc/html/form_223.png b/doc/html/form_223.png index db3981b2118bc9fc1a6bdb25f139871bc4a5b299..3108504aa2f527c4422eb0a1e24843c466bdf91b 100644 GIT binary patch delta 18 acmca1dP8(V6}yR^!G^0d)^2PJ=K=sq!w1^{ delta 18 Zcmca1dP8(V6}yq1;ob%^t_S1* diff --git a/doc/html/form_225.png b/doc/html/form_225.png index f2a398e7d369cb53adebb23fd3570d558958527a..001789935b037d2208762ad5eae05c241497f049 100644 GIT binary patch delta 18 acmZ23w_I*Q6}yR^!G^0d)^2QE#s>gK0|(v! delta 18 acmZ23w_I*Q6}yq1;o?&Y3P#crZ!u;J>AwHq6GSOGrr2H^kz delta 18 ZcmeC>?&Y3P#crf$csTw_=f*}JRscNr29*E+ diff --git a/doc/html/form_227.png b/doc/html/form_227.png index e7b510dd1c79b21030f4b44da182067cc9452b91..55580bac128b9a178cee5d87ea9f19699c19d1d2 100644 GIT binary patch delta 18 acmX@eb&zX96}yR^!G^0d)^2P(zybhAAqV;Z delta 18 acmX@eb&zX96}yq1;oCI_wn diff --git a/doc/html/form_228.png b/doc/html/form_228.png index 678ae44db3ceb682d38ee7a5d179f4a114629aff..13cdf9d3c64bcc1aafe9685675b4f33d74e40376 100644 GIT binary patch delta 18 acmaFE@`hzX6}yR^!G^0d)^2Qk%?JQYY6xrq delta 18 acmaFE@`hzX6}yq1;o{8xBF6}yR^!G^0d)^2R9;RFCrwg^Q4 delta 18 Zcmew>{8xBF6}yq1;o2W9{O diff --git a/doc/html/form_235.png b/doc/html/form_235.png index aea43199746f84fe88fc4a7d82beee7af992a93e..92cc4522896e9c927deba90c6dd5dad24513e210 100644 GIT binary patch delta 18 ZcmeBU?_-}(#crZ!u;J>AwHq6GnE^hO2HF4s delta 18 ZcmeBU?_-}(#crf$csTw_=f*}}W&k{y295v# diff --git a/doc/html/form_236.png b/doc/html/form_236.png index a55d3097123bf20b1239439109685cfced7f6380..a86665ced5ad60dce199b3a5ad117f110d748edf 100644 GIT binary patch delta 18 acmX@lex7|o6}yR^!G^0d)^2R{V+H_6xCfm8 delta 18 ZcmX@lex7|o6}yq1;oAwHq5-838^L2RZ-% delta 18 ZcmZo;X=9mC#crf$csTw_=f=iXMgTk)2JQd= diff --git a/doc/html/form_238.png b/doc/html/form_238.png index 2941261aaf190c9d1848269454b945260ab94370..eee27495a1a06c58b45d0207b706992ec7b08c14 100644 GIT binary patch delta 18 acmey(@tb2p6}yR^!G^0d)^2S4#S8#X2neG9 delta 18 acmey(@tb2p6}yq1;oTKrw9xH diff --git a/doc/html/form_240.png b/doc/html/form_240.png index fb5cd3d7149fd69b83a656e2b33d52933951965b..98e7a21a5431dcbcec94960a79eda113f3b40ba6 100644 GIT binary patch delta 18 acmey(^_y!#6}yR^!G^0d)^2S4#R33NNeHL_ delta 18 acmey(^_y!#6}yq1;ob%~P6%88 diff --git a/doc/html/form_241.png b/doc/html/form_241.png index b0ba953e7fd1f62ef18adf440fe886965f27a283..8d0b58caf890c988a00f751b230002aa7f3fa89a 100644 GIT binary patch delta 18 acmdnbyq|eO6}yR^!G^0d)^2RHV*~(1_6K7C delta 18 Zcmdnbyq|eO6}yq1;oAwHq5b*a1G|2HyYx delta 18 ZcmeC=@8q9Q#crf$csTw_=f*}3b^tu-29p2) diff --git a/doc/html/form_247.png b/doc/html/form_247.png index b231318fd218955e846eabd4d3692432a1b8b990..aa9732f5a81ccea5b423ad39948f14d923cd2501 100644 GIT binary patch delta 17 ZcmaFB^nhtX6}yR^!G^0d)=q4^4*)^d2qORh delta 17 ZcmaFB^nhtX6}yq1;o+A$Os7l delta 18 Zcmey&{+WG36}yq1;oAwHq6`m;pX02GIZj delta 18 ZcmeBX?`EG+#crf$csTw_=f*}ZW&k`b2893s diff --git a/doc/html/form_255.png b/doc/html/form_255.png index 83fe57567f6139c17a94f6113b42b43c7450aebc..fa2a61c3e843e4e1b768bf698a0276e436d3209e 100644 GIT binary patch delta 18 acmZ3)zKDH76}yR^!G^0d)^2Q6WCj31WCs=i delta 18 ZcmZ3)zKDH76}yq1;oj)AwHq6om;pX02Ri@& delta 18 ZcmZqXXy%wu#crf$csTw_=f=h+W&k`b2JZj> diff --git a/doc/html/form_26.png b/doc/html/form_26.png index 6acd3f7c3eb3f12c57ec568aad648854c2d3cda3..704a10417214ec0b2badbb6cfb6e6112c8e80c10 100644 GIT binary patch delta 18 acmcb{a*bs|6}yR^!G^0d)^2RP$_M~SQV1#l delta 18 acmcb{a*bs|6}yq1;oae-q(6}yR^!G^0d)^2P(&kO)a{0Jfd delta 18 acmcb>ae-q(6}yq1;oAwHq5*Sphxv2Fw5e delta 18 ZcmZqUZsVR%#crf$csTw_=f*}>RscKu27mwn diff --git a/doc/html/form_263.png b/doc/html/form_263.png index 0e840f6e1eca47e70c1f654cc86a67f211d38790..8e1ce45ff333632213616e835d126135e93c9dc8 100644 GIT binary patch delta 18 acmey%@|R^o6}yR^!G^0d)^2S4!w3LQ&Iq3X delta 18 acmey%@|R^o6}yq1;oOQ6}yR^!G^0d)^2Q^$OHgD0|#RO delta 18 acmbQlHi>OQ6}yq1;o2aA*#crZ!u;J>AwHq6|6#+*I2kZa< delta 18 ZcmeBi>2aA*#crf$csTw_=f=ivMF2$)2cQ4| diff --git a/doc/html/form_32.png b/doc/html/form_32.png index 704ea60517a0a75e9950df748304ed109c46dfd6..e7514df5fd7324151f99d89640e85e0274864297 100644 GIT binary patch delta 18 acmbQnHH~XR6}yR^!G^0d)^2Q^$^rmE6$g0$ delta 18 acmbQnHH~XR6}yq1;oAwHq55838(q6}yR^!G^0d)^2QE%m@HNN(Ynx delta 18 acmZ3&vV>(q6}yq1;oe1UmF6}yR^!G^0d)^2R{X9NI8S_hT@ delta 18 Zcmcb>e1UmF6}yq1;ob6}yR^!G^0d)^2PRW&;2~F9!Pn delta 18 ZcmbQjJB4>b6}yq1;o delta 18 ZcmX@if0%zl6}yq1;oAwHq5bnE*Y*2FU;b delta 18 ZcmeBT?P8r!#crf$csTw_=f*}(CICCg27Lek diff --git a/doc/html/form_54.png b/doc/html/form_54.png index 64290219bd57097e8b1895625e19f8ab0cdc0dfd..6284fbc7dafa3d5e03ecf29e377523069a3b4baf 100644 GIT binary patch delta 18 acmdnXv6o{)6}yR^!G^0d)^2Rv!wdjMPzUJ% delta 18 acmdnXv6o{)6}yq1;oAwHq5bnE*Y*2FU;b delta 18 ZcmeBT?P8r!#crf$csTw_=f*}(CICCg27Lek diff --git a/doc/html/form_56.png b/doc/html/form_56.png index 729aa9ccb83023ea48c7df3a959fe2d11f921999..825f00a60f9e52860c57e47093fbe2052ed81a8f 100644 GIT binary patch delta 18 acmZ1>wnA(|6}yR^!G^0d)^2QE&IJHPBL~d@ delta 18 acmZ1>wnA(|6}yq1;o delta 18 ZcmZ3$zkq*26}yq1;oAwHq5*SOGoK2FU;b delta 18 ZcmZqWZsnd(#crf$csTw_=f*}BRscKK27Lek diff --git a/doc/html/form_6.png b/doc/html/form_6.png index 42612abc84acc98462ccb93d25bad085ee663928..ea5bbeab3b64e5afa26b51056da263b0a8081871 100644 GIT binary patch delta 18 acmaFL@|0yl6}yR^!G^0d)^2Qk!UzCMZU|QZ delta 18 acmaFL@|0yl6}yq1;oAwHq6mnE*WN2DbnJ delta 18 ZcmZo+ZDE~I#crf$csTw_=f*~6CIC9{25SHS diff --git a/doc/html/form_63.png b/doc/html/form_63.png index c7248aee9a84b6a24b49ff6b715bd7375809b718..b6d137f93f227b56a831b517dafeb71d1d8fd51f 100644 GIT binary patch delta 18 acmcc3dYg4Z6}yR^!G^0d)^2Q!Vgdk3CkMO$ delta 18 Zcmcc3dYg4Z6}yq1;o+q6}yR^!G^0d)^2Rv%?toWEC=QQ delta 18 acmdnPv4>+q6}yq1;oGXnrbF$bCe diff --git a/doc/html/form_65.png b/doc/html/form_65.png index 3b1440eec636a45888b676e2fe5278a9d8f95fba..7b4d49316073c270935c866359768dda51fe46ca 100644 GIT binary patch delta 18 acmdnXvX^B-6}yR^!G^0d)^2Rv!w3LH&IjKB delta 18 acmdnXvX^B-6}yq1;o^K6}yR^!G^0d)^2R{W&{96$_I)7 delta 18 ZcmX@Ze1>^K6}yq1;o6}yR^!G^0d)^2RnW&r?04F@>@ delta 18 ZcmZ3(xrTE>6}yq1;oAwHq7RnE^e#2FL&a delta 18 ZcmeBR?_i%$#crf$csTw_=f*~MW&k_E27CYj diff --git a/doc/html/form_71.png b/doc/html/form_71.png index 39747259c4bf82d8043f29e071e6890db16775fe..95f2cb27d6bce81234cd7d3bc9685b841de6902f 100644 GIT binary patch delta 18 acmdnVvXf;(6}yR^!G^0d)^2Rv!3Y3FJ_pkP delta 18 acmdnVvXf;(6}yq1;oFaiKWLkEWd diff --git a/doc/html/form_72.png b/doc/html/form_72.png index ddf67cb495798bb7c5e01f3a9c26eca95c695eff..1302060df11bbc6f57382d22c58c83651dad35bd 100644 GIT binary patch delta 18 acmdnayq$SM6}yR^!G^0d)^2PxV*~(0)(1-f delta 18 Zcmdnayq$SM6}yq1;ok0|+Dl diff --git a/doc/html/form_79.png b/doc/html/form_79.png index 22281eaf8e836c6e430c718efae90fb67007e223..d68e80b1b252e8e68d15170ca16148aa18dddf4d 100644 GIT binary patch delta 18 acmeyz@sDFd6}yR^!G^0d)^2S4%M1WdbO@{f delta 18 acmeyz@sDFd6}yq1;ot>r!#crZ!u;J>AwHq6|m;gTq2TlM0 delta 18 ZcmeBX>t>r!#crf$csTw_=f=h^CICGQ2Lb>9 diff --git a/doc/html/form_82.png b/doc/html/form_82.png index 7cf12d8b2191e31e493242630152a67861b436bd..79d98b8a2608b7114b5f59957c14c782a4a4f62a 100644 GIT binary patch delta 18 acmeyy{*8S?6}yR^!G^0d)^2PpWd;CEGzby^ delta 18 Zcmeyy{*8S?6}yq1;oeems0a6}yR^!G^0d)^2Qc(*^)gzz9tM delta 18 ZcmX>eems0a6}yq1;oAwHq5*nE*XA2E70P delta 18 ZcmZo;ZDXBK#crf$csTw_=f*}>CICA)25|rY diff --git a/doc/html/form_97.png b/doc/html/form_97.png index 4966dd78405d9ae86ed41bf1793da9cb0208a635..39bf83bd219de1808e409a6a1973cee9ded2688c 100644 GIT binary patch delta 17 ZcmX@jbed^G6}yR^!G^0d)=q3Z1pq%G2jl<% delta 17 ZcmX@jbed^G6}yq1;o diff --git a/doc/html/form_99.png b/doc/html/form_99.png index f3e495c17e4533498e78c3e4d0a508eb2ab5f4f7..e5f855d1f01956a90e38ad8c7cf9fcb75235e380 100644 GIT binary patch delta 18 acmX>uaa>|T6}yR^!G^0d)^2P(#ti^Tzz8n@ delta 18 acmX>uaa>|T6}yq1;o Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
- a -

- - + + diff --git a/doc/html/functions_b.html b/doc/html/functions_b.html index 35160e596..185f39de5 100644 --- a/doc/html/functions_b.html +++ b/doc/html/functions_b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- b -

- - + + diff --git a/doc/html/functions_c.html b/doc/html/functions_c.html index a8b8c8020..055e963ba 100644 --- a/doc/html/functions_c.html +++ b/doc/html/functions_c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- c -

- - + + diff --git a/doc/html/functions_d.html b/doc/html/functions_d.html index a3de14c92..b29bc2c2b 100644 --- a/doc/html/functions_d.html +++ b/doc/html/functions_d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- d -

- - + + diff --git a/doc/html/functions_dup.js b/doc/html/functions_dup.js new file mode 100644 index 000000000..fe7498542 --- /dev/null +++ b/doc/html/functions_dup.js @@ -0,0 +1,29 @@ +var functions_dup = +[ + [ "a", "functions.html", null ], + [ "b", "functions_b.html", null ], + [ "c", "functions_c.html", null ], + [ "d", "functions_d.html", null ], + [ "e", "functions_e.html", null ], + [ "f", "functions_f.html", null ], + [ "g", "functions_g.html", null ], + [ "h", "functions_h.html", null ], + [ "i", "functions_i.html", null ], + [ "j", "functions_j.html", null ], + [ "l", "functions_l.html", null ], + [ "m", "functions_m.html", null ], + [ "n", "functions_n.html", null ], + [ "o", "functions_o.html", null ], + [ "p", "functions_p.html", null ], + [ "q", "functions_q.html", null ], + [ "r", "functions_r.html", null ], + [ "s", "functions_s.html", null ], + [ "t", "functions_t.html", null ], + [ "u", "functions_u.html", null ], + [ "v", "functions_v.html", null ], + [ "w", "functions_w.html", null ], + [ "x", "functions_x.html", null ], + [ "y", "functions_y.html", null ], + [ "z", "functions_z.html", null ], + [ "~", "functions_~.html", null ] +]; \ No newline at end of file diff --git a/doc/html/functions_e.html b/doc/html/functions_e.html index 8dbbb0f02..ab51ba58c 100644 --- a/doc/html/functions_e.html +++ b/doc/html/functions_e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- e -

- - + + diff --git a/doc/html/functions_enum.html b/doc/html/functions_enum.html index 160074df0..19c93e067 100644 --- a/doc/html/functions_enum.html +++ b/doc/html/functions_enum.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
LightingModel : Visualizer
- -
+ + diff --git a/doc/html/functions_eval.html b/doc/html/functions_eval.html index 685a6b717..3d75c8f26 100644 --- a/doc/html/functions_eval.html +++ b/doc/html/functions_eval.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
LIGHTING_PHONG_SHADOWED : Visualizer
- -
+ + diff --git a/doc/html/functions_f.html b/doc/html/functions_f.html index 07e8d21ee..210f0d0b2 100644 --- a/doc/html/functions_f.html +++ b/doc/html/functions_f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
- f -

- - + + diff --git a/doc/html/functions_func.html b/doc/html/functions_func.html index 7ea2cacab..00cc6e755 100644 --- a/doc/html/functions_func.html +++ b/doc/html/functions_func.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- a -

- - + + diff --git a/doc/html/functions_func.js b/doc/html/functions_func.js new file mode 100644 index 000000000..9f5f8bc2e --- /dev/null +++ b/doc/html/functions_func.js @@ -0,0 +1,27 @@ +var functions_func = +[ + [ "a", "functions_func.html", null ], + [ "b", "functions_func_b.html", null ], + [ "c", "functions_func_c.html", null ], + [ "d", "functions_func_d.html", null ], + [ "e", "functions_func_e.html", null ], + [ "f", "functions_func_f.html", null ], + [ "g", "functions_func_g.html", null ], + [ "h", "functions_func_h.html", null ], + [ "i", "functions_func_i.html", null ], + [ "j", "functions_func_j.html", null ], + [ "l", "functions_func_l.html", null ], + [ "m", "functions_func_m.html", null ], + [ "n", "functions_func_n.html", null ], + [ "o", "functions_func_o.html", null ], + [ "p", "functions_func_p.html", null ], + [ "q", "functions_func_q.html", null ], + [ "r", "functions_func_r.html", null ], + [ "s", "functions_func_s.html", null ], + [ "t", "functions_func_t.html", null ], + [ "u", "functions_func_u.html", null ], + [ "v", "functions_func_v.html", null ], + [ "w", "functions_func_w.html", null ], + [ "x", "functions_func_x.html", null ], + [ "~", "functions_func_~.html", null ] +]; \ No newline at end of file diff --git a/doc/html/functions_func_b.html b/doc/html/functions_func_b.html index c5754eb80..00c666813 100644 --- a/doc/html/functions_func_b.html +++ b/doc/html/functions_func_b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- b -

- - + + diff --git a/doc/html/functions_func_c.html b/doc/html/functions_func_c.html index 2073c888c..e31e3875b 100644 --- a/doc/html/functions_func_c.html +++ b/doc/html/functions_func_c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- c -

- - + + diff --git a/doc/html/functions_func_d.html b/doc/html/functions_func_d.html index b1743c948..5dda0f615 100644 --- a/doc/html/functions_func_d.html +++ b/doc/html/functions_func_d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- d -

- - + + diff --git a/doc/html/functions_func_e.html b/doc/html/functions_func_e.html index 2e6209648..7c850c7bd 100644 --- a/doc/html/functions_func_e.html +++ b/doc/html/functions_func_e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- e -

- - + + diff --git a/doc/html/functions_func_f.html b/doc/html/functions_func_f.html index 43196cee2..b53d7d120 100644 --- a/doc/html/functions_func_f.html +++ b/doc/html/functions_func_f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- f -

- - + + diff --git a/doc/html/functions_func_g.html b/doc/html/functions_func_g.html index f26d40b1f..9ef5c2b16 100644 --- a/doc/html/functions_func_g.html +++ b/doc/html/functions_func_g.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- g -

  • getAllObjectIDs() : helios::Context, PlantArchitecture
  • getAllPeduncleUUIDs() : PlantArchitecture
  • getAllPetioleUUIDs() : PlantArchitecture
  • +
  • getAllPlantIDs() : PlantArchitecture
  • getAllPlantObjectIDs() : PlantArchitecture
  • getAllPlantUUIDs() : PlantArchitecture
  • getAllUUIDs() : CanopyGenerator, helios::Context, PlantArchitecture, WeberPennTree
  • @@ -223,10 +234,14 @@

    - g -

    • getPlantCount() : CanopyGenerator
    • getPlantFlowerObjectIDs() : PlantArchitecture
    • getPlantFruitObjectIDs() : PlantArchitecture
    • +
    • getPlantHeight() : PlantArchitecture
    • getPlantInternodeObjectIDs() : PlantArchitecture
    • +
    • getPlantLeafCount() : PlantArchitecture
    • +
    • getPlantLeafInclinationAngleDistribution() : PlantArchitecture
    • getPlantLeafObjectIDs() : PlantArchitecture
    • getPlantPeduncleObjectIDs() : PlantArchitecture
    • getPlantPetioleObjectIDs() : PlantArchitecture
    • +
    • getPlantStemHeight() : PlantArchitecture
    • getPolymeshObjectPointer() : helios::Context
    • getPolymeshObjectVolume() : helios::Context
    • getPrimitiveArea() : helios::Context
    • @@ -331,10 +346,12 @@

      - g -

      - - + + diff --git a/doc/html/functions_func_h.html b/doc/html/functions_func_h.html index 20c79fcc7..31a1372d2 100644 --- a/doc/html/functions_func_h.html +++ b/doc/html/functions_func_h.html @@ -38,7 +38,7 @@ Logo -
       v1.3.26 +
       v1.3.27
      @@ -46,7 +46,7 @@
      - + -
      +
      + +
      +
      +
      +
      - h -

- - + + diff --git a/doc/html/functions_func_i.html b/doc/html/functions_func_i.html index 79f8a897d..9d42dd226 100644 --- a/doc/html/functions_func_i.html +++ b/doc/html/functions_func_i.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- i -

- - + + diff --git a/doc/html/functions_func_j.html b/doc/html/functions_func_j.html index 6cf922baa..78f6a6afd 100644 --- a/doc/html/functions_func_j.html +++ b/doc/html/functions_func_j.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- j -

- - + + diff --git a/doc/html/functions_func_l.html b/doc/html/functions_func_l.html index 2aa882f41..42a220bb9 100644 --- a/doc/html/functions_func_l.html +++ b/doc/html/functions_func_l.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- l -

- - + + diff --git a/doc/html/functions_func_m.html b/doc/html/functions_func_m.html index d6f926e47..a3f9f2096 100644 --- a/doc/html/functions_func_m.html +++ b/doc/html/functions_func_m.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- m -

- - + + diff --git a/doc/html/functions_func_n.html b/doc/html/functions_func_n.html index 42acd03ec..f8b6f2591 100644 --- a/doc/html/functions_func_n.html +++ b/doc/html/functions_func_n.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- n -

- - + + diff --git a/doc/html/functions_func_o.html b/doc/html/functions_func_o.html index b2ff633de..205c8dbfc 100644 --- a/doc/html/functions_func_o.html +++ b/doc/html/functions_func_o.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- o -

- - + + diff --git a/doc/html/functions_func_p.html b/doc/html/functions_func_p.html index fb0596ccc..996a5bae7 100644 --- a/doc/html/functions_func_p.html +++ b/doc/html/functions_func_p.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- p -

- - + + diff --git a/doc/html/functions_func_q.html b/doc/html/functions_func_q.html index 9018340e6..00d4e599d 100644 --- a/doc/html/functions_func_q.html +++ b/doc/html/functions_func_q.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- q -

- - + + diff --git a/doc/html/functions_func_r.html b/doc/html/functions_func_r.html index 23e013107..9e98c947d 100644 --- a/doc/html/functions_func_r.html +++ b/doc/html/functions_func_r.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- r -

- - + + diff --git a/doc/html/functions_func_s.html b/doc/html/functions_func_s.html index fc3acf84c..eb19b5139 100644 --- a/doc/html/functions_func_s.html +++ b/doc/html/functions_func_s.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- s -

- - + + diff --git a/doc/html/functions_func_t.html b/doc/html/functions_func_t.html index 3d3f3af5e..63a641c8b 100644 --- a/doc/html/functions_func_t.html +++ b/doc/html/functions_func_t.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- t -

- - + + diff --git a/doc/html/functions_func_u.html b/doc/html/functions_func_u.html index 3642502e1..d1deac5a4 100644 --- a/doc/html/functions_func_u.html +++ b/doc/html/functions_func_u.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- u -

- - + + diff --git a/doc/html/functions_func_v.html b/doc/html/functions_func_v.html index 30ddf71a5..6f786209f 100644 --- a/doc/html/functions_func_v.html +++ b/doc/html/functions_func_v.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- v -

- - + + diff --git a/doc/html/functions_func_w.html b/doc/html/functions_func_w.html index c2e260044..b17cb3261 100644 --- a/doc/html/functions_func_w.html +++ b/doc/html/functions_func_w.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- w -

  • writeNormDepthImage() : RadiationModel
  • writeOBJ() : helios::Context
  • writeObjectDataLabelMap() : RadiationModel
  • +
  • writePlantMeshVertices() : PlantArchitecture
  • writePLY() : helios::Context
  • writePrimitiveData() : helios::Context
  • writePrimitiveDataLabelMap() : RadiationModel
  • @@ -123,10 +134,12 @@

    - w -

    - - + + diff --git a/doc/html/functions_func_x.html b/doc/html/functions_func_x.html index 319ae45c1..f56c38992 100644 --- a/doc/html/functions_func_x.html +++ b/doc/html/functions_func_x.html @@ -38,7 +38,7 @@ Logo -
     v1.3.26 +
     v1.3.27
    @@ -46,7 +46,7 @@
    - + -
    +
    + +
    +
    +
    +
    - x -

- - + + diff --git a/doc/html/functions_func_~.html b/doc/html/functions_func_~.html index ca2943220..7bb69ee9b 100644 --- a/doc/html/functions_func_~.html +++ b/doc/html/functions_func_~.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- ~ -

- - + + diff --git a/doc/html/functions_g.html b/doc/html/functions_g.html index 1601e7c3b..9485d0f0a 100644 --- a/doc/html/functions_g.html +++ b/doc/html/functions_g.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- g -

  • getAllObjectIDs() : helios::Context, PlantArchitecture
  • getAllPeduncleUUIDs() : PlantArchitecture
  • getAllPetioleUUIDs() : PlantArchitecture
  • +
  • getAllPlantIDs() : PlantArchitecture
  • getAllPlantObjectIDs() : PlantArchitecture
  • getAllPlantUUIDs() : PlantArchitecture
  • getAllUUIDs() : CanopyGenerator, helios::Context, PlantArchitecture, WeberPennTree
  • @@ -225,10 +236,14 @@

    - g -

    • getPlantCount() : CanopyGenerator
    • getPlantFlowerObjectIDs() : PlantArchitecture
    • getPlantFruitObjectIDs() : PlantArchitecture
    • +
    • getPlantHeight() : PlantArchitecture
    • getPlantInternodeObjectIDs() : PlantArchitecture
    • +
    • getPlantLeafCount() : PlantArchitecture
    • +
    • getPlantLeafInclinationAngleDistribution() : PlantArchitecture
    • getPlantLeafObjectIDs() : PlantArchitecture
    • getPlantPeduncleObjectIDs() : PlantArchitecture
    • getPlantPetioleObjectIDs() : PlantArchitecture
    • +
    • getPlantStemHeight() : PlantArchitecture
    • getPolymeshObjectPointer() : helios::Context
    • getPolymeshObjectVolume() : helios::Context
    • getPrimitiveArea() : helios::Context
    • @@ -338,10 +353,12 @@

      - g -

      - - + + diff --git a/doc/html/functions_h.html b/doc/html/functions_h.html index 1a1352a47..1c1c0ff25 100644 --- a/doc/html/functions_h.html +++ b/doc/html/functions_h.html @@ -38,7 +38,7 @@ Logo -
       v1.3.26 +
       v1.3.27
      @@ -46,7 +46,7 @@
      - + -
      +
      + +
      +
      +
      +
      - h -

- - + + diff --git a/doc/html/functions_i.html b/doc/html/functions_i.html index cc1ae00b8..ab59a810b 100644 --- a/doc/html/functions_i.html +++ b/doc/html/functions_i.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- i -

- - + + diff --git a/doc/html/functions_j.html b/doc/html/functions_j.html index 8d553890c..1cdcccf3c 100644 --- a/doc/html/functions_j.html +++ b/doc/html/functions_j.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- j -

- - + + diff --git a/doc/html/functions_l.html b/doc/html/functions_l.html index 7abae0fd0..6e678fd5f 100644 --- a/doc/html/functions_l.html +++ b/doc/html/functions_l.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- l -

- - + + diff --git a/doc/html/functions_m.html b/doc/html/functions_m.html index 005243b8e..d61c10f0a 100644 --- a/doc/html/functions_m.html +++ b/doc/html/functions_m.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- m -

- - + + diff --git a/doc/html/functions_n.html b/doc/html/functions_n.html index e84d0582a..4ac463668 100644 --- a/doc/html/functions_n.html +++ b/doc/html/functions_n.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- n -

- - + + diff --git a/doc/html/functions_o.html b/doc/html/functions_o.html index 1597db855..2f0ea3979 100644 --- a/doc/html/functions_o.html +++ b/doc/html/functions_o.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- o -

- - + + diff --git a/doc/html/functions_p.html b/doc/html/functions_p.html index 2306d4754..0a0dd0004 100644 --- a/doc/html/functions_p.html +++ b/doc/html/functions_p.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- p -

- - + + diff --git a/doc/html/functions_q.html b/doc/html/functions_q.html index b696f030b..7d4956f10 100644 --- a/doc/html/functions_q.html +++ b/doc/html/functions_q.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- q -

- - + + diff --git a/doc/html/functions_r.html b/doc/html/functions_r.html index 1b8af239f..5277bf548 100644 --- a/doc/html/functions_r.html +++ b/doc/html/functions_r.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- r -

- - + + diff --git a/doc/html/functions_rela.html b/doc/html/functions_rela.html index c6c3583f4..897b10608 100644 --- a/doc/html/functions_rela.html +++ b/doc/html/functions_rela.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+ + + diff --git a/doc/html/functions_s.html b/doc/html/functions_s.html index a201cc5c2..c2f0d356c 100644 --- a/doc/html/functions_s.html +++ b/doc/html/functions_s.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
- s -

- - + + diff --git a/doc/html/functions_t.html b/doc/html/functions_t.html index 570f51830..0b3f7814f 100644 --- a/doc/html/functions_t.html +++ b/doc/html/functions_t.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- t -

- - + + diff --git a/doc/html/functions_u.html b/doc/html/functions_u.html index c3775161f..f2545618b 100644 --- a/doc/html/functions_u.html +++ b/doc/html/functions_u.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- u -

- - + + diff --git a/doc/html/functions_v.html b/doc/html/functions_v.html index 9e7146639..85fa65f34 100644 --- a/doc/html/functions_v.html +++ b/doc/html/functions_v.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- v -

- - + + diff --git a/doc/html/functions_vars.html b/doc/html/functions_vars.html index 9aed1168d..8d0f90db8 100644 --- a/doc/html/functions_vars.html +++ b/doc/html/functions_vars.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- a -

- - + + diff --git a/doc/html/functions_vars.js b/doc/html/functions_vars.js new file mode 100644 index 000000000..20fa74585 --- /dev/null +++ b/doc/html/functions_vars.js @@ -0,0 +1,25 @@ +var functions_vars = +[ + [ "a", "functions_vars.html", null ], + [ "b", "functions_vars_b.html", null ], + [ "c", "functions_vars_c.html", null ], + [ "d", "functions_vars_d.html", null ], + [ "e", "functions_vars_e.html", null ], + [ "f", "functions_vars_f.html", null ], + [ "g", "functions_vars_g.html", null ], + [ "h", "functions_vars_h.html", null ], + [ "l", "functions_vars_l.html", null ], + [ "m", "functions_vars_m.html", null ], + [ "n", "functions_vars_n.html", null ], + [ "o", "functions_vars_o.html", null ], + [ "p", "functions_vars_p.html", null ], + [ "r", "functions_vars_r.html", null ], + [ "s", "functions_vars_s.html", null ], + [ "t", "functions_vars_t.html", null ], + [ "u", "functions_vars_u.html", null ], + [ "v", "functions_vars_v.html", null ], + [ "w", "functions_vars_w.html", null ], + [ "x", "functions_vars_x.html", null ], + [ "y", "functions_vars_y.html", null ], + [ "z", "functions_vars_z.html", null ] +]; \ No newline at end of file diff --git a/doc/html/functions_vars_b.html b/doc/html/functions_vars_b.html index 2a39c9ee7..40f859c00 100644 --- a/doc/html/functions_vars_b.html +++ b/doc/html/functions_vars_b.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- b -

- - + + diff --git a/doc/html/functions_vars_c.html b/doc/html/functions_vars_c.html index 734993f00..9d286e24f 100644 --- a/doc/html/functions_vars_c.html +++ b/doc/html/functions_vars_c.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- c -

- - + + diff --git a/doc/html/functions_vars_d.html b/doc/html/functions_vars_d.html index bcbb73166..109a30dab 100644 --- a/doc/html/functions_vars_d.html +++ b/doc/html/functions_vars_d.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- d -

- - + + diff --git a/doc/html/functions_vars_e.html b/doc/html/functions_vars_e.html index dde212760..8de16e278 100644 --- a/doc/html/functions_vars_e.html +++ b/doc/html/functions_vars_e.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- e -

- - + + diff --git a/doc/html/functions_vars_f.html b/doc/html/functions_vars_f.html index ec367ff2f..c02c390ee 100644 --- a/doc/html/functions_vars_f.html +++ b/doc/html/functions_vars_f.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- f -

- - + + diff --git a/doc/html/functions_vars_g.html b/doc/html/functions_vars_g.html index 4c0001f85..6a67c1bf0 100644 --- a/doc/html/functions_vars_g.html +++ b/doc/html/functions_vars_g.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- g -

- - + + diff --git a/doc/html/functions_vars_h.html b/doc/html/functions_vars_h.html index f1becb24b..627eafcde 100644 --- a/doc/html/functions_vars_h.html +++ b/doc/html/functions_vars_h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- h -

- - + + diff --git a/doc/html/functions_vars_l.html b/doc/html/functions_vars_l.html index 9a2ce0df8..bf3f655bf 100644 --- a/doc/html/functions_vars_l.html +++ b/doc/html/functions_vars_l.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- l -

- - + + diff --git a/doc/html/functions_vars_m.html b/doc/html/functions_vars_m.html index ae42274cc..72cbeb9f9 100644 --- a/doc/html/functions_vars_m.html +++ b/doc/html/functions_vars_m.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- m -

- - + + diff --git a/doc/html/functions_vars_n.html b/doc/html/functions_vars_n.html index 2474a649e..46eb2d58e 100644 --- a/doc/html/functions_vars_n.html +++ b/doc/html/functions_vars_n.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- n -

- - + + diff --git a/doc/html/functions_vars_o.html b/doc/html/functions_vars_o.html index b1028f1a4..7d4387020 100644 --- a/doc/html/functions_vars_o.html +++ b/doc/html/functions_vars_o.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- o -

- - + + diff --git a/doc/html/functions_vars_p.html b/doc/html/functions_vars_p.html index ba901d214..fb61efa4c 100644 --- a/doc/html/functions_vars_p.html +++ b/doc/html/functions_vars_p.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- p -

- - + + diff --git a/doc/html/functions_vars_r.html b/doc/html/functions_vars_r.html index 1d45f936e..a4fbadb8b 100644 --- a/doc/html/functions_vars_r.html +++ b/doc/html/functions_vars_r.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- r -

- - + + diff --git a/doc/html/functions_vars_s.html b/doc/html/functions_vars_s.html index 473b57654..9bf9f34ca 100644 --- a/doc/html/functions_vars_s.html +++ b/doc/html/functions_vars_s.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- s -

- - + + diff --git a/doc/html/functions_vars_t.html b/doc/html/functions_vars_t.html index 98c610d98..10516cf1d 100644 --- a/doc/html/functions_vars_t.html +++ b/doc/html/functions_vars_t.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- t -

- - + + diff --git a/doc/html/functions_vars_u.html b/doc/html/functions_vars_u.html index 1741951a9..7f6d0c1c4 100644 --- a/doc/html/functions_vars_u.html +++ b/doc/html/functions_vars_u.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- u -

- - + + diff --git a/doc/html/functions_vars_v.html b/doc/html/functions_vars_v.html index 76286e9be..3aa66ab0a 100644 --- a/doc/html/functions_vars_v.html +++ b/doc/html/functions_vars_v.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- v -

- - + + diff --git a/doc/html/functions_vars_w.html b/doc/html/functions_vars_w.html index b5a0ee68c..e79dc69a4 100644 --- a/doc/html/functions_vars_w.html +++ b/doc/html/functions_vars_w.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- w -

- - + + diff --git a/doc/html/functions_vars_x.html b/doc/html/functions_vars_x.html index 6d31c8aab..0cec9776d 100644 --- a/doc/html/functions_vars_x.html +++ b/doc/html/functions_vars_x.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- x -

- - + + diff --git a/doc/html/functions_vars_y.html b/doc/html/functions_vars_y.html index 58af72eb5..59ee836e2 100644 --- a/doc/html/functions_vars_y.html +++ b/doc/html/functions_vars_y.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- y -

- - + + diff --git a/doc/html/functions_vars_z.html b/doc/html/functions_vars_z.html index b013b92d2..12ea57838 100644 --- a/doc/html/functions_vars_z.html +++ b/doc/html/functions_vars_z.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- z -

- - + + diff --git a/doc/html/functions_w.html b/doc/html/functions_w.html index a6d323a99..6d6b8b3ac 100644 --- a/doc/html/functions_w.html +++ b/doc/html/functions_w.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- w -

  • writeNormDepthImage() : RadiationModel
  • writeOBJ() : helios::Context
  • writeObjectDataLabelMap() : RadiationModel
  • +
  • writePlantMeshVertices() : PlantArchitecture
  • writePLY() : helios::Context
  • writePrimitiveData() : helios::Context
  • writePrimitiveDataLabelMap() : RadiationModel
  • @@ -130,10 +141,12 @@

    - w -

    - - + + diff --git a/doc/html/functions_x.html b/doc/html/functions_x.html index 66283cd41..93f6e8f56 100644 --- a/doc/html/functions_x.html +++ b/doc/html/functions_x.html @@ -38,7 +38,7 @@ Logo -
     v1.3.26 +
     v1.3.27
    @@ -46,7 +46,7 @@
    - + -
    +
    + +
    +
    +
    +
    - x -

- - + + diff --git a/doc/html/functions_y.html b/doc/html/functions_y.html index ee0e97e60..71b1fd2cb 100644 --- a/doc/html/functions_y.html +++ b/doc/html/functions_y.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- y -

- - + + diff --git a/doc/html/functions_z.html b/doc/html/functions_z.html index 27a57f549..7df38792e 100644 --- a/doc/html/functions_z.html +++ b/doc/html/functions_z.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- z -

- - + + diff --git a/doc/html/functions_~.html b/doc/html/functions_~.html index 729d7c89e..83e71b2a0 100644 --- a/doc/html/functions_~.html +++ b/doc/html/functions_~.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- ~ -

- - + + diff --git a/doc/html/global_8cpp.html b/doc/html/global_8cpp.html index 16f9fb265..c79fe09c4 100644 --- a/doc/html/global_8cpp.html +++ b/doc/html/global_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Data Structures | @@ -279,10 +285,13 @@

+ + diff --git a/doc/html/global_8cpp.js b/doc/html/global_8cpp.js new file mode 100644 index 000000000..dafde6c44 --- /dev/null +++ b/doc/html/global_8cpp.js @@ -0,0 +1,4 @@ +var global_8cpp = +[ + [ "jpg_error_mgr", "structjpg__error__mgr.html", null ] +]; \ No newline at end of file diff --git a/doc/html/global_8cpp_source.html b/doc/html/global_8cpp_source.html index a5c1ba694..22ebc18e5 100644 --- a/doc/html/global_8cpp_source.html +++ b/doc/html/global_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
global.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "global.h"
17
18//PNG Libraries (reading and writing PNG images)
@@ -310,21 +317,21 @@
203 int JD = Calendar2Julian( *this );
-
204 if( JD<365 || ( JD==356 && isLeapYear() ) ) {
-
205 Date cal = Julian2Calendar(JD + 1, year);
-
206 day = cal.day;
-
207 month = cal.month;
+
204 if( JD<365 || ( JD==356 && isLeapYear() ) ) {
+
205 Date cal = Julian2Calendar(JD + 1, year);
+
206 day = cal.day;
+
207 month = cal.month;
208 }else{ //it is last day of the year
-
209 day = 1;
-
210 month = 1;
-
211 year ++;
+
209 day = 1;
+
210 month = 1;
+
211 year ++;
212 }
213}
214
-
216 if( (year-2000)%4 == 0 ){ //leap year
+
216 if( (year-2000)%4 == 0 ){ //leap year
217 return true;
218 }else{ //non-leap year
219 return false;
@@ -1477,13 +1484,13 @@
1247template void helios::resize_vector<double>( std::vector<std::vector<double> > &, uint, uint );
1248template void helios::resize_vector<int>( std::vector<std::vector<int> > &, uint, uint );
1249template void helios::resize_vector<uint>( std::vector<std::vector<uint> > &, uint, uint );
-
1250template void helios::resize_vector<std::string>( std::vector<std::vector<std::string> > &, uint, uint );
-
1251template void helios::resize_vector<helios::vec2>( std::vector<std::vector<helios::vec2> > &, uint, uint );
-
1252template void helios::resize_vector<helios::vec3>( std::vector<std::vector<helios::vec3> > &, uint, uint );
-
1253template void helios::resize_vector<helios::vec4>( std::vector<std::vector<helios::vec4> > &, uint, uint );
-
1254template void helios::resize_vector<helios::int2>( std::vector<std::vector<helios::int2> > &, uint, uint );
-
1255template void helios::resize_vector<helios::int3>( std::vector<std::vector<helios::int3> > &, uint, uint );
-
1256template void helios::resize_vector<helios::int4>( std::vector<std::vector<helios::int4> > &, uint, uint );
+
1250template void helios::resize_vector<std::string>( std::vector<std::vector<std::string> > &, uint, uint );
+
1251template void helios::resize_vector<helios::vec2>( std::vector<std::vector<helios::vec2> > &, uint, uint );
+
1252template void helios::resize_vector<helios::vec3>( std::vector<std::vector<helios::vec3> > &, uint, uint );
+
1253template void helios::resize_vector<helios::vec4>( std::vector<std::vector<helios::vec4> > &, uint, uint );
+
1254template void helios::resize_vector<helios::int2>( std::vector<std::vector<helios::int2> > &, uint, uint );
+
1255template void helios::resize_vector<helios::int3>( std::vector<std::vector<helios::int3> > &, uint, uint );
+
1256template void helios::resize_vector<helios::int4>( std::vector<std::vector<helios::int4> > &, uint, uint );
1257
1258template <typename anytype>
@@ -1502,13 +1509,13 @@
1270template void helios::resize_vector<double>( std::vector<std::vector<std::vector<double> > > &, uint, uint, uint );
1271template void helios::resize_vector<int>( std::vector<std::vector<std::vector<int> > > &, uint, uint, uint );
1272template void helios::resize_vector<uint>( std::vector<std::vector<std::vector<uint> > > &, uint, uint, uint );
-
1273template void helios::resize_vector<std::string>( std::vector<std::vector<std::vector<std::string> > > &, uint, uint, uint );
-
1274template void helios::resize_vector<helios::vec2>( std::vector<std::vector<std::vector<helios::vec2> > > &, uint, uint, uint );
-
1275template void helios::resize_vector<helios::vec3>( std::vector<std::vector<std::vector<helios::vec3> > > &, uint, uint, uint );
-
1276template void helios::resize_vector<helios::vec4>( std::vector<std::vector<std::vector<helios::vec4> > > &, uint, uint, uint );
-
1277template void helios::resize_vector<helios::int2>( std::vector<std::vector<std::vector<helios::int2> > > &, uint, uint, uint );
-
1278template void helios::resize_vector<helios::int3>( std::vector<std::vector<std::vector<helios::int3> > > &, uint, uint, uint );
-
1279template void helios::resize_vector<helios::int4>( std::vector<std::vector<std::vector<helios::int4> > > &, uint, uint, uint );
+
1273template void helios::resize_vector<std::string>( std::vector<std::vector<std::vector<std::string> > > &, uint, uint, uint );
+
1274template void helios::resize_vector<helios::vec2>( std::vector<std::vector<std::vector<helios::vec2> > > &, uint, uint, uint );
+
1275template void helios::resize_vector<helios::vec3>( std::vector<std::vector<std::vector<helios::vec3> > > &, uint, uint, uint );
+
1276template void helios::resize_vector<helios::vec4>( std::vector<std::vector<std::vector<helios::vec4> > > &, uint, uint, uint );
+
1277template void helios::resize_vector<helios::int2>( std::vector<std::vector<std::vector<helios::int2> > > &, uint, uint, uint );
+
1278template void helios::resize_vector<helios::int3>( std::vector<std::vector<std::vector<helios::int3> > > &, uint, uint, uint );
+
1279template void helios::resize_vector<helios::int4>( std::vector<std::vector<std::vector<helios::int4> > > &, uint, uint, uint );
1280
1281template <typename anytype>
@@ -1530,13 +1537,13 @@
1296template void helios::resize_vector<double>( std::vector<std::vector<std::vector<std::vector<double> > > > &, uint, uint, uint, uint );
1297template void helios::resize_vector<int>( std::vector<std::vector<std::vector<std::vector<int> > > > &, uint, uint, uint, uint );
1298template void helios::resize_vector<uint>( std::vector<std::vector<std::vector<std::vector<uint> > > > &, uint, uint, uint, uint );
-
1299template void helios::resize_vector<std::string>( std::vector<std::vector<std::vector<std::vector<std::string> > > > &, uint, uint, uint, uint );
-
1300template void helios::resize_vector<helios::vec2>( std::vector<std::vector<std::vector<std::vector<helios::vec2> > > > &, uint, uint, uint, uint );
-
1301template void helios::resize_vector<helios::vec3>( std::vector<std::vector<std::vector<std::vector<helios::vec3> > > > &, uint, uint, uint, uint );
-
1302template void helios::resize_vector<helios::vec4>( std::vector<std::vector<std::vector<std::vector<helios::vec4> > > > &, uint, uint, uint, uint );
-
1303template void helios::resize_vector<helios::int2>( std::vector<std::vector<std::vector<std::vector<helios::int2> > > > &, uint, uint, uint, uint );
-
1304template void helios::resize_vector<helios::int3>( std::vector<std::vector<std::vector<std::vector<helios::int3> > > > &, uint, uint, uint, uint );
-
1305template void helios::resize_vector<helios::int4>( std::vector<std::vector<std::vector<std::vector<helios::int4> > > > &, uint, uint, uint, uint );
+
1299template void helios::resize_vector<std::string>( std::vector<std::vector<std::vector<std::vector<std::string> > > > &, uint, uint, uint, uint );
+
1300template void helios::resize_vector<helios::vec2>( std::vector<std::vector<std::vector<std::vector<helios::vec2> > > > &, uint, uint, uint, uint );
+
1301template void helios::resize_vector<helios::vec3>( std::vector<std::vector<std::vector<std::vector<helios::vec3> > > > &, uint, uint, uint, uint );
+
1302template void helios::resize_vector<helios::vec4>( std::vector<std::vector<std::vector<std::vector<helios::vec4> > > > &, uint, uint, uint, uint );
+
1303template void helios::resize_vector<helios::int2>( std::vector<std::vector<std::vector<std::vector<helios::int2> > > > &, uint, uint, uint, uint );
+
1304template void helios::resize_vector<helios::int3>( std::vector<std::vector<std::vector<std::vector<helios::int3> > > > &, uint, uint, uint, uint );
+
1305template void helios::resize_vector<helios::int4>( std::vector<std::vector<std::vector<std::vector<helios::int4> > > > &, uint, uint, uint, uint );
1306
1307Date helios::CalendarDay( int Julian_day, int year ){
@@ -1996,9 +2003,9 @@
1747 jmp_buf setjmp_buffer; /* for return to caller */
1748};
-
1749typedef struct jpg_error_mgr * jpg_error_ptr;
+
1749typedef struct jpg_error_mgr * jpg_error_ptr;
1750METHODDEF(void) jpg_error_exit (j_common_ptr cinfo){
-
1751 auto myerr = (jpg_error_ptr) cinfo->err;
+
1751 auto myerr = (jpg_error_ptr) cinfo->err;
1752 (*cinfo->err->output_message) (cinfo);
1753 longjmp(myerr->setjmp_buffer, 1);
1754}
@@ -3625,6 +3632,7 @@
int4 make_int4(int x, int y, int z, int w)
Make an int4 vector from three ints.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
+
Date()
Default constructor.
int month
Month of year.
void incrementDay()
Increment Date vector by one day.
Definition global.cpp:202
int day
Day of month.
@@ -3644,31 +3652,34 @@
const float & elevation
Elevation angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int x
First element in vector.
int z
Third element in vector.
int y
Second element in vector.
-
Vector of four elements of type 'int'.
-
Vector of two elements of type 'float'.
+
Vector of four elements of type 'int'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
float magnitude() const
Compute the vector magnitude.
-
Vector of four elements of type 'float'.
+
Vector of four elements of type 'float'.
- -
+ + diff --git a/doc/html/global_8h.html b/doc/html/global_8h.html index fd0ac6402..9bdb8d123 100644 --- a/doc/html/global_8h.html +++ b/doc/html/global_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Data Structures | @@ -280,7 +286,7 @@ std::vector< std::string > helios::separate_string_by_delimiter (const std::string &inputstring, const std::string &delimiter)  Separate string by delimiter and store into a vector.
  -template<typename anytype > +template<typename anytype> anytype helios::clamp (anytype value, anytype min, anytype max)  Clamp value to be within some specified bounds.
  @@ -314,15 +320,15 @@ float helios::median (std::vector< float > vect)  Median of a vector of floats.
  -template<typename anytype > +template<typename anytype> void helios::resize_vector (std::vector< std::vector< anytype > > &vec, uint Nx, uint Ny)  Resize 2D C++ vector.
  -template<typename anytype > +template<typename anytype> void helios::resize_vector (std::vector< std::vector< std::vector< anytype > > > &vec, uint Nx, uint Ny, uint Nz)  Resize 3D C++ vector.
  -template<typename anytype > +template<typename anytype> void helios::resize_vector (std::vector< std::vector< std::vector< std::vector< anytype > > > > &vec, uint Nx, uint Ny, uint Nz, uint Nw)  Resize 4D C++ vector.
  @@ -626,7 +632,7 @@

-

Definition at line 56 of file global.h.

+

Definition at line 60 of file global.h.

@@ -2419,7 +2425,7 @@

-extern +extern

+ + diff --git a/doc/html/global_8h.js b/doc/html/global_8h.js new file mode 100644 index 000000000..9cd103160 --- /dev/null +++ b/doc/html/global_8h.js @@ -0,0 +1,137 @@ +var global_8h = +[ + [ "helios::acos_safe", "group__functions.html#ga9f732ec5c2153020247c879034f81432", null ], + [ "helios::asin_safe", "group__functions.html#gac400d6d37ff2494ec592a9f0a17ee9ab", null ], + [ "helios::atan2_2pi", "group__functions.html#ga37a64a73b3318125a778bb77c29f7dcf", null ], + [ "helios::blend", "global_8h.html#a06a8d8b0bee35e1fd8c564a7674bd07a", null ], + [ "helios::blend", "global_8h.html#a192c018f83c0598738e048212904202d", null ], + [ "helios::calculateTriangleArea", "group__functions.html#ga76dc2dce64e911fc0c5d2bc3ff4f6fe0", null ], + [ "helios::CalendarDay", "global_8h.html#a35cf3fa6f900627c962472dd550e3d39", null ], + [ "helios::cart2sphere", "group__functions.html#ga32a34b00e0a28f4b35e501b8b34cfccd", null ], + [ "helios::clamp", "group__functions.html#gafc2084bde2f2a0e15d637e973658a5a4", null ], + [ "helios::deblank", "group__functions.html#gad5aa3cd5124a2e1e526d6070e53c2bc8", null ], + [ "helios::deblank", "group__functions.html#gaaf03682753b330b32f6c5d117df90db7", null ], + [ "helios::deg2rad", "group__functions.html#ga60f429b247883516de80687774f4155c", null ], + [ "helios::flatten", "group__functions.html#ga8148b3dd86a772edcee01ed3e788c344", null ], + [ "helios::flatten", "group__functions.html#gacce06754824eb0f9ec29d043c8970fdd", null ], + [ "helios::flatten", "group__functions.html#ga7d6b41f67d574ad1eda29386f7602fd3", null ], + [ "helios::flatten", "group__functions.html#gaacf3de9501039033bbf3ce1192a5b980", null ], + [ "helios::flatten", "group__functions.html#gaba0182e0dee319764079263d3c6515cb", null ], + [ "helios::flatten", "group__functions.html#gaa82d824f02499ea89a35f49837c73c16", null ], + [ "helios::flatten", "group__functions.html#ga1d91aa279bfa52924ce4ad1ff25e73fa", null ], + [ "helios::flatten", "group__functions.html#gab81afa45742b33913932e93d18027bb9", null ], + [ "helios::flatten", "group__functions.html#ga121757e2774279472d1ffa068313dbfc", null ], + [ "helios::flatten", "group__functions.html#gacba6e64852b80969f8529e7e4ca9cd0c", null ], + [ "helios::flatten", "group__functions.html#ga480225bd53c0fbc332edca0a0d9a9ebf", null ], + [ "helios::flatten", "group__functions.html#ga4837a536a7387f8721f7b9d8cad201e8", null ], + [ "helios::flatten", "group__functions.html#ga96b392b637a3fcc21a7944000323e57e", null ], + [ "helios::flatten", "group__functions.html#gadc8836b0f49c4a8b5bc5bcab058a63ad", null ], + [ "helios::flatten", "group__functions.html#ga4e10f3b2de7e94bf1d7e6c7c4e5f2573", null ], + [ "helios::flatten", "group__functions.html#ga69b9012c4d9aa9c34bba25cca4e53119", null ], + [ "helios::flatten", "group__functions.html#ga31baa6f6552d52b2cc79561fc3457a88", null ], + [ "helios::flatten", "group__functions.html#ga82feb62a40fb10cba137a8d38eacf003", null ], + [ "helios::flatten", "group__functions.html#ga9b7c03082c314d9f694fb939c0ea1550", null ], + [ "helios::flatten", "group__functions.html#ga0da91aa5e844a63b491026a1b772cea9", null ], + [ "helios::flatten", "group__functions.html#ga1872f5844481b4cd876848cb7282a76a", null ], + [ "helios::flatten", "group__functions.html#gac265cf2f4fcc89d40729f11cccdcd334", null ], + [ "helios::flatten", "group__functions.html#ga228d0ed0a34866dd6ae4be83ec7d3246", null ], + [ "helios::flatten", "group__functions.html#gac15b07838d4cd90b7b7f863821d34665", null ], + [ "helios::flatten", "group__functions.html#gac6c182edd6f37635bbce1abbb5306a20", null ], + [ "helios::flatten", "group__functions.html#ga17ade4062b75a329ec1b59f28d854614", null ], + [ "helios::flatten", "group__functions.html#gad0ba764dc082b4fe92c2edf2b691df06", null ], + [ "helios::flatten", "group__functions.html#ga4bcec227cba69446f0c211a8efa79fa7", null ], + [ "helios::flatten", "group__functions.html#ga3499b80c2201907203b3457f1fb62c80", null ], + [ "helios::flatten", "group__functions.html#ga14adccb0f309850b9d5aa740588b8624", null ], + [ "helios::flatten", "group__functions.html#ga024396adf0d734eb2a5dab7150455412", null ], + [ "helios::flatten", "group__functions.html#ga46b186805c705dc05ded72b791ed90a4", null ], + [ "helios::flatten", "group__functions.html#gabbee61759ee5dbc76a83f1356bc4e427", null ], + [ "helios::fzero", "global_8h.html#a464923f1888b6ba4dc1a3b6881fa9e80", null ], + [ "helios::getFileExtension", "global_8h.html#a58e660bb08e1ce13466825ae666467ef", null ], + [ "helios::getFileName", "global_8h.html#a63bd49091fdab0e262b051f61fb9a902", null ], + [ "helios::getFilePath", "global_8h.html#ad76f15d03b511d1bf5123d64d804d6e8", null ], + [ "helios::getFileStem", "global_8h.html#a9fff8cb6c3474de479f81c12f173d3ed", null ], + [ "helios::getImageResolutionJPEG", "global_8h.html#a94c80cbffdccaea7991b439acf8e9eb4", null ], + [ "helios::helios_runtime_error", "global_8h.html#a672182e7d8beb63c7cf256fa8294dc86", null ], + [ "helios::importVectorFromFile", "global_8h.html#a125e8bef86fb7272d4d66898afb7d368", null ], + [ "helios::interp1", "global_8h.html#a4d45cb06725a89f41266c8c89974c73e", null ], + [ "helios::JulianDay", "group__functions.html#ga4e5ae2905291ff8a5ed97bc93e7fe71d", null ], + [ "helios::JulianDay", "global_8h.html#a7a889dd38f803c031f3e2ce6936b1cdc", null ], + [ "helios::lineIntersection", "group__functions.html#ga3fd112746616c33aae6ac56d9863c9a6", null ], + [ "helios::makeIdentityMatrix", "global_8h.html#ab044c22f6798031f34744e63d95ca614", null ], + [ "helios::makeRotationMatrix", "group__functions.html#ga42c109f6c1a5b59ffcefc262ee78d291", null ], + [ "helios::makeRotationMatrix", "group__functions.html#gaae1a72fb7a970c9bf65e10b26ab6fb51", null ], + [ "helios::makeRotationMatrix", "group__functions.html#ga55a4cd9377af44ec86d945ffd72e1dc5", null ], + [ "helios::makeScaleMatrix", "group__functions.html#gaf092b1b3100fcbc2f9d106a4b560efcd", null ], + [ "helios::makeScaleMatrix", "group__functions.html#ga9af58af4f070bf9f81a45141569e9c72", null ], + [ "helios::makeTranslationMatrix", "group__functions.html#ga6c071a3206c9d7a7d8694275b46b8d42", null ], + [ "helios::matmult", "global_8h.html#a2404c4bfe8b03cdbde4421a2e0be2b19", null ], + [ "helios::max", "group__functions.html#ga828d302d1bb6e0aee3e2bf5efd670f86", null ], + [ "helios::max", "group__functions.html#ga812947a11191483677a73636e0b7ed06", null ], + [ "helios::max", "group__functions.html#gaa3b7bf55e065bf2ab8a9d975963ce7ca", null ], + [ "helios::mean", "group__functions.html#gadfcde1fcf4db2a62012ed5ddf43c943d", null ], + [ "helios::median", "group__functions.html#ga461699c384fe606656ce1cc59618e727", null ], + [ "helios::min", "group__functions.html#ga522f5d4232ccb2c899ff620eafc744b5", null ], + [ "helios::min", "group__functions.html#gabdeaa8440597bcdcf1f43cd3a8f2383f", null ], + [ "helios::min", "group__functions.html#ga656494728a1221b22464a693936d41f5", null ], + [ "helios::parse_double", "global_8h.html#a0209e53a2bdd31c9977de93b27e968b6", null ], + [ "helios::parse_float", "global_8h.html#a162c3d8c139c75bac9607b512768b937", null ], + [ "helios::parse_int", "global_8h.html#a6b9de37fd00d939cb9e049a9002e8db0", null ], + [ "helios::parse_int2", "global_8h.html#a142375b255b9dcb456764558725becc1", null ], + [ "helios::parse_int3", "global_8h.html#a88766e5973accffb6a548fb321c288df", null ], + [ "helios::parse_RGBcolor", "global_8h.html#a786c694c21d9115a7c3e18deba6a8732", null ], + [ "helios::parse_uint", "global_8h.html#a51430e9e359c2aad9d22d41650b2221a", null ], + [ "helios::parse_vec2", "global_8h.html#a3e1e35a11454f9616bad5639ccb49ff3", null ], + [ "helios::parse_vec3", "global_8h.html#a2e62477aa096b070d49a68b88427f7a5", null ], + [ "helios::parse_xml_tag_float", "global_8h.html#a0627913352046dda81c72c9ce234a7e7", null ], + [ "helios::parse_xml_tag_int", "global_8h.html#afcb3f2f96f4679210db6f68845c87a51", null ], + [ "helios::parse_xml_tag_string", "global_8h.html#a8a48786337175ba01ad180ef493f460b", null ], + [ "helios::parse_xml_tag_vec2", "global_8h.html#a6d4fc938af8d1e0db7836a610b7feda0", null ], + [ "helios::parse_xml_tag_vec3", "global_8h.html#a1b7e887e4b92085bc9f52a00227ca1d0", null ], + [ "helios::PNGHasAlpha", "global_8h.html#a07b0dda8b9aee4100e9f6332dbfe7f64", null ], + [ "helios::point_distance", "global_8h.html#a4d55bb8abc86cb7dabab1d4e6201a754", null ], + [ "helios::pointInPolygon", "group__functions.html#gaaa7da223bd02271d4f037b9e5305c023", null ], + [ "helios::rad2deg", "group__functions.html#ga0b9a2dac200293044d7e2ae1c03a3140", null ], + [ "helios::randu", "group__functions.html#ga06cb0bc53a3903c6c487dd524bc2315e", null ], + [ "helios::randu", "group__functions.html#gad8ccb7b3d22876e477b80d5c2bdb94c1", null ], + [ "helios::readJPEG", "global_8h.html#a248b712fb0f1b77074a223179850a6dd", null ], + [ "helios::readPNG", "global_8h.html#a99f41f50ffe7f2c092e16377f5cef979", null ], + [ "helios::readPNGAlpha", "global_8h.html#ade5b9b8370f50d8c2002ba48d47521f5", null ], + [ "helios::resize_vector", "group__functions.html#ga8b6573f58a513ebbc539ae7529daa748", null ], + [ "helios::resize_vector", "group__functions.html#ga71f9bf6c09e75b9c8d8ff36c7187a31d", null ], + [ "helios::resize_vector", "group__functions.html#ga9c202da0366b53b742824bfac2e8f536", null ], + [ "helios::rotatePoint", "group__functions.html#ga17de9e03f309dedcd648606653ddd05e", null ], + [ "helios::rotatePoint", "group__functions.html#gaa8705d90b2af04d56fa5086b917d9b7a", null ], + [ "helios::rotatePointAboutLine", "global_8h.html#a09ae9efe6ba5dddb144519931bcf94b5", null ], + [ "helios::separate_string_by_delimiter", "group__functions.html#gae239abbec7c2ff618b3603bf69ccf2ed", null ], + [ "helios::sphere2cart", "group__functions.html#ga97e12cf9fda6bf8b65b3ccc17e788c12", null ], + [ "helios::spline_interp3", "group__functions.html#ga7f8e948aa3a70481ebd3a829531bee4e", null ], + [ "helios::stdev", "group__functions.html#ga8a9b7ab24b0bb17b901c3ba41af760ec", null ], + [ "helios::string2int2", "group__functions.html#ga2f83561e691aad4ecd41ac3879e59568", null ], + [ "helios::string2int3", "group__functions.html#gad1dbf51cdf1912828487e67ca51cccef", null ], + [ "helios::string2int4", "group__functions.html#ga4aa73326d27fdaba24fac984db5b8009", null ], + [ "helios::string2RGBcolor", "group__functions.html#ga8180158609698aae15da7574b085b817", null ], + [ "helios::string2vec2", "group__functions.html#ga18616cd1df8b05b03eb6c2be0de54e3b", null ], + [ "helios::string2vec3", "group__functions.html#ga65954cbb0f79c3fd5032f2cc27ad3b4f", null ], + [ "helios::string2vec4", "group__functions.html#gadf3012a1d77a5aa50347de3a7175cb1a", null ], + [ "helios::sum", "group__functions.html#gaa20cc657b6475964d10022adc9850313", null ], + [ "helios::trim_whitespace", "group__functions.html#ga56b873fa7b729dd84412d44156fa2dca", null ], + [ "helios::validateOutputPath", "global_8h.html#a614486c4ac0686c5b58813f03f0cedf9", null ], + [ "helios::vecmult", "global_8h.html#ae8cc6f4a10a4efab6057ab6c4c114304", null ], + [ "helios::vecmult", "global_8h.html#a40054144f951b396cd9f9ba32586862a", null ], + [ "helios::wait", "group__functions.html#gad28da0b06687dc68c1212c1624e54bd0", null ], + [ "helios::writeJPEG", "global_8h.html#a95600894b45bcc627d66c3dd8c202cd8", null ], + [ "helios::writePNG", "global_8h.html#afc2520441ef9a290c5221dd892ea9f01", null ], + [ "helios::XMLloadfloat", "global_8h.html#a74ae3a9e16e2ca39dab735a1ac97a506", null ], + [ "helios::XMLloadint", "global_8h.html#a4b756357236942bec6cc7f853aa77fc5", null ], + [ "helios::XMLloadint2", "global_8h.html#ae55d4cef14213f642705952dc1ad4659", null ], + [ "helios::XMLloadint3", "global_8h.html#ae4661a50a9f13eb6fb645e9f767b51a2", null ], + [ "helios::XMLloadint4", "global_8h.html#a08c21d08fc1e1dd07ff612f8b503e295", null ], + [ "helios::XMLloadrgb", "global_8h.html#acb80e4e13497682968468c596a9b3690", null ], + [ "helios::XMLloadrgba", "global_8h.html#a148e80cd6b8477c0704e642243ab2547", null ], + [ "helios::XMLloadstring", "global_8h.html#a8240b43ac3ce36bc7a4d52128bc9fda3", null ], + [ "helios::XMLloadvec2", "global_8h.html#a1f3041e69cbe61a909866a24c8d77457", null ], + [ "helios::XMLloadvec3", "global_8h.html#aa4c58cabe7bc5244435613ffdb00cf34", null ], + [ "helios::XMLloadvec4", "global_8h.html#a928c91522128145370150652ca59f3af", null ], + [ "helios::nullorigin", "global_8h.html#a876dc18d1da8ace50c131f428f8883be", null ], + [ "helios::nullrotation", "global_8h.html#adcd5a98ec7c45292736ec8e19ce9de51", null ] +]; \ No newline at end of file diff --git a/doc/html/global_8h_source.html b/doc/html/global_8h_source.html index 0aefff803..b67385d6c 100644 --- a/doc/html/global_8h_source.html +++ b/doc/html/global_8h_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
global.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifdef __GNUC__
17#define DEPRECATED(func) func __attribute__ ((deprecated))
18#elif defined(_MSC_VER)
@@ -145,476 +152,483 @@
53#include <iomanip>
54#include <filesystem>
55
-
56typedef unsigned int uint;
-
57
-
58#include "helios_vector_types.h"
+
56#ifdef USE_OPENMP
+
57#include <omp.h>
+
58#endif
59
-
60//pugi XML parser
-
61#include "pugixml.hpp"
-
62
-
63// *** Groups *** //
-
64
+
60typedef unsigned int uint;
+
61
+
62#include "helios_vector_types.h"
+
63
+
64//pugi XML parser
+
65#include "pugixml.hpp"
66
-
71
-
76
-
80namespace helios{
-
81
+
67// *** Groups *** //
+
68
+
70
+
73
+
75
+
78
+
80
83
-
86 void helios_runtime_error( const std::string &error_message );
-
87
-
88//--------------------- HELPER FUNCTIONS -----------------------------------//
-
89
+
84namespace helios{
+
85
+
87
+
90 void helios_runtime_error( const std::string &error_message );
91
-
97 void makeRotationMatrix( float rotation, const char* axis, float (&transform)[16] );
-
98
-
100
-
106 void makeRotationMatrix( float rotation, const helios::vec3& axis, float (&transform)[16] );
-
107
-
109
-
116 void makeRotationMatrix( float rotation, const helios::vec3& origin, const helios::vec3& axis, float (&transform)[16] );
-
117
-
119
-
124 void makeTranslationMatrix( const helios::vec3& translation, float (&transform)[16] );
-
125
-
127
-
132 void makeScaleMatrix( const helios::vec3& scale, float (&T)[16] );
-
133
-
135
-
141 void makeScaleMatrix( const helios::vec3 &scale, const helios::vec3 &point, float (&T)[16] );
-
142
-
144 void matmult( const float ML[16], const float MR[16], float (&T)[16] );
-
145
-
147 void vecmult( const float M[16], const float v[3], float (&result)[3] );
-
148
-
150 void vecmult( const float M[16], const helios::vec3& v3, helios::vec3& result );
-
151
-
153 void makeIdentityMatrix( float (&T)[16] );
-
154
-
156
-
162 float deg2rad( float deg );
-
163
-
165
-
171 float rad2deg( float rad );
-
172
-
174
-
178 float atan2_2pi(float y, float x);
-
179
-
181
-
187 SphericalCoord cart2sphere( const vec3& Cartesian );
-
188
-
190
-
196 vec3 sphere2cart( const SphericalCoord& Spherical );
-
197
-
199
-
202 vec2 string2vec2( const char* str );
-
203
-
205
-
208 vec3 string2vec3( const char* str );
-
209
-
211
-
214 vec4 string2vec4( const char* str );
-
215
-
217
-
220 int2 string2int2( const char* str );
-
221
-
223
-
226 int3 string2int3( const char* str );
-
227
-
229
-
232 int4 string2int4( const char* str );
-
233
-
235
-
240 bool parse_float( const std::string &input_string, float &converted_float );
-
241
-
243
-
248 bool parse_double( const std::string &input_string, double &converted_double );
-
249
-
251
-
256 bool parse_int( const std::string &input_string, int &converted_int );
-
257
-
259
-
264 bool parse_int2( const std::string &input_string, int2 &converted_int2 );
-
265
-
267
-
272 bool parse_int3( const std::string &input_string, int3 &converted_int3 );
-
273
-
275
-
280 bool parse_uint( const std::string &input_string, uint &converted_uint );
-
281
-
283
-
288 bool parse_vec2( const std::string &input_string, vec2 &converted_vec2 );
-
289
-
291
-
296 bool parse_vec3( const std::string &input_string, vec3 &converted_vec3 );
-
297
-
299
-
304 bool parse_RGBcolor( const std::string &input_string, RGBcolor &converted_rgb );
-
305
-
306 bool open_xml_file( const std::string &xml_file, pugi::xml_document &xmldoc, std::string &error_string );
-
307
+
92//--------------------- HELPER FUNCTIONS -----------------------------------//
+
93
+
95
+
101 void makeRotationMatrix( float rotation, const char* axis, float (&transform)[16] );
+
102
+
104
+
110 void makeRotationMatrix( float rotation, const helios::vec3& axis, float (&transform)[16] );
+
111
+
113
+
120 void makeRotationMatrix( float rotation, const helios::vec3& origin, const helios::vec3& axis, float (&transform)[16] );
+
121
+
123
+
128 void makeTranslationMatrix( const helios::vec3& translation, float (&transform)[16] );
+
129
+
131
+
136 void makeScaleMatrix( const helios::vec3& scale, float (&T)[16] );
+
137
+
139
+
145 void makeScaleMatrix( const helios::vec3 &scale, const helios::vec3 &point, float (&T)[16] );
+
146
+
148 void matmult( const float ML[16], const float MR[16], float (&T)[16] );
+
149
+
151 void vecmult( const float M[16], const float v[3], float (&result)[3] );
+
152
+
154 void vecmult( const float M[16], const helios::vec3& v3, helios::vec3& result );
+
155
+
157 void makeIdentityMatrix( float (&T)[16] );
+
158
+
160
+
166 float deg2rad( float deg );
+
167
+
169
+
175 float rad2deg( float rad );
+
176
+
178
+
182 float atan2_2pi(float y, float x);
+
183
+
185
+
191 SphericalCoord cart2sphere( const vec3& Cartesian );
+
192
+
194
+
200 vec3 sphere2cart( const SphericalCoord& Spherical );
+
201
+
203
+
206 vec2 string2vec2( const char* str );
+
207
+
209
+
212 vec3 string2vec3( const char* str );
+
213
+
215
+
218 vec4 string2vec4( const char* str );
+
219
+
221
+
224 int2 string2int2( const char* str );
+
225
+
227
+
230 int3 string2int3( const char* str );
+
231
+
233
+
236 int4 string2int4( const char* str );
+
237
+
239
+
244 bool parse_float( const std::string &input_string, float &converted_float );
+
245
+
247
+
252 bool parse_double( const std::string &input_string, double &converted_double );
+
253
+
255
+
260 bool parse_int( const std::string &input_string, int &converted_int );
+
261
+
263
+
268 bool parse_int2( const std::string &input_string, int2 &converted_int2 );
+
269
+
271
+
276 bool parse_int3( const std::string &input_string, int3 &converted_int3 );
+
277
+
279
+
284 bool parse_uint( const std::string &input_string, uint &converted_uint );
+
285
+
287
+
292 bool parse_vec2( const std::string &input_string, vec2 &converted_vec2 );
+
293
+
295
+
300 bool parse_vec3( const std::string &input_string, vec3 &converted_vec3 );
+
301
+
303
+
308 bool parse_RGBcolor( const std::string &input_string, RGBcolor &converted_rgb );
309
-
315 int parse_xml_tag_int(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
-
316
-
318
-
324 float parse_xml_tag_float( const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
-
325
-
327
-
333 vec2 parse_xml_tag_vec2( const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
-
334
-
336
-
342 vec3 parse_xml_tag_vec3( const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
-
343
-
345
-
351 std::string parse_xml_tag_string( const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
-
352
-
354
-
357 RGBAcolor string2RGBcolor( const char* str );
-
358
-
360
-
363 std::string deblank(const char* input);
-
364
-
366
-
369 std::string deblank(const std::string &input);
-
370
-
372
-
375 std::string trim_whitespace(const std::string &input);
-
376
-
378
-
384 std::vector<std::string> separate_string_by_delimiter( const std::string &inputstring, const std::string &delimiter );
-
385
-
387
-
392 template <typename anytype>
-
393 anytype clamp( anytype value, anytype min, anytype max );
-
394
-
396
-
400 float sum( const std::vector<float>& vect );
-
401
-
403
-
407 float mean( const std::vector<float>& vect );
-
408
-
410
-
414 float min( const std::vector<float>& vect );
-
415
-
417
-
421 int min( const std::vector<int>& vect );
-
422
-
424
-
428 vec3 min( const std::vector<vec3>& vect );
-
429
-
431
-
435 float max( const std::vector<float>& vect );
-
436
-
438
-
442 int max( const std::vector<int>& vect );
-
443
-
445
-
449 vec3 max( const std::vector<vec3>& vect );
-
450
-
452
-
456 float stdev( const std::vector<float> &vect );
-
457
-
459
-
463 float median( std::vector<float> vect );
-
464
-
466
-
472 template <typename anytype>
-
473 void resize_vector( std::vector<std::vector<anytype> > &vec, uint Nx, uint Ny );
-
474
-
476
-
483 template <typename anytype>
-
484 void resize_vector( std::vector<std::vector<std::vector<anytype> > > &vec, uint Nx, uint Ny, uint Nz );
-
485
-
487
-
495 template <typename anytype>
-
496 void resize_vector( std::vector<std::vector<std::vector<std::vector<anytype> > > > &vec, uint Nx, uint Ny, uint Nz, uint Nw );
-
497
-
499
-
504 RGBcolor blend(const RGBcolor &color0, const RGBcolor &color1, float weight );
-
505
-
507
-
512 RGBAcolor blend(const RGBAcolor &color0, const RGBAcolor &color1, float weight );
-
513
-
515
-
520 vec3 rotatePoint(const vec3& position, const SphericalCoord& rotation );
-
521
-
523
-
529 vec3 rotatePoint(const vec3& position, float theta, float phi);
-
530
-
532
-
538 vec3 rotatePointAboutLine(const vec3& point, const vec3& line_base, const vec3& line_direction, float theta);
-
539
-
541
-
548 float calculateTriangleArea( const vec3& v0, const vec3& v1, const vec3& v2 );
-
549
-
551
-
558 Date CalendarDay( int Julian_day, int year );
-
559
-
561
-
569 int JulianDay( int day, int month, int year );
-
570
-
572
-
579 int JulianDay( const Date& date );
-
580
-
582
-
583 float randu();
-
584
-
586
-
589 int randu( int imin, int imax );
-
590
-
592
-
595 float acos_safe( float x );
-
596
-
598
-
601 float asin_safe( float x );
-
602
-
604
-
607 bool lineIntersection(const vec2 &p1, const vec2 &q1, const vec2 &p2, const vec2 &q2);
-
608
-
610
-
613 bool pointInPolygon(const vec2 &point, const std::vector<vec2> &polygon_verts );
-
614
-
616
-
-
619 struct Timer{
-
620 public:
-
621
-
622 Timer(){
-
623 running=false;
-
624 }
+
310 bool open_xml_file( const std::string &xml_file, pugi::xml_document &xmldoc, std::string &error_string );
+
311
+
313
+
319 int parse_xml_tag_int(const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
+
320
+
322
+
328 float parse_xml_tag_float( const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
+
329
+
331
+
337 vec2 parse_xml_tag_vec2( const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
+
338
+
340
+
346 vec3 parse_xml_tag_vec3( const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
+
347
+
349
+
355 std::string parse_xml_tag_string( const pugi::xml_node &node, const std::string &tag, const std::string &calling_function );
+
356
+
358
+
361 RGBAcolor string2RGBcolor( const char* str );
+
362
+
364
+
367 std::string deblank(const char* input);
+
368
+
370
+
373 std::string deblank(const std::string &input);
+
374
+
376
+
379 std::string trim_whitespace(const std::string &input);
+
380
+
382
+
388 std::vector<std::string> separate_string_by_delimiter( const std::string &inputstring, const std::string &delimiter );
+
389
+
391
+
396 template <typename anytype>
+
397 anytype clamp( anytype value, anytype min, anytype max );
+
398
+
400
+
404 float sum( const std::vector<float>& vect );
+
405
+
407
+
411 float mean( const std::vector<float>& vect );
+
412
+
414
+
418 float min( const std::vector<float>& vect );
+
419
+
421
+
425 int min( const std::vector<int>& vect );
+
426
+
428
+
432 vec3 min( const std::vector<vec3>& vect );
+
433
+
435
+
439 float max( const std::vector<float>& vect );
+
440
+
442
+
446 int max( const std::vector<int>& vect );
+
447
+
449
+
453 vec3 max( const std::vector<vec3>& vect );
+
454
+
456
+
460 float stdev( const std::vector<float> &vect );
+
461
+
463
+
467 float median( std::vector<float> vect );
+
468
+
470
+
476 template <typename anytype>
+
477 void resize_vector( std::vector<std::vector<anytype> > &vec, uint Nx, uint Ny );
+
478
+
480
+
487 template <typename anytype>
+
488 void resize_vector( std::vector<std::vector<std::vector<anytype> > > &vec, uint Nx, uint Ny, uint Nz );
+
489
+
491
+
499 template <typename anytype>
+
500 void resize_vector( std::vector<std::vector<std::vector<std::vector<anytype> > > > &vec, uint Nx, uint Ny, uint Nz, uint Nw );
+
501
+
503
+
508 RGBcolor blend(const RGBcolor &color0, const RGBcolor &color1, float weight );
+
509
+
511
+
516 RGBAcolor blend(const RGBAcolor &color0, const RGBAcolor &color1, float weight );
+
517
+
519
+
524 vec3 rotatePoint(const vec3& position, const SphericalCoord& rotation );
+
525
+
527
+
533 vec3 rotatePoint(const vec3& position, float theta, float phi);
+
534
+
536
+
542 vec3 rotatePointAboutLine(const vec3& point, const vec3& line_base, const vec3& line_direction, float theta);
+
543
+
545
+
552 float calculateTriangleArea( const vec3& v0, const vec3& v1, const vec3& v2 );
+
553
+
555
+
562 Date CalendarDay( int Julian_day, int year );
+
563
+
565
+
573 int JulianDay( int day, int month, int year );
+
574
+
576
+
583 int JulianDay( const Date& date );
+
584
+
586
+
587 float randu();
+
588
+
590
+
593 int randu( int imin, int imax );
+
594
+
596
+
599 float acos_safe( float x );
+
600
+
602
+
605 float asin_safe( float x );
+
606
+
608
+
611 bool lineIntersection(const vec2 &p1, const vec2 &q1, const vec2 &p2, const vec2 &q2);
+
612
+
614
+
617 bool pointInPolygon(const vec2 &point, const std::vector<vec2> &polygon_verts );
+
618
+
620
+
+
623 struct Timer{
+
624 public:
625
-
-
627 void tic(){
-
628 timer_start = std::chrono::high_resolution_clock::now();
-
629 running = true;
-
630 };
+
626 Timer(){
+
627 running=false;
+
628 }
+
629
+
+
631 void tic(){
+
632 timer_start = std::chrono::high_resolution_clock::now();
+
633 running = true;
+
634 };
-
631
-
-
633 double toc() const{
-
634 return toc("");
-
635 }
+
635
+
+
637 double toc() const{
+
638 return toc("");
+
639 }
-
636
-
638
-
-
641 double toc( const char* message ) const {
-
642 if (!running) {
-
643 std::cerr << "ERROR (Timer): You must call `tic' before calling `toc'. Ignoring call to `toc'..." << std::endl;
-
644 return 0;
-
645 }
-
646
-
647 auto timer_end = std::chrono::high_resolution_clock::now();;
-
648 double duration = std::chrono::duration<double>(timer_end - timer_start).count();
-
649 if (strcmp(message, "mute")!=0) {
-
650 std::cout << "Elapsed time is " << duration << " seconds: " << message << std::endl;
-
651 }
-
652 return duration;
-
653 }
+
640
+
642
+
+
645 double toc( const char* message ) const {
+
646 if (!running) {
+
647 std::cerr << "ERROR (Timer): You must call `tic' before calling `toc'. Ignoring call to `toc'..." << std::endl;
+
648 return 0;
+
649 }
+
650
+
651 auto timer_end = std::chrono::high_resolution_clock::now();;
+
652 double duration = std::chrono::duration<double>(timer_end - timer_start).count();
+
653 if (strcmp(message, "mute")!=0) {
+
654 std::cout << "Elapsed time is " << duration << " seconds: " << message << std::endl;
+
655 }
+
656 return duration;
+
657 }
-
654
-
655 private:
-
656
-
657 bool running;
-
658 std::chrono::high_resolution_clock::time_point timer_start;
-
659
-
660 };
-
-
661
+
658
+
659 private:
+
660
+
661 bool running;
+
662 std::chrono::high_resolution_clock::time_point timer_start;
663
-
667 void wait( float seconds );
-
668
-
670
-
673 bool PNGHasAlpha( const char* filename );
-
674
-
676
-
680 std::vector<std::vector<bool> > readPNGAlpha(const std::string &filename );
-
681
-
683
-
689 void readPNG( const std::string &filename, uint &width, uint &height, std::vector<helios::RGBAcolor> &pixel_data);
-
690
-
692
-
698 void writePNG( const std::string &filename, uint width, uint height, const std::vector<helios::RGBAcolor> &pixel_data );
-
699
-
700
-
702
-
708 void readJPEG( const std::string &filename, uint &width, uint &height, std::vector<helios::RGBcolor> &pixel_data);
-
709
-
711
-
714 helios::int2 getImageResolutionJPEG( const std::string &filename );
-
715
-
717
-
723 void writeJPEG( const std::string &filename, uint width, uint height, const std::vector<helios::RGBcolor> &pixel_data );
-
724
-
726
-
729 std::vector<int> flatten( const std::vector<std::vector<int> > &vec );
-
730
-
732
-
735 std::vector<uint> flatten( const std::vector<std::vector<uint> > &vec );
-
736
-
738
-
741 std::vector<float> flatten( const std::vector<std::vector<float> > &vec );
-
742
-
744
-
747 std::vector<double> flatten( const std::vector<std::vector<double> > &vec );
-
748
-
750
-
753 std::vector<helios::vec2> flatten( const std::vector<std::vector<helios::vec2> > &vec );
-
754
-
756
-
759 std::vector<helios::vec3> flatten( const std::vector<std::vector<helios::vec3> > &vec );
-
760
-
762
-
765 std::vector<helios::vec4> flatten( const std::vector<std::vector<helios::vec4> > &vec );
-
766
-
768
-
771 std::vector<helios::int2> flatten( const std::vector<std::vector<helios::int2> > &vec );
-
772
-
774
-
777 std::vector<helios::int3> flatten( const std::vector<std::vector<helios::int3> > &vec );
-
778
-
780
-
783 std::vector<helios::int4> flatten( const std::vector<std::vector<helios::int4> > &vec );
-
784
-
786
-
789 std::vector<std::string> flatten( const std::vector<std::vector<std::string> > &vec );
-
790
-
792
-
795 std::vector<int> flatten( const std::vector<std::vector<std::vector<int> > > &vec );
-
796
-
798
-
801 std::vector<uint> flatten( const std::vector<std::vector<std::vector<uint> > > &vec );
-
802
-
804
-
807 std::vector<float> flatten( const std::vector<std::vector<std::vector<float> > > &vec );
-
808
-
810
-
813 std::vector<double> flatten( const std::vector<std::vector<std::vector<double> > > &vec );
-
814
-
816
-
819 std::vector<helios::vec2> flatten( const std::vector<std::vector<std::vector<helios::vec2> > > &vec );
-
820
-
822
-
825 std::vector<helios::vec3> flatten( const std::vector<std::vector<std::vector<helios::vec3> > > &vec );
-
826
-
828
-
831 std::vector<helios::vec4> flatten( const std::vector<std::vector<std::vector<helios::vec4> > > &vec );
-
832
-
834
-
837 std::vector<helios::int2> flatten( const std::vector<std::vector<std::vector<helios::int2> > > &vec );
-
838
-
840
-
843 std::vector<helios::int3> flatten( const std::vector<std::vector<std::vector<helios::int3> > > &vec );
-
844
-
846
-
849 std::vector<helios::int4> flatten( const std::vector<std::vector<std::vector<helios::int4> > > &vec );
-
850
-
852
-
855 std::vector<std::string> flatten( const std::vector<std::vector<std::vector<std::string> > > &vec );
-
856
-
857
-
859
-
862 std::vector<int> flatten( const std::vector<std::vector<std::vector<std::vector<int> > > > &vec );
-
863
-
865
-
868 std::vector<uint> flatten( const std::vector<std::vector<std::vector<std::vector<uint> > > > &vec );
-
869
-
871
-
874 std::vector<float> flatten( const std::vector<std::vector<std::vector<std::vector<float> > > > &vec );
-
875
-
877
-
880 std::vector<double> flatten( const std::vector<std::vector<std::vector<std::vector<double> > > > &vec );
-
881
-
883
-
886 std::vector<helios::vec2> flatten( const std::vector<std::vector<std::vector<std::vector<helios::vec2> > > > &vec );
-
887
-
889
-
892 std::vector<helios::vec3> flatten( const std::vector<std::vector<std::vector<std::vector<helios::vec3> > > > &vec );
-
893
-
895
-
898 std::vector<helios::vec4> flatten( const std::vector<std::vector<std::vector<std::vector<helios::vec4> > > > &vec );
-
899
-
901
-
904 std::vector<helios::int2> flatten( const std::vector<std::vector<std::vector<std::vector<helios::int2> > > > &vec );
-
905
-
907
-
910 std::vector<helios::int3> flatten( const std::vector<std::vector<std::vector<std::vector<helios::int3> > > > &vec );
-
911
-
913
-
916 std::vector<helios::int4> flatten( const std::vector<std::vector<std::vector<std::vector<helios::int4> > > > &vec );
-
917
-
919
-
922 std::vector<std::string> flatten( const std::vector<std::vector<std::vector<std::vector<std::string> > > > &vec );
-
923
-
924
-
926
-
935 helios::vec3 spline_interp3(float u, const vec3 &x_start, const vec3 &tan_start, const vec3 &x_end, const vec3 &tan_end );
-
936
-
938
-
942 float XMLloadfloat( pugi::xml_node node, const char* field );
-
943
-
945
-
949 int XMLloadint( pugi::xml_node node, const char* field );
-
950
-
952
-
956 std::string XMLloadstring( pugi::xml_node node, const char* field );
-
957
-
959
-
963 helios::vec2 XMLloadvec2( pugi::xml_node node, const char* field );
-
964
-
966
-
970 helios::vec3 XMLloadvec3( pugi::xml_node node, const char* field );
-
971
-
973
-
977 helios::vec4 XMLloadvec4( pugi::xml_node node, const char* field );
-
978
-
980
-
984 helios::int2 XMLloadint2( pugi::xml_node node, const char* field );
-
985
-
987
-
991 helios::int3 XMLloadint3( pugi::xml_node node, const char* field );
-
992
-
994
-
998 helios::int4 XMLloadint4( pugi::xml_node node, const char* field );
-
999
-
1001
-
1005 helios::RGBcolor XMLloadrgb( pugi::xml_node node, const char* field );
-
1006
-
1008
-
1012 helios::RGBAcolor XMLloadrgba( pugi::xml_node node, const char* field );
-
1013
-
1015
-
1023 float fzero(float(*function)(float value, std::vector<float> &variables, const void *parameters), std::vector<float> &variables, const void *parameters, float init_guess, float err_tol = 0.0001f, int max_iterations = 100 );
-
1024
-
1026
-
1031 float interp1( const std::vector<helios::vec2> &points, float x );
-
1032
-
1034
-
1039 float point_distance( const helios::vec3 &p1 , const helios::vec3 &p2);
-
1040
-
1042
-
1048 std::string getFileExtension( const std::string &filepath );
-
1049
-
1051
-
1057 std::string getFileStem( const std::string &filepath );
-
1058
-
1060
-
1066 std::string getFileName( const std::string &filepath );
-
1067
-
1069
-
1076 std::string getFilePath( const std::string &filepath, bool trailingslash = true );
-
1077
-
1079
-
1084 bool validateOutputPath(std::string &output_directory, const std::vector<std::string> &allowable_file_extensions = {});
-
1085
-
1087
-
1091 std::vector<float> importVectorFromFile(const std::string &filepath);
-
1092
-
1094 extern SphericalCoord nullrotation;
-
1096 extern vec3 nullorigin;
-
1097
-
1098}
-
1099
-
1100#endif
+
664 };
+
+
665
+
667
+
671 void wait( float seconds );
+
672
+
674
+
677 bool PNGHasAlpha( const char* filename );
+
678
+
680
+
684 std::vector<std::vector<bool> > readPNGAlpha(const std::string &filename );
+
685
+
687
+
693 void readPNG( const std::string &filename, uint &width, uint &height, std::vector<helios::RGBAcolor> &pixel_data);
+
694
+
696
+
702 void writePNG( const std::string &filename, uint width, uint height, const std::vector<helios::RGBAcolor> &pixel_data );
+
703
+
704
+
706
+
712 void readJPEG( const std::string &filename, uint &width, uint &height, std::vector<helios::RGBcolor> &pixel_data);
+
713
+
715
+
718 helios::int2 getImageResolutionJPEG( const std::string &filename );
+
719
+
721
+
727 void writeJPEG( const std::string &filename, uint width, uint height, const std::vector<helios::RGBcolor> &pixel_data );
+
728
+
730
+
733 std::vector<int> flatten( const std::vector<std::vector<int> > &vec );
+
734
+
736
+
739 std::vector<uint> flatten( const std::vector<std::vector<uint> > &vec );
+
740
+
742
+
745 std::vector<float> flatten( const std::vector<std::vector<float> > &vec );
+
746
+
748
+
751 std::vector<double> flatten( const std::vector<std::vector<double> > &vec );
+
752
+
754
+
757 std::vector<helios::vec2> flatten( const std::vector<std::vector<helios::vec2> > &vec );
+
758
+
760
+
763 std::vector<helios::vec3> flatten( const std::vector<std::vector<helios::vec3> > &vec );
+
764
+
766
+
769 std::vector<helios::vec4> flatten( const std::vector<std::vector<helios::vec4> > &vec );
+
770
+
772
+
775 std::vector<helios::int2> flatten( const std::vector<std::vector<helios::int2> > &vec );
+
776
+
778
+
781 std::vector<helios::int3> flatten( const std::vector<std::vector<helios::int3> > &vec );
+
782
+
784
+
787 std::vector<helios::int4> flatten( const std::vector<std::vector<helios::int4> > &vec );
+
788
+
790
+
793 std::vector<std::string> flatten( const std::vector<std::vector<std::string> > &vec );
+
794
+
796
+
799 std::vector<int> flatten( const std::vector<std::vector<std::vector<int> > > &vec );
+
800
+
802
+
805 std::vector<uint> flatten( const std::vector<std::vector<std::vector<uint> > > &vec );
+
806
+
808
+
811 std::vector<float> flatten( const std::vector<std::vector<std::vector<float> > > &vec );
+
812
+
814
+
817 std::vector<double> flatten( const std::vector<std::vector<std::vector<double> > > &vec );
+
818
+
820
+
823 std::vector<helios::vec2> flatten( const std::vector<std::vector<std::vector<helios::vec2> > > &vec );
+
824
+
826
+
829 std::vector<helios::vec3> flatten( const std::vector<std::vector<std::vector<helios::vec3> > > &vec );
+
830
+
832
+
835 std::vector<helios::vec4> flatten( const std::vector<std::vector<std::vector<helios::vec4> > > &vec );
+
836
+
838
+
841 std::vector<helios::int2> flatten( const std::vector<std::vector<std::vector<helios::int2> > > &vec );
+
842
+
844
+
847 std::vector<helios::int3> flatten( const std::vector<std::vector<std::vector<helios::int3> > > &vec );
+
848
+
850
+
853 std::vector<helios::int4> flatten( const std::vector<std::vector<std::vector<helios::int4> > > &vec );
+
854
+
856
+
859 std::vector<std::string> flatten( const std::vector<std::vector<std::vector<std::string> > > &vec );
+
860
+
861
+
863
+
866 std::vector<int> flatten( const std::vector<std::vector<std::vector<std::vector<int> > > > &vec );
+
867
+
869
+
872 std::vector<uint> flatten( const std::vector<std::vector<std::vector<std::vector<uint> > > > &vec );
+
873
+
875
+
878 std::vector<float> flatten( const std::vector<std::vector<std::vector<std::vector<float> > > > &vec );
+
879
+
881
+
884 std::vector<double> flatten( const std::vector<std::vector<std::vector<std::vector<double> > > > &vec );
+
885
+
887
+
890 std::vector<helios::vec2> flatten( const std::vector<std::vector<std::vector<std::vector<helios::vec2> > > > &vec );
+
891
+
893
+
896 std::vector<helios::vec3> flatten( const std::vector<std::vector<std::vector<std::vector<helios::vec3> > > > &vec );
+
897
+
899
+
902 std::vector<helios::vec4> flatten( const std::vector<std::vector<std::vector<std::vector<helios::vec4> > > > &vec );
+
903
+
905
+
908 std::vector<helios::int2> flatten( const std::vector<std::vector<std::vector<std::vector<helios::int2> > > > &vec );
+
909
+
911
+
914 std::vector<helios::int3> flatten( const std::vector<std::vector<std::vector<std::vector<helios::int3> > > > &vec );
+
915
+
917
+
920 std::vector<helios::int4> flatten( const std::vector<std::vector<std::vector<std::vector<helios::int4> > > > &vec );
+
921
+
923
+
926 std::vector<std::string> flatten( const std::vector<std::vector<std::vector<std::vector<std::string> > > > &vec );
+
927
+
928
+
930
+
939 helios::vec3 spline_interp3(float u, const vec3 &x_start, const vec3 &tan_start, const vec3 &x_end, const vec3 &tan_end );
+
940
+
942
+
946 float XMLloadfloat( pugi::xml_node node, const char* field );
+
947
+
949
+
953 int XMLloadint( pugi::xml_node node, const char* field );
+
954
+
956
+
960 std::string XMLloadstring( pugi::xml_node node, const char* field );
+
961
+
963
+
967 helios::vec2 XMLloadvec2( pugi::xml_node node, const char* field );
+
968
+
970
+
974 helios::vec3 XMLloadvec3( pugi::xml_node node, const char* field );
+
975
+
977
+
981 helios::vec4 XMLloadvec4( pugi::xml_node node, const char* field );
+
982
+
984
+
988 helios::int2 XMLloadint2( pugi::xml_node node, const char* field );
+
989
+
991
+
995 helios::int3 XMLloadint3( pugi::xml_node node, const char* field );
+
996
+
998
+
1002 helios::int4 XMLloadint4( pugi::xml_node node, const char* field );
+
1003
+
1005
+
1009 helios::RGBcolor XMLloadrgb( pugi::xml_node node, const char* field );
+
1010
+
1012
+
1016 helios::RGBAcolor XMLloadrgba( pugi::xml_node node, const char* field );
+
1017
+
1019
+
1027 float fzero(float(*function)(float value, std::vector<float> &variables, const void *parameters), std::vector<float> &variables, const void *parameters, float init_guess, float err_tol = 0.0001f, int max_iterations = 100 );
+
1028
+
1030
+
1035 float interp1( const std::vector<helios::vec2> &points, float x );
+
1036
+
1038
+
1043 float point_distance( const helios::vec3 &p1 , const helios::vec3 &p2);
+
1044
+
1046
+
1052 std::string getFileExtension( const std::string &filepath );
+
1053
+
1055
+
1061 std::string getFileStem( const std::string &filepath );
+
1062
+
1064
+
1070 std::string getFileName( const std::string &filepath );
+
1071
+
1073
+
1080 std::string getFilePath( const std::string &filepath, bool trailingslash = true );
+
1081
+
1083
+
1088 bool validateOutputPath(std::string &output_directory, const std::vector<std::string> &allowable_file_extensions = {});
+
1089
+
1091
+
1095 std::vector<float> importVectorFromFile(const std::string &filepath);
+
1096
+ +
1100 extern vec3 nullorigin;
+
1101
+
1102}
+
1103
+
1104#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:954
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
@@ -677,23 +691,27 @@
std::vector< std::string > separate_string_by_delimiter(const std::string &inputstring, const std::string &delimiter)
Separate string by delimiter and store into a vector.
Definition global.cpp:1032
anytype clamp(anytype value, anytype min, anytype max)
Clamp value to be within some specified bounds.
Definition global.cpp:1055
+
R-G-B-A color vector.
R-G-B color vector.
-
MATLAB-style timer. Call tic() to start timer, call toc() to stop timer and print duration.
Definition global.h:619
-
double toc(const char *message) const
Stop timer and print elapsed time and a user-defined message.
Definition global.h:641
-
void tic()
Start timer.
Definition global.h:627
-
double toc() const
Stop timer and print elapsed time.
Definition global.h:633
-
Vector of two elements of type 'int'.
-
Vector of three elements of type 'int'.
-
Vector of four elements of type 'int'.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
-
Vector of four elements of type 'float'.
+
Vector of spherical coordinates (elevation,azimuth)
+
double toc(const char *message) const
Stop timer and print elapsed time and a user-defined message.
Definition global.h:645
+
void tic()
Start timer.
Definition global.h:631
+
double toc() const
Stop timer and print elapsed time.
Definition global.h:637
+
Vector of two elements of type 'int'.
+
Vector of three elements of type 'int'.
+
Vector of four elements of type 'int'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
+
Vector of four elements of type 'float'.
- -
+ + diff --git a/doc/html/globals.html b/doc/html/globals.html index 8c8ecccd7..b9b8c31ed 100644 --- a/doc/html/globals.html +++ b/doc/html/globals.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
- w -

- - + + diff --git a/doc/html/globals_enum.html b/doc/html/globals_enum.html index bd209a637..e3a8e6ce3 100644 --- a/doc/html/globals_enum.html +++ b/doc/html/globals_enum.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
RadiationSourceType : RadiationModel.h
- -
+ + diff --git a/doc/html/globals_func.html b/doc/html/globals_func.html index d5828ed63..554374afa 100644 --- a/doc/html/globals_func.html +++ b/doc/html/globals_func.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
- w -

- - + + diff --git a/doc/html/grapevine_8cpp.html b/doc/html/grapevine_8cpp.html index 0c568dad7..df3f6fb35 100644 --- a/doc/html/grapevine_8cpp.html +++ b/doc/html/grapevine_8cpp.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
@@ -152,10 +158,13 @@

+ + diff --git a/doc/html/grapevine_8cpp_source.html b/doc/html/grapevine_8cpp_source.html index b230f1cdb..22131fd31 100644 --- a/doc/html/grapevine_8cpp_source.html +++ b/doc/html/grapevine_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
grapevine.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "CanopyGenerator.h"
17
18using namespace helios;
@@ -144,8 +151,8 @@
51 xgrape.y = position.y+RB*cos(theta)+unif_distribution(generator)*0.25f*grape_rad;
52 xgrape.z = z+unif_distribution(generator)*0.25f*grape_rad;
53
-
54 uint objID=context->addSphereObject( fmax(2.f,float(grape_subdiv)), xgrape, grape_rad, grape_color );
-
55 std::vector<uint> U = context->getObjectPrimitiveUUIDs(objID);
+
54 uint objID=context->addSphereObject( fmax(2.f,float(grape_subdiv)), xgrape, grape_rad, grape_color );
+
55 std::vector<uint> U = context->getObjectPrimitiveUUIDs(objID);
56 UUID.push_back(U);
57
58 theta=theta+dtheta;
@@ -158,7 +165,7 @@
65 }
66
67 if( enable_element_labels ) {
-
68 context->setPrimitiveData( UUID, "element_label", "berry");
+
68 context->setPrimitiveData( UUID, "element_label", "berry");
69 }
70
71 return UUID;
@@ -255,7 +262,7 @@
160
161 bool is_dead = false;
162 if( params.dead_probability > 0 ){
-
163 float random_draw = context->randu();
+
163 float random_draw = context->randu();
164 is_dead = random_draw <= params.dead_probability;
165 }
166
@@ -285,10 +292,10 @@
190
191 int wood_subdivisions = std::max( 3, params.wood_subdivisions +getVariation(params.wood_subdivisions_spread, generator));
192
-
193 uint objID = context->addTubeObject(wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
-
194 UUID_trunk_plant = context->getObjectPrimitiveUUIDs(objID);
+
193 uint objID = context->addTubeObject(wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
+
194 UUID_trunk_plant = context->getObjectPrimitiveUUIDs(objID);
195 if( enable_element_labels ) {
-
196 context->setPrimitiveData(UUID_trunk_plant, "element_label", "trunk");
+
196 context->setPrimitiveData(UUID_trunk_plant, "element_label", "trunk");
197 }
198
199 //---- Cordons -----//
@@ -326,8 +333,8 @@
231 tmp.at(i) = pos_cordw.at(i) + origin;
232 }
233
-
234 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cordw,params.wood_texture_file.c_str() );
-
235 UUID_branch_plant = context->getObjectPrimitiveUUIDs(objID);
+
234 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cordw,params.wood_texture_file.c_str() );
+
235 UUID_branch_plant = context->getObjectPrimitiveUUIDs(objID);
236
237 //East Cordon
238 std::vector<float> rad_corde;
@@ -349,12 +356,12 @@
254 tmp.at(i) = pos_corde.at(i) + origin;
255 }
256
-
257 objID = context->addTubeObject(wood_subdivisions,tmp,rad_corde,params.wood_texture_file.c_str() );
-
258 U = context->getObjectPrimitiveUUIDs(objID);
+
257 objID = context->addTubeObject(wood_subdivisions,tmp,rad_corde,params.wood_texture_file.c_str() );
+
258 U = context->getObjectPrimitiveUUIDs(objID);
259 UUID_branch_plant.insert(UUID_branch_plant.end(), U.begin(), U.end() );
260
261 if( enable_element_labels ) { //note: only need to set label once because the UUID vector contains both cordons
-
262 context->setPrimitiveData(UUID_branch_plant, "element_label", "cordon");
+
262 context->setPrimitiveData(UUID_branch_plant, "element_label", "cordon");
263 }
264
265 //------- primary shoots ---------//
@@ -454,11 +461,11 @@
359 tmp.at(i) = pos_pshoot.at(i) + origin;
360 }
361
-
362 objID = context->addTubeObject(wood_subdivisions,tmp,rad_pshoot, params.wood_texture_file.c_str() );
-
363 U = context->getObjectPrimitiveUUIDs(objID);
+
362 objID = context->addTubeObject(wood_subdivisions,tmp,rad_pshoot, params.wood_texture_file.c_str() );
+
363 U = context->getObjectPrimitiveUUIDs(objID);
364 UUID_branch_plant.insert(UUID_branch_plant.end(), U.begin(), U.end() );
365 if( enable_element_labels ) {
-
366 context->setPrimitiveData( U, "element_label", "cane");
+
366 context->setPrimitiveData( U, "element_label", "cane");
367 }
368
369 if( is_dead ){
@@ -521,12 +528,12 @@
426
427 vec3 position = origin+pos_leaf+leaf_offset;
428
-
429 std::vector<uint> UUID_leaf = context->copyPrimitive( leaf_ptype );
+
429 std::vector<uint> UUID_leaf = context->copyPrimitive( leaf_ptype );
430// context->addPolymeshObject( UUID_leaf );
-
431 context->scalePrimitive( UUID_leaf, make_vec3(lsize,lsize,lsize));
-
432 context->rotatePrimitive( UUID_leaf, -Rtheta,"y");
-
433 context->rotatePrimitive( UUID_leaf, Rphi,"z");
-
434 context->translatePrimitive( UUID_leaf, position);
+
431 context->scalePrimitive( UUID_leaf, make_vec3(lsize,lsize,lsize));
+
432 context->rotatePrimitive( UUID_leaf, -Rtheta,"y");
+
433 context->rotatePrimitive( UUID_leaf, Rphi,"z");
+
434 context->translatePrimitive( UUID_leaf, position);
435
436 UUID_leaf_plant.push_back( UUID_leaf );
437
@@ -535,7 +542,7 @@
440 flip++;
441
442 if( enable_element_labels ) {
-
443 context->setPrimitiveData( UUID_leaf, "element_label", "leaf");
+
443 context->setPrimitiveData( UUID_leaf, "element_label", "leaf");
444 }
445
446 }
@@ -545,7 +552,7 @@
450 }
451
452 //context->deleteObject(ID0);
-
453 context->deletePrimitive( leaf_ptype );
+
453 context->deletePrimitive( leaf_ptype );
454
455 UUID_trunk.push_back( UUID_trunk_plant );
456 UUID_branch.push_back( UUID_branch_plant );
@@ -571,7 +578,7 @@
474
475 bool is_dead = false;
476 if( params.dead_probability > 0 ){
-
477 float random_draw = context->randu();
+
477 float random_draw = context->randu();
478 is_dead = random_draw <= params.dead_probability;
479 }
480
@@ -601,8 +608,8 @@
504
505 int wood_subdivisions = std::max( 3, params.wood_subdivisions + getVariation(params.wood_subdivisions_spread, generator));
506
-
507 uint objID = context->addTubeObject(wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
-
508 UUID_trunk_plant = context->getObjectPrimitiveUUIDs(objID);
+
507 uint objID = context->addTubeObject(wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
+
508 UUID_trunk_plant = context->getObjectPrimitiveUUIDs(objID);
509
510 //------ crown -------//
511
@@ -633,8 +640,8 @@
536 pos_crownw.at(i) = pos_crownw.at(i) + origin;
537 }
538
-
539 objID = context->addTubeObject(wood_subdivisions,pos_crownw,rad_crown, params.wood_texture_file.c_str() );
-
540 U = context->getObjectPrimitiveUUIDs(objID);
+
539 objID = context->addTubeObject(wood_subdivisions,pos_crownw,rad_crown, params.wood_texture_file.c_str() );
+
540 U = context->getObjectPrimitiveUUIDs(objID);
541 UUID_trunk_plant.insert( UUID_trunk_plant.end(), U.begin(), U.end() );
542
543 std::vector<vec3> pos_crowne;
@@ -648,8 +655,8 @@
551 pos_crowne.at(i) = pos_crowne.at(i) + origin;
552 }
553
-
554 objID = context->addTubeObject(wood_subdivisions,pos_crowne,rad_crown, params.wood_texture_file.c_str() );
-
555 U = context->getObjectPrimitiveUUIDs(objID);
+
554 objID = context->addTubeObject(wood_subdivisions,pos_crowne,rad_crown, params.wood_texture_file.c_str() );
+
555 U = context->getObjectPrimitiveUUIDs(objID);
556 UUID_trunk_plant.insert( UUID_trunk_plant.end(), U.begin(), U.end() );
557
558 //---- Cordons -----//
@@ -681,8 +688,8 @@
584 tmp.at(i) = pos_cordnw.at(i) + origin;
585 }
586
-
587 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
-
588 UUID_branch_plant = context->getObjectPrimitiveUUIDs(objID);
+
587 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
+
588 UUID_branch_plant = context->getObjectPrimitiveUUIDs(objID);
589
590 std::vector<vec3> pos_cordsw;
591 pos_cordsw.push_back(make_vec3(0.7f*0.5f*cordon_spacing*cost,0.7f*0.5f*cordon_spacing*sint,0.99f*cordon_height));
@@ -698,8 +705,8 @@
601 tmp.at(i) = pos_cordsw.at(i) + origin;
602 }
603
-
604 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
-
605 U = context->getObjectPrimitiveUUIDs(objID);
+
604 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
+
605 U = context->getObjectPrimitiveUUIDs(objID);
606 UUID_branch_plant.insert( UUID_branch_plant.end(), U.begin(), U.end() );
607
608 //East Cordon
@@ -717,8 +724,8 @@
620 tmp.at(i) = pos_cordne.at(i) + origin;
621 }
622
-
623 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
-
624 U = context->getObjectPrimitiveUUIDs(objID);
+
623 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
+
624 U = context->getObjectPrimitiveUUIDs(objID);
625 UUID_branch_plant.insert( UUID_branch_plant.end(), U.begin(), U.end() );
626
627 std::vector<vec3> pos_cordse;
@@ -735,13 +742,13 @@
638 tmp.at(i) = pos_cordse.at(i) + origin;
639 }
640
-
641 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
-
642 U = context->getObjectPrimitiveUUIDs(objID);
+
641 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
+
642 U = context->getObjectPrimitiveUUIDs(objID);
643 UUID_branch_plant.insert( UUID_branch_plant.end(), U.begin(), U.end() );
644
645 //------- primary shoots ---------//
646
-
647 uint ID0 = context->addTileObject( make_vec3(0,0,0), make_vec2(1,1), make_SphericalCoord(0,PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
+
647 uint ID0 = context->addTileObject( make_vec3(0,0,0), make_vec2(1,1), make_SphericalCoord(0,PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
648
649 float shoot_length = std::max(0.f, params.shoot_length + getVariation(params.shoot_length_spread, generator));
650 float shoot_radius = std::max( 1e-5f, params.shoot_radius + getVariation(params.shoot_radius_spread, generator));
@@ -829,8 +836,8 @@
732 tmp.at(i) = pos_pshoot.at(i) + origin;
733 }
734
-
735 objID = context->addTubeObject(wood_subdivisions,tmp,rad_pshoot, params.wood_texture_file.c_str() );
-
736 U = context->getObjectPrimitiveUUIDs(objID);
+
735 objID = context->addTubeObject(wood_subdivisions,tmp,rad_pshoot, params.wood_texture_file.c_str() );
+
736 U = context->getObjectPrimitiveUUIDs(objID);
737 UUID_branch_plant.insert(UUID_branch_plant.end(), U.begin(), U.end() );
738
739 if( is_dead ){
@@ -894,13 +901,13 @@
797
798 vec3 position = origin+pos_leaf+leaf_offset;
799
-
800 uint ID = context->copyObject(ID0);
-
801 context->getTileObjectPointer(ID)->scale(make_vec3(lsize,lsize,1));
-
802 context->getObjectPointer(ID)->rotate(-Rtheta,"y");
-
803 context->getObjectPointer(ID)->rotate(Rphi,"z");
-
804 context->getObjectPointer(ID)->translate(position);
+
800 uint ID = context->copyObject(ID0);
+
801 context->getTileObjectPointer(ID)->scale(make_vec3(lsize,lsize,1));
+
802 context->getObjectPointer(ID)->rotate(-Rtheta,"y");
+
803 context->getObjectPointer(ID)->rotate(Rphi,"z");
+
804 context->getObjectPointer(ID)->translate(position);
805
-
806 UUID_leaf_plant.push_back(context->getObjectPointer(ID)->getPrimitiveUUIDs());
+
806 UUID_leaf_plant.push_back(context->getObjectPointer(ID)->getPrimitiveUUIDs());
807
808 lfrac = lfrac - leaf_spacing_fraction*lsize*(1.f+getVariation(0.25f,generator));
809
@@ -913,7 +920,7 @@
816 }
817 }
818
-
819 context->deleteObject(ID0);
+
819 context->deleteObject(ID0);
820
821 UUID_trunk.push_back( UUID_trunk_plant );
822 UUID_branch.push_back( UUID_branch_plant );
@@ -944,7 +951,7 @@
845
846 bool is_dead = false;
847 if( params.dead_probability > 0 ){
-
848 float random_draw = context->randu();
+
848 float random_draw = context->randu();
849 is_dead = random_draw <= params.dead_probability;
850 }
851
@@ -976,8 +983,8 @@
877
878 int wood_subdivisions = std::max( 0, params.wood_subdivisions + getVariation(params.wood_subdivisions_spread, generator));
879
-
880 uint objID = context->addTubeObject(wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
-
881 UUID_trunk_plant = context->getObjectPrimitiveUUIDs(objID);
+
880 uint objID = context->addTubeObject(wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
+
881 UUID_trunk_plant = context->getObjectPrimitiveUUIDs(objID);
882
883 //---- Cordons -----//
884
@@ -1012,12 +1019,12 @@
913 tmp.at(i) = pos_cord.at(i) + origin;
914 }
915
-
916 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
-
917 UUID_branch_plant = context->getObjectPrimitiveUUIDs(objID);
+
916 objID = context->addTubeObject(wood_subdivisions,tmp,rad_cord,params.wood_texture_file.c_str() );
+
917 UUID_branch_plant = context->getObjectPrimitiveUUIDs(objID);
918
919 //------- primary shoots ---------//
920
-
921 uint ID0 = context->addTileObject( make_vec3(0,0,0), make_vec2(1,1), make_SphericalCoord(0,PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
+
921 uint ID0 = context->addTileObject( make_vec3(0,0,0), make_vec2(1,1), make_SphericalCoord(0,PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
922
923 float shoot_length = std::max(0.f, params.shoot_length + getVariation(params.shoot_length_spread, generator));
924 float shoot_radius = std::max(1e-5f, params.shoot_radius + getVariation(params.shoot_radius_spread, generator));
@@ -1070,8 +1077,8 @@
971 tmp.at(i) = pos_pshoot.at(i) + origin;
972 }
973
-
974 objID = context->addTubeObject(wood_subdivisions,tmp,rad_pshoot, params.wood_texture_file.c_str() );
-
975 U = context->getObjectPrimitiveUUIDs(objID);
+
974 objID = context->addTubeObject(wood_subdivisions,tmp,rad_pshoot, params.wood_texture_file.c_str() );
+
975 U = context->getObjectPrimitiveUUIDs(objID);
976 UUID_branch_plant.insert(UUID_branch_plant.end(), U.begin(), U.end() );
977
978 if( is_dead ){
@@ -1134,13 +1141,13 @@
1035
1036 vec3 position = origin+pos_leaf-leaf_offset;
1037
-
1038 uint ID = context->copyObject(ID0);
-
1039 context->getTileObjectPointer(ID)->scale(make_vec3(lsize,lsize,1));
-
1040 context->getObjectPointer(ID)->rotate(-Rtheta,"y");
-
1041 context->getObjectPointer(ID)->rotate(Rphi,"z");
-
1042 context->getObjectPointer(ID)->translate(position);
+
1038 uint ID = context->copyObject(ID0);
+
1039 context->getTileObjectPointer(ID)->scale(make_vec3(lsize,lsize,1));
+
1040 context->getObjectPointer(ID)->rotate(-Rtheta,"y");
+
1041 context->getObjectPointer(ID)->rotate(Rphi,"z");
+
1042 context->getObjectPointer(ID)->translate(position);
1043
-
1044 UUID_leaf_plant.push_back(context->getObjectPointer(ID)->getPrimitiveUUIDs());
+
1044 UUID_leaf_plant.push_back(context->getObjectPointer(ID)->getPrimitiveUUIDs());
1045
1046 lfrac = lfrac - leaf_spacing_fraction*lsize*(1.f+getVariation(0.25f,generator));
1047
@@ -1150,7 +1157,7 @@
1051
1052 }
1053
-
1054 context->deleteObject(ID0);
+
1054 context->deleteObject(ID0);
1055
1056 UUID_trunk.push_back( UUID_trunk_plant );
1057 UUID_branch.push_back( UUID_branch_plant );
@@ -1179,7 +1186,7 @@
1078
1079 bool is_dead = false;
1080 if( params.dead_probability > 0 ){
-
1081 float random_draw = context->randu();
+
1081 float random_draw = context->randu();
1082 is_dead = random_draw <= params.dead_probability;
1083 }
1084
@@ -1209,8 +1216,8 @@
1108
1109 int wood_subdivisions = std::max(0, params.wood_subdivisions + getVariation(params.wood_subdivisions_spread, generator));
1110
-
1111 uint objID = context->addTubeObject(wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
-
1112 UUID_trunk_plant = context->getObjectPrimitiveUUIDs(objID);
+
1111 uint objID = context->addTubeObject(wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
+
1112 UUID_trunk_plant = context->getObjectPrimitiveUUIDs(objID);
1113
1114 //------- primary shoots ---------//
1115
@@ -1220,7 +1227,7 @@
1119 float shoot_radius = std::max( 0.f, params.shoot_radius + getVariation(params.shoot_radius_spread, generator));
1120 uint shoots_per_cordon = std::max(0u, params.shoots_per_cordon + getVariation(params.shoots_per_cordon_spread, generator));
1121
-
1122 uint ID0 = context->addTileObject( make_vec3(0,0,0), make_vec2(1,1), make_SphericalCoord(0,PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
+
1122 uint ID0 = context->addTileObject( make_vec3(0,0,0), make_vec2(1,1), make_SphericalCoord(0,PI_F), params.leaf_subdivisions, params.leaf_texture_file.c_str() );
1123
1124 for( uint c=0; c<2; c++ ){
1125
@@ -1262,8 +1269,8 @@
1161 tmp.at(i) = pos_pshoot.at(i) + origin;
1162 }
1163
-
1164 objID = context->addTubeObject(wood_subdivisions,tmp,rad_pshoot, params.wood_texture_file.c_str() );
-
1165 U = context->getObjectPrimitiveUUIDs(objID);
+
1164 objID = context->addTubeObject(wood_subdivisions,tmp,rad_pshoot, params.wood_texture_file.c_str() );
+
1165 U = context->getObjectPrimitiveUUIDs(objID);
1166 UUID_branch_plant.insert(UUID_branch_plant.end(), U.begin(), U.end() );
1167
1168 if( is_dead ){
@@ -1326,13 +1333,13 @@
1225
1226 vec3 position = origin+pos_leaf-leaf_offset;
1227
-
1228 uint ID = context->copyObject(ID0);
-
1229 context->getTileObjectPointer(ID)->scale(make_vec3(lsize,lsize,1));
-
1230 context->getObjectPointer(ID)->rotate(-Rtheta,"y");
-
1231 context->getObjectPointer(ID)->rotate(Rphi,"z");
-
1232 context->getObjectPointer(ID)->translate(position);
+
1228 uint ID = context->copyObject(ID0);
+
1229 context->getTileObjectPointer(ID)->scale(make_vec3(lsize,lsize,1));
+
1230 context->getObjectPointer(ID)->rotate(-Rtheta,"y");
+
1231 context->getObjectPointer(ID)->rotate(Rphi,"z");
+
1232 context->getObjectPointer(ID)->translate(position);
1233
-
1234 UUID_leaf_plant.push_back(context->getObjectPointer(ID)->getPrimitiveUUIDs());
+
1234 UUID_leaf_plant.push_back(context->getObjectPointer(ID)->getPrimitiveUUIDs());
1235
1236 lfrac = lfrac - leaf_spacing_fraction*lsize*(1.f+getVariation(0.25f,generator));
1237
@@ -1344,7 +1351,7 @@
1243
1244 }
1245
-
1246 context->deleteObject(ID0);
+
1246 context->deleteObject(ID0);
1247
1248 UUID_trunk.push_back( UUID_trunk_plant );
1249 UUID_branch.push_back( UUID_branch_plant );
@@ -1363,27 +1370,10 @@
uint grapevineGoblet(const GobletGrapevineParameters &params, const helios::vec3 &origin)
Function to add an individual grapevine plant on a goblet (vent a taille) trellis.
uint grapevineUnilateral(const UnilateralGrapevineParameters &params, const helios::vec3 &origin)
Function to add an individual grapevine plant on a unilateral trellis.
uint grapevineVSP(const VSPGrapevineParameters &params, const helios::vec3 &origin)
Function to add an individual grapevine plant on a vertical shoot positioned (VSP) trellis.
-
void rotate(float rotation_radians, const char *rotation_axis_xyz_string)
Method to rotate a Compound Object about the x-, y-, or z-axis.
Definition Context.cpp:2377
-
void scale(const helios::vec3 &scale)
Method to scale a compound object in the x-, y- and z-directions.
Definition Context.cpp:2471
-
void translate(const helios::vec3 &shift)
Method to translate/shift a Compound Object.
Definition Context.cpp:2353
-
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
-
Stores the state associated with simulation.
Definition Context.h:1882
-
uint copyObject(uint ObjID)
Make a copy of a Compound Objects from the context.
Definition Context.cpp:2642
+
Stores the state associated with simulation.
Definition Context.h:1888
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
-
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
-
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
std::vector< uint > getObjectPrimitiveUUIDs(uint ObjID) const
Get primitive UUIDs associated with compound object (single object ID input)
Definition Context.cpp:2907
-
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
-
void deleteObject(uint ObjID)
Delete a single Compound Object from the context.
Definition Context.cpp:2609
-
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1491
-
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
-
Tile * getTileObjectPointer(uint ObjID) const
Get a pointer to a Tile Compound Object.
Definition Context.cpp:3312
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
-
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:4728
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
-
uint addSphereObject(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:4310
vec3 rotatePoint(const vec3 &position, const SphericalCoord &rotation)
Function to rotate a 3D vector given spherical angles elevation and azimuth.
Definition global.cpp:79
helios::vec3 spline_interp3(float u, const vec3 &x_start, const vec3 &tan_start, const vec3 &x_end, const vec3 &tan_end)
Function to perform cubic Hermite spline interpolation.
Definition global.cpp:2768
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
@@ -1439,20 +1429,23 @@
Parameters defining the grapevine canopy with unilateral trellis.
Parameters defining the grapevine canopy with vertical shoot positioned (VSP) trellis.
R-G-B color vector.
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/group__compoundobjects.html b/doc/html/group__compoundobjects.html index 3b2b53778..07546d0d5 100644 --- a/doc/html/group__compoundobjects.html +++ b/doc/html/group__compoundobjects.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
Definition at line 6147 of file Context.cpp.

+

Definition at line 6174 of file Context.cpp.

@@ -361,7 +371,7 @@

Returns
Vector of UUIDs for each sub-patch
Note
This version of addBox assumes that all surface normal vectors point away from the box
-

Definition at line 6158 of file Context.cpp.

+

Definition at line 6185 of file Context.cpp.

@@ -412,7 +422,7 @@

Returns
Vector of UUIDs for each sub-patch
Note
This version of addBox assumes that all surface normal vectors point away from the box
-

Definition at line 6256 of file Context.cpp.

+

Definition at line 6283 of file Context.cpp.

@@ -458,7 +468,7 @@

Returns
Vector of UUIDs for each sub-patch
Note
This version of addBox assumes that all surface normal vectors point away from the box
-

Definition at line 6154 of file Context.cpp.

+

Definition at line 6181 of file Context.cpp.

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

Returns
Vector of UUIDs for each sub-patch
Note
This version of addBox assumes that all surface normal vectors point away from the box
-

Definition at line 6162 of file Context.cpp.

+

Definition at line 6189 of file Context.cpp.

@@ -552,7 +562,7 @@

Definition at line 5000 of file Context.cpp.

+

Definition at line 5027 of file Context.cpp.

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

Returns
Object ID of new box object
Note
This version of addBox assumes that all surface normal vectors point away from the box
-

Definition at line 5011 of file Context.cpp.

+

Definition at line 5038 of file Context.cpp.

@@ -644,7 +654,7 @@

Returns
Object ID of new box object
Note
This version of addBox assumes that all surface normal vectors point away from the box
-

Definition at line 5007 of file Context.cpp.

+

Definition at line 5034 of file Context.cpp.

@@ -696,7 +706,7 @@

Returns
Object ID of new box object
Note
This version of addBox assumes that all surface normal vectors point away from the box
-

Definition at line 5015 of file Context.cpp.

+

Definition at line 5042 of file Context.cpp.

@@ -747,7 +757,7 @@

Returns
Object ID of new box object
Note
This version of addBox assumes that all surface normal vectors point away from the box
-

Definition at line 5136 of file Context.cpp.

+

Definition at line 5163 of file Context.cpp.

@@ -802,7 +812,7 @@

Note
Ndivs must be greater than 2.
-

Definition at line 6459 of file Context.cpp.

+

Definition at line 6486 of file Context.cpp.

@@ -859,7 +869,7 @@

Note
Ndivs must be greater than 2.
-

Definition at line 6556 of file Context.cpp.

+

Definition at line 6583 of file Context.cpp.

@@ -916,7 +926,7 @@

Note
Ndivs must be greater than 2.
-

Definition at line 6468 of file Context.cpp.

+

Definition at line 6495 of file Context.cpp.

@@ -972,7 +982,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Ndivs must be greater than 2.
-

Definition at line 5426 of file Context.cpp.

+

Definition at line 5453 of file Context.cpp.

@@ -1030,7 +1040,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Ndivs must be greater than 2.
-

Definition at line 5528 of file Context.cpp.

+

Definition at line 5555 of file Context.cpp.

@@ -1088,7 +1098,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Ndivs must be greater than 2.
-

Definition at line 5433 of file Context.cpp.

+

Definition at line 5460 of file Context.cpp.

@@ -1140,7 +1150,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Assumes a default color of black.
-

Definition at line 6417 of file Context.cpp.

+

Definition at line 6444 of file Context.cpp.

@@ -1191,7 +1201,7 @@

Returns
Vector of UUIDs for each sub-triangle
-

Definition at line 6380 of file Context.cpp.

+

Definition at line 6407 of file Context.cpp.

@@ -1242,7 +1252,7 @@

Returns
Vector of UUIDs for each sub-triangle
-

Definition at line 6376 of file Context.cpp.

+

Definition at line 6403 of file Context.cpp.

@@ -1284,7 +1294,7 @@

Definition at line 6356 of file Context.cpp.

+

Definition at line 6383 of file Context.cpp.

@@ -1330,7 +1340,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Assumes a default color of black.
-

Definition at line 6360 of file Context.cpp.

+

Definition at line 6387 of file Context.cpp.

@@ -1382,7 +1392,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Assumes a default color of black.
-

Definition at line 6372 of file Context.cpp.

+

Definition at line 6399 of file Context.cpp.

@@ -1433,7 +1443,7 @@

Returns
Vector of UUIDs for each sub-triangle
-

Definition at line 6368 of file Context.cpp.

+

Definition at line 6395 of file Context.cpp.

@@ -1484,7 +1494,7 @@

Returns
Vector of UUIDs for each sub-triangle
-

Definition at line 6364 of file Context.cpp.

+

Definition at line 6391 of file Context.cpp.

@@ -1536,7 +1546,7 @@

Returns
Object ID of new disk object
Note
Assumes a default color of black.
-

Definition at line 5338 of file Context.cpp.

+

Definition at line 5365 of file Context.cpp.

@@ -1587,7 +1597,7 @@

Returns
Object ID of new disk object
-

Definition at line 5280 of file Context.cpp.

+

Definition at line 5307 of file Context.cpp.

@@ -1638,7 +1648,7 @@

Returns
Object ID of new disk object
-

Definition at line 5276 of file Context.cpp.

+

Definition at line 5303 of file Context.cpp.

@@ -1680,7 +1690,7 @@

Definition at line 5256 of file Context.cpp.

+

Definition at line 5283 of file Context.cpp.

@@ -1726,7 +1736,7 @@

Returns
Object ID of new disk object
Note
Assumes a default color of black.
-

Definition at line 5260 of file Context.cpp.

+

Definition at line 5287 of file Context.cpp.

@@ -1778,7 +1788,7 @@

Returns
Object ID of new disk object
Note
Assumes a default color of black.
-

Definition at line 5272 of file Context.cpp.

+

Definition at line 5299 of file Context.cpp.

@@ -1829,7 +1839,7 @@

Returns
Object ID of new disk object
-

Definition at line 5268 of file Context.cpp.

+

Definition at line 5295 of file Context.cpp.

@@ -1880,7 +1890,7 @@

Returns
Object ID of new disk object
-

Definition at line 5264 of file Context.cpp.

+

Definition at line 5291 of file Context.cpp.

@@ -1908,7 +1918,7 @@

Returns
Object ID of new Polymesh
-

Definition at line 5399 of file Context.cpp.

+

Definition at line 5426 of file Context.cpp.

@@ -1948,7 +1958,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Assumes a default color of green
-

Definition at line 5646 of file Context.cpp.

+

Definition at line 5673 of file Context.cpp.

@@ -1993,7 +2003,7 @@

Returns
Vector of UUIDs for each sub-triangle
-

Definition at line 5704 of file Context.cpp.

+

Definition at line 5731 of file Context.cpp.

@@ -2038,7 +2048,7 @@

Returns
Vector of UUIDs for each sub-triangle
-

Definition at line 5654 of file Context.cpp.

+

Definition at line 5681 of file Context.cpp.

@@ -2078,7 +2088,7 @@

Returns
Object ID of new sphere object.
Note
Assumes a default color of green
-

Definition at line 4322 of file Context.cpp.

+

Definition at line 4349 of file Context.cpp.

@@ -2123,7 +2133,7 @@

Returns
Object ID of new sphere object.
-

Definition at line 4413 of file Context.cpp.

+

Definition at line 4440 of file Context.cpp.

@@ -2168,7 +2178,7 @@

Returns
Object ID of new sphere object.
-

Definition at line 4328 of file Context.cpp.

+

Definition at line 4355 of file Context.cpp.

@@ -2208,7 +2218,7 @@

Returns
Object ID of new sphere object.
Note
Assumes a default color of green
-

Definition at line 4310 of file Context.cpp.

+

Definition at line 4337 of file Context.cpp.

@@ -2253,7 +2263,7 @@

Returns
Object ID of new sphere object.
-

Definition at line 4318 of file Context.cpp.

+

Definition at line 4345 of file Context.cpp.

@@ -2298,7 +2308,7 @@

Returns
Object ID of new sphere object.
-

Definition at line 4314 of file Context.cpp.

+

Definition at line 4341 of file Context.cpp.

@@ -2344,7 +2354,7 @@

Returns
Vector of UUIDs for each sub-patch
Note
Assumes default color of green
-

Definition at line 5809 of file Context.cpp.

+

Definition at line 5836 of file Context.cpp.

@@ -2395,7 +2405,7 @@

Returns
Vector of UUIDs for each sub-patch
-

Definition at line 5853 of file Context.cpp.

+

Definition at line 5880 of file Context.cpp.

@@ -2446,7 +2456,7 @@

Returns
Vector of UUIDs for each sub-patch
-

Definition at line 5816 of file Context.cpp.

+

Definition at line 5843 of file Context.cpp.

@@ -2492,7 +2502,7 @@

Returns
Object ID of new tile object.
Note
Assumes default color of green
-

Definition at line 4550 of file Context.cpp.

+

Definition at line 4577 of file Context.cpp.

@@ -2543,7 +2553,7 @@

Returns
Object ID of new tile object.
-

Definition at line 4622 of file Context.cpp.

+

Definition at line 4649 of file Context.cpp.

@@ -2594,7 +2604,7 @@

Returns
Object ID of new tile object.
-

Definition at line 4557 of file Context.cpp.

+

Definition at line 4584 of file Context.cpp.

@@ -2638,7 +2648,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Ndivs must be greater than 2.
-

Definition at line 5930 of file Context.cpp.

+

Definition at line 5957 of file Context.cpp.

@@ -2684,7 +2694,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Ndivs must be greater than 2.
-

Definition at line 6037 of file Context.cpp.

+

Definition at line 6064 of file Context.cpp.

@@ -2730,7 +2740,7 @@

Returns
Vector of UUIDs for each sub-triangle
Note
Ndivs must be greater than 2.
-

Definition at line 5945 of file Context.cpp.

+

Definition at line 5972 of file Context.cpp.

@@ -2774,7 +2784,7 @@

Returns
Object ID of new tube object.
Note
Ndivs must be greater than 2.
-

Definition at line 4728 of file Context.cpp.

+

Definition at line 4755 of file Context.cpp.

@@ -2822,7 +2832,7 @@

Definition at line 4857 of file Context.cpp.

+

Definition at line 4884 of file Context.cpp.

@@ -2876,7 +2886,7 @@

Definition at line 4867 of file Context.cpp.

+

Definition at line 4894 of file Context.cpp.

@@ -2922,15 +2932,17 @@

Returns
Object ID of new tube object.
Note
Ndivs must be greater than 2.
-

Definition at line 4743 of file Context.cpp.

+

Definition at line 4770 of file Context.cpp.

- - + + diff --git a/doc/html/group__functions.html b/doc/html/group__functions.html index a0efffbe7..36011c53c 100644 --- a/doc/html/group__functions.html +++ b/doc/html/group__functions.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
std::vector< std::string > helios::separate_string_by_delimiter (const std::string &inputstring, const std::string &delimiter)  Separate string by delimiter and store into a vector.
  -template<typename anytype > +template<typename anytype> anytype helios::clamp (anytype value, anytype min, anytype max)  Clamp value to be within some specified bounds.
  @@ -215,15 +225,15 @@ float helios::median (std::vector< float > vect)  Median of a vector of floats.
  -template<typename anytype > +template<typename anytype> void helios::resize_vector (std::vector< std::vector< anytype > > &vec, uint Nx, uint Ny)  Resize 2D C++ vector.
  -template<typename anytype > +template<typename anytype> void helios::resize_vector (std::vector< std::vector< std::vector< anytype > > > &vec, uint Nx, uint Ny, uint Nz)  Resize 3D C++ vector.
  -template<typename anytype > +template<typename anytype> void helios::resize_vector (std::vector< std::vector< std::vector< std::vector< anytype > > > > &vec, uint Nx, uint Ny, uint Nz, uint Nw)  Resize 4D C++ vector.
  @@ -508,7 +518,7 @@

-template<typename anytype >
+template<typename anytype>
@@ -1914,7 +1924,7 @@

-template<typename anytype >
+template<typename anytype>

anytype helios::clamp
@@ -1954,7 +1964,7 @@

-template<typename anytype >
+template<typename anytype>

void helios::resize_vector
@@ -2000,7 +2010,7 @@

-template<typename anytype >
+template<typename anytype>

void helios::resize_vector
@@ -2479,10 +2489,12 @@

+ + diff --git a/doc/html/group__primitives.html b/doc/html/group__primitives.html index ff7fe9e48..a6aed306a 100644 --- a/doc/html/group__primitives.html +++ b/doc/html/group__primitives.html @@ -38,7 +38,7 @@

@@ -46,7 +46,7 @@
void helios::resize_vector
-
 v1.3.26 +
 v1.3.27

- +
-
+
+ +
+
+
+
+ + diff --git a/doc/html/group__timeseries.html b/doc/html/group__timeseries.html index d893283af..6f0231ff1 100644 --- a/doc/html/group__timeseries.html +++ b/doc/html/group__timeseries.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
+ + diff --git a/doc/html/group__vectors.html b/doc/html/group__vectors.html index a4e3c9e78..2163ab51c 100644 --- a/doc/html/group__vectors.html +++ b/doc/html/group__vectors.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
+ + diff --git a/doc/html/helios__vector__types_8h.html b/doc/html/helios__vector__types_8h.html index 3068a8928..736c75cf9 100644 --- a/doc/html/helios__vector__types_8h.html +++ b/doc/html/helios__vector__types_8h.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Data Structures | @@ -399,7 +405,7 @@

-inline +inline

+ + diff --git a/doc/html/helios__vector__types_8h.js b/doc/html/helios__vector__types_8h.js new file mode 100644 index 000000000..2b6c4583b --- /dev/null +++ b/doc/html/helios__vector__types_8h.js @@ -0,0 +1,38 @@ +var helios__vector__types_8h = +[ + [ "helios::blend", "global_8h.html#a06a8d8b0bee35e1fd8c564a7674bd07a", null ], + [ "helios::blend", "global_8h.html#a192c018f83c0598738e048212904202d", null ], + [ "helios::Calendar2Julian", "group__vectors.html#gada57ce3d59ce227448a97e8631a4430e", null ], + [ "helios::cross", "helios__vector__types_8h.html#aa4e7459e7404915c12903a5c08588f5b", null ], + [ "helios::Julian2Calendar", "group__vectors.html#gad744b2f0b25c66570a13cba4ace0455b", null ], + [ "helios::make_Date", "group__vectors.html#gad4c811a7a39319de43f58c93e14ecda6", null ], + [ "helios::make_Date", "group__vectors.html#ga5199de860b171749c8e153e94a2984b2", null ], + [ "helios::make_int2", "group__vectors.html#ga39457188bb8c3aba1fdc9217ecc16f74", null ], + [ "helios::make_int2", "group__vectors.html#ga61cbe7ba7a687fde1273f9883e54c2ac", null ], + [ "helios::make_int3", "helios__vector__types_8h.html#a88347513c8d7e764d5c820b61e5905e2", null ], + [ "helios::make_int3", "helios__vector__types_8h.html#a7003de16002f0da5916c10bb566ad0eb", null ], + [ "helios::make_int4", "helios__vector__types_8h.html#ad1dc8d4f618d34d2f7ada3eb0ca7e4db", null ], + [ "helios::make_int4", "helios__vector__types_8h.html#acdfd23cf323df4bdd409c8e4e2bcdfdc", null ], + [ "helios::make_Location", "group__vectors.html#gaa720b1e8afc6a431dda4e3ecb97df112", null ], + [ "helios::make_RGBAcolor", "group__vectors.html#gacc4916e29a0757214b7c558c6e5f7cd3", null ], + [ "helios::make_RGBAcolor", "group__vectors.html#ga55bc372b981da2d30826fcb5f9254888", null ], + [ "helios::make_RGBcolor", "group__vectors.html#gae5b981fa224fe6f30b850467ec655c0b", null ], + [ "helios::make_SphericalCoord", "helios__vector__types_8h.html#ad89212892cf1bdc45eeae189e6d490a1", null ], + [ "helios::make_SphericalCoord", "helios__vector__types_8h.html#a6e6a11dede0cfd0c725e11224f48d2b7", null ], + [ "helios::make_Time", "group__vectors.html#ga7a29e9916b97d9f7533e87e7125e5b66", null ], + [ "helios::make_Time", "group__vectors.html#ga57bfa5a4e5595e2e385d03883733f978", null ], + [ "helios::make_vec2", "group__vectors.html#ga7e3752eb5ff9909862380d188d2b3f24", null ], + [ "helios::make_vec3", "helios__vector__types_8h.html#aa19986ef06f067d450534135735bc36b", null ], + [ "helios::make_vec3", "helios__vector__types_8h.html#a7a7e3dfbb0f3b50e9a5992a25a913566", null ], + [ "helios::make_vec4", "helios__vector__types_8h.html#ab232dd96cf103ad9ac02b6f5c264ced0", null ], + [ "helios::make_vec4", "helios__vector__types_8h.html#a797d2ee9d38d23a6a7a3fa2b826b053b", null ], + [ "helios::operator*", "helios__vector__types_8h.html#a36a0796c19320ea5804ade9835341060", null ], + [ "helios::operator*", "helios__vector__types_8h.html#a5b21978f962a37f7edd5837241d17821", null ], + [ "helios::operator*", "helios__vector__types_8h.html#a9a2cbdb93bb7a6f7460ea0a8ffcc62c6", null ], + [ "helios::operator+", "helios__vector__types_8h.html#a8dfabc1a2f089ccb3b49eef4813dbb88", null ], + [ "helios::operator+", "helios__vector__types_8h.html#aba7a658887aa3d4fdf041fea304a6c35", null ], + [ "helios::operator+", "helios__vector__types_8h.html#a145447708e8a06709ff6904b22087d1b", null ], + [ "helios::operator-", "helios__vector__types_8h.html#a7436b011b35d256deae673fe5c35cf75", null ], + [ "helios::operator-", "helios__vector__types_8h.html#a434fe3718d57c13e067aa06818652be3", null ], + [ "helios::operator-", "helios__vector__types_8h.html#a2ac8eb255c768eba03401b9d7f58df50", null ] +]; \ No newline at end of file diff --git a/doc/html/helios__vector__types_8h_source.html b/doc/html/helios__vector__types_8h_source.html index d068a126e..f445f23d8 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
helios_vector_types.h
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#ifndef HELIOS_VECTOR_TYPES
17#define HELIOS_VECTOR_TYPES
18
@@ -121,21 +128,22 @@
29#include <stdexcept>
30#include <exception>
31#include <iomanip>
-
32
-
34
+
32
+
34
+
37
38namespace helios{
-
39
-
41
+
39
+
41
-
44struct int2{
+
44struct int2{
45public:
-
46
+
46
48 int x;
50 int y;
-
51
+
51
53 /* initializes to zero */
54 int2() : x(0), y(0) {}
-
55
+
55
57 explicit int2( const std::vector<int> &v ){
58 if( v.size()!=2){
@@ -145,11 +153,12 @@
62 y=v[1];
63 }
+
64
65 explicit int2( const int v[2] ) : x(v[0]), y(v[1]) {}
-
66
+
66
68 int2( int v0, int v1 ) : x(v0), y(v1) {}
69
-
70
+
70
72 int2 operator+(const int2& a) const;
74 int2& operator+=(const int2& a);
76 int2& operator-=(const int2& a);
@@ -157,8 +166,8 @@
80 bool operator==( const int2& a ) const;
82 bool operator!=( const int2& a ) const;
84 int2 operator-() const;
-
85
-
+
85
+
87 friend std::ostream &operator<<(std::ostream &os, const helios::int2 &vec) {
88 return os << "helios::int2<" << vec.x << ", " << vec.y << ">";
89 }
@@ -166,15 +175,15 @@
90
91};
-
92
-
94
+
92
+
94
99inline int2 make_int2( int x, int y ){
100 return {x,y};
101}
102
-
104
+
104
108inline int2 make_int2( int X[2] ){
109 return {X[0],X[1]};
@@ -182,13 +191,13 @@
111
-
112inline int2 int2::operator+(const int2& a) const{
+
112inline int2 int2::operator+(const int2& a) const{
113 return {a.x+x, a.y+y};
114}
115
-
116inline int2& int2::operator+=(const int2& a){
+
116inline int2& int2::operator+=(const int2& a){
117 this->x += a.x;
118 this->y += a.y;
119 return *this;
@@ -196,7 +205,7 @@
121
-
122inline int2& int2::operator-=(const int2& a){
+
122inline int2& int2::operator-=(const int2& a){
123 this->x -= a.x;
124 this->y -= a.y;
125 return *this;
@@ -204,41 +213,41 @@
127
-
128inline int2 int2::operator-(const int2& a) const{
+
128inline int2 int2::operator-(const int2& a) const{
129 return {x-a.x, y-a.y};
130}
131
-
132inline bool int2::operator==( const int2& a ) const{
+
132inline bool int2::operator==( const int2& a ) const{
133 return a.x==x && a.y==y;
134}
135
-
136inline bool int2::operator!=( const int2& a ) const{
+
136inline bool int2::operator!=( const int2& a ) const{
137 return a.x!=x || a.y!=y;
138}
139
-
140inline int2 int2::operator-() const{
+
140inline int2 int2::operator-() const{
141 return {-x,-y};
142}
-
143
-
145
+
143
+
145
-
146struct int3{
+
146struct int3{
147public:
-
148
+
148
150 int x;
152 int y;
154 int z;
-
155
+
155
157 /* initializes to zero */
158 int3() : x(0), y(0), z(0) {}
-
159
+
159
161 explicit int3( const std::vector<int> &v ){
162 if( v.size()!=3){
@@ -249,10 +258,11 @@
167 z=v[2];
168 }
+
169
170 explicit int3( const int v[3] ) : x(v[0]), y(v[1]), z(v[2]) {}
-
171
+
171
173 int3( int v0, int v1, int v2 ) : x(v0), y(v1), z(v2) {}
-
174
+
174
176 int3 operator+(const int3& a) const;
178 int3& operator+=(const int3& a);
180 int3& operator-=(const int3& a);
@@ -260,8 +270,8 @@
184 bool operator==( const int3& a ) const;
186 bool operator!=( const int3& a ) const;
188 int3 operator-() const;
-
189
-
+
189
+
191 friend std::ostream &operator<<(std::ostream &os, const helios::int3 &vec) {
192 return os << "helios::int3<" << vec.x << ", " << vec.y << ", " << vec.z << ">";
193 }
@@ -269,13 +279,13 @@
194
195};
-
196
+
196
198inline int3 make_int3( int X, int Y, int Z ){
199 return {X,Y,Z};
200}
-
201
+
201
203inline int3 make_int3( int X[3] ){
204 return {X[0],X[1],X[2]};
@@ -283,13 +293,13 @@
206
-
207inline int3 int3::operator+(const int3& a) const{
+
207inline int3 int3::operator+(const int3& a) const{
208 return {a.x+x, a.y+y, a.z+z};
209}
210
-
211inline int3& int3::operator+=(const int3& a){
+
211inline int3& int3::operator+=(const int3& a){
212 this->x += a.x;
213 this->y += a.y;
214 this->z += a.z;
@@ -298,7 +308,7 @@
217
-
218inline int3& int3::operator-=(const int3& a){
+
218inline int3& int3::operator-=(const int3& a){
219 this->x -= a.x;
220 this->y -= a.y;
221 this->z -= a.z;
@@ -307,42 +317,42 @@
224
-
225inline int3 int3::operator-(const int3& a) const{
+
225inline int3 int3::operator-(const int3& a) const{
226 return {x-a.x, y-a.y, z-a.z};
227}
228
-
229inline bool int3::operator==( const int3& a ) const{
+
229inline bool int3::operator==( const int3& a ) const{
230 return a.x==x && a.y==y && a.z==z;
231}
232
-
233inline bool int3::operator!=( const int3& a ) const{
+
233inline bool int3::operator!=( const int3& a ) const{
234 return a.x!=x || a.y!=y || a.z!=z;
235}
236
-
237inline int3 int3::operator-() const{
+
237inline int3 int3::operator-() const{
238 return {-x,-y,-z};
239}
-
240
-
242
+
240
+
242
-
243struct int4{
+
243struct int4{
244public:
-
245
+
245
247 int x;
249 int y;
251 int z;
253 int w;
-
254
+
254
256 /* initializes to zero */
257 int4() : x(0), y(0), z(0), w(0) {}
-
258
+
258
260 explicit int4( const std::vector<int> &v ){
261 if( v.size()!=4){
@@ -354,11 +364,11 @@
267 w=v[3];
268 }
-
269
+
269
271 explicit int4( const int v[3] ) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
-
272
+
272
274 int4( int v0, int v1, int v2, int v3 ) : x(v0), y(v1), z(v2), w(v3) {}
-
275
+
275
277 int4 operator+(const int4& a) const;
279 int4& operator+=(const int4& a);
281 int4& operator-=(const int4& a);
@@ -366,8 +376,8 @@
285 bool operator==( const int4& a ) const;
287 bool operator!=( const int4& a ) const;
289 int4 operator-() const;
-
290
-
+
290
+
292 friend std::ostream &operator<<(std::ostream &os, const helios::int4 &vec) {
293 return os << "helios::int4<" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ">";
294 }
@@ -375,13 +385,13 @@
295
296};
-
297
+
297
299 inline int4 make_int4(int x, int y, int z, int w ){
300 return {x, y, z, w};
301 }
-
302
+
302
304inline int4 make_int4( const int X[4] ){
305 return {X[0],X[1],X[2],X[3]};
@@ -389,13 +399,13 @@
307
-
308inline int4 int4::operator+(const int4& a) const{
+
308inline int4 int4::operator+(const int4& a) const{
309 return {a.x+x, a.y+y, a.z+z, a.w+w};
310}
311
-
312inline int4& int4::operator+=(const int4& a){
+
312inline int4& int4::operator+=(const int4& a){
313 this->x += a.x;
314 this->y += a.y;
315 this->z += a.z;
@@ -405,7 +415,7 @@
319
-
320inline int4& int4::operator-=(const int4& a){
+
320inline int4& int4::operator-=(const int4& a){
321 this->x -= a.x;
322 this->y -= a.y;
323 this->z -= a.z;
@@ -415,56 +425,56 @@
327
-
328inline int4 int4::operator-(const int4& a) const{
+
328inline int4 int4::operator-(const int4& a) const{
329 return {a.x-x, a.y-y, a.z-z, a.w-w};
330}
331
-
332inline bool int4::operator==( const int4& a ) const{
+
332inline bool int4::operator==( const int4& a ) const{
333 return a.x==x && a.y==y && a.z==z && a.w==w;
334}
335
-
336inline bool int4::operator!=( const int4& a ) const{
+
336inline bool int4::operator!=( const int4& a ) const{
337 return a.x!=x || a.y!=y || a.z!=z || a.w!=w;
338}
339
-
340inline int4 int4::operator-() const{
+
340inline int4 int4::operator-() const{
341 return {-x,-y,-z,-w};
342}
-
343
-
345
+
343
+
345
-
346struct vec2{
+
346struct vec2{
347public:
-
348
+
348
350 float x;
352 float y;
-
353
+
353
- +
356 float mag = sqrt( x*x + y*y );
357 x/=mag;
358 y/=mag;
359 return {x,y};
360 }
-
361
-
363
+
361
+
363
366 [[nodiscard]] float magnitude() const{
367 return sqrtf( x*x + y*y );
368 }
-
369
-
371
+
369
+
371
372 vec2() : x(0), y(0) {}
-
373
+
373
375 explicit vec2( const std::vector<float> &v ){
376 if( v.size()!=2){
@@ -474,10 +484,11 @@
380 y=v.at(1);
381 }
+
382
383 explicit vec2( const float v[2] ) : x(v[0]), y(v[1]) {}
-
384
+
384
386 vec2( float v0, float v1 ) : x(v0), y(v1) {}
-
387
+
387
389 float operator*(const vec2& a) const;
391 vec2 operator+(const vec2& a) const;
393 vec2& operator+=(const vec2& a);
@@ -490,8 +501,8 @@
407 bool operator==(const vec2& a) const;
409 bool operator!=(const vec2& a) const;
411 vec2 operator-() const;
-
412
-
+
412
+
414 friend std::ostream &operator<<(std::ostream &os, const helios::vec2 &vec) {
415 return os << "helios::vec2<" << vec.x << ", " << vec.y << ">";
416 }
@@ -499,12 +510,12 @@
417
418};
-
419
+
419
421vec2 operator*( float a, const vec2& v);
423vec2 operator+( float a, const vec2& v);
425vec2 operator-( float a, const vec2& v);
-
426
-
428
+
426
+
428
433inline vec2 make_vec2(float x, float y ){
434 return {x, y};
@@ -512,19 +523,19 @@
436
-
437inline float vec2::operator*(const vec2& a) const{
+
437inline float vec2::operator*(const vec2& a) const{
438 return a.x*x+a.y*y;
439}
440
-
441inline vec2 vec2::operator+(const vec2& a) const{
+
441inline vec2 vec2::operator+(const vec2& a) const{
442 return {a.x+x,a.y+y};
443}
444
-
445inline vec2& vec2::operator+=(const vec2& a){
+
445inline vec2& vec2::operator+=(const vec2& a){
446 this->x += a.x;
447 this->y += a.y;
448 return *this;
@@ -532,7 +543,7 @@
450
-
451inline vec2& vec2::operator-=(const vec2& a){
+
451inline vec2& vec2::operator-=(const vec2& a){
452 this->x -= a.x;
453 this->y -= a.y;
454 return *this;
@@ -540,7 +551,7 @@
456
-
457inline vec2 vec2::operator+(const float a) const {
+
457inline vec2 vec2::operator+(const float a) const {
458 return {a+x, a+y};
459}
@@ -552,13 +563,13 @@
464
-
465inline vec2 vec2::operator-(const vec2& a) const{
+
465inline vec2 vec2::operator-(const vec2& a) const{
466 return {x-a.x,y-a.y};
467}
468
-
469inline vec2 vec2::operator-(const float a) const {
+
469inline vec2 vec2::operator-(const float a) const {
470 return {x-a, y-a};
471}
@@ -570,7 +581,7 @@
476
-
477inline vec2 vec2::operator*(const float a) const{
+
477inline vec2 vec2::operator*(const float a) const{
478 return {x*a,y*a};
479}
@@ -582,40 +593,40 @@
484
-
485inline vec2 vec2::operator/(const float a) const{
+
485inline vec2 vec2::operator/(const float a) const{
486 return {x/a,y/a};
487}
488
-
489inline bool vec2::operator==(const vec2& a) const{
+
489inline bool vec2::operator==(const vec2& a) const{
490 return x == a.x && y == a.y;
491}
492
-
493inline bool vec2::operator!=(const vec2& a) const{
+
493inline bool vec2::operator!=(const vec2& a) const{
494 return x != a.x || y != a.y;
495}
496
-
497inline vec2 vec2::operator-() const{
+
497inline vec2 vec2::operator-() const{
498 return {-x,-y};
499}
-
500
-
502
+
500
+
502
-
503struct vec3{
+
503struct vec3{
504public:
-
505
+
505
507 float x;
509 float y;
511 float z;
-
512
+
512
- +
515 float mag = sqrt( x*x + y*y + z*z );
516 x/=mag;
517 y/=mag;
@@ -623,17 +634,17 @@
519 return {x,y,z};
520 }
-
521
-
523
+
521
+
523
526 [[nodiscard]] float magnitude() const{
527 return sqrtf( x*x + y*y + z*z );
528 }
-
529
-
531
+
529
+
531
532 vec3() : x(0), y(0), z(0) {}
-
533
+
533
535 explicit vec3( const std::vector<float> &v ){
536 if( v.size()!=3){
@@ -644,10 +655,11 @@
541 z=v[2];
542 }
+
543
544 explicit vec3( const float v[3] ) : x(v[0]), y(v[1]), z(v[2]) {}
-
545
+
545
547 vec3( float v0, float v1, float v2 ) : x(v0), y(v1), z(v2) {}
-
548
+
548
550 float operator*(const vec3& a) const;
552 vec3 operator+(const vec3& a) const;
554 vec3& operator+=(const vec3& a);
@@ -660,8 +672,8 @@
568 bool operator==(const vec3& a) const;
570 bool operator!=(const vec3& a) const;
572 vec3 operator-() const;
-
573
-
+
573
+
575 friend std::ostream &operator<<(std::ostream &os, const helios::vec3 &vec) {
576 return os << "helios::vec3<" << vec.x << ", " << vec.y << ", " << vec.z << ">";
577 }
@@ -669,23 +681,23 @@
578
579};
-
580
+
580
582vec3 operator*( float a, const vec3& v);
584vec3 operator+( float a, const vec3& v);
586vec3 operator-( float a, const vec3& v);
-
587
+
587
589inline vec3 make_vec3(float x, float y, float z ){
590 return {x, y, z};
591}
-
592
+
592
594inline vec3 make_vec3( float X[3] ){
595 return {X[0],X[1],X[2]};
596}
-
597
+
597
599inline vec3 cross(const vec3 &a, const vec3 &b ){
600 return {a.y*b.z - b.y*a.z,b.x*a.z - a.x*b.z,a.x*b.y - b.x*a.y };
@@ -693,19 +705,19 @@
602
-
603inline float vec3::operator*(const vec3& a) const{
+
603inline float vec3::operator*(const vec3& a) const{
604 return a.x*x+a.y*y+a.z*z;
605}
606
-
607inline vec3 vec3::operator+(const vec3& a) const{
+
607inline vec3 vec3::operator+(const vec3& a) const{
608 return {a.x+x,a.y+y,a.z+z};
609}
610
-
611inline vec3& vec3::operator+=(const vec3& a){
+
611inline vec3& vec3::operator+=(const vec3& a){
612 this->x += a.x;
613 this->y += a.y;
614 this->z += a.z;
@@ -714,7 +726,7 @@
617
-
618inline vec3& vec3::operator-=(const vec3& a){
+
618inline vec3& vec3::operator-=(const vec3& a){
619 this->x -= a.x;
620 this->y -= a.y;
621 this->z -= a.z;
@@ -723,7 +735,7 @@
624
-
625inline vec3 vec3::operator+(const float a) const{
+
625inline vec3 vec3::operator+(const float a) const{
626 return { x+a, y+a, z+a };
627}
@@ -735,13 +747,13 @@
632
-
633inline vec3 vec3::operator-(const vec3& a) const{
+
633inline vec3 vec3::operator-(const vec3& a) const{
634 return {x-a.x,y-a.y,z-a.z};
635}
636
-
637inline vec3 vec3::operator-(const float a) const{
+
637inline vec3 vec3::operator-(const float a) const{
638 return { x-a, y-a, z-a };
639}
@@ -753,7 +765,7 @@
644
-
645inline vec3 vec3::operator*(const float a) const{
+
645inline vec3 vec3::operator*(const float a) const{
646 return {x*a,y*a,z*a};
647}
@@ -765,41 +777,41 @@
652
-
653inline vec3 vec3::operator/(const float a) const{
+
653inline vec3 vec3::operator/(const float a) const{
654 return {x/a,y/a,z/a};
655}
656
-
657inline bool vec3::operator==(const vec3& a) const{
+
657inline bool vec3::operator==(const vec3& a) const{
658 return x == a.x && y == a.y && z == a.z;
659}
660
-
661inline bool vec3::operator!=(const vec3& a) const{
+
661inline bool vec3::operator!=(const vec3& a) const{
662 return x != a.x || y != a.y || z != a.z;
663}
664
-
665inline vec3 vec3::operator-() const{
+
665inline vec3 vec3::operator-() const{
666 return {-x,-y,-z};
667}
-
668
-
670
+
668
+
670
-
673struct vec4{
+
673struct vec4{
674public:
-
675
+
675
677 float x;
679 float y;
681 float z;
683 float w;
-
684
+
684
- +
687 float mag = sqrt( x*x + y*y + z*z + w*w );
688 x/=mag;
689 y/=mag;
@@ -808,17 +820,17 @@
692 return {x,y,z,w};
693 }
-
694
-
696
+
694
+
696
699 [[nodiscard]] float magnitude() const{
700 return sqrt( x*x + y*y + z*z + w*w );
701 }
-
702
-
704
+
702
+
704
705 vec4() : x(0), y(0), z(0), w(0) {}
-
706
+
706
708 explicit vec4( const std::vector<float> &v ){
709 if( v.size()!=4){
@@ -830,10 +842,11 @@
715 w=v[3];
716 }
+
717
718 explicit vec4( const float v[4] ) : x(v[0]), y(v[1]), z(v[2]), w(v[3]) {}
-
719
+
719
721 vec4( float v0, float v1, float v2, float v3 ) : x(v0), y(v1), z(v2), w(v3) {}
-
722
+
722
724 float operator*(const vec4& a) const;
726 vec4 operator+(const vec4& a) const;
728 vec4& operator+=(const vec4& a);
@@ -846,8 +859,8 @@
742 bool operator==(const vec4& a) const;
744 bool operator!=(const vec4& a) const;
746 vec4 operator-() const;
-
747
-
+
747
+
749 friend std::ostream &operator<<(std::ostream &os, const helios::vec4 &vec) {
750 return os << "helios::vec4<" << vec.x << ", " << vec.y << ", " << vec.z << ", " << vec.w << ">";
751 }
@@ -855,17 +868,17 @@
752
753};
-
754
+
754
756vec4 operator*( float a, const vec4& v);
758vec4 operator+( float a, const vec4& v);
760vec4 operator-( float a, const vec4& v);
-
761
+
761
763 inline vec4 make_vec4( float x, float y, float z, float w ){
764 return {x, y, z, w};
765}
-
766
+
766
768inline vec4 make_vec4( float X[4] ){
769 return {X[0],X[1],X[2],X[3]};
@@ -873,19 +886,19 @@
771
-
772inline float vec4::operator*(const vec4& a) const{
+
772inline float vec4::operator*(const vec4& a) const{
773 return a.x*x+a.y*y+a.z*z+a.w*w;
774}
775
-
776inline vec4 vec4::operator+(const vec4& a) const{
+
776inline vec4 vec4::operator+(const vec4& a) const{
777 return {a.x+x,a.y+y,a.z+z,a.w+w};
778}
779
-
780inline vec4& vec4::operator+=(const vec4& a){
+
780inline vec4& vec4::operator+=(const vec4& a){
781 this->x += a.x;
782 this->y += a.y;
783 this->z += a.z;
@@ -895,7 +908,7 @@
787
-
788inline vec4& vec4::operator-=(const vec4& a){
+
788inline vec4& vec4::operator-=(const vec4& a){
789 this->x -= a.x;
790 this->y -= a.y;
791 this->z -= a.z;
@@ -905,7 +918,7 @@
795
-
796inline vec4 vec4::operator+(const float a) const{
+
796inline vec4 vec4::operator+(const float a) const{
797 return { x+a, y+a, z+a, w+a };
798}
@@ -917,13 +930,13 @@
803
-
804inline vec4 vec4::operator-(const vec4& a) const{
+
804inline vec4 vec4::operator-(const vec4& a) const{
805 return {x-a.x,y-a.y,z-a.z,w-a.w};
806}
807
-
808inline vec4 vec4::operator-(const float a) const{
+
808inline vec4 vec4::operator-(const float a) const{
809 return { x-a, y-a, z-a, w-a };
810}
@@ -935,7 +948,7 @@
815
-
816inline vec4 vec4::operator*(const float a) const{
+
816inline vec4 vec4::operator*(const float a) const{
817 return {x*a,y*a,z*a,w*a};
818}
@@ -947,44 +960,44 @@
823
-
824inline vec4 vec4::operator/(const float a) const{
+
824inline vec4 vec4::operator/(const float a) const{
825 return {x/a,y/a,z/a,w/a};
826}
827
-
828inline bool vec4::operator==(const vec4& a) const{
+
828inline bool vec4::operator==(const vec4& a) const{
829 return x == a.x && y == a.y && z == a.z && w == a.w;
830}
831
-
832inline bool vec4::operator!=(const vec4& a) const{
+
832inline bool vec4::operator!=(const vec4& a) const{
833 return x != a.x || y != a.y || z != a.z || w != a.w;
834}
835
-
836inline vec4 vec4::operator-() const{
+
836inline vec4 vec4::operator-() const{
837 return {-x,-y,-z, -w};
838}
-
839
-
841
+
839
+
841
-
844struct RGBcolor{
+
844struct RGBcolor{
845public:
-
846
-
848
+
846
+
848
849 float r;
-
851
+
851
852 float g;
-
854
+
854
855 float b;
-
856
+
856
858 RGBcolor() : r(0), g(0), b(0) {}
-
859
-
861
+
859
+
861
867 RGBcolor( float r, float g, float b ){
868 this->r=clamp(r);
@@ -992,7 +1005,8 @@
870 this->b=clamp(b);
871 }
-
873
+
872
+
873
877 explicit RGBcolor( const float C[3] ){
878 r=clamp(C[0]);
@@ -1000,7 +1014,8 @@
880 b=clamp(C[2]);
881 }
-
883
+
882
+
883
887 explicit RGBcolor( const std::vector<float> &C ){
888 if( C.size()!=3 ){
@@ -1011,7 +1026,8 @@
893 b=clamp(C[2]);
894 }
-
896
+
895
+
896
900 explicit RGBcolor(const vec3 &C ){
901 r=clamp(C.x);
@@ -1019,8 +1035,8 @@
903 b=clamp(C.z);
904 }
-
905
-
907
+
905
+
907
910 void scale( float scale_factor ){
911 if(scale_factor < 0 ){
@@ -1031,19 +1047,19 @@
916 b*=scale_factor;
917 }
-
918
-
+
918
+
920 friend std::ostream &operator<<(std::ostream &os, const helios::RGBcolor &c) {
921 return os << "helios::RGBcolor<" << c.r << ", " << c.g << ", " << c.b << ">";
922 }
-
923
+
923
925 bool operator==( const RGBcolor &c ) const;
927 bool operator!=( const RGBcolor &c ) const;
928
929private:
-
931
-
935 static float clamp( float value ){
+
931
+
935 static float clamp( float value ){
936 if( value<0.f ){
937 return 0.f;
938 }else if( value>1.f ){
@@ -1055,31 +1071,31 @@
944
945};
-
946
-
948
+
946
+
948
954inline RGBcolor make_RGBcolor( float r, float g, float b ){
955 return {r,g,b};
956}
-
957
-
959
+
957
+
959
964RGBcolor blend(const RGBcolor &color0_RGB, const RGBcolor &color1_RGB, float weight_RGB );
965
-
966inline bool RGBcolor::operator==( const RGBcolor &c ) const{
+
966inline bool RGBcolor::operator==( const RGBcolor &c ) const{
967 return c.r==r && c.g==g && c.b==b;
968}
969
-
970inline bool RGBcolor::operator!=( const RGBcolor &c ) const{
+
970inline bool RGBcolor::operator!=( const RGBcolor &c ) const{
971 return c.r!=r || c.g!=g || c.b!=b;
972}
-
973
+
973
975namespace RGB{
-
976
+
976
978 extern RGBcolor red;
980 extern RGBcolor blue;
982 extern RGBcolor green;
@@ -1102,24 +1118,24 @@
1016 extern RGBcolor goldenrod;
1017
1018}
-
1019
-
1021
+
1019
+
1021
- +
1025public:
-
1026
-
1028
+
1026
+
1028
1029 float r;
-
1031
+
1031
1032 float g;
-
1034
+
1034
1035 float b;
-
1037
+
1037
1038 float a;
-
1039
+
1039
1041 RGBAcolor() : r(0), g(0), b(0), a(1) {}
-
1042
-
1044
+
1042
+
1044
1051 RGBAcolor( float r, float g, float b, float a ){
1052 this->r=clamp(r);
@@ -1128,7 +1144,8 @@
1055 this->a=clamp(a);
1056 }
-
1058
+
1057
+
1058
1062 explicit RGBAcolor( const float C[4] ){
1063 r=clamp(C[0]);
@@ -1137,7 +1154,8 @@
1066 a=clamp(C[3]);
1067 }
-
1069
+
1068
+
1069
1073 explicit RGBAcolor( const std::vector<float> &C ){
1074 if( C.size()!=4 ){
@@ -1149,8 +1167,8 @@
1080 a=clamp(C[3]);
1081 }
-
1082
-
1084
+
1082
+
1084
1087 void scale( float scale_factor ){
1088 if(scale_factor < 0 ){
@@ -1162,19 +1180,19 @@
1094 a*=scale_factor;
1095 }
-
1096
-
+
1096
+
1098 friend std::ostream &operator<<(std::ostream &os, const helios::RGBAcolor &c) {
1099 return os << "helios::RGBAcolor<" << c.r << ", " << c.g << ", " << c.b << ", " << c.a << ">";
1100 }
-
1101
+
1101
1103 bool operator==( const helios::RGBAcolor &c ) const;
1105 bool operator!=( const helios::RGBAcolor &c ) const;
1106
1107private:
-
1109
-
1113 static float clamp( float value ){
+
1109
+
1113 static float clamp( float value ){
1114 if( value<0.f ){
1115 return 0.f;
1116 }else if( value>1.f ){
@@ -1186,45 +1204,45 @@
1122
1123};
-
1124
-
1126
+
1124
+
1126
1133inline RGBAcolor make_RGBAcolor( float r, float g, float b, float a ){
1134 return {r,g,b,a};
1135}
-
1136
-
1138
+
1136
+
1138
1143inline RGBAcolor make_RGBAcolor( RGBcolor color, float a ){
1144 return {color.r,color.g,color.b,a};
1145}
-
1146
-
1148
+
1146
+
1148
1153RGBAcolor blend(const helios::RGBAcolor &color0_RGBA, const helios::RGBAcolor &color1_RGBA, float weight_RGBA );
1154
-
1155inline bool RGBAcolor::operator==( const RGBAcolor &c ) const{
+
1155inline bool RGBAcolor::operator==( const RGBAcolor &c ) const{
1156 return c.r==r && c.g==g && c.b==b && c.a==a;
1157}
1158
-
1159inline bool RGBAcolor::operator!=( const RGBAcolor &c ) const{
+
1159inline bool RGBAcolor::operator!=( const RGBAcolor &c ) const{
1160 return c.r!=r || c.g!=g || c.b!=b || c.a!=a;
1161}
-
1162
-
1164
+
1162
+
1164
-
1168struct Date{
+
1168struct Date{
1169public:
-
1170
+
1170
1172 int day;
1176 int year;
-
1177
+
1177
1180 day = 1;
@@ -1232,8 +1250,8 @@
1182 year = 2000;
1183 }
-
1184
-
1186
+
1184
+
1186
1191 Date(int day, int month, int year ){
1192
@@ -1251,19 +1269,19 @@
1204
1205 }
-
1206
-
1208
+
1206
+
1208
1211 [[nodiscard]] int JulianDay() const;
-
1212
+
1212
1214 void incrementDay();
-
1215
-
1217
+
1215
+
1217
1220 [[nodiscard]] bool isLeapYear() const;
-
1221
+
1221
1223 bool operator==( const helios::Date &c ) const;
1225 bool operator!=( const helios::Date &c ) const;
-
1226
-
+
1226
+
1228 friend std::ostream &operator<<(std::ostream &os, helios::Date const &d) {
1229 return os << d.year << "-" << std::setfill('0') << std::setw(2) << d.month << "-" << std::setfill('0') << std::setw(2) << d.day;
1230 }
@@ -1271,8 +1289,8 @@
1231
1232};
-
1233
-
1235
+
1233
+
1235
1241inline Date make_Date( int day, int month, int year ){
1242 if( day<1 || day>31 ){
@@ -1289,20 +1307,20 @@
1253
-
1254inline bool Date::operator==( const Date &c ) const{
+
1254inline bool Date::operator==( const Date &c ) const{
1255 return c.day==day && c.month==month && c.year==year;
1256}
1257
-
1258inline bool Date::operator!=( const Date &c ) const{
+
1258inline bool Date::operator!=( const Date &c ) const{
1259 return c.day!=day || c.month!=month || c.year!=year;
1260}
-
1261
-
1263
+
1261
+
1263
-
1268inline Date Julian2Calendar( int JulianDay, int year ){
+
1268inline Date Julian2Calendar( int JulianDay, int year ){
1269
1270 int day, month;
1271
@@ -1310,7 +1328,7 @@
1273 int skips_nonleap[] = {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
1274 int* skips;
1275
-
1276 if( JulianDay<1 || JulianDay>366 ){
+
1277 throw(std::runtime_error("ERROR (Julian2Calendar): Julian day of " + std::to_string(JulianDay) + " is out of range (should be >0 and <367)."));
1278 }
1279
@@ -1339,8 +1357,8 @@
1302
1303}
-
1304
-
1306
+
1304
+
1306
1310inline int Calendar2Julian( Date date ){
1311
@@ -1361,11 +1379,11 @@
1326
1327}
-
1328
-
1330
+
1328
+
1330
-
1335inline Date make_Date( int JulianDay, int year ){
-
1336 if( JulianDay<1 || JulianDay>366 ){
+
1335inline Date make_Date( int JulianDay, int year ){
+
1337 throw(std::runtime_error("ERROR (make_Date): Julian day is out of range (Julian day of " + std::to_string(JulianDay) + " was given)."));
1338 }else if( year<1000 ){
1339 throw(std::runtime_error("ERROR (make_Date): Year should be specified in YYYY format."));
@@ -1376,15 +1394,15 @@
1344}
1345
-
1346
-
1348
+
1346
+
1348
-
1352struct Time{
-
1353
+
1352struct Time{
+
1353
1359 int hour;
-
1360
+
1360
1363 second = 0;
@@ -1392,8 +1410,8 @@
1365 hour = 0;
1366 }
-
1367
-
1369
+
1367
+
1369
1373 Time( int hour, int minute ){
1374
@@ -1409,8 +1427,8 @@
1384
1385 }
-
1386
-
1388
+
1386
+
1388
1393 Time( int hour, int minute, int second ){
1394
@@ -1428,11 +1446,11 @@
1406
1407 }
-
1408
+
1408
1410 bool operator==( const helios::Time &c ) const;
1412 bool operator!=( const helios::Time &c ) const;
-
1413
-
+
1413
+
1415 friend std::ostream &operator<<(std::ostream &os, helios::Time const &t) {
1416 return os << t.hour << ":" << std::setfill('0') << std::setw(2) << t.minute << ":" << std::setfill('0') << std::setw(2) << t.second;
1417 }
@@ -1440,8 +1458,8 @@
1418
1419};
-
1420
-
1422
+
1420
+
1422
1427inline Time make_Time( int hour, int minute ){
1428 if( minute<0 || minute>59 ){
@@ -1454,8 +1472,8 @@
1435
1436}
-
1437
-
1439
+
1437
+
1439
1445inline Time make_Time( int hour, int minute, int second ){
1446 if( second<0 || second>59 ){
@@ -1472,25 +1490,25 @@
1457
-
1458inline bool Time::operator==( const Time &c ) const{
+
1458inline bool Time::operator==( const Time &c ) const{
1459 return c.hour==hour && c.minute==minute && c.second==second;
1460}
1461
-
1462inline bool Time::operator!=( const Time &c ) const{
+
1462inline bool Time::operator!=( const Time &c ) const{
1463 return c.hour!=hour || c.minute!=minute || c.second!=second;
1464}
-
1465
-
1467
+
1465
+
1467
-
1470 struct Location{
-
1471
+
1470 struct Location{
+
1471
-
1478
+
1478
1481 latitude_deg = 38.55f;
@@ -1498,8 +1516,8 @@
1483 UTC_offset = 8;
1484 }
-
1485
-
1487
+
1485
+
1487
1492
@@ -1509,11 +1527,11 @@
1496
1497 }
-
1498
+
1498
1500 bool operator==( const helios::Location &c ) const;
1502 bool operator!=( const helios::Location &c ) const;
-
1503
-
+
1503
+
1505 friend std::ostream &operator<<(std::ostream &os, helios::Location const &t) {
1506 return os << "<" << t.latitude_deg << "," << t.longitude_deg << "," << t.UTC_offset << ">";
1507 }
@@ -1521,8 +1539,8 @@
1508
1509 };
-
1510
-
1512
+
1510
+
1512
1518 inline Location make_Location( float latitude_deg, float longitude_deg, float UTC_offset ){
1519 return {latitude_deg,longitude_deg,UTC_offset};
@@ -1530,27 +1548,27 @@
1521
-
1522 inline bool Location::operator==( const Location &c ) const{
+
1522 inline bool Location::operator==( const Location &c ) const{
1524 }
1525
-
1526 inline bool Location::operator!=( const Location &c ) const{
+
1526 inline bool Location::operator!=( const Location &c ) const{
1528 }
-
1529
-
1531
+
1529
+
1531
- +
1535private:
1536
1537 float elevation_private;
1538 float zenith_private;
1539
1540public:
-
1541
+
1541
1543 float radius;
1545 /*
1546 * \note Elevation angle is read-only, since it is linked to the zenith angle.
@@ -1561,21 +1579,22 @@
1552 */
1553 const float &zenith;
1555 float azimuth;
-
1556
-
1558
+
1556
+
1558
1559 SphericalCoord() : elevation_private(0.5f*float(M_PI)), zenith_private(0.f), elevation(elevation_private), zenith(zenith_private) {
1560 radius=1;
1561 azimuth=0;
1562 }
-
1564
+
1563
+
1564
1569 SphericalCoord(float radius, float elevation_radians, float azimuth_radians ) : elevation_private(elevation_radians), zenith_private(0.5f * float(M_PI) - elevation_radians), radius(radius), elevation(elevation_private), zenith(zenith_private), azimuth(azimuth_radians) {}
-
1570
-
1572 SphericalCoord( const SphericalCoord &c ) : elevation_private(c.elevation_private), zenith_private(c.zenith_private), radius(c.radius), elevation(c.elevation_private), zenith(c.zenith_private), azimuth(c.azimuth) {}
-
1573
+
1570
+
1572 SphericalCoord( const SphericalCoord &c ) : elevation_private(c.elevation_private), zenith_private(c.zenith_private), radius(c.radius), elevation(c.elevation_private), zenith(c.zenith_private), azimuth(c.azimuth) {}
+
1573
- +
1576 if( this != &c ){
1577 elevation_private = c.elevation_private;
1578 zenith_private = c.zenith_private;
@@ -1585,11 +1604,11 @@
1582 return *this;
1583 }
-
1584
+
1584
1586 bool operator==( const helios::SphericalCoord &c ) const;
1588 bool operator!=( const helios::SphericalCoord &c ) const;
-
1589
-
+
1589
+
1591 friend std::ostream &operator<<(std::ostream &os, helios::SphericalCoord const &coord) {
1592 return os << "helios::SphericalCoord<" << coord.radius << ", " << coord.elevation << ", " << coord.azimuth << ">";
1593 }
@@ -1597,15 +1616,15 @@
1594
1595};
-
1596
-
1598
+
1596
+
1598
1602inline SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians ){
1603 return {1, elevation_radians, azimuth_radians};
1604}
-
1605
-
1607
+
1605
+
1607
1612 inline SphericalCoord make_SphericalCoord(float radius, float elevation_radians, float azimuth_radians ){
1613 return {radius, elevation_radians, azimuth_radians};
@@ -1613,13 +1632,13 @@
1615
-
1616inline bool SphericalCoord::operator==( const SphericalCoord &c ) const{
+
1616inline bool SphericalCoord::operator==( const SphericalCoord &c ) const{
1617 return c.radius==radius && c.zenith==zenith && c.elevation==elevation && c.azimuth==azimuth;
1618}
1619
-
1620inline bool SphericalCoord::operator!=( const SphericalCoord &c ) const {
+
1620inline bool SphericalCoord::operator!=( const SphericalCoord &c ) const {
1621 return c.radius!=radius || c.zenith!=zenith || c.elevation!=elevation || c.azimuth!=azimuth;
1622}
@@ -1629,6 +1648,7 @@
1626
1627#endif
int JulianDay(int day, int month, int year)
Convert calendar day (day,month,year) to Julian day.
Definition global.cpp:1350
+
anytype clamp(anytype value, anytype min, anytype max)
Clamp value to be within some specified bounds.
Definition global.cpp:1055
int2 make_int2(int x, int y)
Make an int2 vector from two ints.
Time make_Time(int hour, int minute)
Make a Time vector.
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
@@ -1716,7 +1736,7 @@
bool operator==(const helios::Time &c) const
check for equality of two times
Time(int hour, int minute, int second)
minute/hour constructor
bool operator!=(const helios::Time &c) const
check for inequality of two times
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int2 operator+(const int2 &a) const
Add two int2 vectors.
int y
Second element in vector.
int2 operator-() const
Multiply each element by -1.
@@ -1730,7 +1750,7 @@
int x
First element in vector.
int2()
Default constructor.
int2(const int v[2])
Construct int2 from an array of ints.
-
Vector of three elements of type 'int'.
+
Vector of three elements of type 'int'.
int3()
Default constructor.
int x
First element in vector.
int3(int v0, int v1, int v2)
Construct int3 from three ints.
@@ -1745,7 +1765,7 @@
int z
Third element in vector.
int3 operator-() const
Multiply each element by -1.
int y
Second element in vector.
-
Vector of four elements of type 'int'.
+
Vector of four elements of type 'int'.
int4(const std::vector< int > &v)
Construct int3 from a vector of ints.
int x
First element in vector.
int4 & operator-=(const int4 &a)
Decrement int4 vector.
@@ -1761,7 +1781,7 @@
int4(const int v[3])
Construct int4 from an array of ints.
int y
Second element in vector.
bool operator!=(const int4 &a) const
Inequality for all elements.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
vec2 & operator+=(const vec2 &a)
Increment vec2 vector.
vec2 normalize()
Normalize vector components such that the magnitude is unity.
bool operator!=(const vec2 &a) const
check for inequality of two vec2 vectors
@@ -1779,7 +1799,7 @@
vec2 operator-() const
Multiply each element by -1.
vec2(float v0, float v1)
Initialize vec2 using two floats.
float operator*(const vec2 &a) const
Dot (scalar) product of two vec2 vectors.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
bool operator==(const vec3 &a) const
check for equality of two vec3 vectors
vec3 operator/(float a) const
Divide each element by scalar (scalar is divided on right: vec3/a)
vec3 operator+(const vec3 &a) const
Sum of two vec3 vectors.
@@ -1798,7 +1818,7 @@
bool operator!=(const vec3 &a) const
check for inequality of two vec3 vectors
float magnitude() const
Compute the vector magnitude.
float operator*(const vec3 &a) const
Dot (scalar) product of two vec3 vectors.
-
Vector of four elements of type 'float'.
+
Vector of four elements of type 'float'.
vec4 operator+(const vec4 &a) const
Sum of two vec4 vectors.
vec4(const std::vector< float > &v)
Initialize vec4 using a vector of floats.
friend std::ostream & operator<<(std::ostream &os, const helios::vec4 &vec)
Write vec4 to output stream.
@@ -1819,10 +1839,13 @@
float operator*(const vec4 &a) const
Dot (scalar) product of two vec4 vectors.
vec4(float v0, float v1, float v2, float v3)
Initialize vec4 using four floats.
- -
+ + diff --git a/doc/html/hierarchy.html b/doc/html/hierarchy.html index be32c13f3..452466119 100644 --- a/doc/html/hierarchy.html +++ b/doc/html/hierarchy.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
- -
+ + diff --git a/doc/html/hierarchy.js b/doc/html/hierarchy.js new file mode 100644 index 000000000..f92919eac --- /dev/null +++ b/doc/html/hierarchy.js @@ -0,0 +1,105 @@ +var hierarchy = +[ + [ "AerialHitPoint", "struct_aerial_hit_point.html", null ], + [ "AerialLiDARcloud", "class_aerial_li_d_a_rcloud.html", null ], + [ "AerialScanMetadata", "struct_aerial_scan_metadata.html", null ], + [ "AxisRotation", "struct_axis_rotation.html", null ], + [ "BaseCanopyParameters", "struct_base_canopy_parameters.html", [ + [ "BaseGrapeVineParameters", "struct_base_grape_vine_parameters.html", [ + [ "GobletGrapevineParameters", "struct_goblet_grapevine_parameters.html", null ], + [ "SplitGrapevineParameters", "struct_split_grapevine_parameters.html", null ], + [ "UnilateralGrapevineParameters", "struct_unilateral_grapevine_parameters.html", null ], + [ "VSPGrapevineParameters", "struct_v_s_p_grapevine_parameters.html", null ] + ] ], + [ "BeanParameters", "struct_bean_parameters.html", null ], + [ "ConicalCrownsCanopyParameters", "struct_conical_crowns_canopy_parameters.html", null ], + [ "HomogeneousCanopyParameters", "struct_homogeneous_canopy_parameters.html", null ], + [ "SorghumCanopyParameters", "struct_sorghum_canopy_parameters.html", null ], + [ "SphericalCrownsCanopyParameters", "struct_spherical_crowns_canopy_parameters.html", null ], + [ "StrawberryParameters", "struct_strawberry_parameters.html", null ], + [ "TomatoParameters", "struct_tomato_parameters.html", null ], + [ "WalnutCanopyParameters", "struct_walnut_canopy_parameters.html", null ], + [ "WhiteSpruceCanopyParameters", "struct_white_spruce_canopy_parameters.html", null ] + ] ], + [ "BBcoefficients", "struct_b_bcoefficients.html", null ], + [ "BBLcoefficients", "struct_b_b_lcoefficients.html", null ], + [ "BLConductanceModel", "class_b_l_conductance_model.html", null ], + [ "BMFcoefficients", "struct_b_m_fcoefficients.html", null ], + [ "BWBcoefficients", "struct_b_w_bcoefficients.html", null ], + [ "CameraCalibration", "struct_camera_calibration.html", null ], + [ "CameraProperties", "struct_camera_properties.html", null ], + [ "CanopyGenerator", "class_canopy_generator.html", null ], + [ "Colormap", "struct_colormap.html", null ], + [ "helios::CompoundObject", "classhelios_1_1_compound_object.html", [ + [ "helios::Box", "classhelios_1_1_box.html", null ], + [ "helios::Cone", "classhelios_1_1_cone.html", null ], + [ "helios::Disk", "classhelios_1_1_disk.html", null ], + [ "helios::Polymesh", "classhelios_1_1_polymesh.html", null ], + [ "helios::Sphere", "classhelios_1_1_sphere.html", null ], + [ "helios::Tile", "classhelios_1_1_tile.html", null ], + [ "helios::Tube", "classhelios_1_1_tube.html", null ] + ] ], + [ "helios::Context", "classhelios_1_1_context.html", null ], + [ "helios::Date", "structhelios_1_1_date.html", null ], + [ "DummyModel", "class_dummy_model.html", null ], + [ "Dupex", "struct_dupex.html", null ], + [ "EmpiricalModelCoefficients", "struct_empirical_model_coefficients.html", null ], + [ "EnergyBalanceModel", "class_energy_balance_model.html", null ], + [ "FarquharModelCoefficients", "struct_farquhar_model_coefficients.html", null ], + [ "FloralBud", "struct_floral_bud.html", null ], + [ "helios::GlobalData", "structhelios_1_1_global_data.html", null ], + [ "Glyph", "class_glyph.html", null ], + [ "CameraCalibration::GradientDescentParameters", "struct_camera_calibration_1_1_gradient_descent_parameters.html", null ], + [ "GridCell", "struct_grid_cell.html", null ], + [ "HitPoint", "struct_hit_point.html", null ], + [ "HitTable< datatype >", "class_hit_table.html", null ], + [ "helios::int2", "structhelios_1_1int2.html", null ], + [ "helios::int3", "structhelios_1_1int3.html", null ], + [ "helios::int4", "structhelios_1_1int4.html", null ], + [ "jpg_error_mgr", "structjpg__error__mgr.html", null ], + [ "LeafOptics", "class_leaf_optics.html", null ], + [ "LeafOpticsProperties", "struct_leaf_optics_properties.html", null ], + [ "LeafPrototype", "struct_leaf_prototype.html", null ], + [ "LiDARcloud", "class_li_d_a_rcloud.html", null ], + [ "helios::Location", "structhelios_1_1_location.html", null ], + [ "MOPTcoefficients", "struct_m_o_p_tcoefficients.html", null ], + [ "my_error_mgr", "structmy__error__mgr.html", null ], + [ "PerRayData", "struct_per_ray_data.html", null ], + [ "PhotosynthesisModel", "class_photosynthesis_model.html", null ], + [ "PhotosyntheticTemperatureResponseParameters", "struct_photosynthetic_temperature_response_parameters.html", null ], + [ "Phytomer", "struct_phytomer.html", null ], + [ "PhytomerParameters", "struct_phytomer_parameters.html", null ], + [ "PlantArchitecture", "class_plant_architecture.html", null ], + [ "PlantInstance", "struct_plant_instance.html", null ], + [ "RadiationBand", "struct_radiation_band.html", null ], + [ "RadiationCamera", "struct_radiation_camera.html", null ], + [ "RadiationModel", "class_radiation_model.html", null ], + [ "RadiationSource", "struct_radiation_source.html", null ], + [ "RandomParameter_float", "struct_random_parameter__float.html", null ], + [ "RandomParameter_int", "struct_random_parameter__int.html", null ], + [ "helios::RGBAcolor", "structhelios_1_1_r_g_b_acolor.html", null ], + [ "helios::RGBcolor", "structhelios_1_1_r_g_bcolor.html", null ], + [ "ScanMetadata", "struct_scan_metadata.html", null ], + [ "Shader", "struct_shader.html", null ], + [ "Shoot", "struct_shoot.html", null ], + [ "ShootParameters", "struct_shoot_parameters.html", null ], + [ "Shx", "struct_shx.html", null ], + [ "SolarPosition", "class_solar_position.html", null ], + [ "helios::SphericalCoord", "structhelios_1_1_spherical_coord.html", null ], + [ "StomatalConductanceModel", "class_stomatal_conductance_model.html", null ], + [ "SyntheticAnnotation", "class_synthetic_annotation.html", null ], + [ "helios::Texture", "classhelios_1_1_texture.html", null ], + [ "helios::Time", "structhelios_1_1_time.html", null ], + [ "helios::Timer", "structhelios_1_1_timer.html", null ], + [ "Triad", "struct_triad.html", null ], + [ "Triangulation", "struct_triangulation.html", null ], + [ "helios::vec2", "structhelios_1_1vec2.html", null ], + [ "helios::vec3", "structhelios_1_1vec3.html", null ], + [ "helios::vec4", "structhelios_1_1vec4.html", null ], + [ "VegetativeBud", "struct_vegetative_bud.html", null ], + [ "Visualizer", "class_visualizer.html", null ], + [ "VoxelIntersection", "class_voxel_intersection.html", null ], + [ "WeberPennTree", "class_weber_penn_tree.html", null ], + [ "WeberPennTreeParameters", "struct_weber_penn_tree_parameters.html", null ], + [ "helios::XMLparser", "classhelios_1_1_x_m_lparser.html", null ] +]; \ No newline at end of file diff --git a/doc/html/index.html b/doc/html/index.html index 91b01e0ee..3b4a007ef 100644 --- a/doc/html/index.html +++ b/doc/html/index.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
-
Helios Documentation v1.3.26
+
Helios Documentation


@@ -127,17 +137,10 @@

Downloading the Code



-
+
-


-
-

-

Financial support provided by:

-
- -
-


+



Acknowledgement of third-party software:

@@ -149,10 +152,12 @@

Downloading the Code

- -
+ + diff --git a/doc/html/lidar_2include_2random_8h_source.html b/doc/html/lidar_2include_2random_8h_source.html index 13e6d7440..7d02cdde3 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
random.h
@@ -159,10 +165,13 @@
53 return ((float) lcg(prev) / (float) 0x01000000);
54}
- -
+ + diff --git a/doc/html/lidar_2src_2file_i_o_8cpp.html b/doc/html/lidar_2src_2file_i_o_8cpp.html index 851721a53..c8d3362ef 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
fileIO.cpp File Reference
@@ -116,10 +122,13 @@

Definition in file fileIO.cpp.

- -
+ + 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 f94964c16..523a8a514 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
fileIO.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "LiDAR.h"
17#include "pugixml.hpp"
18
@@ -494,9 +501,9 @@
398 throw( std::runtime_error("ERROR (LiDARcloud::loadASCIIFile): ASCII data file '" + scandata.data_file + "' does not exist.") );
399 }
400
-
401 vec3 temp_xyz;
+
401 vec3 temp_xyz;
402 float temp_zenith, temp_azimuth;
-
403 RGBcolor temp_rgb;
+
403 RGBcolor temp_rgb;
404 float temp_row, temp_column;
405 double temp_data;
406 std::map<std::string, double> data;
@@ -573,7 +580,7 @@
477 }
478
479 //direction
-
480 SphericalCoord temp_direction(1.f, 0.5f*M_PI-temp_zenith, temp_azimuth);
+
480 SphericalCoord temp_direction(1.f, 0.5f*M_PI-temp_zenith, temp_azimuth);
481 if( temp_direction.elevation==-9999 || temp_direction.azimuth==-9999 ){
482 temp_direction = cart2sphere( temp_xyz - scandata.origin );
483 }
@@ -718,329 +725,403 @@
613 for( int i=0; i<getGridCellCount(); i++ ){
614 inclinations.at(i).resize( Nbins );
615 }
-
616
-
617 float db = 0.5f*M_PI/float(Nbins); //bin width
-
618
-
619 for( std::size_t t=0; t<triangles.size(); t++ ){
-
620
-
621 Triangulation tri = triangles.at(t);
-
622
-
623 int cell = tri.gridcell;
-
624
-
625 if( cell<0 ){
-
626 continue;
-
627 }
-
628
-
629 vec3 v0 = tri.vertex0;
-
630 vec3 v1 = tri.vertex1;
-
631 vec3 v2 = tri.vertex2;
-
632
-
633 vec3 normal = cross( v1-v0, v2-v0 );
-
634 normal.normalize();
-
635
-
636 float angle = acos_safe(fabs(normal.z));
-
637
-
638 float area = tri.area;
-
639
-
640 uint bin = floor(angle/db);
-
641 if( bin>=Nbins ){
-
642 bin = Nbins-1;
-
643 }
-
644
-
645 inclinations.at(cell).at(bin) += area;
-
646
-
647 }
-
648
-
649 ofstream file;
-
650
-
651 file.open(filename);
-
652
-
653 if( !file.is_open() ){
-
654 throw( std::runtime_error("ERROR (LiDARcloud::exportTriangleInclinationDistribution): Could not open file '" + std::string(filename) + "' for writing.") );
-
655 }
-
656
-
657 for( int cell=0; cell<getGridCellCount(); cell++ ){
-
658 for( int bin=0; bin<Nbins; bin++ ) {
-
659 file << inclinations.at(cell).at(bin) << " ";
-
660 }
-
661 file << std::endl;
-
662 }
-
663
-
664 file.close();
-
665
-
666}
+
616 std::vector<float> cell_area(inclinations.size(),0);
+
617
+
618 float db = 0.5f*M_PI/float(Nbins); //bin width
+
619
+
620 for( std::size_t t=0; t<triangles.size(); t++ ){
+
621
+
622 Triangulation tri = triangles.at(t);
+
623
+
624 int cell = tri.gridcell;
+
625
+
626 if( cell<0 ){
+
627 continue;
+
628 }
+
629
+
630 vec3 v0 = tri.vertex0;
+
631 vec3 v1 = tri.vertex1;
+
632 vec3 v2 = tri.vertex2;
+
633
+
634 vec3 normal = cross( v1-v0, v2-v0 );
+
635 normal.normalize();
+
636
+
637 float angle = acos_safe(fabs(normal.z));
+
638
+
639 float area = tri.area;
+
640
+
641 uint bin = floor(angle/db);
+
642 if( bin>=Nbins ){
+
643 bin = Nbins-1;
+
644 }
+
645
+
646 inclinations.at(cell).at(bin) += area;
+
647
+
648 cell_area.at(cell) += area;
+
649
+
650 }
+
651
+
652 ofstream file;
+
653
+
654 file.open(filename);
+
655
+
656 if( !file.is_open() ){
+
657 throw( std::runtime_error("ERROR (LiDARcloud::exportTriangleInclinationDistribution): Could not open file '" + std::string(filename) + "' for writing.") );
+
658 }
+
659
+
660 for( int cell=0; cell<getGridCellCount(); cell++ ){
+
661 for( int bin=0; bin<Nbins; bin++ ) {
+
662 file << inclinations.at(cell).at(bin)/cell_area.at(cell) << " ";
+
663 }
+
664 file << std::endl;
+
665 }
+
666
+
667 file.close();
+
668
+
669}
-
667
-
-
668void LiDARcloud::exportLeafAreas( const char* filename ){
-
669
-
670 ofstream file;
-
671
-
672 file.open(filename);
-
673
-
674 if( !file.is_open() ) {
-
675 throw (std::runtime_error("ERROR (LiDARcloud::exportLeafAreas): Could not open file '" + std::string(filename) + "' for writing."));
+
670
+
+
671void LiDARcloud::exportTriangleAzimuthDistribution( const char* filename, uint Nbins ){
+
672
+
673 std::vector<std::vector<float>> azimuths( getGridCellCount() );
+
674 for( int i=0; i<getGridCellCount(); i++ ){
+
675 azimuths.at(i).resize( Nbins );
676 }
-
677
-
678 for( uint i=0; i<getGridCellCount(); i++ ){
-
679
-
680 file << getCellLeafArea(i) << std::endl;
-
681
-
682 }
-
683
-
684 file.close();
-
685
-
686}
-
-
687
-
-
688void LiDARcloud::exportLeafAreaDensities( const char* filename ){
-
689
-
690 ofstream file;
-
691
-
692 file.open(filename);
-
693
-
694 if( !file.is_open() ) {
-
695 throw (std::runtime_error("ERROR (LiDARcloud::exportLeafAreaDensities): Could not open file '" + std::string(filename) + "' for writing."));
-
696 }
-
697
-
698 for( uint i=0; i<getGridCellCount(); i++ ){
-
699
-
700 file << getCellLeafAreaDensity(i) << std::endl;
-
701
-
702 }
-
703
-
704 file.close();
-
705
-
706}
-
+
677 std::vector<float> cell_area(azimuths.size(),0);
+
678
+
679 float db = 2*M_PI/float(Nbins); //bin width
+
680
+
681 for( std::size_t t=0; t<triangles.size(); t++ ){
+
682
+
683 Triangulation tri = triangles.at(t);
+
684
+
685 int cell = tri.gridcell;
+
686
+
687 if( cell<0 ){
+
688 continue;
+
689 }
+
690
+
691 vec3 v0 = tri.vertex0;
+
692 vec3 v1 = tri.vertex1;
+
693 vec3 v2 = tri.vertex2;
+
694
+
695 vec3 normal = cross( v1-v0, v2-v0 );
+
696 normal.normalize();
+
697 SphericalCoord n_sph= cart2sphere(normal);
+
698
+
699 float azimuth= n_sph.azimuth;
+
700
+
701 if (normal.z<0){
+
702 azimuth=azimuth+M_PI;
+
703 if (azimuth >M_PI*2){
+
704 azimuth=azimuth-M_PI*2;
+
705 }
+
706 }
707
-
-
708void LiDARcloud::exportGtheta( const char* filename ){
-
709
-
710 ofstream file;
-
711
-
712 file.open(filename);
-
713
-
714 if( !file.is_open() ) {
-
715 throw (std::runtime_error("ERROR (LiDARcloud::exportGtheta): Could not open file '" + std::string(filename) + "' for writing."));
-
716 }
-
717
-
718 for( uint i=0; i<getGridCellCount(); i++ ){
-
719
-
720 file << getCellGtheta(i) << std::endl;
-
721
-
722 }
-
723
-
724 file.close();
-
725
-
726}
-
-
727
-
-
728void LiDARcloud::exportPointCloud( const char* filename ){
-
729
-
730 if(getScanCount() ==1 ){
-
731 exportPointCloud( filename, 0 );
-
732 }else{
-
733
-
734 for( int i=0; i< getScanCount(); i++ ){
+
708
+
709 float area = tri.area;
+
710
+
711 uint bin = floor(azimuth/db);
+
712 if( bin>=Nbins ){
+
713 bin = Nbins-1;
+
714 }
+
715
+
716 azimuths.at(cell).at(bin) += area;
+
717 cell_area.at(cell) += area;
+
718
+
719 }
+
720
+
721 ofstream file;
+
722
+
723 file.open(filename);
+
724
+
725 if( !file.is_open() ){
+
726 throw( std::runtime_error("ERROR (LiDARcloud::exportTriangleAzimuthDistribution): Could not open file '" + std::string(filename) + "' for writing.") );
+
727 }
+
728
+
729 for( int cell=0; cell<getGridCellCount(); cell++ ){
+
730 for( int bin=0; bin<Nbins; bin++ ) {
+
731 file << azimuths.at(cell).at(bin)/cell_area.at(cell) << " ";
+
732 }
+
733 file << std::endl;
+
734 }
735
-
736 std::string filename_a = filename;
-
737 char scan[20];
-
738 sprintf(scan,"%d",i);
+
736 file.close();
+
737
+
738}
+
739
-
740 size_t dotindex = filename_a.find_last_of(".");
-
741 if( dotindex == filename_a.size()-1 || filename_a.size()-1-dotindex>4 ){//no file extension was provided
-
742 filename_a = filename_a + "_" + scan;
-
743 }else{ //has file extension
-
744 std::string ext = filename_a.substr(dotindex,filename_a.size()-1);
-
745 filename_a = filename_a.substr(0,dotindex) + "_" + scan + ext;
-
746 }
-
747
-
748 exportPointCloud( filename_a.c_str(), i );
+
+
740void LiDARcloud::exportLeafAreas( const char* filename ){
+
741
+
742 ofstream file;
+
743
+
744 file.open(filename);
+
745
+
746 if( !file.is_open() ) {
+
747 throw (std::runtime_error("ERROR (LiDARcloud::exportLeafAreas): Could not open file '" + std::string(filename) + "' for writing."));
+
748 }
749
-
750 }
+
750 for( uint i=0; i<getGridCellCount(); i++ ){
751
-
752 }
-
753}
-
-
754
+
752 file << getCellLeafArea(i) << std::endl;
+
753
+
754 }
755
-
-
756void LiDARcloud::exportPointCloud( const char* filename, uint scanID ){
+
756 file.close();
757
-
758 if( scanID> getScanCount()){
-
759 std::cerr << "ERROR (LiDARcloud::exportPointCloud): Cannot export scan " << scanID << " because this scan does not exist." << std::endl;
-
760 throw 1;
-
761 }
-
762
-
763 ofstream file;
-
764
-
765 file.open(filename);
-
766
-
767 if( !file.is_open() ) {
-
768 throw (std::runtime_error("ERROR (LiDARcloud::exportPointCloud): Could not open file '" + std::string(filename) + "' for writing."));
-
769 }
-
770
-
771 std::vector<std::string> hit_data;
-
772 for( int r=0; r< getHitCount(); r++ ){
-
773 std::map<std::string,double> data = hits.at(r).data;
-
774 for( std::map<std::string,double>::iterator iter=data.begin(); iter!=data.end(); ++iter ){
-
775 std::vector<std::string>::iterator it = find(hit_data.begin(),hit_data.end(),iter->first);
-
776 if( it==hit_data.end() ){
-
777 hit_data.push_back(iter->first);
-
778 }
-
779 }
-
780 }
+
758}
+
+
759
+
+
760void LiDARcloud::exportLeafAreaDensities( const char* filename ){
+
761
+
762 ofstream file;
+
763
+
764 file.open(filename);
+
765
+
766 if( !file.is_open() ) {
+
767 throw (std::runtime_error("ERROR (LiDARcloud::exportLeafAreaDensities): Could not open file '" + std::string(filename) + "' for writing."));
+
768 }
+
769
+
770 for( uint i=0; i<getGridCellCount(); i++ ){
+
771
+
772 file << getCellLeafAreaDensity(i) << std::endl;
+
773
+
774 }
+
775
+
776 file.close();
+
777
+
778}
+
+
779
+
+
780void LiDARcloud::exportGtheta( const char* filename ){
781
-
782 std::vector<std::string> ASCII_format = getScanColumnFormat(scanID);
+
782 ofstream file;
783
-
784 if( ASCII_format.size()==0 ){
-
785 ASCII_format.push_back("x");
-
786 ASCII_format.push_back("y");
-
787 ASCII_format.push_back("z");
+
784 file.open(filename);
+
785
+
786 if( !file.is_open() ) {
+
787 throw (std::runtime_error("ERROR (LiDARcloud::exportGtheta): Could not open file '" + std::string(filename) + "' for writing."));
788 }
789
-
790 for( int r=0; r< getHitCount(); r++ ){
+
790 for( uint i=0; i<getGridCellCount(); i++ ){
791
-
792 if( getHitScanID(r) != scanID ){
-
793 continue;
-
794 }
+
792 file << getCellGtheta(i) << std::endl;
+
793
+
794 }
795
-
796 vec3 xyz = getHitXYZ(r);
-
797 RGBcolor color = getHitColor(r);
-
798
-
799 for( int c=0; c<ASCII_format.size(); c++ ){
-
800
-
801 if( ASCII_format.at(c).compare("x")==0 ){
-
802 file << xyz.x;
-
803 }else if( ASCII_format.at(c).compare("y")==0 ){
-
804 file << xyz.y;
-
805 }else if( ASCII_format.at(c).compare("z")==0 ){
-
806 file << xyz.z;
-
807 }else if( ASCII_format.at(c).compare("r")==0 ){
-
808 file << color.r;
-
809 }else if( ASCII_format.at(c).compare("g")==0 ){
-
810 file << color.g;
-
811 }else if( ASCII_format.at(c).compare("b")==0 ){
-
812 file << color.b;
-
813 }else if( ASCII_format.at(c).compare("r255")==0 ){
-
814 file << round(color.r*255);
-
815 }else if( ASCII_format.at(c).compare("g255")==0 ){
-
816 file << round(color.g*255);
-
817 }else if( ASCII_format.at(c).compare("b255")==0 ){
-
818 file << round(color.b*255);
-
819 }else if( ASCII_format.at(c).compare("zenith")==0 ){
-
820 file << getHitRaydir(r).zenith;
-
821 }else if( ASCII_format.at(c).compare("azimuth")==0 ){
-
822 file << getHitRaydir(r).azimuth;
-
823 }else if( hits.at(r).data.find(ASCII_format.at(c))!=hits.at(r).data.end() ){ //hit scalar data
-
824 file << getHitData(r,ASCII_format.at(c).c_str());
-
825 }else{
-
826 file << -9999;
-
827 }
-
828
-
829 if( c<ASCII_format.size()-1 ){
-
830 file << " ";
-
831 }
-
832
-
833 }
+
796 file.close();
+
797
+
798}
+
+
799
+
+
800void LiDARcloud::exportPointCloud( const char* filename ){
+
801
+
802 if(getScanCount() ==1 ){
+
803 exportPointCloud( filename, 0 );
+
804 }else{
+
805
+
806 for( int i=0; i< getScanCount(); i++ ){
+
807
+
808 std::string filename_a = filename;
+
809 char scan[20];
+
810 sprintf(scan,"%d",i);
+
811
+
812 size_t dotindex = filename_a.find_last_of(".");
+
813 if( dotindex == filename_a.size()-1 || filename_a.size()-1-dotindex>4 ){//no file extension was provided
+
814 filename_a = filename_a + "_" + scan;
+
815 }else{ //has file extension
+
816 std::string ext = filename_a.substr(dotindex,filename_a.size()-1);
+
817 filename_a = filename_a.substr(0,dotindex) + "_" + scan + ext;
+
818 }
+
819
+
820 exportPointCloud( filename_a.c_str(), i );
+
821
+
822 }
+
823
+
824 }
+
825}
+
+
826
+
827
+
+
828void LiDARcloud::exportPointCloud( const char* filename, uint scanID ){
+
829
+
830 if( scanID> getScanCount()){
+
831 std::cerr << "ERROR (LiDARcloud::exportPointCloud): Cannot export scan " << scanID << " because this scan does not exist." << std::endl;
+
832 throw 1;
+
833 }
834
-
835 file << std::endl;
+
835 ofstream file;
836
-
837 }
+
837 file.open(filename);
838
-
839 file.close();
-
840
-
841}
-
+
839 if( !file.is_open() ) {
+
840 throw (std::runtime_error("ERROR (LiDARcloud::exportPointCloud): Could not open file '" + std::string(filename) + "' for writing."));
+
841 }
842
-
-
843void LiDARcloud::exportPointCloudPTX( const char* filename, uint scanID ){
-
844
-
845 if( scanID> getScanCount()){
-
846 std::cerr << "ERROR (LiDARcloud::exportPointCloudPTX): Cannot export scan " << scanID << " because this scan does not exist." << std::endl;
-
847 throw 1;
-
848 }
-
849
-
850 ofstream file;
-
851
-
852 file.open(filename);
+
843 std::vector<std::string> hit_data;
+
844 for( int r=0; r< getHitCount(); r++ ){
+
845 std::map<std::string,double> data = hits.at(r).data;
+
846 for( std::map<std::string,double>::iterator iter=data.begin(); iter!=data.end(); ++iter ){
+
847 std::vector<std::string>::iterator it = find(hit_data.begin(),hit_data.end(),iter->first);
+
848 if( it==hit_data.end() ){
+
849 hit_data.push_back(iter->first);
+
850 }
+
851 }
+
852 }
853
-
854 if( !file.is_open() ) {
-
855 throw (std::runtime_error("ERROR (LiDARcloud::exportPointCloudPTX): Could not open file '" + std::string(filename) + "' for writing."));
-
856 }
-
857
-
858 std::vector<std::string> ASCII_format = getScanColumnFormat(scanID);
-
859
-
860 uint Nx = getScanSizeTheta(scanID);
-
861 uint Ny = getScanSizePhi(scanID);
-
862
-
863 file << Nx << std::endl;
-
864 file << Ny << std::endl;
-
865 file << "0 0 0" << std::endl;
-
866 file << "1 0 0" << std::endl;
-
867 file << "0 1 0" << std::endl;
-
868 file << "0 0 1" << std::endl;
-
869 file << "1 0 0 0" << std::endl;
-
870 file << "0 1 0 0" << std::endl;
-
871 file << "0 0 1 0" << std::endl;
-
872 file << "0 0 0 1" << std::endl;
-
873
-
874 std::vector<std::vector<vec4> > xyzi(Ny);
-
875 for( int j=0; j<Ny; j++ ){
-
876 xyzi.at(j).resize(Nx);
-
877 for( int i=0; i<Nx; i++ ){
-
878 xyzi.at(j).at(i) = make_vec4(0,0,0,1);
-
879 }
-
880 }
-
881
-
882 vec3 origin = getScanOrigin(scanID);
-
883
-
884 for( int r=0; r<getHitCount(); r++ ){
-
885
-
886 if( getHitScanID(r) != scanID ){
-
887 continue;
-
888 }
-
889
-
890 SphericalCoord raydir = getHitRaydir(r);
-
891
-
892 int2 row_column = scans.at(scanID).direction2rc(raydir);
-
893
-
894 assert( row_column.x>=0 && row_column.x<Nx && row_column.y>=0 && row_column.y<Ny );
-
895
-
896 vec3 xyz = getHitXYZ(r);
-
897
-
898 if( (xyz-origin).magnitude()>=1e4 ){
-
899 continue;
-
900 }
-
901
-
902 float intensity = 1.f;
-
903 if( hits.at(r).data.find("intensity")!=hits.at(r).data.end() ) {
-
904 intensity = getHitData(r, "intensity");
+
854 std::vector<std::string> ASCII_format = getScanColumnFormat(scanID);
+
855
+
856 if( ASCII_format.size()==0 ){
+
857 ASCII_format.push_back("x");
+
858 ASCII_format.push_back("y");
+
859 ASCII_format.push_back("z");
+
860 }
+
861
+
862 for( int r=0; r< getHitCount(); r++ ){
+
863
+
864 if( getHitScanID(r) != scanID ){
+
865 continue;
+
866 }
+
867
+
868 vec3 xyz = getHitXYZ(r);
+
869 RGBcolor color = getHitColor(r);
+
870
+
871 for( int c=0; c<ASCII_format.size(); c++ ){
+
872
+
873 if( ASCII_format.at(c).compare("x")==0 ){
+
874 file << xyz.x;
+
875 }else if( ASCII_format.at(c).compare("y")==0 ){
+
876 file << xyz.y;
+
877 }else if( ASCII_format.at(c).compare("z")==0 ){
+
878 file << xyz.z;
+
879 }else if( ASCII_format.at(c).compare("r")==0 ){
+
880 file << color.r;
+
881 }else if( ASCII_format.at(c).compare("g")==0 ){
+
882 file << color.g;
+
883 }else if( ASCII_format.at(c).compare("b")==0 ){
+
884 file << color.b;
+
885 }else if( ASCII_format.at(c).compare("r255")==0 ){
+
886 file << round(color.r*255);
+
887 }else if( ASCII_format.at(c).compare("g255")==0 ){
+
888 file << round(color.g*255);
+
889 }else if( ASCII_format.at(c).compare("b255")==0 ){
+
890 file << round(color.b*255);
+
891 }else if( ASCII_format.at(c).compare("zenith")==0 ){
+
892 file << getHitRaydir(r).zenith;
+
893 }else if( ASCII_format.at(c).compare("azimuth")==0 ){
+
894 file << getHitRaydir(r).azimuth;
+
895 }else if( hits.at(r).data.find(ASCII_format.at(c))!=hits.at(r).data.end() ){ //hit scalar data
+
896 file << getHitData(r,ASCII_format.at(c).c_str());
+
897 }else{
+
898 file << -9999;
+
899 }
+
900
+
901 if( c<ASCII_format.size()-1 ){
+
902 file << " ";
+
903 }
+
904
905 }
906
-
907 xyzi.at(row_column.y).at(row_column.x) = make_vec4( xyz.x, xyz.y, xyz.z, intensity );
+
907 file << std::endl;
908
909 }
910
-
911 for( int j=0; j<Ny; j++ ){
-
912 for( int i=0; i<Nx; i++ ){
-
913 file << xyzi.at(j).at(i).x << " " << xyzi.at(j).at(i).y << " " << xyzi.at(j).at(i).z << " " << xyzi.at(j).at(i).w << std::endl;
-
914 }
-
915 }
+
911 file.close();
+
912
+
913}
+
+
914
+
+
915void LiDARcloud::exportPointCloudPTX( const char* filename, uint scanID ){
916
-
917 file.close();
-
918
-
919}
+
917 if( scanID> getScanCount()){
+
918 std::cerr << "ERROR (LiDARcloud::exportPointCloudPTX): Cannot export scan " << scanID << " because this scan does not exist." << std::endl;
+
919 throw 1;
+
920 }
+
921
+
922 ofstream file;
+
923
+
924 file.open(filename);
+
925
+
926 if( !file.is_open() ) {
+
927 throw (std::runtime_error("ERROR (LiDARcloud::exportPointCloudPTX): Could not open file '" + std::string(filename) + "' for writing."));
+
928 }
+
929
+
930 std::vector<std::string> ASCII_format = getScanColumnFormat(scanID);
+
931
+
932 uint Nx = getScanSizeTheta(scanID);
+
933 uint Ny = getScanSizePhi(scanID);
+
934
+
935 file << Nx << std::endl;
+
936 file << Ny << std::endl;
+
937 file << "0 0 0" << std::endl;
+
938 file << "1 0 0" << std::endl;
+
939 file << "0 1 0" << std::endl;
+
940 file << "0 0 1" << std::endl;
+
941 file << "1 0 0 0" << std::endl;
+
942 file << "0 1 0 0" << std::endl;
+
943 file << "0 0 1 0" << std::endl;
+
944 file << "0 0 0 1" << std::endl;
+
945
+
946 std::vector<std::vector<vec4> > xyzi(Ny);
+
947 for( int j=0; j<Ny; j++ ){
+
948 xyzi.at(j).resize(Nx);
+
949 for( int i=0; i<Nx; i++ ){
+
950 xyzi.at(j).at(i) = make_vec4(0,0,0,1);
+
951 }
+
952 }
+
953
+
954 vec3 origin = getScanOrigin(scanID);
+
955
+
956 for( int r=0; r<getHitCount(); r++ ){
+
957
+
958 if( getHitScanID(r) != scanID ){
+
959 continue;
+
960 }
+
961
+
962 SphericalCoord raydir = getHitRaydir(r);
+
963
+
964 int2 row_column = scans.at(scanID).direction2rc(raydir);
+
965
+
966 assert( row_column.x>=0 && row_column.x<Nx && row_column.y>=0 && row_column.y<Ny );
+
967
+
968 vec3 xyz = getHitXYZ(r);
+
969
+
970 if( (xyz-origin).magnitude()>=1e4 ){
+
971 continue;
+
972 }
+
973
+
974 float intensity = 1.f;
+
975 if( hits.at(r).data.find("intensity")!=hits.at(r).data.end() ) {
+
976 intensity = getHitData(r, "intensity");
+
977 }
+
978
+
979 xyzi.at(row_column.y).at(row_column.x) = make_vec4( xyz.x, xyz.y, xyz.z, intensity );
+
980
+
981 }
+
982
+
983 for( int j=0; j<Ny; j++ ){
+
984 for( int i=0; i<Nx; i++ ){
+
985 file << xyzi.at(j).at(i).x << " " << xyzi.at(j).at(i).y << " " << xyzi.at(j).at(i).z << " " << xyzi.at(j).at(i).w << std::endl;
+
986 }
+
987 }
+
988
+
989 file.close();
+
990
+
991}
-
920
+
992
void coordinateRotation(const helios::SphericalCoord &rotation)
Rotate all points in the point cloud about the origin.
Definition LiDAR.cpp:464
double getHitData(uint index, const char *label) const
Set floating point data value associated with a hit point.
Definition LiDAR.cpp:345
uint getGridCellCount() const
Get the number of cells in the grid.
Definition LiDAR.cpp:1791
-
void exportPointCloud(const char *filename)
Export to file all points in the point cloud to an ASCII text file following the column format specif...
Definition fileIO.cpp:728
+
void exportPointCloud(const char *filename)
Export to file all points in the point cloud to an ASCII text file following the column format specif...
Definition fileIO.cpp:800
float getCellLeafAreaDensity(uint index) const
Get the leaf area density of a grid cell in 1/m.
Definition LiDAR.cpp:1938
uint getScanSizeTheta(uint scanID) const
Get the number of scan points in the theta (zenithal) direction.
Definition LiDAR.cpp:265
void exportTriangleAreas(const char *filename)
Export to file the area of all triangles formed.
Definition fileIO.cpp:562
@@ -1048,25 +1129,26 @@
int getHitScanID(uint index) const
Get the scan with which a hit is associated.
Definition LiDAR.cpp:385
uint getHitCount() const
Get the number of hit points in the point cloud.
Definition LiDAR.cpp:254
void loadXML(const char *filename)
Read an XML file containing scan information.
Definition fileIO.cpp:22
-
void exportLeafAreaDensities(const char *filename)
Export to file the leaf area density within each grid cell. Lines of the file correspond to each grid...
Definition fileIO.cpp:688
+
void exportLeafAreaDensities(const char *filename)
Export to file the leaf area density within each grid cell. Lines of the file correspond to each grid...
Definition fileIO.cpp:760
void addHitPoint(uint scanID, const helios::vec3 &xyz, const helios::SphericalCoord &direction)
Specify a scan point as a hit by providing the (x,y,z) coordinates and scan ray direction.
Definition LiDAR.cpp:171
void coordinateShift(const helios::vec3 &shift)
Apply a translation to all points in the point cloud.
Definition LiDAR.cpp:436
-
void exportLeafAreas(const char *filename)
Export to file the leaf area within each grid cell. Lines of the file correspond to each grid cell.
Definition fileIO.cpp:668
+
void exportLeafAreas(const char *filename)
Export to file the leaf area within each grid cell. Lines of the file correspond to each grid cell.
Definition fileIO.cpp:740
helios::vec3 getScanOrigin(uint scanID) const
Get the (x,y,z) scan origin.
Definition LiDAR.cpp:258
helios::SphericalCoord getHitRaydir(uint index) const
Get ray direction of hit point in the scan based on its index.
Definition LiDAR.cpp:324
uint getScanCount()
Get number of scans in point cloud.
Definition LiDAR.cpp:135
void exportTriangleInclinationDistribution(const char *filename, uint Nbins)
Export to file discrete area-weighted inclination angle probability distribution based on the triangu...
Definition fileIO.cpp:610
uint getScanSizePhi(uint scanID) const
Get the number of scan points in the phi (azimuthal) direction.
Definition LiDAR.cpp:272
helios::RGBcolor getHitColor(uint index) const
Get color of hit point.
Definition LiDAR.cpp:375
+
void exportTriangleAzimuthDistribution(const char *filename, uint Nbins)
Export to file discrete azimuthal angle probability distribution based on the triangulation....
Definition fileIO.cpp:671
uint addScan(ScanMetadata &newscan)
Add a LiDAR scan to the point cloud.
Definition LiDAR.cpp:139
std::vector< std::string > getScanColumnFormat(uint scanID) const
Get the labels for columns in ASCII input/output file.
Definition LiDAR.cpp:307
-
void exportPointCloudPTX(const char *filename, uint scanID)
Export to file all points from a given scan to PTX file.
Definition fileIO.cpp:843
+
void exportPointCloudPTX(const char *filename, uint scanID)
Export to file all points from a given scan to PTX file.
Definition fileIO.cpp:915
helios::vec3 getHitXYZ(uint index) const
Get (x,y,z) coordinate of hit point by index.
Definition LiDAR.cpp:314
void addGridCell(const helios::vec3 &center, const helios::vec3 &size, float rotation)
Add a cell to the grid.
Definition LiDAR.cpp:1795
float getCellLeafArea(uint index) const
Get the leaf area of a grid cell in m^2.
Definition LiDAR.cpp:1928
void exportTriangleNormals(const char *filename)
Export to file the normal vectors (nx,ny,nz) for all triangles formed.
Definition fileIO.cpp:499
void distanceFilter(float maxdistance)
Filter scan by imposing a maximum distance from the scanner.
Definition LiDAR.cpp:1035
-
void exportGtheta(const char *filename)
Export to file the G(theta) value within each grid cell. Lines of the file correspond to each grid ce...
Definition fileIO.cpp:708
+
void exportGtheta(const char *filename)
Export to file the G(theta) value within each grid cell. Lines of the file correspond to each grid ce...
Definition fileIO.cpp:780
void helios_runtime_error(const std::string &error_message)
Function to throw a runtime error.
Definition global.cpp:29
vec3 rotatePoint(const vec3 &position, const SphericalCoord &rotation)
Function to rotate a 3D vector given spherical angles elevation and azimuth.
Definition global.cpp:79
vec2 string2vec2(const char *str)
Convert a space-delimited string into a vec2 vector.
Definition global.cpp:623
@@ -1095,24 +1177,27 @@
const float & zenith
Zenithal angle (radians)
const float & elevation
Elevation angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of two elements of type 'int'.
+
Vector of two elements of type 'int'.
int y
Second element in vector.
int x
First element in vector.
-
Vector of three elements of type 'int'.
-
Vector of two elements of type 'float'.
+
Vector of three elements of type 'int'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
float magnitude() const
Compute the vector magnitude.
- -
+ + diff --git a/doc/html/main_8cpp_source.html b/doc/html/main_8cpp_source.html index 146120074..b96037a15 100644 --- a/doc/html/main_8cpp_source.html +++ b/doc/html/main_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
main.cpp
@@ -114,10 +120,10 @@
8
9 Context context;
10
-
11 std::vector<uint> UUIDs_tree = context.loadPLY( "../../../PLY/Tree.ply", nullorigin, 4, nullrotation
+
11 std::vector<uint> UUIDs_tree = context.loadPLY( "../../../PLY/Tree.ply", nullorigin, 4, nullrotation
12);
13
-
14 std::vector<uint> UUIDs_ground = context.addTile( nullorigin, make_vec2(7,7), nullrotation,
+
14 std::vector<uint> UUIDs_ground = context.addTile( nullorigin, make_vec2(7,7), nullrotation,
15make_int2(50,50));
16 context.setPrimitiveData( UUIDs_ground, "twosided_flag", uint(0));
17
@@ -198,7 +204,7 @@
Radiation transport model plugin.
Class for visualization of simulation results.
Definition Visualizer.h:275
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
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.
@@ -209,18 +215,23 @@
std::vector< uint > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
void setPrimitiveData(const uint &UUID, const char *label, const int &data)
Add data value (int) associated with a primitive element.
void setTime(int minute, int hour)
Set simulation time.
Definition Context.cpp:1136
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
+
vec3 nullorigin
Default null vec3 that gives the origin (0,0,0)
Definition global.cpp:58
+
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
+
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5836
void wait(float seconds)
Wait/sleep for a specified amount of time.
Definition global.cpp:306
void setCurrentTimeseriesPoint(const char *label, uint index)
Set the Context date and time by providing the index of a timeseries data point.
Definition Context.cpp:1886
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:1894
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.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
- -
+ + diff --git a/doc/html/navtree.js b/doc/html/navtree.js new file mode 100644 index 000000000..2d4fa84a5 --- /dev/null +++ b/doc/html/navtree.js @@ -0,0 +1,483 @@ +/* + @licstart The following is the entire license notice for the JavaScript code in this file. + + The MIT License (MIT) + + Copyright (C) 1997-2020 by Dimitri van Heesch + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software + and associated documentation files (the "Software"), to deal in the Software without restriction, + including without limitation the rights to use, copy, modify, merge, publish, distribute, + sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or + substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING + BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + @licend The above is the entire license notice for the JavaScript code in this file + */ + +function initNavTree(toroot,relpath) { + let navTreeSubIndices = []; + const ARROW_DOWN = '▼'; + const ARROW_RIGHT = '►'; + const NAVPATH_COOKIE_NAME = ''+'navpath'; + + const getData = function(varName) { + const i = varName.lastIndexOf('/'); + const n = i>=0 ? varName.substring(i+1) : varName; + return eval(n.replace(/-/g,'_')); + } + + const stripPath = function(uri) { + return uri.substring(uri.lastIndexOf('/')+1); + } + + const stripPath2 = function(uri) { + const i = uri.lastIndexOf('/'); + const s = uri.substring(i+1); + const m = uri.substring(0,i+1).match(/\/d\w\/d\w\w\/$/); + return m ? uri.substring(i-6) : s; + } + + const hashValue = function() { + return $(location).attr('hash').substring(1).replace(/[^\w-]/g,''); + } + + const hashUrl = function() { + return '#'+hashValue(); + } + + const pathName = function() { + return $(location).attr('pathname').replace(/[^-A-Za-z0-9+&@#/%?=~_|!:,.;()]/g, ''); + } + + const storeLink = function(link) { + if (!$("#nav-sync").hasClass('sync')) { + Cookie.writeSetting(NAVPATH_COOKIE_NAME,link,0); + } + } + + const deleteLink = function() { + Cookie.eraseSetting(NAVPATH_COOKIE_NAME); + } + + const cachedLink = function() { + return Cookie.readSetting(NAVPATH_COOKIE_NAME,''); + } + + const getScript = function(scriptName,func) { + const head = document.getElementsByTagName("head")[0]; + const script = document.createElement('script'); + script.id = scriptName; + script.type = 'text/javascript'; + script.onload = func; + script.src = scriptName+'.js'; + head.appendChild(script); + } + + const createIndent = function(o,domNode,node) { + let level=-1; + let n = node; + while (n.parentNode) { level++; n=n.parentNode; } + if (node.childrenData) { + const imgNode = document.createElement("span"); + imgNode.className = 'arrow'; + imgNode.style.paddingLeft=(16*level).toString()+'px'; + imgNode.innerHTML=ARROW_RIGHT; + node.plus_img = imgNode; + node.expandToggle = document.createElement("a"); + node.expandToggle.href = "javascript:void(0)"; + node.expandToggle.onclick = function() { + if (node.expanded) { + $(node.getChildrenUL()).slideUp("fast"); + node.plus_img.innerHTML=ARROW_RIGHT; + node.expanded = false; + } else { + expandNode(o, node, false, true); + } + } + node.expandToggle.appendChild(imgNode); + domNode.appendChild(node.expandToggle); + } else { + let span = document.createElement("span"); + span.className = 'arrow'; + span.style.width = 16*(level+1)+'px'; + span.innerHTML = ' '; + domNode.appendChild(span); + } + } + + let animationInProgress = false; + + const gotoAnchor = function(anchor,aname) { + let pos, docContent = $('#doc-content'); + let ancParent = $(anchor.parent()); + if (ancParent.hasClass('memItemLeft') || ancParent.hasClass('memtitle') || + ancParent.hasClass('fieldname') || ancParent.hasClass('fieldtype') || + ancParent.is(':header')) { + pos = ancParent.offset().top; + } else if (anchor.position()) { + pos = anchor.offset().top; + } + if (pos) { + const dcOffset = docContent.offset().top; + const dcHeight = docContent.height(); + const dcScrHeight = docContent[0].scrollHeight + const dcScrTop = docContent.scrollTop(); + let dist = Math.abs(Math.min(pos-dcOffset,dcScrHeight-dcHeight-dcScrTop)); + animationInProgress = true; + docContent.animate({ + scrollTop: pos + dcScrTop - dcOffset + },Math.max(50,Math.min(500,dist)),function() { + animationInProgress=false; + if (anchor.parent().attr('class')=='memItemLeft') { + let rows = $('.memberdecls tr[class$="'+hashValue()+'"]'); + glowEffect(rows.children(),300); // member without details + } else if (anchor.parent().attr('class')=='fieldname') { + glowEffect(anchor.parent().parent(),1000); // enum value + } else if (anchor.parent().attr('class')=='fieldtype') { + glowEffect(anchor.parent().parent(),1000); // struct field + } else if (anchor.parent().is(":header")) { + glowEffect(anchor.parent(),1000); // section header + } else { + glowEffect(anchor.next(),1000); // normal member + } + }); + } + } + + const newNode = function(o, po, text, link, childrenData, lastNode) { + const node = { + children : [], + childrenData : childrenData, + depth : po.depth + 1, + relpath : po.relpath, + isLast : lastNode, + li : document.createElement("li"), + parentNode : po, + itemDiv : document.createElement("div"), + labelSpan : document.createElement("span"), + label : document.createTextNode(text), + expanded : false, + childrenUL : null, + getChildrenUL : function() { + if (!this.childrenUL) { + this.childrenUL = document.createElement("ul"); + this.childrenUL.className = "children_ul"; + this.childrenUL.style.display = "none"; + this.li.appendChild(node.childrenUL); + } + return node.childrenUL; + }, + }; + + node.itemDiv.className = "item"; + node.labelSpan.className = "label"; + createIndent(o,node.itemDiv,node); + node.itemDiv.appendChild(node.labelSpan); + node.li.appendChild(node.itemDiv); + + const a = document.createElement("a"); + node.labelSpan.appendChild(a); + po.getChildrenUL().appendChild(node.li); + a.appendChild(node.label); + if (link) { + let url; + if (link.substring(0,1)=='^') { + url = link.substring(1); + link = url; + } else { + url = node.relpath+link; + } + a.className = stripPath(link.replace('#',':')); + if (link.indexOf('#')!=-1) { + const aname = '#'+link.split('#')[1]; + const srcPage = stripPath(pathName()); + const targetPage = stripPath(link.split('#')[0]); + a.href = srcPage!=targetPage ? url : aname; + a.onclick = function() { + storeLink(link); + aPPar = $(a).parent().parent(); + if (!aPPar.hasClass('selected')) { + $('.item').removeClass('selected'); + $('.item').removeAttr('id'); + aPPar.addClass('selected'); + aPPar.attr('id','selected'); + } + const anchor = $(aname); + gotoAnchor(anchor,aname); + }; + } else { + a.href = url; + a.onclick = () => storeLink(link); + } + } else if (childrenData != null) { + a.className = "nolink"; + a.href = "javascript:void(0)"; + a.onclick = node.expandToggle.onclick; + } + return node; + } + + const showRoot = function() { + const headerHeight = $("#top").height(); + const footerHeight = $("#nav-path").height(); + const windowHeight = $(window).height() - headerHeight - footerHeight; + (function() { // retry until we can scroll to the selected item + try { + const navtree=$('#nav-tree'); + navtree.scrollTo('#selected',100,{offset:-windowHeight/2}); + } catch (err) { + setTimeout(arguments.callee, 0); + } + })(); + } + + const expandNode = function(o, node, imm, setFocus) { + if (node.childrenData && !node.expanded) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + expandNode(o, node, imm, setFocus); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).slideDown("fast"); + node.plus_img.innerHTML = ARROW_DOWN; + node.expanded = true; + if (setFocus) { + $(node.expandToggle).focus(); + } + } + } + } + + const glowEffect = function(n,duration) { + n.addClass('glow').delay(duration).queue(function(next) { + $(this).removeClass('glow');next(); + }); + } + + const highlightAnchor = function() { + const aname = hashUrl(); + const anchor = $(aname); + gotoAnchor(anchor,aname); + } + + const selectAndHighlight = function(hash,n) { + let a; + if (hash) { + const link=stripPath(pathName())+':'+hash.substring(1); + a=$('.item a[class$="'+link+'"]'); + } + if (a && a.length) { + a.parent().parent().addClass('selected'); + a.parent().parent().attr('id','selected'); + highlightAnchor(); + } else if (n) { + $(n.itemDiv).addClass('selected'); + $(n.itemDiv).attr('id','selected'); + } + let topOffset=5; + if ($('#nav-tree-contents .item:first').hasClass('selected')) { + topOffset+=25; + } + $('#nav-sync').css('top',topOffset+'px'); + showRoot(); + } + + const showNode = function(o, node, index, hash) { + if (node && node.childrenData) { + if (typeof(node.childrenData)==='string') { + const varName = node.childrenData; + getScript(node.relpath+varName,function() { + node.childrenData = getData(varName); + showNode(o,node,index,hash); + }); + } else { + if (!node.childrenVisited) { + getNode(o, node); + } + $(node.getChildrenUL()).css({'display':'block'}); + node.plus_img.innerHTML = ARROW_DOWN; + node.expanded = true; + const n = node.children[o.breadcrumbs[index]]; + if (index+11 ? '#'+parts[1].replace(/[^\w-]/g,'') : ''; + } + if (hash.match(/^#l\d+$/)) { + const anchor=$('a[name='+hash.substring(1)+']'); + glowEffect(anchor.parent(),1000); // line number + hash=''; // strip line number anchors + } + const url=root+hash; + let i=-1; + while (NAVTREEINDEX[i+1]<=url) i++; + if (i==-1) { i=0; root=NAVTREE[0][1]; } // fallback: show index + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath) + } else { + getScript(relpath+'navtreeindex'+i,function() { + navTreeSubIndices[i] = eval('NAVTREEINDEX'+i); + if (navTreeSubIndices[i]) { + gotoNode(o,i,root,hash,relpath); + } + }); + } + } + + const showSyncOff = function(n,relpath) { + n.html(''); + } + + const showSyncOn = function(n,relpath) { + n.html(''); + } + + const o = { + toroot : toroot, + node : { + childrenData : NAVTREE, + children : [], + childrenUL : document.createElement("ul"), + getChildrenUL : function() { return this.childrenUL }, + li : document.getElementById("nav-tree-contents"), + depth : 0, + relpath : relpath, + expanded : false, + isLast : true, + plus_img : document.createElement("span"), + }, + }; + o.node.li.appendChild(o.node.childrenUL); + o.node.plus_img.className = 'arrow'; + o.node.plus_img.innerHTML = ARROW_RIGHT; + + const navSync = $('#nav-sync'); + if (cachedLink()) { + showSyncOff(navSync,relpath); + navSync.removeClass('sync'); + } else { + showSyncOn(navSync,relpath); + } + + navSync.click(() => { + const navSync = $('#nav-sync'); + if (navSync.hasClass('sync')) { + navSync.removeClass('sync'); + showSyncOff(navSync,relpath); + storeLink(stripPath2(pathName())+hashUrl()); + } else { + navSync.addClass('sync'); + showSyncOn(navSync,relpath); + deleteLink(); + } + }); + + navTo(o,toroot,hashUrl(),relpath); + showRoot(); + + $(window).bind('hashchange', () => { + if (!animationInProgress) { + if (window.location.hash && window.location.hash.length>1) { + let a; + if ($(location).attr('hash')) { + const clslink=stripPath(pathName())+':'+hashValue(); + a=$('.item a[class$="'+clslink.replace(/ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- +
-
+
+ +
+
+
+
- -
+ + diff --git a/doc/html/plugins_2lidar_2src_2self_test_8cpp.html b/doc/html/plugins_2lidar_2src_2self_test_8cpp.html index a7bd7113c..01c29b7da 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
selfTest.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file selfTest.cpp.

- -
+ + 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 f9eca4470..e6d4797bb 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
selfTest.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "LiDAR.h"
17
18using namespace std;
@@ -125,7 +132,7 @@
32
33 std::cout << "Running single voxel sphere test..." << std::flush;
34
-
35 LiDARcloud pointcloud;
+
35 LiDARcloud pointcloud;
36 pointcloud.disableMessages();
37
38 pointcloud.loadXML("plugins/lidar/xml/sphere.xml");
@@ -147,7 +154,7 @@
54
55 std::cout << "Running single voxel isotropic patches test..." << std::flush;
56
-
57 LiDARcloud synthetic_1;
+
57 LiDARcloud synthetic_1;
58 synthetic_1.disableMessages();
59
60 synthetic_1.loadXML( "plugins/lidar/xml/synthetic_test.xml" );
@@ -182,7 +189,7 @@
89
90 std::cout << "Running eight voxel isotropic patches test..." << std::flush;
91
-
92 LiDARcloud synthetic_2;
+
92 LiDARcloud synthetic_2;
93 synthetic_2.disableMessages();
94
95 synthetic_2.loadXML( "plugins/lidar/xml/synthetic_test_8.xml" );
@@ -235,7 +242,7 @@
142
143 std::cout << "Running single voxel anisotropic patches test..." << std::flush;
144
-
145 LiDARcloud synthetic_3;
+
145 LiDARcloud synthetic_3;
146 synthetic_3.disableMessages();
147
148 synthetic_3.loadXML( "plugins/lidar/xml/synthetic_test.xml" );
@@ -270,7 +277,7 @@
177
178 context_4.loadOBJ("plugins/lidar/xml/AlmondWP.obj",make_vec3(0,0,0),6.,make_SphericalCoord(0,0),RGB::red,true);
179
-
180 LiDARcloud synthetic_4;
+
180 LiDARcloud synthetic_4;
181 synthetic_4.disableMessages();
182
183 synthetic_4.loadXML( "plugins/lidar/xml/almond.xml" );
@@ -384,7 +391,7 @@
291}
-
Primary class for terrestrial LiDAR scan.
Definition LiDAR.h:270
+
LiDARcloud()
LiDAR point cloud constructor.
Definition LiDAR.cpp:89
std::vector< float > calculateSyntheticLeafArea(helios::Context *context)
Calculate the surface area of all primitives in the context.
Definition LiDAR.cu:3712
uint getGridCellCount() const
Get the number of cells in the grid.
Definition LiDAR.cpp:1791
float getCellLeafAreaDensity(uint index) const
Get the leaf area density of a grid cell in 1/m.
Definition LiDAR.cpp:1938
@@ -401,29 +408,32 @@
float getCellLeafArea(uint index) const
Get the leaf area of a grid cell in m^2.
Definition LiDAR.cpp:1928
void disableMessages()
Disable all print messages to the screen except for fatal error messages.
Definition LiDAR.cpp:100
void calculateLeafAreaGPU()
Calculate the leaf area for each grid volume.
Definition LiDAR.cu:897
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
std::vector< uint > loadXML(const char *filename, bool quiet=false)
Load inputs specified in an XML file.
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
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.
+
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 > getAllUUIDs() const
Get all primitive UUIDs currently in the Context.
Definition Context.cpp:1763
-
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7104
-
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:7122
+
helios::vec3 getPrimitiveNormal(uint UUID) const
Method to return the normal vector of a Primitive.
Definition Context.cpp:7131
+
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:7149
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
uint getPrimitiveCount() const
Get the total number of Primitives in the Context.
Definition Context.cpp:1759
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- -
+ + diff --git a/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp.html b/doc/html/plugins_2plantarchitecture_2src_2self_test_8cpp.html index aaea9e34f..d1681c85e 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
selfTest.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file selfTest.cpp.

- -
+ + 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 fc2ee0c67..3d6817eb1 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
selfTest.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "PlantArchitecture.h"
17
18using namespace std;
@@ -121,7 +128,7 @@
28 try {
29 std::cout << "Building " << plant_label << " plant model..." << std::flush;
30 Context context;
-
31 PlantArchitecture plantarchitecture(&context);
+
31 PlantArchitecture plantarchitecture(&context);
32 plantarchitecture.loadPlantModelFromLibrary( plant_label );
33 plantarchitecture.buildPlantInstanceFromLibrary(make_vec3(0,0,0), 5000);
34 std::cout << "done." << std::endl;
@@ -149,17 +156,20 @@
56}
-
static int selfTest()
Unit test routines.
Definition selfTest.cpp:21
+
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 loadPlantModelFromLibrary(const std::string &plant_label)
Load an existing plant model from the library.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
- -
+ + diff --git a/doc/html/plugins_2radiation_2src_2self_test_8cpp.html b/doc/html/plugins_2radiation_2src_2self_test_8cpp.html index 8af750e92..efda4310c 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
selfTest.cpp File Reference
@@ -115,10 +121,13 @@

Definition in file selfTest.cpp.

- - + + 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 705f5aec0..709700a0b 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
selfTest.cpp
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include "RadiationModel.h"
17
18using namespace helios;
@@ -141,7 +148,7 @@
48
49 shortwave_exact_0 = 0.7f*Qs;
50 shortwave_exact_1 = 0.3f*0.2f*Qs;
-
51 longwave_exact_0 = 0.f;//sigma*powf(300.f,4)*0.2f;
+
51 longwave_exact_0 = 0.f;
52 longwave_exact_1 = sigma*powf(300.f,4)*0.2f;
53
54 Context context_1;
@@ -158,7 +165,7 @@
65 shortwave_rho = 0.3f;
66 context_1.setPrimitiveData(0,"reflectivity_SW",HELIOS_TYPE_FLOAT,1,&shortwave_rho);
67
-
68 RadiationModel radiationmodel_1(&context_1);
+
68 RadiationModel radiationmodel_1(&context_1);
69 radiationmodel_1.disableMessages();
70
71 //Longwave band
@@ -256,7 +263,7 @@
163 context_2.setPrimitiveData(0,"twosided_flag",flag);
164 context_2.setPrimitiveData(1,"twosided_flag",flag);
165
-
166 RadiationModel radiationmodel_2(&context_2);
+
166 RadiationModel radiationmodel_2(&context_2);
167 radiationmodel_2.disableMessages();
168
169 //Shortwave band
@@ -338,7 +345,7 @@
245 context_3.setPrimitiveData(0,"twosided_flag",flag);
246 context_3.setPrimitiveData(1,"twosided_flag",flag);
247
-
248 RadiationModel radiationmodel_3(&context_3);
+
248 RadiationModel radiationmodel_3(&context_3);
249 radiationmodel_3.disableMessages();
250
251 //Longwave band
@@ -399,7 +406,7 @@
306
307 context_4.addPatch( make_vec3(0.5f*l1,0.5f*l2,0), make_vec2(l1,l2) );
308
-
309 RadiationModel radiationmodel_4(&context_4);
+
309 RadiationModel radiationmodel_4(&context_4);
310 radiationmodel_4.disableMessages();
311
312 uint Source_4 = radiationmodel_4.addSphereRadiationSource( make_vec3(0,0,d), r );
@@ -471,7 +478,7 @@
378 context_5.setPrimitiveData(2,"twosided_flag",flag);
379 context_5.setPrimitiveData(3,"twosided_flag",flag);
380
-
381 RadiationModel radiationmodel_5(&context_5);
+
381 RadiationModel radiationmodel_5(&context_5);
382 radiationmodel_5.disableMessages();
383
384 //Longwave band
@@ -557,7 +564,7 @@
464
465 std::cout << "Test #6: Parallel disks (Texture Masked Patches)..." << std::flush;
466
-
467 uint Ndirect_6 = 100;
+
467 uint Ndirect_6 = 1000;
468 uint Ndiffuse_6 = 500000;
469
470 shortwave_rho = 0.3;
@@ -596,7 +603,7 @@
503 context_6.setPrimitiveData(1,"twosided_flag",flag);
504 context_6.setPrimitiveData(2,"twosided_flag",flag);
505
-
506 RadiationModel radiationmodel_6(&context_6);
+
506 RadiationModel radiationmodel_6(&context_6);
507 radiationmodel_6.disableMessages();
508
509 uint SunSource_6 = radiationmodel_6.addCollimatedRadiationSource( make_vec3(0,0,1) );
@@ -688,7 +695,7 @@
595
596 context_7.setPrimitiveData(UUIDt,"temperature",T);
597
-
598 RadiationModel radiationmodel_7(&context_7);
+
598 RadiationModel radiationmodel_7(&context_7);
599 radiationmodel_7.disableMessages();
600
601 //Longwave band
@@ -759,7 +766,7 @@
666
667 Context context_8;
668
-
669 RadiationModel radiation(&context_8);
+
669 RadiationModel radiation(&context_8);
670
671 uint source = radiation.addCollimatedRadiationSource( make_vec3(0,0,1) );
672
@@ -992,7 +999,7 @@
899
900 context_9.setPrimitiveData( UUIDs_ground, "twosided_flag", uint(0) );
901
-
902 RadiationModel radiation_9(&context_9);
+
902 RadiationModel radiation_9(&context_9);
903 radiation_9.disableMessages();
904
905 radiation_9.addRadiationBand("direct");
@@ -1139,7 +1146,7 @@
1046 context_10.setPrimitiveData( UUIDs_patches, "emissivity_LW", eps_m_10 );
1047 context_10.setPrimitiveData( UUIDs_patches, "reflectivity_LW", 1.f-eps_m_10 );
1048
-
1049 RadiationModel radiation_10(&context_10);
+
1049 RadiationModel radiation_10(&context_10);
1050 radiation_10.disableMessages();
1051
1052 radiation_10.addRadiationBand("LW");
@@ -1244,7 +1251,7 @@
1151 context_11.setPrimitiveData( UUIDs_patches_11, "emissivity_LW", 1.f-omega_11 );
1152 context_11.setPrimitiveData( UUIDs_patches_11, "reflectivity_LW", omega_11 );
1153
-
1154 RadiationModel radiation_11(&context_11);
+
1154 RadiationModel radiation_11(&context_11);
1155 radiation_11.disableMessages();
1156
1157 radiation_11.addRadiationBand("LW");
@@ -1325,7 +1332,7 @@
1232
1233 context_12.setPrimitiveData( UUIDs_ground_12, "twosided_flag", uint(0) );
1234
-
1235 RadiationModel radiation_12(&context_12);
+
1235 RadiationModel radiation_12(&context_12);
1236 radiation_12.disableMessages();
1237
1238 radiation_12.addRadiationBand("direct");
@@ -1471,7 +1478,7 @@
1378
1379 context_13.setPrimitiveData( UUIDs_ground_13, "twosided_flag", uint(0) );
1380
-
1381 RadiationModel radiation_13(&context_13);
+
1381 RadiationModel radiation_13(&context_13);
1382 radiation_13.disableMessages();
1383
1384 radiation_13.addRadiationBand("direct");
@@ -1587,7 +1594,7 @@
1494
1495 context_14.setPrimitiveData( UUID_14, "twosided_flag", uint(0) );
1496
-
1497 RadiationModel radiation_14(&context_14);
+
1497 RadiationModel radiation_14(&context_14);
1498 radiation_14.disableMessages();
1499
1500 radiation_14.addRadiationBand( "diffuse" );
@@ -1635,7 +1642,7 @@
1542 float a_15 = 0.5; //distance between radiation source and element
1543
1544 Context context_15;
-
1545 RadiationModel radiation_15(&context_15);
+
1545 RadiationModel radiation_15(&context_15);
1546 radiation_15.disableMessages();
1547
1548 uint UUID_15 = context_15.addPatch( make_vec3(0,0,0), make_vec2(2*r2_15,2*r2_15), make_SphericalCoord(0.5*M_PI,0), "lib/images/disk_texture.png");
@@ -1683,7 +1690,7 @@
1590 float c_16 = 0.5; //distance between source and patch
1591
1592 Context context_16;
-
1593 RadiationModel radiation_16(&context_16);
+
1593 RadiationModel radiation_16(&context_16);
1594 radiation_16.disableMessages();
1595
1596 uint UUID_16 = context_16.addPatch( make_vec3(0,0,0), make_vec2(a_16,b_16), nullrotation);
@@ -1749,7 +1756,7 @@
1656 for (auto & CSposition : CSpositions){
1657 vec3 transpos = movew+make_vec3(CSposition.at(0),CSposition.at(1),CSposition.at(2));
1658 CameraCalibration cameracalibration(&context_17);
-
1659 std::vector<uint> iCUUIDsn = cameracalibration.readROMCCanopy();
+
1659 std::vector<uint> iCUUIDsn = cameracalibration.readROMCCanopy();
1660 context_17.translatePrimitive(iCUUIDsn, transpos);
1661 context_17.setPrimitiveData(iCUUIDsn, "twosided_flag", uint(1));
1662 context_17.setPrimitiveData(iCUUIDsn, "reflectivity_spectrum","leaf_reflectivity");
@@ -1777,7 +1784,7 @@
1684 // Add sensors to receive radiation
1685 vec3 camera_lookat= make_vec3(0,0,heightscene);
1686 std::vector<std::string> cameralabels;
-
1687 RadiationModel radiation_17(&context_17);
+
1687 RadiationModel radiation_17(&context_17);
1688 radiation_17.disableMessages();
1689 for (float viewangle:viewangles){
1690 // Set camera properties
@@ -1857,9 +1864,8 @@
@ HELIOS_TYPE_VEC2
helios::vec2 data type
Definition Context.h:51
@ HELIOS_TYPE_FLOAT
floating point data type
Definition Context.h:47
-
Radiation transport model plugin.
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 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.
uint addSphereRadiationSource(const helios::vec3 &position, float radius)
Add an external source of radiation that emits from the surface of a sphere.
void enforcePeriodicBoundary(const std::string &boundary)
Use a periodic boundary condition in one or more lateral directions.
@@ -1868,24 +1874,25 @@
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.
+
RadiationModel(helios::Context *context)
Default constructor.
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.
void rotate(float rotation_radians, const char *rotation_axis_xyz_string)
Method to rotate a Compound Object about the x-, y-, or z-axis.
Definition Context.cpp:2377
void translate(const helios::vec3 &shift)
Method to translate/shift a Compound Object.
Definition Context.cpp:2353
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
uint copyObject(uint ObjID)
Make a copy of a Compound Objects from the context.
Definition Context.cpp:2642
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7053
+
float getPrimitiveArea(uint UUID) const
Method to return the surface area of a Primitive.
Definition Context.cpp:7080
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:1536
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
@@ -1897,10 +1904,10 @@
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:1659
SphericalCoord nullrotation
Default null SphericalCoord that applies no rotation.
Definition global.cpp:57
-
std::vector< uint > addBox(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:6147
-
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5000
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
-
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4550
+
std::vector< uint > addBox(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:6174
+
uint addBoxObject(const vec3 &center, const vec3 &size, const int3 &subdiv)
Add a rectangular prism tessellated with Patch primitives.
Definition Context.cpp:5027
+
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5836
+
uint addTileObject(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:4577
float deg2rad(float deg)
Convert degrees to radians.
Definition global.cpp:576
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
@@ -1912,27 +1919,29 @@
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
SphericalCoord make_SphericalCoord(float elevation_radians, float azimuth_radians)
Make a SphericalCoord by specifying elevation and azimuth.
Camera calibration structure used for camera calibration tasks.
-
std::vector< uint > readROMCCanopy()
Read ROMC canopy file (Used for self test).
Properties defining a radiation camera.
helios::int2 camera_resolution
Camera sensor resolution (number of pixels) in the horizontal (.x) and vertical (....
float focal_plane_distance
Distance from the viewing plane to the focal plane.
float HFOV
Camera horizontal field of view in degrees.
-
float lens_diameter
Diameter of the camera lens (lens_diameter = 0 gives a 'pinhole' camera with everything in focus)
-
float FOV_aspect_ratio
Physical dimensions of the pixel array sensor in the horizontal (.x) and vertical (....
+
float lens_diameter
Diameter of the camera lens (lens_diameter = 0 gives a 'pinhole' camera with everything in focus)
+
float FOV_aspect_ratio
Ratio of horizontal to vertical camera field of view.
Vector of spherical coordinates (elevation,azimuth)
const float & elevation
Elevation angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
- -
+ + 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 4db693b6b..c0fb8d7e8 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
selfTest.cpp
@@ -136,7 +142,7 @@
29 context_s.setDate(date);
30 context_s.setTime(time);
31
-
32 SolarPosition solarposition_1(UTC, latitude, longitude, &context_s);
+
32 SolarPosition solarposition_1(UTC, latitude, longitude, &context_s);
33
34 float theta_s = solarposition_1.getSunElevation() * 180.f / M_PI;
35 float phi_s = solarposition_1.getSunAzimuth() * 180.f / M_PI;
@@ -164,7 +170,7 @@
57 context_s.setDate(date);
58 context_s.setTime(time);
59
-
60 SolarPosition solarposition_2(UTC, latitude, longitude, &context_s);
+
60 SolarPosition solarposition_2(UTC, latitude, longitude, &context_s);
61
62 float pressure = 96660;
63 float temperature = 290;
@@ -185,7 +191,7 @@
78
79 try {
80
-
81 SolarPosition solarposition_3(UTC, latitude, longitude, &context_s);
+
81 SolarPosition solarposition_3(UTC, latitude, longitude, &context_s);
82
83 float temperature = 290;
84 float humidity = 0.5;
@@ -207,7 +213,7 @@
100 auto test_getSunriseTime = [&error_count]() {
101 try {
102 Context context;
-
103 SolarPosition solarPos(8, 38.55, 121.76, &context);
+
103 SolarPosition solarPos(8, 38.55, 121.76, &context);
104 Time sunrise = solarPos.getSunriseTime();
105 }catch (std::exception &e) {
106 error_count++;
@@ -217,8 +223,8 @@
110 auto test_calibrateTurbidityFromTimeseries = [&error_count]() {
111 try {
112 Context context;
-
113 SolarPosition solarPos(8, 38.55, 121.76, &context);
-
114 context.addTimeseriesData("timeseries_shortwave_flux_label_Wm2", 1000, context.getDate(), context.getTime() );
+
113 SolarPosition solarPos(8, 38.55, 121.76, &context);
+
114 context.addTimeseriesData("timeseries_shortwave_flux_label_Wm2", 1000, context.getDate(), context.getTime() );
115 float turbidity = solarPos.calibrateTurbidityFromTimeseries("timeseries_shortwave_flux_label_Wm2");
116 }catch (std::exception &e) {
117 error_count++;
@@ -228,8 +234,8 @@
121 auto test_enableCloudCalibration = [&error_count]() {
122 try {
123 Context context;
-
124 SolarPosition solarPos(8, 38.55, 121.76, &context);
-
125 context.addTimeseriesData("timeseries_shortwave_flux_label_Wm2", 1000, context.getDate(), context.getTime() );
+
124 SolarPosition solarPos(8, 38.55, 121.76, &context);
+
125 context.addTimeseriesData("timeseries_shortwave_flux_label_Wm2", 1000, context.getDate(), context.getTime() );
126 solarPos.enableCloudCalibration("timeseries_shortwave_flux_label_Wm2");
127 }catch (std::exception &e) {
128 error_count++;
@@ -239,10 +245,10 @@
132 auto test_applyCloudCalibration = [&error_count]() {
133 try {
134 Context context;
-
135 SolarPosition solarPos(8, 38.55, 121.76, &context);
+
135 SolarPosition solarPos(8, 38.55, 121.76, &context);
136 float R_calc_Wm2 = 1000.0;
137 float fdiff_calc = 0.5;
-
138 context.addTimeseriesData("timeseries_shortwave_flux_label_Wm2", 1000, context.getDate(), context.getTime() );
+
138 context.addTimeseriesData("timeseries_shortwave_flux_label_Wm2", 1000, context.getDate(), context.getTime() );
139 solarPos.enableCloudCalibration("timeseries_shortwave_flux_label_Wm2");
140 solarPos.applyCloudCalibration(R_calc_Wm2, fdiff_calc);
141 }catch (std::exception &e) {
@@ -253,7 +259,7 @@
146 auto test_turbidityResidualFunction = [&error_count]() {
147 try {
148 Context context;
-
149 SolarPosition solarPos(8, 38.55, 121.76, &context);
+
149 SolarPosition solarPos(8, 38.55, 121.76, &context);
150 std::vector<float> parameters = {101325, 300, 0.5, 900.0};
151 float residual = turbidityResidualFunction(2.0, parameters, &solarPos);
152 }catch (std::exception &e) {
@@ -280,7 +286,7 @@
173}
- +
SolarPosition(helios::Context *context_ptr)
Solar position model default constructor. Initializes location based on the location set in the Conte...
float getSunAzimuth() const
Get the current sun azimuthal angle in radians for the current location. The sun angle is computed ba...
helios::Time getSunriseTime() const
Get the approximate time of sunrise at the current location.
float getSunElevation() const
Get the current sun elevation angle in radians for the current location. The sun angle is computed ba...
@@ -288,21 +294,21 @@
void enableCloudCalibration(const std::string &timeseries_shortwave_flux_label_Wm2)
Enable calibration of solar flux and diffuse fraction when possibility of clouds are present against ...
int selfTest() const
Function to perform a self-test of model functions.
Definition selfTest.cpp:5
float calibrateTurbidityFromTimeseries(const std::string &timeseries_shortwave_flux_label_Wm2) const
Calculate the turbidity value based on a timeseries of net radiation measurements.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
void setDate(int day, int month, int year)
Set simulation date by day, month, year.
Definition Context.cpp:1059
-
helios::Time getTime() const
Get the simulation time.
Definition Context.cpp:1166
-
helios::Date getDate() const
Get simulation date.
Definition Context.cpp:1099
void setTime(int minute, int hour)
Set simulation time.
Definition Context.cpp:1136
-
void addTimeseriesData(const char *label, float value, const Date &date, const Time &time)
Add a data point to timeseries of data.
Definition Context.cpp:1823
Time make_Time(int hour, int minute)
Make a Time vector.
Date make_Date(int day, int month, int year)
Make a Date vector.
- - + + diff --git a/doc/html/primitive_intersection_8cu.html b/doc/html/primitive_intersection_8cu.html index 536317397..2af44b57c 100644 --- a/doc/html/primitive_intersection_8cu.html +++ b/doc/html/primitive_intersection_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
Functions | @@ -809,10 +815,13 @@

+ + diff --git a/doc/html/primitive_intersection_8cu.js b/doc/html/primitive_intersection_8cu.js new file mode 100644 index 000000000..84b488af8 --- /dev/null +++ b/doc/html/primitive_intersection_8cu.js @@ -0,0 +1,15 @@ +var primitive_intersection_8cu = +[ + [ "bbox_bounds", "primitive_intersection_8cu.html#a463610deabc8971f8d92607f462e28f3", null ], + [ "bbox_intersect", "primitive_intersection_8cu.html#a4b1369e96290adffabbbcc86b92d8560", null ], + [ "disk_bounds", "primitive_intersection_8cu.html#aab2e16ff4d5a4bca2d90c49f777500e9", null ], + [ "disk_intersect", "primitive_intersection_8cu.html#a45dc4da4927abe579fd24be608e4cd75", null ], + [ "rectangle_bounds", "primitive_intersection_8cu.html#a31b2bef2ed3e97edbd08bfa1243e9d40", null ], + [ "rectangle_intersect", "primitive_intersection_8cu.html#a84078834a363095c77877d20e45cc16b", null ], + [ "tile_bounds", "primitive_intersection_8cu.html#a4fd84a7124be9fea427690a9a2442b3b", null ], + [ "tile_intersect", "primitive_intersection_8cu.html#ac645addc8bc3071933ca33a0f053af07", null ], + [ "triangle_bounds", "primitive_intersection_8cu.html#a0a93209b8d30eee91f87b1b714991b3a", null ], + [ "triangle_intersect", "primitive_intersection_8cu.html#a393a839ba1216483ca3d447e45d930ab", null ], + [ "voxel_bounds", "primitive_intersection_8cu.html#a904cdd1733732aa1a8dbaf2e958176a9", null ], + [ "voxel_intersect", "primitive_intersection_8cu.html#ac0a2a895d2e98227a3905e56939228fe", null ] +]; \ No newline at end of file diff --git a/doc/html/primitive_intersection_8cu_source.html b/doc/html/primitive_intersection_8cu_source.html index b72e5886b..3307df071 100644 --- a/doc/html/primitive_intersection_8cu_source.html +++ b/doc/html/primitive_intersection_8cu_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
primitiveIntersection.cu
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include <optix.h>
17#include <optixu/optixu_math_namespace.h>
18#include <optixu/optixu_matrix_namespace.h>
@@ -159,7 +166,8 @@
67rtBuffer<char, 1> twosided_flag;
68
69//----------------- Rectangle Primitive ----------------------//
-
70
+
70
+
72
73RT_PROGRAM void rectangle_intersect(int objID )
74{
@@ -241,7 +249,8 @@
150
151}
-
152
+
152
+
154
155RT_PROGRAM void rectangle_bounds (int objID, float result[6])
156{
@@ -257,7 +266,8 @@
166
167//----------------- Triangle Primitive ----------------------//
-
168
+
168
+
170
171RT_PROGRAM void triangle_intersect(int objID )
172{
@@ -341,7 +351,7 @@
250}
251
-
252
+
252
254RT_PROGRAM void triangle_bounds (int objID, float result[6])
255{
@@ -356,7 +366,8 @@
264
265//----------------- Disk Primitive ----------------------//
-
266
+
266
+
268
269RT_PROGRAM void disk_intersect(int objID )
270{
@@ -392,7 +403,7 @@
300}
301
-
302
+
302
304RT_PROGRAM void disk_bounds (int objID, float result[6])
305{
@@ -404,7 +415,8 @@
311
312//----------------- Voxel Primitive ----------------------//
-
313
+
313
+
315
316RT_PROGRAM void voxel_intersect(int objID )
317{
@@ -491,7 +503,8 @@
398
399}
-
400
+
400
+
402
403RT_PROGRAM void voxel_bounds (int objID, float result[6])
404{
@@ -503,7 +516,8 @@
410
411//----------------- Bounding Box Primitive ----------------------//
-
412
+
412
+
414
415RT_PROGRAM void bbox_intersect(int objID )
416{
@@ -551,7 +565,8 @@
458
459}
-
460
+
460
+
462
463RT_PROGRAM void bbox_bounds (int objID, float result[6])
464{
@@ -567,7 +582,8 @@
474
475//----------------- Tile Object ----------------------//
-
476
+
476
+
478
479RT_PROGRAM void tile_intersect(int objID )
480{
@@ -639,7 +655,8 @@
546
547}
-
548
+
548
+
550
551RT_PROGRAM void tile_bounds (int objID, float result[6])
552{
@@ -669,10 +686,13 @@
RT_PROGRAM void tile_intersect(int objID)
- -
+ + diff --git a/doc/html/radiation_2include_2random_8h_source.html b/doc/html/radiation_2include_2random_8h_source.html index 8e2d5cca3..85ebed8df 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
random.h
@@ -220,10 +226,13 @@
114}
float sum(const std::vector< float > &vect)
Sum of a vector of floats.
Definition global.cpp:1069
- -
+ + diff --git a/doc/html/radiation__beers_law.html b/doc/html/radiation__beers_law.html index 38af27112..04b24f69f 100644 --- a/doc/html/radiation__beers_law.html +++ b/doc/html/radiation__beers_law.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy
@@ -321,10 +327,13 @@

}

- - + + diff --git a/doc/html/radiation_basics.html b/doc/html/radiation_basics.html index e304bd13c..8f6d7baaf 100644 --- a/doc/html/radiation_basics.html +++ b/doc/html/radiation_basics.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Tutorial 10: Radiation model basics - tree light interception
@@ -197,10 +203,13 @@

- - + + diff --git a/doc/html/ray_generation_8cu.html b/doc/html/ray_generation_8cu.html index be7604838..40256e1d6 100644 --- a/doc/html/ray_generation_8cu.html +++ b/doc/html/ray_generation_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
Functions | @@ -602,10 +608,13 @@

+ + diff --git a/doc/html/ray_generation_8cu_source.html b/doc/html/ray_generation_8cu_source.html index 99255ed38..395ba254d 100644 --- a/doc/html/ray_generation_8cu_source.html +++ b/doc/html/ray_generation_8cu_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
rayGeneration.cu
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
16#include <optix_world.h>
17#include "RayTracing.cu.h"
18
@@ -375,7 +382,7 @@
283 }else if( source_types[rr]==1 || source_types[rr]==2 ){ //sphere source
284
285 //sample point on surface of sphere
-
286 float theta_s = acos_safe(1.f-2.f*rnd(prd.seed));
+
286 float theta_s = acos_safe(1.f-2.f*rnd(prd.seed));
287 float phi_s = rnd(prd.seed)*2.f*M_PI;
288 float3 sphere_point = 0.5*source_widths[rr].x*make_float3( sin(theta_s)*cos(phi_s), sin(theta_s)*sin(phi_s), cos(theta_s) );
289
@@ -387,7 +394,7 @@
295 uint N = 10;
296 for( uint j=0; j<N; j++ ){
297 for( uint i=0; i<N; i++ ){
-
298 float theta = acos_safe(1.f-2.f*(float(i)+0.5f)/float(N));
+
298 float theta = acos_safe(1.f-2.f*(float(i)+0.5f)/float(N));
299 float phi = (float(j)+0.5f)*2.f*M_PI/float(N);
300 float3 light_direction = make_float3( sin(theta)*cos(phi), sin(theta)*sin(phi), cos(theta) );
301 if( dot(light_direction,ray_direction)<0 ){
@@ -716,9 +723,9 @@
624
625 float t;
626 if( ptype==4 ){ //voxel
-
627 t = acos_safe(1.f-Rt);
+
627 t = acos_safe(1.f-Rt);
628 }else{ //other
-
629 t = asin_safe(sqrtf(Rt));
+
629 t = asin_safe(sqrtf(Rt));
630 }
631 float p = 2.f*M_PI*Rp;
632
@@ -750,7 +757,7 @@
658
659 }else{ //not a voxel
660
-
661 ray_direction = d_rotatePoint( ray_direction, acos_safe(normal.z), atan2(normal.y,normal.x) );
+
661 ray_direction = d_rotatePoint( ray_direction, acos_safe(normal.z), atan2(normal.y,normal.x) );
662
663 prd.strength = 1.f/float(dimx);
664
@@ -937,8 +944,6 @@
__device__ void d_transformPoint(const float(&transform_matrix)[16], float3 &v)
Function to transform a 3D point based on current affine transformation matrix on the GPU.
__device__ float d_magnitude(const float3 v)
Function to calculate the magnitude of float3 vector on the GPU.
__device__ float3 d_rotatePoint(const float3 &position, const float &theta, const float &phi)
-
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
-
float asin_safe(float x)
arcsine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:247
vec3 cross(const vec3 &a, const vec3 &b)
Cross product of two vec3 vectors.
unsigned char source_ID
Numerical identifier for radiation source corresponding to each ray.
@@ -949,10 +954,13 @@
unsigned char periodic_depth
Number of periodic boundary intersections for ray.
bool face
Face of primitive from which ray was launched (true=top, false=bottom)
- -
+ + diff --git a/doc/html/ray_hit_8cu.html b/doc/html/ray_hit_8cu.html index 8a88e95a1..f9189d8a1 100644 --- a/doc/html/ray_hit_8cu.html +++ b/doc/html/ray_hit_8cu.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
Functions | @@ -133,9 +139,12 @@  rtDeclareVariable (unsigned int, UUID, attribute UUID,)   -rtDeclareVariable (unsigned int, Nbands,,) -  +rtDeclareVariable (unsigned int, Nbands_launch,,) +  +rtDeclareVariable (unsigned int, Nbands_global,,) +   rtDeclareVariable (unsigned int, Nprimitives,,)   @@ -253,7 +262,7 @@

-

Definition at line 286 of file rayHit.cu.

+

Definition at line 290 of file rayHit.cu.

@@ -272,7 +281,7 @@

-

Definition at line 123 of file rayHit.cu.

+

Definition at line 124 of file rayHit.cu.

@@ -291,7 +300,7 @@

-

Definition at line 81 of file rayHit.cu.

+

Definition at line 82 of file rayHit.cu.

@@ -310,7 +319,7 @@

-

Definition at line 428 of file rayHit.cu.

+

Definition at line 432 of file rayHit.cu.

@@ -329,7 +338,7 @@

-

Definition at line 612 of file rayHit.cu.

+

Definition at line 622 of file rayHit.cu.

@@ -348,7 +357,7 @@

-

Definition at line 527 of file rayHit.cu.

+

Definition at line 534 of file rayHit.cu.

@@ -367,7 +376,7 @@

-

Definition at line 479 of file rayHit.cu.

+

Definition at line 483 of file rayHit.cu.

@@ -386,7 +395,7 @@

-

Definition at line 637 of file rayHit.cu.

+

Definition at line 647 of file rayHit.cu.

@@ -403,7 +412,7 @@

-

Definition at line 33 of file rayHit.cu.

+

Definition at line 34 of file rayHit.cu.

@@ -419,7 +428,7 @@

-

Definition at line 75 of file rayHit.cu.

+

Definition at line 76 of file rayHit.cu.

@@ -435,7 +444,7 @@

-

Definition at line 60 of file rayHit.cu.

+

Definition at line 61 of file rayHit.cu.

@@ -451,7 +460,7 @@

-

Definition at line 59 of file rayHit.cu.

+

Definition at line 60 of file rayHit.cu.

@@ -467,7 +476,7 @@

-

Definition at line 41 of file rayHit.cu.

+

Definition at line 42 of file rayHit.cu.

@@ -483,7 +492,7 @@

-

Definition at line 39 of file rayHit.cu.

+

Definition at line 40 of file rayHit.cu.

@@ -499,7 +508,7 @@

-

Definition at line 37 of file rayHit.cu.

+

Definition at line 38 of file rayHit.cu.

@@ -515,7 +524,7 @@

-

Definition at line 40 of file rayHit.cu.

+

Definition at line 41 of file rayHit.cu.

@@ -531,7 +540,7 @@

-

Definition at line 77 of file rayHit.cu.

+

Definition at line 78 of file rayHit.cu.

@@ -547,7 +556,7 @@

-

Definition at line 48 of file rayHit.cu.

+

Definition at line 49 of file rayHit.cu.

@@ -563,7 +572,7 @@

-

Definition at line 50 of file rayHit.cu.

+

Definition at line 51 of file rayHit.cu.

@@ -579,7 +588,7 @@

-

Definition at line 51 of file rayHit.cu.

+

Definition at line 52 of file rayHit.cu.

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

-

Definition at line 53 of file rayHit.cu.

+

Definition at line 54 of file rayHit.cu.

@@ -611,7 +620,7 @@

-

Definition at line 52 of file rayHit.cu.

+

Definition at line 53 of file rayHit.cu.

@@ -627,7 +636,7 @@

-

Definition at line 45 of file rayHit.cu.

+

Definition at line 46 of file rayHit.cu.

@@ -643,7 +652,7 @@

-

Definition at line 46 of file rayHit.cu.

+

Definition at line 47 of file rayHit.cu.

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

-

Definition at line 71 of file rayHit.cu.

+

Definition at line 72 of file rayHit.cu.

@@ -675,7 +684,7 @@

-

Definition at line 55 of file rayHit.cu.

+

Definition at line 56 of file rayHit.cu.

@@ -691,7 +700,7 @@

-

Definition at line 57 of file rayHit.cu.

+

Definition at line 58 of file rayHit.cu.

@@ -707,7 +716,7 @@

-

Definition at line 54 of file rayHit.cu.

+

Definition at line 55 of file rayHit.cu.

@@ -723,7 +732,7 @@

-

Definition at line 56 of file rayHit.cu.

+

Definition at line 57 of file rayHit.cu.

@@ -739,7 +748,7 @@

-

Definition at line 66 of file rayHit.cu.

+

Definition at line 67 of file rayHit.cu.

@@ -755,7 +764,7 @@

-

Definition at line 67 of file rayHit.cu.

+

Definition at line 68 of file rayHit.cu.

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

-

Definition at line 69 of file rayHit.cu.

+

Definition at line 70 of file rayHit.cu.

@@ -787,7 +796,7 @@

-

Definition at line 68 of file rayHit.cu.

+

Definition at line 69 of file rayHit.cu.

@@ -803,7 +812,7 @@

-

Definition at line 45 of file rayHit.cu.

+

Definition at line 46 of file rayHit.cu.

@@ -819,7 +828,7 @@

-

Definition at line 46 of file rayHit.cu.

+

Definition at line 47 of file rayHit.cu.

@@ -835,15 +844,18 @@

-

Definition at line 73 of file rayHit.cu.

+

Definition at line 74 of file rayHit.cu.

- - + + diff --git a/doc/html/ray_hit_8cu_source.html b/doc/html/ray_hit_8cu_source.html index bbddcf5fd..a147a98a3 100644 --- a/doc/html/ray_hit_8cu_source.html +++ b/doc/html/ray_hit_8cu_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
rayHit.cu
-Go to the documentation of this file.
1
+Go to the documentation of this file.
1
+
15
+
16
17#include <optix_world.h>
18#include <optixu/optixu_math_namespace.h>
19
@@ -120,628 +128,640 @@
29
30rtDeclareVariable( unsigned int, UUID, attribute UUID, );
31
-
32rtDeclareVariable( unsigned int, Nbands,, );
-
33rtBuffer<bool, 1> band_launch_flag;
-
34
-
35rtDeclareVariable( unsigned int, Nprimitives,, );
-
36
-
37rtBuffer<float, 1> diffuse_flux;
-
38
-
39rtBuffer<float, 1> diffuse_extinction;
-
40rtBuffer<float3, 1> diffuse_peak_dir;
-
41rtBuffer<float, 1> diffuse_dist_norm;
-
42
-
43rtDeclareVariable(float2, periodic_flag,, );
-
44
-
45rtBuffer<float, 1> rho, tau;
-
46rtBuffer<float, 1> rho_cam, tau_cam;
-
47
-
48rtBuffer<unsigned int, 1> primitive_type;
-
49
-
50rtBuffer<float, 1> radiation_in;
-
51rtBuffer<float, 1> radiation_in_camera;
-
52rtBuffer<float, 1> radiation_out_top;
-
53rtBuffer<float, 1> radiation_out_bottom;
-
54rtBuffer<float, 1> scatter_buff_top;
-
55rtBuffer<float, 1> scatter_buff_bottom;
-
56rtBuffer<float, 1> scatter_buff_top_cam;
-
57rtBuffer<float, 1> scatter_buff_bottom_cam;
-
58
-
59rtBuffer<unsigned int, 1> camera_pixel_label;
-
60rtBuffer<float, 1> camera_pixel_depth;
-
61rtDeclareVariable( unsigned int, camera_ID,, );
-
62rtDeclareVariable( unsigned int, Ncameras,, );
-
63
-
64//Radiation sources buffers
-
65rtDeclareVariable( unsigned int, Nsources, , );
-
66rtBuffer<float, 1> source_fluxes;
-
67rtBuffer<float3, 1> source_positions;
-
68rtBuffer<float2, 1> source_widths;
-
69rtBuffer<unsigned int, 1> source_types;
-
70
-
71rtBuffer<float, 1> Rsky;
-
72
-
73rtBuffer<float, 2> transform_matrix;
-
74
-
75rtBuffer<float3, 2> bbox_vertices;
-
76
-
77rtBuffer<uint, 1> objectID;
-
78
-
79rtDeclareVariable( float2, camera_direction, , );
-
80
-
81RT_PROGRAM void closest_hit_direct(){
-
82
-
83 uint objID = objectID[UUID];
-
84
-
85 float3 ray_origin = ray.origin;
-
86
-
87 if( (periodic_flag.x==1 || periodic_flag.y==1) && primitive_type[objID] == 5 ){ //periodic boundary condition
-
88
-
89 ray_origin = ray_origin + t_hit*ray.direction;
-
90
-
91 float eps=1e-4;
-
92
-
93 if( prd.periodic_depth<9 ) {
-
94
-
95 float2 xbounds = make_float2(bbox_vertices[make_uint2(0, 0)].x, bbox_vertices[make_uint2(1, 1)].x);
-
96 float2 ybounds = make_float2(bbox_vertices[make_uint2(0, 0)].y, bbox_vertices[make_uint2(1, 1)].y);
-
97
-
98 if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.x)<=eps ) {//-x facing boundary
-
99 ray_origin.x = xbounds.y - eps;
-
100 } else if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.y)<=eps ) {//+x facing boundary
-
101 ray_origin.x = xbounds.x + eps;
-
102 }
-
103 if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.x)<=eps ) {//-y facing boundary
-
104 ray_origin.y = ybounds.y - eps;
-
105 } else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.y)<=eps ) {//+y facing boundary
-
106 ray_origin.y = ybounds.x + eps;
-
107 }
-
108
-
109 }
-
110
-
111 float3 ray_direction = ray.direction;
-
112
-
113 optix::Ray ray_periodic = optix::make_Ray(ray_origin, ray_direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
-
114 PerRayData prd_periodic = prd;
-
115 prd_periodic.periodic_depth++;
-
116
-
117 rtTrace(top_object, ray_periodic, prd_periodic);
-
118
-
119 }
-
120
-
121};
-
122
-
123RT_PROGRAM void closest_hit_diffuse() {
-
124
-
125 uint origin_UUID = prd.origin_UUID;
-
126
-
127 uint objID = objectID[UUID];
-
128
-
129 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[objID] == 5) { //periodic boundary condition
-
130
-
131 float3 ray_origin = ray.origin + t_hit * ray.direction;
-
132
-
133 float eps = 1e-5;
-
134
-
135 if (prd.periodic_depth < 9) {
-
136
-
137 float2 xbounds = make_float2(bbox_vertices[make_uint2(0, 0)].x, bbox_vertices[make_uint2(1, 1)].x);
-
138 float2 ybounds = make_float2(bbox_vertices[make_uint2(0, 0)].y, bbox_vertices[make_uint2(1, 1)].y);
-
139
-
140 if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.x)<=eps ) {//-x facing boundary
-
141 ray_origin.x = xbounds.y - eps;
-
142 } else if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.y)<=eps ) {//+x facing boundary
-
143 ray_origin.x = xbounds.x + eps;
-
144 }else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.x)<=eps ) {//-y facing boundary
-
145 ray_origin.y = ybounds.y - eps;
-
146 } else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.y)<=eps ) {//+y facing boundary
-
147 ray_origin.y = ybounds.x + eps;
-
148 }
-
149
-
150 }
-
151
-
152 float3 ray_direction = ray.direction;
-
153
-
154 optix::Ray ray_periodic = optix::make_Ray(ray_origin, ray_direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
-
155 PerRayData prd_periodic = prd;
-
156 prd_periodic.periodic_depth++;
-
157
-
158 rtTrace(top_object, ray_periodic, prd_periodic);
-
159
-
160 } else {
-
161
-
162 //Note: UUID corresponds to the object that the ray hit (i.e., where energy is coming from), and UUID_origin is the object the ray originated from (i.e., where the energy is being recieved)
-
163
-
164 //find out if we hit top or bottom surface
-
165 float3 normal;
-
166
-
167 float m[16];
-
168 for (uint i = 0; i < 16; i++) {
-
169 m[i] = transform_matrix[optix::make_uint2(i, objID)];
-
170 }
-
171
-
172 if (primitive_type[objID] == 0 || primitive_type[objID] == 3) {//hit patch or tile
-
173 float3 s0 = make_float3(0, 0, 0);
-
174 float3 s1 = make_float3(1, 0, 0);
-
175 float3 s2 = make_float3(0, 1, 0);
-
176 d_transformPoint(m, s0);
-
177 d_transformPoint(m, s1);
-
178 d_transformPoint(m, s2);
-
179 normal = cross(s1 - s0, s2 - s0);
-
180 } else if (primitive_type[UUID] == 1) {//hit triangle
-
181 float3 v0 = make_float3(0, 0, 0);
-
182 d_transformPoint(m, v0);
-
183 float3 v1 = make_float3(0, 1, 0);
-
184 d_transformPoint(m, v1);
-
185 float3 v2 = make_float3(1, 1, 0);
-
186 d_transformPoint(m, v2);
-
187 normal = cross(v1 - v0, v2 - v1);
-
188 } else if (primitive_type[UUID] == 2) {//hit disk
-
189 float3 v0 = make_float3(0, 0, 0);
-
190 d_transformPoint(m, v0);
-
191 float3 v1 = make_float3(1, 0, 0);
-
192 d_transformPoint(m, v1);
-
193 float3 v2 = make_float3(0, 1, 0);
-
194 d_transformPoint(m, v2);
-
195 normal = cross(v1 - v0, v2 - v0);
-
196 } else if (primitive_type[UUID] == 4) {//hit voxel
-
197 float3 vmin = make_float3(-0.5, -0.5, -0.5);
-
198 d_transformPoint(m, vmin);
-
199 float3 vmax = make_float3(0.5, 0.5, 0.5);
-
200 d_transformPoint(m, vmax);
-
201 }
-
202 normal = normalize(normal);
-
203
-
204 bool face = dot(normal, ray.direction) < 0;
-
205
-
206 for (size_t b = 0; b < Nbands; b++) {
-
207
-
208 if( band_launch_flag[b]==0 ){
-
209 continue;
-
210 }
-
211
-
212 size_t ind_origin = Nbands * origin_UUID + b;
-
213 size_t ind_hit = Nbands * UUID + b;
+
32rtDeclareVariable( unsigned int, Nbands_launch,, );
+
33rtDeclareVariable( unsigned int, Nbands_global,, );
+
34rtBuffer<bool, 1> band_launch_flag;
+
35
+
36rtDeclareVariable( unsigned int, Nprimitives,, );
+
37
+
38rtBuffer<float, 1> diffuse_flux;
+
39
+
40rtBuffer<float, 1> diffuse_extinction;
+
41rtBuffer<float3, 1> diffuse_peak_dir;
+
42rtBuffer<float, 1> diffuse_dist_norm;
+
43
+
44rtDeclareVariable(float2, periodic_flag,, );
+
45
+
46rtBuffer<float, 1> rho, tau;
+
47rtBuffer<float, 1> rho_cam, tau_cam;
+
48
+
49rtBuffer<unsigned int, 1> primitive_type;
+
50
+
51rtBuffer<float, 1> radiation_in;
+
52rtBuffer<float, 1> radiation_in_camera;
+
53rtBuffer<float, 1> radiation_out_top;
+
54rtBuffer<float, 1> radiation_out_bottom;
+
55rtBuffer<float, 1> scatter_buff_top;
+
56rtBuffer<float, 1> scatter_buff_bottom;
+
57rtBuffer<float, 1> scatter_buff_top_cam;
+
58rtBuffer<float, 1> scatter_buff_bottom_cam;
+
59
+
60rtBuffer<unsigned int, 1> camera_pixel_label;
+
61rtBuffer<float, 1> camera_pixel_depth;
+
62rtDeclareVariable( unsigned int, camera_ID,, );
+
63rtDeclareVariable( unsigned int, Ncameras,, );
+
64
+
65//Radiation sources buffers
+
66rtDeclareVariable( unsigned int, Nsources, , );
+
67rtBuffer<float, 1> source_fluxes;
+
68rtBuffer<float3, 1> source_positions;
+
69rtBuffer<float2, 1> source_widths;
+
70rtBuffer<unsigned int, 1> source_types;
+
71
+
72rtBuffer<float, 1> Rsky;
+
73
+
74rtBuffer<float, 2> transform_matrix;
+
75
+
76rtBuffer<float3, 2> bbox_vertices;
+
77
+
78rtBuffer<uint, 1> objectID;
+
79
+
80rtDeclareVariable( float2, camera_direction, , );
+
81
+
82RT_PROGRAM void closest_hit_direct(){
+
83
+
84 uint objID = objectID[UUID];
+
85
+
86 float3 ray_origin = ray.origin;
+
87
+
88 if( (periodic_flag.x==1 || periodic_flag.y==1) && primitive_type[objID] == 5 ){ //periodic boundary condition
+
89
+
90 ray_origin = ray_origin + t_hit*ray.direction;
+
91
+
92 float eps=1e-4;
+
93
+
94 if( prd.periodic_depth<9 ) {
+
95
+
96 float2 xbounds = make_float2(bbox_vertices[make_uint2(0, 0)].x, bbox_vertices[make_uint2(1, 1)].x);
+
97 float2 ybounds = make_float2(bbox_vertices[make_uint2(0, 0)].y, bbox_vertices[make_uint2(1, 1)].y);
+
98
+
99 if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.x)<=eps ) {//-x facing boundary
+
100 ray_origin.x = xbounds.y - eps;
+
101 } else if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.y)<=eps ) {//+x facing boundary
+
102 ray_origin.x = xbounds.x + eps;
+
103 }
+
104 if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.x)<=eps ) {//-y facing boundary
+
105 ray_origin.y = ybounds.y - eps;
+
106 } else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.y)<=eps ) {//+y facing boundary
+
107 ray_origin.y = ybounds.x + eps;
+
108 }
+
109
+
110 }
+
111
+
112 float3 ray_direction = ray.direction;
+
113
+
114 optix::Ray ray_periodic = optix::make_Ray(ray_origin, ray_direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
+
115 PerRayData prd_periodic = prd;
+
116 prd_periodic.periodic_depth++;
+
117
+
118 rtTrace(top_object, ray_periodic, prd_periodic);
+
119
+
120 }
+
121
+
122};
+
123
+
124RT_PROGRAM void closest_hit_diffuse() {
+
125
+
126 uint origin_UUID = prd.origin_UUID;
+
127
+
128 uint objID = objectID[UUID];
+
129
+
130 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[objID] == 5) { //periodic boundary condition
+
131
+
132 float3 ray_origin = ray.origin + t_hit * ray.direction;
+
133
+
134 float eps = 1e-5;
+
135
+
136 if (prd.periodic_depth < 9) {
+
137
+
138 float2 xbounds = make_float2(bbox_vertices[make_uint2(0, 0)].x, bbox_vertices[make_uint2(1, 1)].x);
+
139 float2 ybounds = make_float2(bbox_vertices[make_uint2(0, 0)].y, bbox_vertices[make_uint2(1, 1)].y);
+
140
+
141 if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.x)<=eps ) {//-x facing boundary
+
142 ray_origin.x = xbounds.y - eps;
+
143 } else if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.y)<=eps ) {//+x facing boundary
+
144 ray_origin.x = xbounds.x + eps;
+
145 }else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.x)<=eps ) {//-y facing boundary
+
146 ray_origin.y = ybounds.y - eps;
+
147 } else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.y)<=eps ) {//+y facing boundary
+
148 ray_origin.y = ybounds.x + eps;
+
149 }
+
150
+
151 }
+
152
+
153 float3 ray_direction = ray.direction;
+
154
+
155 optix::Ray ray_periodic = optix::make_Ray(ray_origin, ray_direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
+
156 PerRayData prd_periodic = prd;
+
157 prd_periodic.periodic_depth++;
+
158
+
159 rtTrace(top_object, ray_periodic, prd_periodic);
+
160
+
161 } else {
+
162
+
163 //Note: UUID corresponds to the object that the ray hit (i.e., where energy is coming from), and UUID_origin is the object the ray originated from (i.e., where the energy is being recieved)
+
164
+
165 //find out if we hit top or bottom surface
+
166 float3 normal;
+
167
+
168 float m[16];
+
169 for (uint i = 0; i < 16; i++) {
+
170 m[i] = transform_matrix[optix::make_uint2(i, objID)];
+
171 }
+
172
+
173 if (primitive_type[objID] == 0 || primitive_type[objID] == 3) {//hit patch or tile
+
174 float3 s0 = make_float3(0, 0, 0);
+
175 float3 s1 = make_float3(1, 0, 0);
+
176 float3 s2 = make_float3(0, 1, 0);
+
177 d_transformPoint(m, s0);
+
178 d_transformPoint(m, s1);
+
179 d_transformPoint(m, s2);
+
180 normal = cross(s1 - s0, s2 - s0);
+
181 } else if (primitive_type[UUID] == 1) {//hit triangle
+
182 float3 v0 = make_float3(0, 0, 0);
+
183 d_transformPoint(m, v0);
+
184 float3 v1 = make_float3(0, 1, 0);
+
185 d_transformPoint(m, v1);
+
186 float3 v2 = make_float3(1, 1, 0);
+
187 d_transformPoint(m, v2);
+
188 normal = cross(v1 - v0, v2 - v1);
+
189 } else if (primitive_type[UUID] == 2) {//hit disk
+
190 float3 v0 = make_float3(0, 0, 0);
+
191 d_transformPoint(m, v0);
+
192 float3 v1 = make_float3(1, 0, 0);
+
193 d_transformPoint(m, v1);
+
194 float3 v2 = make_float3(0, 1, 0);
+
195 d_transformPoint(m, v2);
+
196 normal = cross(v1 - v0, v2 - v0);
+
197 } else if (primitive_type[UUID] == 4) {//hit voxel
+
198 float3 vmin = make_float3(-0.5, -0.5, -0.5);
+
199 d_transformPoint(m, vmin);
+
200 float3 vmax = make_float3(0.5, 0.5, 0.5);
+
201 d_transformPoint(m, vmax);
+
202 }
+
203 normal = normalize(normal);
+
204
+
205 bool face = dot(normal, ray.direction) < 0;
+
206
+
207 int b = -1;
+
208 for (int b_global = 0; b_global < Nbands_global; b_global++) {
+
209
+
210 if( band_launch_flag[b_global]==0 ){
+
211 continue;
+
212 }
+
213 b++;
214
-
215 double strength;
-
216 if (face || primitive_type[objID] == 4) {
-
217 strength = radiation_out_top[ ind_hit ] * prd.strength;
-
218 } else {
-
219 strength = radiation_out_bottom[ ind_hit ] * prd.strength;
-
220 }
-
221
-
222 if( strength==0 ){
-
223 continue;
-
224 }
-
225
-
226 float t_rho = rho[ Nprimitives*Nbands*prd.source_ID + Nbands*origin_UUID + b ];
-
227 float t_tau = tau[ Nprimitives*Nbands*prd.source_ID + Nbands*origin_UUID + b ];
+
215 size_t ind_origin = Nbands_launch * origin_UUID + b;
+
216 size_t ind_hit = Nbands_launch * UUID + b;
+
217
+
218 double strength;
+
219 if (face || primitive_type[objID] == 4) {
+
220 strength = radiation_out_top[ ind_hit ] * prd.strength;
+
221 } else {
+
222 strength = radiation_out_bottom[ ind_hit ] * prd.strength;
+
223 }
+
224
+
225 if( strength==0 ){
+
226 continue;
+
227 }
228
-
229 if (primitive_type[objectID[origin_UUID]] == 4) { //ray was launched from voxel
-
230
-
231// float kappa = t_rho; //just a reminder that rho is actually the absorption coefficient
-
232// float sigma_s = t_tau; //just a reminder that tau is actually the scattering coefficient
-
233// float beta = kappa + sigma_s;
-
234//
-
235// // absorption
-
236// atomicAdd(&radiation_in[ind_origin], strength * exp(-beta * 0.5 * prd.area) * kappa / beta);
-
237//
-
238// // scattering
-
239// atomicAdd(&scatter_buff_top[ind_origin], strength * exp(-beta * 0.5 * prd.area) * sigma_s / beta);
-
240
-
241 } else { //ray was NOT launched from voxel
-
242
-
243 // absorption
-
244 atomicAdd(&radiation_in[ind_origin], strength * (1.f - t_rho - t_tau));
-
245
-
246 if ((t_rho > 0 || t_tau > 0) && strength > 0) {
-
247 if (prd.face) {//reflection from top, transmission from bottom
-
248 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho); //reflection
-
249 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau); //transmission
-
250 } else {//reflection from bottom, transmission from top
-
251 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho); //reflection
-
252 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau); //transmission
-
253 }
-
254 }
-
255 if( Ncameras>0 ) {
-
256 size_t indc = prd.source_ID*Nprimitives*Nbands*Ncameras + origin_UUID*Nbands*Ncameras + b*Ncameras + camera_ID;
-
257 float t_rho_cam = rho_cam[ indc ];
-
258 float t_tau_cam = tau_cam[ indc ];
-
259 if ((t_rho_cam > 0 || t_tau_cam > 0) && strength > 0) {
-
260 if (prd.face) {//reflection from top, transmission from bottom
-
261 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam); //reflection
-
262 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam); //transmission
-
263 } else {//reflection from bottom, transmission from top
-
264 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam); //reflection
-
265 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam); //transmission
-
266 }
-
267 }
-
268 }
-
269 }
-
270
-
271 // if( primitive_type[UUID] == 4 ){ //if we hit a voxel, reduce strength and launch another ray
-
272 // optix::Ray ray_transmit = optix::make_Ray(ray.origin+(t_hit+prd.area+1e-5)*ray.direction, ray.direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
-
273 // PerRayData prd_transmit = prd;
-
274 // float beta = rho[UUID]+tau[UUID];
-
275 // prd_transmit.strength = prd.strength*(1.f-exp(-beta*0.5*prd.area));
-
276 // rtTrace( top_object, ray_transmit, prd_transmit);
-
277 // }
-
278
-
279
-
280 }
-
281
-
282 }
+
229 size_t radprop_ind_global = Nprimitives*Nbands_global*prd.source_ID + Nbands_global*origin_UUID + b_global;
+
230 float t_rho = rho[ radprop_ind_global ];
+
231 float t_tau = tau[ radprop_ind_global ];
+
232
+
233 if (primitive_type[objectID[origin_UUID]] == 4) { //ray was launched from voxel
+
234
+
235// float kappa = t_rho; //just a reminder that rho is actually the absorption coefficient
+
236// float sigma_s = t_tau; //just a reminder that tau is actually the scattering coefficient
+
237// float beta = kappa + sigma_s;
+
238//
+
239// // absorption
+
240// atomicAdd(&radiation_in[ind_origin], strength * exp(-beta * 0.5 * prd.area) * kappa / beta);
+
241//
+
242// // scattering
+
243// atomicAdd(&scatter_buff_top[ind_origin], strength * exp(-beta * 0.5 * prd.area) * sigma_s / beta);
+
244
+
245 } else { //ray was NOT launched from voxel
+
246
+
247 // absorption
+
248 atomicAdd(&radiation_in[ind_origin], strength * (1.f - t_rho - t_tau));
+
249
+
250 if ((t_rho > 0 || t_tau > 0) && strength > 0) {
+
251 if (prd.face) {//reflection from top, transmission from bottom
+
252 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho); //reflection
+
253 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau); //transmission
+
254 } else {//reflection from bottom, transmission from top
+
255 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho); //reflection
+
256 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau); //transmission
+
257 }
+
258 }
+
259 if( Ncameras>0 ) {
+
260 size_t indc = prd.source_ID*Nprimitives*Nbands_global*Ncameras + origin_UUID*Nbands_global*Ncameras + b_global*Ncameras + camera_ID;
+
261 float t_rho_cam = rho_cam[ indc ];
+
262 float t_tau_cam = tau_cam[ indc ];
+
263 if ((t_rho_cam > 0 || t_tau_cam > 0) && strength > 0) {
+
264 if (prd.face) {//reflection from top, transmission from bottom
+
265 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam); //reflection
+
266 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam); //transmission
+
267 } else {//reflection from bottom, transmission from top
+
268 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam); //reflection
+
269 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam); //transmission
+
270 }
+
271 }
+
272 }
+
273 }
+
274
+
275 // if( primitive_type[UUID] == 4 ){ //if we hit a voxel, reduce strength and launch another ray
+
276 // optix::Ray ray_transmit = optix::make_Ray(ray.origin+(t_hit+prd.area+1e-5)*ray.direction, ray.direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
+
277 // PerRayData prd_transmit = prd;
+
278 // float beta = rho[UUID]+tau[UUID];
+
279 // prd_transmit.strength = prd.strength*(1.f-exp(-beta*0.5*prd.area));
+
280 // rtTrace( top_object, ray_transmit, prd_transmit);
+
281 // }
+
282
283
-
284}
+
284 }
285
-
286RT_PROGRAM void closest_hit_camera() {
+
286 }
287
-
288 uint objID = objectID[UUID];
+
288}
289
-
290 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[objID] == 5) { //periodic boundary condition
+
290RT_PROGRAM void closest_hit_camera() {
291
-
292 float3 ray_origin = ray.origin + t_hit * ray.direction;
+
292 uint objID = objectID[UUID];
293
-
294 float eps = 1e-5;
+
294 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[objID] == 5) { //periodic boundary condition
295
-
296 if (prd.periodic_depth < 9) {
+
296 float3 ray_origin = ray.origin + t_hit * ray.direction;
297
-
298 float2 xbounds = make_float2(bbox_vertices[make_uint2(0, 0)].x, bbox_vertices[make_uint2(1, 1)].x);
-
299 float2 ybounds = make_float2(bbox_vertices[make_uint2(0, 0)].y, bbox_vertices[make_uint2(1, 1)].y);
-
300
-
301 if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.x)<=eps ) {//-x facing boundary
-
302 ray_origin.x = xbounds.y - eps;
-
303 } else if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.y)<=eps ) {//+x facing boundary
-
304 ray_origin.x = xbounds.x + eps;
-
305 }
-
306 if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.x)<=eps ) {//-y facing boundary
-
307 ray_origin.y = ybounds.y - eps;
-
308 } else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.y)<=eps ) {//+y facing boundary
-
309 ray_origin.y = ybounds.x + eps;
-
310 }
-
311
-
312 }
-
313
-
314 float3 ray_direction = ray.direction;
+
298 float eps = 1e-5;
+
299
+
300 if (prd.periodic_depth < 9) {
+
301
+
302 float2 xbounds = make_float2(bbox_vertices[make_uint2(0, 0)].x, bbox_vertices[make_uint2(1, 1)].x);
+
303 float2 ybounds = make_float2(bbox_vertices[make_uint2(0, 0)].y, bbox_vertices[make_uint2(1, 1)].y);
+
304
+
305 if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.x)<=eps ) {//-x facing boundary
+
306 ray_origin.x = xbounds.y - eps;
+
307 } else if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.y)<=eps ) {//+x facing boundary
+
308 ray_origin.x = xbounds.x + eps;
+
309 }
+
310 if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.x)<=eps ) {//-y facing boundary
+
311 ray_origin.y = ybounds.y - eps;
+
312 } else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.y)<=eps ) {//+y facing boundary
+
313 ray_origin.y = ybounds.x + eps;
+
314 }
315
-
316 optix::Ray ray_periodic = optix::make_Ray(ray_origin, ray_direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
-
317 PerRayData prd_periodic = prd;
-
318 prd_periodic.periodic_depth++;
+
316 }
+
317
+
318 float3 ray_direction = ray.direction;
319
-
320 rtTrace(top_object, ray_periodic, prd_periodic);
-
321
-
322 } else {
+
320 optix::Ray ray_periodic = optix::make_Ray(ray_origin, ray_direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
+
321 PerRayData prd_periodic = prd;
+
322 prd_periodic.periodic_depth++;
323
-
324 //Note: UUID corresponds to the object that the ray hit (i.e., where energy is coming from), and UUID_origin is the object the ray originated from (i.e., where the energy is being received)
+
324 rtTrace(top_object, ray_periodic, prd_periodic);
325
-
326 //find out if we hit top or bottom surface // per each ray
-
327 float3 normal;
-
328
-
329 float m[16];
-
330 for (uint i = 0; i < 16; i++) {
-
331 m[i] = transform_matrix[optix::make_uint2(i, objID)];
-
332 }
-
333
-
334 if (primitive_type[objID] == 0 || primitive_type[objID] == 3) {//hit patch or tile
-
335 float3 s0 = make_float3(0, 0, 0);
-
336 float3 s1 = make_float3(1, 0, 0);
-
337 float3 s2 = make_float3(0, 1, 0);
-
338 d_transformPoint(m, s0);
-
339 d_transformPoint(m, s1);
-
340 d_transformPoint(m, s2);
-
341 normal = cross(s1 - s0, s2 - s0);
-
342 } else if (primitive_type[UUID] == 1) {//hit triangle
-
343 float3 v0 = make_float3(0, 0, 0);
-
344 d_transformPoint(m, v0);
-
345 float3 v1 = make_float3(0, 1, 0);
-
346 d_transformPoint(m, v1);
-
347 float3 v2 = make_float3(1, 1, 0);
-
348 d_transformPoint(m, v2);
-
349 normal = cross(v1 - v0, v2 - v1);
-
350 } else if (primitive_type[UUID] == 2) {//hit disk
-
351 float3 v0 = make_float3(0, 0, 0);
-
352 d_transformPoint(m, v0);
-
353 float3 v1 = make_float3(1, 0, 0);
-
354 d_transformPoint(m, v1);
-
355 float3 v2 = make_float3(0, 1, 0);
-
356 d_transformPoint(m, v2);
-
357 normal = cross(v1 - v0, v2 - v0);
-
358 } else if (primitive_type[UUID] == 4) {//hit voxel
-
359 float3 vmin = make_float3(-0.5, -0.5, -0.5);
-
360 d_transformPoint(m, vmin);
-
361 float3 vmax = make_float3(0.5, 0.5, 0.5);
-
362 d_transformPoint(m, vmax);
-
363 }
-
364 normal = normalize(normal);
-
365
-
366 bool face = dot(normal, ray.direction) < 0;
-
367
-
368
-
369 float3 camera_normal = d_rotatePoint( make_float3(0,0,1), -0.5*M_PI+camera_direction.x, 0.5f*M_PI-camera_direction.y );
-
370
-
371 double strength;
-
372 for( size_t b=0; b<Nbands; b++ ) {
-
373
-
374 if (face || primitive_type[objID] == 4) {
-
375 strength = radiation_out_top[Nbands * UUID + b] * prd.strength; //this one /fabs(dot())
-
376 } else {
-
377 strength = radiation_out_bottom[Nbands * UUID + b] * prd.strength;
-
378 }
-
379
-
380
-
381 //specular reflection
-
382
-
383// float strength_spec = 0;
-
384// for( int rr=0; rr<Nsources; rr++ ) {
-
385//
-
386// //light direction
-
387// float3 light_direction;
-
388// float light_magnitude;
-
389// float spec = 0;
-
390// if (source_types[rr] == 0) { //collimated source
-
391// light_direction = normalize(source_positions[rr]);
-
392// spec = fabs(dot(normal, light_direction)) * source_fluxes[rr*Nbands + b];
-
393//
-
394// } else { //sphere source
-
395//
-
396// float3 ray_origin = ray.origin + t_hit * ray.direction;
+
326 } else {
+
327
+
328 //Note: UUID corresponds to the object that the ray hit (i.e., where energy is coming from), and UUID_origin is the object the ray originated from (i.e., where the energy is being received)
+
329
+
330 //find out if we hit top or bottom surface // per each ray
+
331 float3 normal;
+
332
+
333 float m[16];
+
334 for (uint i = 0; i < 16; i++) {
+
335 m[i] = transform_matrix[optix::make_uint2(i, objID)];
+
336 }
+
337
+
338 if (primitive_type[objID] == 0 || primitive_type[objID] == 3) {//hit patch or tile
+
339 float3 s0 = make_float3(0, 0, 0);
+
340 float3 s1 = make_float3(1, 0, 0);
+
341 float3 s2 = make_float3(0, 1, 0);
+
342 d_transformPoint(m, s0);
+
343 d_transformPoint(m, s1);
+
344 d_transformPoint(m, s2);
+
345 normal = cross(s1 - s0, s2 - s0);
+
346 } else if (primitive_type[UUID] == 1) {//hit triangle
+
347 float3 v0 = make_float3(0, 0, 0);
+
348 d_transformPoint(m, v0);
+
349 float3 v1 = make_float3(0, 1, 0);
+
350 d_transformPoint(m, v1);
+
351 float3 v2 = make_float3(1, 1, 0);
+
352 d_transformPoint(m, v2);
+
353 normal = cross(v1 - v0, v2 - v1);
+
354 } else if (primitive_type[UUID] == 2) {//hit disk
+
355 float3 v0 = make_float3(0, 0, 0);
+
356 d_transformPoint(m, v0);
+
357 float3 v1 = make_float3(1, 0, 0);
+
358 d_transformPoint(m, v1);
+
359 float3 v2 = make_float3(0, 1, 0);
+
360 d_transformPoint(m, v2);
+
361 normal = cross(v1 - v0, v2 - v0);
+
362 } else if (primitive_type[UUID] == 4) {//hit voxel
+
363 float3 vmin = make_float3(-0.5, -0.5, -0.5);
+
364 d_transformPoint(m, vmin);
+
365 float3 vmax = make_float3(0.5, 0.5, 0.5);
+
366 d_transformPoint(m, vmax);
+
367 }
+
368 normal = normalize(normal);
+
369
+
370 bool face = dot(normal, ray.direction) < 0;
+
371
+
372
+
373 float3 camera_normal = d_rotatePoint( make_float3(0,0,1), -0.5*M_PI+camera_direction.x, 0.5f*M_PI-camera_direction.y );
+
374
+
375 double strength;
+
376 for( size_t b=0; b<Nbands_launch; b++ ) {
+
377
+
378 if (face || primitive_type[objID] == 4) {
+
379 strength = radiation_out_top[Nbands_launch * UUID + b] * prd.strength; //this one /fabs(dot())
+
380 } else {
+
381 strength = radiation_out_bottom[Nbands_launch * UUID + b] * prd.strength;
+
382 }
+
383
+
384
+
385 //specular reflection
+
386
+
387// float strength_spec = 0;
+
388// for( int rr=0; rr<Nsources; rr++ ) {
+
389//
+
390// //light direction
+
391// float3 light_direction;
+
392// float light_magnitude;
+
393// float spec = 0;
+
394// if (source_types[rr] == 0) { //collimated source
+
395// light_direction = normalize(source_positions[rr]);
+
396// spec = fabs(dot(normal, light_direction)) * source_fluxes[rr*Nbands_launch + b];
397//
-
398// //sample point on surface of sphere
-
399// float theta_s = acos_safe(1.f - 2.f * rnd(prd.seed));
-
400// float phi_s = rnd(prd.seed) * 2.f * M_PI;
-
401// float3 sphere_point = 0.5 * source_widths[rr].x * make_float3(sin(theta_s) * cos(phi_s), sin(theta_s) * sin(phi_s), cos(theta_s));
-
402//
-
403// light_direction = sphere_point + source_positions[rr] - ray_origin;
-
404//
-
405// light_magnitude = d_magnitude(light_direction);
-
406// light_direction = normalize(light_direction);
-
407// spec = fabs(dot(normal, light_direction)) * source_fluxes[ rr*Nbands + b] * fabs(dot(normal, light_direction)) / (light_magnitude * light_magnitude)*source_widths[rr].x*source_widths[rr].x;
-
408// }
-
409//
-
410// float3 specular_direction = normalize(2 * abs(dot(light_direction, normal)) * normal - light_direction);
-
411//
-
412// strength_spec += spec * powf( abs(dot(specular_direction,ray.direction)), 1.7f) *1.f/float(launch_dim.x*launch_dim.y);
+
398// } else { //sphere source
+
399//
+
400// float3 ray_origin = ray.origin + t_hit * ray.direction;
+
401//
+
402// //sample point on surface of sphere
+
403// float theta_s = acos_safe(1.f - 2.f * rnd(prd.seed));
+
404// float phi_s = rnd(prd.seed) * 2.f * M_PI;
+
405// float3 sphere_point = 0.5 * source_widths[rr].x * make_float3(sin(theta_s) * cos(phi_s), sin(theta_s) * sin(phi_s), cos(theta_s));
+
406//
+
407// light_direction = sphere_point + source_positions[rr] - ray_origin;
+
408//
+
409// light_magnitude = d_magnitude(light_direction);
+
410// light_direction = normalize(light_direction);
+
411// spec = fabs(dot(normal, light_direction)) * source_fluxes[ rr*Nbands_launch + b] * fabs(dot(normal, light_direction)) / (light_magnitude * light_magnitude)*source_widths[rr].x*source_widths[rr].x;
+
412// }
413//
+
414// float3 specular_direction = normalize(2 * abs(dot(light_direction, normal)) * normal - light_direction);
415//
-
416// }
-
417
-
418 // absorption
-
419
-
420 atomicAdd(&radiation_in_camera[Nbands * prd.origin_UUID + b], strength );
-
421// atomicAdd(&radiation_in_camera[Nbands * prd.origin_UUID + b], strength+strength_spec );
-
422
-
423 }
-
424
-
425 }
-
426}
-
427
-
428RT_PROGRAM void closest_hit_pixel_label() {
-
429
-
430 uint origin_UUID = prd.origin_UUID;
+
416// strength_spec += spec * powf( abs(dot(specular_direction,ray.direction)), 1.7f) *1.f/float(launch_dim.x*launch_dim.y);
+
417//
+
419//
+
420// }
+
421
+
422 // absorption
+
423
+
424 atomicAdd(&radiation_in_camera[Nbands_launch * prd.origin_UUID + b], strength );
+
425// atomicAdd(&radiation_in_camera[Nbands_launch * prd.origin_UUID + b], strength+strength_spec );
+
426
+
427 }
+
428
+
429 }
+
430}
431
-
432 uint objID = objectID[UUID];
+
432RT_PROGRAM void closest_hit_pixel_label() {
433
-
434 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[objID] == 5) { //periodic boundary condition
+
434 uint origin_UUID = prd.origin_UUID;
435
-
436 float3 ray_origin = ray.origin + t_hit * ray.direction;
+
436 uint objID = objectID[UUID];
437
-
438 float eps = 1e-5;
+
438 if ((periodic_flag.x == 1 || periodic_flag.y == 1) && primitive_type[objID] == 5) { //periodic boundary condition
439
-
440 if (prd.periodic_depth < 9) {
+
440 float3 ray_origin = ray.origin + t_hit * ray.direction;
441
-
442 float2 xbounds = make_float2(bbox_vertices[make_uint2(0, 0)].x, bbox_vertices[make_uint2(1, 1)].x);
-
443 float2 ybounds = make_float2(bbox_vertices[make_uint2(0, 0)].y, bbox_vertices[make_uint2(1, 1)].y);
-
444
-
445 if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.x)<=eps ) {//-x facing boundary
-
446 ray_origin.x = xbounds.y - eps;
-
447 } else if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.y)<=eps ) {//+x facing boundary
-
448 ray_origin.x = xbounds.x + eps;
-
449 }else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.x)<=eps ) {//-y facing boundary
-
450 ray_origin.y = ybounds.y - eps;
-
451 } else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.y)<=eps ) {//+y facing boundary
-
452 ray_origin.y = ybounds.x + eps;
-
453 }
-
454
-
455 }
-
456
-
457 float3 ray_direction = ray.direction;
+
442 float eps = 1e-5;
+
443
+
444 if (prd.periodic_depth < 9) {
+
445
+
446 float2 xbounds = make_float2(bbox_vertices[make_uint2(0, 0)].x, bbox_vertices[make_uint2(1, 1)].x);
+
447 float2 ybounds = make_float2(bbox_vertices[make_uint2(0, 0)].y, bbox_vertices[make_uint2(1, 1)].y);
+
448
+
449 if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.x)<=eps ) {//-x facing boundary
+
450 ray_origin.x = xbounds.y - eps;
+
451 } else if ( periodic_flag.x == 1 && fabs(ray_origin.x-xbounds.y)<=eps ) {//+x facing boundary
+
452 ray_origin.x = xbounds.x + eps;
+
453 }else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.x)<=eps ) {//-y facing boundary
+
454 ray_origin.y = ybounds.y - eps;
+
455 } else if ( periodic_flag.y == 1 && fabs(ray_origin.y-ybounds.y)<=eps ) {//+y facing boundary
+
456 ray_origin.y = ybounds.x + eps;
+
457 }
458
-
459 optix::Ray ray_periodic = optix::make_Ray(ray_origin, ray_direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
-
460 PerRayData prd_periodic = prd;
-
461 prd_periodic.periodic_depth++;
-
462 prd_periodic.strength += t_hit;
-
463
-
464 rtTrace(top_object, ray_periodic, prd_periodic);
-
465
-
466 } else {
+
459 }
+
460
+
461 float3 ray_direction = ray.direction;
+
462
+
463 optix::Ray ray_periodic = optix::make_Ray(ray_origin, ray_direction, ray.ray_type, 1e-4, RT_DEFAULT_MAX);
+
464 PerRayData prd_periodic = prd;
+
465 prd_periodic.periodic_depth++;
+
466 prd_periodic.strength += t_hit;
467
-
468 //Note: UUID corresponds to the object that the ray hit (i.e., where energy is coming from), and UUID_origin is the object the ray originated from (i.e., where the energy is being received)
-
469 //Note: We are reserving a value of 0 for the sky, so we will store UUID+1
-
470 camera_pixel_label[origin_UUID] = UUID+1;
+
468 rtTrace(top_object, ray_periodic, prd_periodic);
+
469
+
470 } else {
471
-
472 float depth = prd.strength + t_hit;
-
473 float3 camera_direction3 = d_rotatePoint( make_float3(1,0,0), -0.5*M_PI+camera_direction.x, 0.5f*M_PI-camera_direction.y );
-
474 camera_pixel_depth[origin_UUID] = abs(dot(camera_direction3, ray.direction))*depth;
+
472 //Note: UUID corresponds to the object that the ray hit (i.e., where energy is coming from), and UUID_origin is the object the ray originated from (i.e., where the energy is being received)
+
473 //Note: We are reserving a value of 0 for the sky, so we will store UUID+1
+
474 camera_pixel_label[origin_UUID] = UUID+1;
475
-
476 }
-
477}
-
478
-
479RT_PROGRAM void miss_direct(){
-
480
-
481 uint objID = objectID[prd.origin_UUID];
+
476 float depth = prd.strength + t_hit;
+
477 float3 camera_direction3 = d_rotatePoint( make_float3(1,0,0), -0.5*M_PI+camera_direction.x, 0.5f*M_PI-camera_direction.y );
+
478 camera_pixel_depth[origin_UUID] = abs(dot(camera_direction3, ray.direction))*depth;
+
479
+
480 }
+
481}
482
-
483 for( size_t b=0; b<Nbands; b++ ) {
+
483RT_PROGRAM void miss_direct(){
484
-
485 if( band_launch_flag[b]==0 ){
-
486 continue;
-
487 }
-
488
-
489 size_t ind_origin = Nbands*prd.origin_UUID+b;
-
490
-
491 float t_rho = rho[Nprimitives*Nbands*prd.source_ID+Nbands*prd.origin_UUID+b];
-
492 float t_tau = tau[Nprimitives*Nbands*prd.source_ID+Nbands*prd.origin_UUID+b];
-
493
-
494 double strength = prd.strength * source_fluxes[ prd.source_ID*Nbands + b ];
-
495
-
496 //absorption
-
497 atomicAdd(&radiation_in[ind_origin], strength * (1.f - t_rho - t_tau) );
-
498
-
499 if (t_rho > 0 || t_tau > 0) {
-
500 if (prd.face) {//reflection from top, transmission from bottom
-
501 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho); //reflection
-
502 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau); //transmission
-
503 } else {//reflection from bottom, transmission from top
-
504 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho); //reflection
-
505 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau); //transmission
-
506 }
-
507 }
-
508 if( Ncameras>0 ) {
-
509 size_t indc = prd.source_ID*Nprimitives*Nbands*Ncameras + prd.origin_UUID*Nbands*Ncameras + b*Ncameras + camera_ID;
-
510 float t_rho_cam = rho_cam[ indc ];
-
511 float t_tau_cam = tau_cam[ indc ];
-
512 if ( (t_rho_cam > 0 || t_tau_cam > 0) && strength>0 ) {
-
513 if (prd.face) {//reflection from top, transmission from bottom
-
514 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam); //reflection
-
515 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam); //transmission
-
516 } else {//reflection from bottom, transmission from top
-
517 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam); //reflection
-
518 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam); //transmission
-
519 }
-
520 }
-
521 }
-
522
-
523 }
-
524
-
525}
-
526
-
527RT_PROGRAM void miss_diffuse() {
-
528
-
529// double strength;
-
530// if (prd.face || primitive_type[objectID[prd.origin_UUID]] == 3) {
-
531// strength = radiation_out_top[prd.origin_UUID] * prd.strength * prd.area;
-
532// } else {
-
533// strength = radiation_out_bottom[prd.origin_UUID] * prd.strength * prd.area;
-
534// }
-
535//
-
536// atomicFloatAdd(&Rsky[prd.origin_UUID], strength);
-
537
-
538 for( size_t b=0; b<Nbands; b++ ) {
-
539
-
540 if( band_launch_flag[b]==0 ){
-
541 continue;
-
542 }
-
543
-
544 if (diffuse_flux[b] > 0.f) {
-
545
-
546 size_t ind_origin = Nbands * prd.origin_UUID + b;
+
485 uint objID = objectID[prd.origin_UUID];
+
486
+
487 int b=-1;
+
488 for( int b_global=0; b_global<Nbands_global; b_global++ ) {
+
489
+
490 if( band_launch_flag[b_global]==0 ){
+
491 continue;
+
492 }
+
493 b++;
+
494
+
495 size_t ind_origin = Nbands_launch*prd.origin_UUID+b;
+
496
+
497 size_t radprop_ind_global = Nprimitives*Nbands_global*prd.source_ID + Nbands_global*prd.origin_UUID + b_global;
+
498 float t_rho = rho[ radprop_ind_global ];
+
499 float t_tau = tau[ radprop_ind_global ];
+
500
+
501 double strength = prd.strength * source_fluxes[ prd.source_ID*Nbands_launch + b ];
+
502
+
503 //absorption
+
504 atomicAdd(&radiation_in[ind_origin], strength * (1.f - t_rho - t_tau) );
+
505
+
506 if (t_rho > 0 || t_tau > 0) {
+
507 if (prd.face) {//reflection from top, transmission from bottom
+
508 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho); //reflection
+
509 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau); //transmission
+
510 } else {//reflection from bottom, transmission from top
+
511 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho); //reflection
+
512 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau); //transmission
+
513 }
+
514 }
+
515 if( Ncameras>0 ) {
+
516 size_t indc = prd.source_ID*Nprimitives*Nbands_global*Ncameras + prd.origin_UUID*Nbands_global*Ncameras + b_global*Ncameras + camera_ID;
+
517 float t_rho_cam = rho_cam[ indc ];
+
518 float t_tau_cam = tau_cam[ indc ];
+
519 if ( (t_rho_cam > 0 || t_tau_cam > 0) && strength>0 ) {
+
520 if (prd.face) {//reflection from top, transmission from bottom
+
521 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam); //reflection
+
522 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam); //transmission
+
523 } else {//reflection from bottom, transmission from top
+
524 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam); //reflection
+
525 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam); //transmission
+
526 }
+
527 }
+
528 }
+
529
+
530 }
+
531
+
532}
+
533
+
534RT_PROGRAM void miss_diffuse() {
+
535
+
536// double strength;
+
537// if (prd.face || primitive_type[objectID[prd.origin_UUID]] == 3) {
+
538// strength = radiation_out_top[prd.origin_UUID] * prd.strength * prd.area;
+
539// } else {
+
540// strength = radiation_out_bottom[prd.origin_UUID] * prd.strength * prd.area;
+
541// }
+
542//
+
543// atomicFloatAdd(&Rsky[prd.origin_UUID], strength);
+
544
+
545 int b=-1;
+
546 for( size_t b_global=0; b_global<Nbands_global; b_global++ ) {
547
-
548 float t_rho = rho[Nprimitives*Nbands*prd.source_ID+Nbands*prd.origin_UUID+b];
-
549 float t_tau = tau[Nprimitives*Nbands*prd.source_ID+Nbands*prd.origin_UUID+b];
-
550
-
551 if (primitive_type[objectID[prd.origin_UUID]] == 4) { //ray was launched from voxel
+
548 if( band_launch_flag[b_global]==0 ){
+
549 continue;
+
550 }
+
551 b++;
552
-
553 float kappa = t_rho; //just a reminder that rho is actually the absorption coefficient
-
554 float sigma_s = t_tau; //just a reminder that tau is actually the scattering coefficient
-
555 float beta = kappa + sigma_s;
+
553 if (diffuse_flux[b] > 0.f) {
+
554
+
555 size_t ind_origin = Nbands_launch * prd.origin_UUID + b;
556
-
557 // absorption
-
558 atomicAdd(&radiation_in[ind_origin], diffuse_flux[b] * prd.strength * kappa / beta);
-
559
-
560 // scattering
-
561 atomicAdd(&scatter_buff_top[ind_origin], diffuse_flux[b] * prd.strength * sigma_s / beta);
+
557 size_t radprop_ind_global = Nprimitives*Nbands_global*prd.source_ID + Nbands_global*prd.origin_UUID + b_global;
+
558 float t_rho = rho[ radprop_ind_global ];
+
559 float t_tau = tau[ radprop_ind_global ];
+
560
+
561 if (primitive_type[objectID[prd.origin_UUID]] == 4) { //ray was launched from voxel
562
-
563 } else { //ray was NOT launched from voxel
-
564
-
565 float fd = 1.f;
-
566 if ( diffuse_extinction[b] > 0.f) {
-
567 float psi = acos_safe(dot(diffuse_peak_dir[b], ray.direction));
-
568 if (psi < M_PI / 180.f) {
-
569 fd = powf(M_PI / 180.f, -diffuse_extinction[b]) * diffuse_dist_norm[b]; //Replace 'pow' by 'powf' in
-
570 } else {
-
571 fd = powf(psi, -diffuse_extinction[b]) * diffuse_dist_norm[b];
-
572 }
-
573 }
+
563 float kappa = t_rho; //just a reminder that rho is actually the absorption coefficient
+
564 float sigma_s = t_tau; //just a reminder that tau is actually the scattering coefficient
+
565 float beta = kappa + sigma_s;
+
566
+
567 // absorption
+
568 atomicAdd(&radiation_in[ind_origin], diffuse_flux[b] * prd.strength * kappa / beta);
+
569
+
570 // scattering
+
571 atomicAdd(&scatter_buff_top[ind_origin], diffuse_flux[b] * prd.strength * sigma_s / beta);
+
572
+
573 } else { //ray was NOT launched from voxel
574
-
575 float strength = fd * diffuse_flux[b] * prd.strength;
-
576
-
577 // absorption
-
578 atomicAdd(&radiation_in[ind_origin], strength * (1.f - t_rho - t_tau) );
-
579
-
580 if (t_rho > 0 || t_tau > 0) {
-
581 if (prd.face) {//reflection from top, transmission from bottom
-
582 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho); //reflection
-
583 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau); //transmission
-
584 } else {//reflection from bottom, transmission from top
-
585 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho); //reflection
-
586 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau); //transmission
-
587 }
-
588 }
-
589 if( Ncameras>0 ) {
-
590 size_t indc = prd.source_ID*Nprimitives*Nbands*Ncameras + prd.origin_UUID*Nbands*Ncameras + b*Ncameras + camera_ID;
-
591 float t_rho_cam = rho_cam[ indc ];
-
592 float t_tau_cam = tau_cam[ indc ];
-
593 if ( (t_rho_cam > 0 || t_tau_cam > 0) && prd.strength>0 ) {
-
594 if (prd.face) {//reflection from top, transmission from bottom
-
595 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam); //reflection
-
596 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam); //transmission
-
597 } else {//reflection from bottom, transmission from top
-
598 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam); //reflection
-
599 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam); //transmission
-
600 }
-
601 }
-
602 }
-
603 }
-
604
-
605 }
-
606
-
607
-
608 }
-
609
-
610}
-
611
-
612RT_PROGRAM void miss_camera() {
-
613
-
614 for( size_t b=0; b<Nbands; b++ ) {
-
615
-
616 if (diffuse_flux[b] > 0.f) {
+
575 float fd = 1.f;
+
576 if ( diffuse_extinction[b] > 0.f) {
+
577 float psi = acos_safe(dot(diffuse_peak_dir[b], ray.direction));
+
578 if (psi < M_PI / 180.f) {
+
579 fd = powf(M_PI / 180.f, -diffuse_extinction[b]) * diffuse_dist_norm[b]; //Replace 'pow' by 'powf' in
+
580 } else {
+
581 fd = powf(psi, -diffuse_extinction[b]) * diffuse_dist_norm[b];
+
582 }
+
583 }
+
584
+
585 float strength = fd * diffuse_flux[b] * prd.strength;
+
586
+
587 // absorption
+
588 atomicAdd(&radiation_in[ind_origin], strength * (1.f - t_rho - t_tau) );
+
589
+
590 if (t_rho > 0 || t_tau > 0) {
+
591 if (prd.face) {//reflection from top, transmission from bottom
+
592 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_rho); //reflection
+
593 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_tau); //transmission
+
594 } else {//reflection from bottom, transmission from top
+
595 atomicFloatAdd(&scatter_buff_bottom[ind_origin], strength * t_rho); //reflection
+
596 atomicFloatAdd(&scatter_buff_top[ind_origin], strength * t_tau); //transmission
+
597 }
+
598 }
+
599 if( Ncameras>0 ) {
+
600 size_t indc = prd.source_ID*Nprimitives*Nbands_global*Ncameras + prd.origin_UUID*Nbands_global*Ncameras + b_global*Ncameras + camera_ID;
+
601 float t_rho_cam = rho_cam[ indc ];
+
602 float t_tau_cam = tau_cam[ indc ];
+
603 if ( (t_rho_cam > 0 || t_tau_cam > 0) && prd.strength>0 ) {
+
604 if (prd.face) {//reflection from top, transmission from bottom
+
605 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_rho_cam); //reflection
+
606 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_tau_cam); //transmission
+
607 } else {//reflection from bottom, transmission from top
+
608 atomicFloatAdd(&scatter_buff_bottom_cam[ind_origin], strength * t_rho_cam); //reflection
+
609 atomicFloatAdd(&scatter_buff_top_cam[ind_origin], strength * t_tau_cam); //transmission
+
610 }
+
611 }
+
612 }
+
613 }
+
614
+
615 }
+
616
617
-
618 float fd = 1.f;
-
619 if (diffuse_extinction[b] > 0.f) {
-
620 float psi = acos_safe(dot(diffuse_peak_dir[b], ray.direction));
-
621 if (psi < M_PI / 180.f) {
-
622 fd = powf(float(M_PI) / 180.f, -diffuse_extinction[b]) * diffuse_dist_norm[b];
-
623 } else {
-
624 fd = powf(psi, -diffuse_extinction[b]) * diffuse_dist_norm[b];
-
625 }
-
626 }
+
618 }
+
619
+
620}
+
621
+
622RT_PROGRAM void miss_camera() {
+
623
+
624 for( size_t b=0; b<Nbands_launch; b++ ) {
+
625
+
626 if (diffuse_flux[b] > 0.f) {
627
-
628 //absorption
-
629 atomicAdd(&radiation_in_camera[Nbands*prd.origin_UUID+b], fd * diffuse_flux[b] * prd.strength);
-
630
-
631 }
-
632
-
633 }
-
634
-
635}
-
636
-
637RT_PROGRAM void miss_pixel_label() {
-
638
-
639 camera_pixel_depth[prd.origin_UUID] = -1;
+
628 float fd = 1.f;
+
629 if (diffuse_extinction[b] > 0.f) {
+
630 float psi = acos_safe(dot(diffuse_peak_dir[b], ray.direction));
+
631 if (psi < M_PI / 180.f) {
+
632 fd = powf(float(M_PI) / 180.f, -diffuse_extinction[b]) * diffuse_dist_norm[b];
+
633 } else {
+
634 fd = powf(psi, -diffuse_extinction[b]) * diffuse_dist_norm[b];
+
635 }
+
636 }
+
637
+
638 //absorption
+
639 atomicAdd(&radiation_in_camera[Nbands_launch*prd.origin_UUID+b], fd * diffuse_flux[b] * prd.strength);
640
-
641}
+
641 }
+
642
+
643 }
+
644
+
645}
+
646
+
647RT_PROGRAM void miss_pixel_label() {
+
648
+
649 camera_pixel_depth[prd.origin_UUID] = -1;
+
650
+
651}
__device__ void d_transformPoint(const float(&transform_matrix)[16], float3 &v)
Function to transform a 3D point based on current affine transformation matrix on the GPU.
__device__ float3 d_rotatePoint(const float3 &position, const float &theta, const float &phi)
-
float acos_safe(float x)
arccosine function to handle cases when round-off errors cause an argument <-1 or >1,...
Definition global.cpp:241
vec3 cross(const vec3 &a, const vec3 &b)
Cross product of two vec3 vectors.
double strength
"strength" or amount of energy associated with the ray.
unsigned char periodic_depth
Number of periodic boundary intersections for ray.
- -
+ + diff --git a/doc/html/s__hull__pro_8h_source.html b/doc/html/s__hull__pro_8h_source.html index 75ccd762e..83fec13ca 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
s_hull_pro.h
@@ -137,18 +143,18 @@
31
32
-
33struct Triad
+
33struct Triad
34{
35 int a,b, c;
36 int ab, bc, ac; // adjacent edges index to neighbouring triangle.
37 float ro, R,C;
38 //std::set<int> idx;
-
39 Triad() {};
-
40 Triad(int x, int y) : a(x), b(y),c(0), ab(-1), bc(-1), ac(-1), ro(-1), R(0), C(0) {};
-
41 Triad(int x, int y, int z) : a(x), b(y), c(z), ab(-1), bc(-1), ac(-1), ro(-1), R(0), C(0) {};
-
42 Triad(const Triad &p) : a(p.a), b(p.b), c(p.c), ab(p.ab), bc(p.bc), ac(p.ac), ro(p.ro), R(p.R), C(p.C) {};
+
39 Triad() {};
+
40 Triad(int x, int y) : a(x), b(y),c(0), ab(-1), bc(-1), ac(-1), ro(-1), R(0), C(0) {};
+
41 Triad(int x, int y, int z) : a(x), b(y), c(z), ab(-1), bc(-1), ac(-1), ro(-1), R(0), C(0) {};
+
42 Triad(const Triad &p) : a(p.a), b(p.b), c(p.c), ab(p.ab), bc(p.bc), ac(p.ac), ro(p.ro), R(p.R), C(p.C) {};
43
-
44 Triad &operator=(const Triad &p)
+
44 Triad &operator=(const Triad &p)
45 {
46 a = p.a;
47 b = p.b;
@@ -177,17 +183,17 @@
69
70
-
71struct Shx
+
71struct Shx
72{
73 int id, trid;
74 float r,c, tr,tc ;
75 float ro;
-
76 Shx() {};
-
77 Shx(float a, float b) : r(a), c(b), ro(0.0), tr(0.0), tc(0.0), id(-1) {};
-
78 Shx(float a, float b, float x) : r(a), c(b), ro(x), id(-1), tr(0), tc(0) {};
-
79 Shx(const Shx &p) : id(p.id), trid(p.trid), r(p.r), c(p.c), tr(p.tr), tc(p.tc), ro(p.ro) {};
+
76 Shx() {};
+
77 Shx(float a, float b) : r(a), c(b), ro(0.0), tr(0.0), tc(0.0), id(-1) {};
+
78 Shx(float a, float b, float x) : r(a), c(b), ro(x), id(-1), tr(0), tc(0) {};
+
79 Shx(const Shx &p) : id(p.id), trid(p.trid), r(p.r), c(p.c), tr(p.tr), tc(p.tc), ro(p.ro) {};
80
-
81 Shx &operator=(const Shx &p)
+
81 Shx &operator=(const Shx &p)
82 {
83 id = p.id;
84 trid = p.trid;
@@ -217,17 +223,17 @@
107
108
-
109struct Dupex
+
109struct Dupex
110{
111 int id;
112 float r,c;
113
-
114 Dupex() {};
-
115 Dupex(float a, float b) : r(a), c(b), id(-1) {};
-
116 Dupex(float a, float b, int x) : r(a), c(b), id(x) {};
-
117 Dupex(const Dupex &p) : id(p.id), r(p.r), c(p.c) {};
+
114 Dupex() {};
+
115 Dupex(float a, float b) : r(a), c(b), id(-1) {};
+
116 Dupex(float a, float b, int x) : r(a), c(b), id(x) {};
+
117 Dupex(const Dupex &p) : id(p.id), r(p.r), c(p.c) {};
118
-
119 Dupex &operator=(const Dupex &p)
+
119 Dupex &operator=(const Dupex &p)
120 {
121 id = p.id;
122 r = p.r;
@@ -277,12 +283,14 @@
165#endif
-
- -
+ + diff --git a/doc/html/search/all_10.js b/doc/html/search/all_10.js index ea8251879..c2faf4e1d 100644 --- a/doc/html/search/all_10.js +++ b/doc/html/search/all_10.js @@ -7,7 +7,7 @@ var searchData= ['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_20dependencies_6',['Installing Helios Dependencies',['../_dependent_software.html#Automatically',1,'']]], - ['helios_20documentation_20v1_203_2026_7',['Helios Documentation v1.3.26',['../index.html',1,'']]], + ['helios_20documentation_7',['Helios Documentation',['../index.html',1,'']]], ['helios_20prerequisites_8',['Helios Prerequisites',['../_overview.html#PrereqsHelios',1,'']]], ['helios_20programming_9',['Which platform to use for Helios programming?',['../_dependent_software.html#WhichPlatform',1,'']]], ['helios_20vector_20types_20tutorial_10',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], diff --git a/doc/html/search/all_17.js b/doc/html/search/all_17.js index 54516c8f2..7a899a592 100644 --- a/doc/html/search/all_17.js +++ b/doc/html/search/all_17.js @@ -49,7 +49,7 @@ var searchData= ['operator_2d_46',['operator-',['../structhelios_1_1int2.html#acfb7317221012445f653b395c28f774f',1,'helios::int2::operator-(const int2 &a) const'],['../structhelios_1_1int2.html#a39dfd15acdd548f1c93be6e7b8a1a475',1,'helios::int2::operator-() const'],['../structhelios_1_1int3.html#adbe1fd230ee2591e64fdc15d71204848',1,'helios::int3::operator-(const int3 &a) const'],['../structhelios_1_1int3.html#ade3be6bb42b51bd8875e485ca9e6274b',1,'helios::int3::operator-() const'],['../structhelios_1_1int4.html#a67b8bf23d9a9377fb295d4dad92ead6a',1,'helios::int4::operator-(const int4 &a) const'],['../structhelios_1_1int4.html#a4d7a1b7d29e0d436fe35f927d645b7c7',1,'helios::int4::operator-() const'],['../structhelios_1_1vec2.html#a91e810accf20886a20afc9ed0c3d5f07',1,'helios::vec2::operator-(const vec2 &a) const'],['../structhelios_1_1vec2.html#a919b93ba0bf660ae2b7e65500982e3d7',1,'helios::vec2::operator-(float a) const'],['../structhelios_1_1vec2.html#ad37fb5771915e31225d39d3df8c669ed',1,'helios::vec2::operator-() const'],['../structhelios_1_1vec3.html#ab6d099de4a986d24b7414114700bb66a',1,'helios::vec3::operator-(const vec3 &a) const'],['../structhelios_1_1vec3.html#ad5557e6f3320abb0cab521a0aa87532f',1,'helios::vec3::operator-(float a) const'],['../structhelios_1_1vec3.html#a5a0176fe2d334f8a30ab00a975c2bdb1',1,'helios::vec3::operator-() const'],['../structhelios_1_1vec4.html#a98039082899cd4872d383e039cc0b812',1,'helios::vec4::operator-(const vec4 &a) const'],['../structhelios_1_1vec4.html#afd6f6b82dd6d3512cc8e1560e218bab2',1,'helios::vec4::operator-(float a) const'],['../structhelios_1_1vec4.html#a64f1627b4f2c6487231f315527afbf15',1,'helios::vec4::operator-() const'],['../helios__vector__types_8h.html#a7436b011b35d256deae673fe5c35cf75',1,'helios::operator-(float a, const vec2 &v)'],['../helios__vector__types_8h.html#a434fe3718d57c13e067aa06818652be3',1,'helios::operator-(float a, const vec3 &v)'],['../helios__vector__types_8h.html#a2ac8eb255c768eba03401b9d7f58df50',1,'helios::operator-(float a, const vec4 &v)']]], ['operator_2d_3d_47',['operator-=',['../structhelios_1_1int2.html#a5838914611d1837e927638c83f4a1bf9',1,'helios::int2::operator-=()'],['../structhelios_1_1int3.html#a383f2cb4438661dd93bef01cfb52d646',1,'helios::int3::operator-=()'],['../structhelios_1_1int4.html#a3726af5576f9ed3ed3cf5d7c97a8159d',1,'helios::int4::operator-=()'],['../structhelios_1_1vec2.html#a575d6107bcec4582c106b711142a17c2',1,'helios::vec2::operator-=()'],['../structhelios_1_1vec3.html#a47a2080f5ba1e3690956ad8dd9160780',1,'helios::vec3::operator-=()'],['../structhelios_1_1vec4.html#a5cff99d238392c388015d1a0ac4456ae',1,'helios::vec4::operator-=()']]], ['operator_2f_48',['operator/',['../structhelios_1_1vec2.html#a910c611bcf9c2ea1cd3ff38f0bd375e8',1,'helios::vec2::operator/()'],['../structhelios_1_1vec3.html#a09c648b26b7333d2726b7fbceab85be7',1,'helios::vec3::operator/()'],['../structhelios_1_1vec4.html#aa86d6caee3381dd0a14a74ea5e743604',1,'helios::vec4::operator/()']]], - ['operator_3c_3c_49',['operator<<',['../structhelios_1_1int2.html#aa70779f707686be8b004587a4220a153',1,'helios::int2::operator<<'],['../structhelios_1_1int3.html#a6f576c885af0d781aadda850a2ca77af',1,'helios::int3::operator<<'],['../structhelios_1_1int4.html#ac6b32d39d92de0b8585c64048040f0f9',1,'helios::int4::operator<<'],['../structhelios_1_1vec2.html#a5e585083b0cf16b2e73958747390e152',1,'helios::vec2::operator<<'],['../structhelios_1_1vec3.html#a87277dd90e0869e2e8e7ce376dfc7033',1,'helios::vec3::operator<<'],['../structhelios_1_1vec4.html#a32f014dbb41084ece2ad85f19c540874',1,'helios::vec4::operator<<'],['../structhelios_1_1_r_g_bcolor.html#a47b1d94ed5f6fa0c8ae897e02a06435c',1,'helios::RGBcolor::operator<<'],['../structhelios_1_1_r_g_b_acolor.html#aaa76985ee048b321703f78175e2b87b7',1,'helios::RGBAcolor::operator<<'],['../structhelios_1_1_date.html#a189b8537a2e0696e2f38da34e0f13eec',1,'helios::Date::operator<<'],['../structhelios_1_1_time.html#a5d53ebf9a42b3aa2d959a3cd5023c71a',1,'helios::Time::operator<<'],['../structhelios_1_1_location.html#a60375cac034fe50880b47569df6e8f69',1,'helios::Location::operator<<'],['../structhelios_1_1_spherical_coord.html#ad9381fdcb8448d8834b4ce43465b5335',1,'helios::SphericalCoord::operator<<']]], + ['operator_3c_3c_49',['operator<<',['../structhelios_1_1int2.html#aa70779f707686be8b004587a4220a153',1,'helios::int2::operator<<()'],['../structhelios_1_1int3.html#a6f576c885af0d781aadda850a2ca77af',1,'helios::int3::operator<<()'],['../structhelios_1_1int4.html#ac6b32d39d92de0b8585c64048040f0f9',1,'helios::int4::operator<<()'],['../structhelios_1_1vec2.html#a5e585083b0cf16b2e73958747390e152',1,'helios::vec2::operator<<()'],['../structhelios_1_1vec3.html#a87277dd90e0869e2e8e7ce376dfc7033',1,'helios::vec3::operator<<()'],['../structhelios_1_1vec4.html#a32f014dbb41084ece2ad85f19c540874',1,'helios::vec4::operator<<()'],['../structhelios_1_1_r_g_bcolor.html#a47b1d94ed5f6fa0c8ae897e02a06435c',1,'helios::RGBcolor::operator<<()'],['../structhelios_1_1_r_g_b_acolor.html#aaa76985ee048b321703f78175e2b87b7',1,'helios::RGBAcolor::operator<<()'],['../structhelios_1_1_date.html#a189b8537a2e0696e2f38da34e0f13eec',1,'helios::Date::operator<<()'],['../structhelios_1_1_time.html#a5d53ebf9a42b3aa2d959a3cd5023c71a',1,'helios::Time::operator<<()'],['../structhelios_1_1_location.html#a60375cac034fe50880b47569df6e8f69',1,'helios::Location::operator<<()'],['../structhelios_1_1_spherical_coord.html#ad9381fdcb8448d8834b4ce43465b5335',1,'helios::SphericalCoord::operator<<()']]], ['operator_3d_50',['operator=',['../classhelios_1_1_context.html#aef8acffd049cf98f2544143188c164e2',1,'helios::Context::operator=()'],['../structhelios_1_1_spherical_coord.html#afe4ef2437aad9bca5863eeb387b1eee5',1,'helios::SphericalCoord::operator=()'],['../struct_leaf_prototype.html#a2dc8e0e35313b52c69cb7076d0392c2a',1,'LeafPrototype::operator=()']]], ['operator_3d_3d_51',['operator==',['../structhelios_1_1int2.html#a6f1ec1cd4223e5f0bbfaa16e636af533',1,'helios::int2::operator==()'],['../structhelios_1_1int3.html#aced326938393fe95e1725e55b9bd4dd8',1,'helios::int3::operator==()'],['../structhelios_1_1int4.html#a779368fbba5e30ad5bba83072c9fdf83',1,'helios::int4::operator==()'],['../structhelios_1_1vec2.html#ab0c78672d242efe3aede0a4bd03eaeea',1,'helios::vec2::operator==()'],['../structhelios_1_1vec3.html#a00f6165fb3f01c65d7046111b6143fd4',1,'helios::vec3::operator==()'],['../structhelios_1_1vec4.html#aa8f6ace5ba502b2b958b64b1d032d1c3',1,'helios::vec4::operator==()'],['../structhelios_1_1_r_g_bcolor.html#a3cfc4c0f132c841f3a18ff9bdae21e22',1,'helios::RGBcolor::operator==()'],['../structhelios_1_1_r_g_b_acolor.html#abed23df133a671e295dcbf559c8a3ff5',1,'helios::RGBAcolor::operator==()'],['../structhelios_1_1_date.html#a097ff893e7fc52d101fdcb4ced84354b',1,'helios::Date::operator==()'],['../structhelios_1_1_time.html#a8a0bab271dcb31616ba52c4fd5f754cd',1,'helios::Time::operator==()'],['../structhelios_1_1_location.html#a2d451323ab20191a7f123849da04e269',1,'helios::Location::operator==()'],['../structhelios_1_1_spherical_coord.html#afa6791361ed489019d0689a52cac5621',1,'helios::SphericalCoord::operator==()']]], ['optimality_20based_20model_52',['Medlyn et al. (2011) Optimality-Based Model',['../_stomatal_doc.html#MoptTheory',1,'']]], diff --git a/doc/html/search/all_18.js b/doc/html/search/all_18.js index 9b4a901ca..bfff3217e 100644 --- a/doc/html/search/all_18.js +++ b/doc/html/search/all_18.js @@ -162,5 +162,6 @@ var searchData= ['prospect_159',['PROSPECT',['../class_leaf_optics.html#a8af86e8cce4d721230ddc746580b7dcf',1,'LeafOptics']]], ['prototype_5ffunction_160',['prototype_function',['../struct_leaf_prototype.html#ab709ab7749bf4ad562946441bc7a937e',1,'LeafPrototype']]], ['prototypes_161',['Prototypes',['../_plant_architecture_doc.html#PlantArchOrgans',1,'Creating Plant Organ Prototypes'],['../_plant_architecture_doc.html#FlowerPrototypes',1,'Flower Prototypes'],['../_plant_architecture_doc.html#FruitPrototypes',1,'Fruit Prototypes'],['../_plant_architecture_doc.html#LeafPrototypes',1,'Leaf Prototypes']]], - ['pseudocolor_20map_162',['Coloring by pseudocolor map',['../_visualizer_doc.html#ColoringPseudo',1,'']]] + ['prunetubenodes_162',['pruneTubeNodes',['../classhelios_1_1_tube.html#a4d8bc6d05dab160f3e0fbee48ad3fd2c',1,'helios::Tube::pruneTubeNodes()'],['../classhelios_1_1_context.html#a7e47d13895d9e65ae719e2afce8d1d54',1,'helios::Context::pruneTubeNodes()']]], + ['pseudocolor_20map_163',['Coloring by pseudocolor map',['../_visualizer_doc.html#ColoringPseudo',1,'']]] ]; diff --git a/doc/html/search/all_1e.js b/doc/html/search/all_1e.js index f646c2dda..394d005bd 100644 --- a/doc/html/search/all_1e.js +++ b/doc/html/search/all_1e.js @@ -1,54 +1,53 @@ var searchData= [ - ['v1_203_2026_0',['Helios Documentation v1.3.26',['../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']]], - ['variables_20and_20primitive_20data_5',['Variables and Primitive Data',['../_voxel_intersection_doc.html#VoxVarsAndProps',1,'']]], - ['vec2_6',['vec2',['../structhelios_1_1vec2.html',1,'helios::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_7',['vec3',['../structhelios_1_1vec3.html',1,'helios::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_8',['vec4',['../structhelios_1_1vec4.html',1,'helios::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)']]], - ['vecmult_9',['vecmult',['../global_8h.html#ae8cc6f4a10a4efab6057ab6c4c114304',1,'helios::vecmult(const float M[16], const float v[3], float(&result)[3])'],['../global_8h.html#a40054144f951b396cd9f9ba32586862a',1,'helios::vecmult(const float M[16], const helios::vec3 &v3, helios::vec3 &result)']]], - ['vector_10',['Vector',['../context_vectors.html#Datetut',1,'Date Vector'],['../context_vectors.html#RGBtut',1,'RGB Color Vector'],['../context_vectors.html#Timetut',1,'Time Vector']]], - ['vector_20of_20floats_11',['Vector of Floats',['../context_vectors.html#vec3tut',1,'']]], - ['vector_20of_20integers_12',['Vector of Integers',['../context_vectors.html#int3tut',1,'']]], - ['vector_20types_13',['Vector Types',['../_a_p_i.html#VecTypes',1,'']]], - ['vector_20types_20tutorial_14',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], - ['vectors_15',['Vectors',['../group__vectors.html',1,'']]], - ['vectors_16',['R-G-B(-A) color vectors',['../_a_p_i.html#RGB',1,'']]], - ['vegetative_5fbud_5fbreak_5fprobability_5fdecay_5frate_17',['vegetative_bud_break_probability_decay_rate',['../struct_shoot_parameters.html#abe60e69a5cf66199d1dfd6688e4d4ced',1,'ShootParameters::vegetative_bud_break_probability_decay_rate'],['../_plant_architecture_doc.html#ShootParam_vegetative_prob',1,'vegetative_bud_break_probability_min and vegetative_bud_break_probability_decay_rate']]], - ['vegetative_5fbud_5fbreak_5fprobability_5fmin_20and_20vegetative_5fbud_5fbreak_5fprobability_5fdecay_5frate_18',['vegetative_bud_break_probability_min and vegetative_bud_break_probability_decay_rate',['../_plant_architecture_doc.html#ShootParam_vegetative_prob',1,'']]], - ['vegetativebud_19',['VegetativeBud',['../struct_vegetative_bud.html',1,'']]], - ['version_20',['Version',['../_choosing_c_u_d_a.html#chooseCUDA',1,'CUDA Version'],['../_choosing_c_u_d_a.html#chooseOptiX',1,'OptiX Version']]], - ['version_21',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], - ['version_20given_20in_20buckley_20turnbull_20and_20adams_202012_22',['Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)',['../_stomatal_doc.html#BMFTheory',1,'']]], - ['view_20controls_23',['View Controls',['../_visualizer_doc.html#ViewControls',1,'']]], - ['view_20options_24',['View Options',['../_visualizer_doc.html#Options',1,'']]], - ['visual_20studio_20c_20compiler_20tools_25',['Install Microsoft Visual Studio C++ compiler tools',['../_dependent_software.html#SetupPCMSVC',1,'']]], - ['visualization_26',['Visualization',['../visualizer_pdata.html#Tutorial8_vis',1,'']]], - ['visualization_20window_27',['Visualization Window',['../_visualizer_doc.html#Window',1,'']]], - ['visualizer_28',['Visualizer',['../visualizer_basics.html#vis_step2',1,'Step 2. Add geometry to the Visualizer'],['../class_visualizer.html',1,'Visualizer'],['../class_visualizer.html#a9277e99596d46d77d31a2249a1406983',1,'Visualizer::Visualizer(uint Wdisplay)'],['../class_visualizer.html#ac39e631c7d248c0e0f4f9ebba58a6dc4',1,'Visualizer::Visualizer(uint Wdisplay, uint Hdisplay)'],['../class_visualizer.html#a9c6edf93389fa78548f2024aec944b82',1,'Visualizer::Visualizer(uint Wdisplay, uint Hdisplay, int aliasing_samples, bool window_decorations)']]], - ['visualizer_20basics_29',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]], - ['visualizer_20class_30',['Step 1. Declare and initialize the Visualizer class',['../visualizer_basics.html#vis_step1',1,'']]], - ['visualizer_20options_31',['Step 3. Modify Visualizer options',['../visualizer_basics.html#vis_step3',1,'']]], - ['visualizer_20plug_20in_32',['Visualizer Plug In',['../_tutorials.html#VisualizerTuts',1,'Visualizer Plug-In'],['../_radiation_doc.html#RadVis',1,'Visualizing Model Outputs using the Visualizer Plug-In']]], - ['visualizer_20plug_20in_33',['Visualizer Plug in',['../_dependent_software.html#SetupLinuxVis',1,'Dependencies of the Visualizer Plug-in'],['../_visualizer_doc.html#UseVis',1,'Using the Visualizer Plug-in']]], - ['visualizer_20plugin_20documentation_34',['Visualizer Plugin Documentation',['../_visualizer_doc.html',1,'PlugIns']]], - ['visualizer_2ecpp_35',['Visualizer.cpp',['../_visualizer_8cpp.html',1,'']]], - ['visualizer_2eh_36',['Visualizer.h',['../_visualizer_8h.html',1,'']]], - ['visualizing_20model_20outputs_20using_20the_20visualizer_20plug_20in_37',['Visualizing Model Outputs using the Visualizer Plug-In',['../_radiation_doc.html#RadVis',1,'']]], - ['visualizing_20primitive_20data_20values_38',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], - ['visualizing_20results_39',['Visualizing results',['../_li_d_a_r_doc.html#LiDARvis',1,'']]], - ['von_20caemmerer_20berry_20model_20description_40',['Farquhar, von Caemmerer, Berry Model Description',['../_photosynthesis_doc.html#FarquharDescription',1,'']]], - ['voxel_20intersection_20plugin_20documentation_41',['Voxel Intersection Plugin Documentation',['../_voxel_intersection_doc.html',1,'PlugIns']]], - ['voxel_5fbounds_42',['voxel_bounds',['../primitive_intersection_8cu.html#a904cdd1733732aa1a8dbaf2e958176a9',1,'primitiveIntersection.cu']]], - ['voxel_5fintersect_43',['voxel_intersect',['../primitive_intersection_8cu.html#ac0a2a895d2e98227a3905e56939228fe',1,'primitiveIntersection.cu']]], - ['voxelintersection_44',['VoxelIntersection',['../class_voxel_intersection.html',1,'VoxelIntersection'],['../class_voxel_intersection.html#a45bf9a3a44c9373452753480c8e47c72',1,'VoxelIntersection::VoxelIntersection()']]], - ['voxelintersection_2ecpp_45',['VoxelIntersection.cpp',['../_voxel_intersection_8cpp.html',1,'']]], - ['voxelintersection_2ecu_46',['VoxelIntersection.cu',['../_voxel_intersection_8cu.html',1,'']]], - ['voxelintersection_2eh_47',['VoxelIntersection.h',['../_voxel_intersection_8h.html',1,'']]], - ['voxels_48',['Adding Voxels',['../_a_p_i.html#AddingVoxel',1,'']]], - ['vsp_20trellis_49',['VSP Trellis',['../_canopy_generator_doc.html#CGenUnilateral',1,'Grapevine Canopy with a Unilateral VSP Trellis'],['../_canopy_generator_doc.html#CGenVSP',1,'Grapevine Canopy with VSP Trellis']]], - ['vspgrapevineparameters_50',['VSPGrapevineParameters',['../struct_v_s_p_grapevine_parameters.html',1,'VSPGrapevineParameters'],['../struct_v_s_p_grapevine_parameters.html#af61690f86b14f0f6852e2c43b5549217',1,'VSPGrapevineParameters::VSPGrapevineParameters()'],['../struct_v_s_p_grapevine_parameters.html#a07cb2adfeec316d0cf5ce9ffb2266dc2',1,'VSPGrapevineParameters::VSPGrapevineParameters(const pugi::xml_node canopy_node)']]] + ['validateoutputpath_0',['validateOutputPath',['../global_8h.html#a614486c4ac0686c5b58813f03f0cedf9',1,'helios']]], + ['values_1',['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_2',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], + ['variables_3',['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']]], + ['variables_20and_20primitive_20data_4',['Variables and Primitive Data',['../_voxel_intersection_doc.html#VoxVarsAndProps',1,'']]], + ['vec2_5',['vec2',['../structhelios_1_1vec2.html',1,'helios::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_6',['vec3',['../structhelios_1_1vec3.html',1,'helios::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_7',['vec4',['../structhelios_1_1vec4.html',1,'helios::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)']]], + ['vecmult_8',['vecmult',['../global_8h.html#ae8cc6f4a10a4efab6057ab6c4c114304',1,'helios::vecmult(const float M[16], const float v[3], float(&result)[3])'],['../global_8h.html#a40054144f951b396cd9f9ba32586862a',1,'helios::vecmult(const float M[16], const helios::vec3 &v3, helios::vec3 &result)']]], + ['vector_9',['Vector',['../context_vectors.html#Datetut',1,'Date Vector'],['../context_vectors.html#RGBtut',1,'RGB Color Vector'],['../context_vectors.html#Timetut',1,'Time Vector']]], + ['vector_20of_20floats_10',['Vector of Floats',['../context_vectors.html#vec3tut',1,'']]], + ['vector_20of_20integers_11',['Vector of Integers',['../context_vectors.html#int3tut',1,'']]], + ['vector_20types_12',['Vector Types',['../_a_p_i.html#VecTypes',1,'']]], + ['vector_20types_20tutorial_13',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], + ['vectors_14',['Vectors',['../group__vectors.html',1,'']]], + ['vectors_15',['R-G-B(-A) color vectors',['../_a_p_i.html#RGB',1,'']]], + ['vegetative_5fbud_5fbreak_5fprobability_5fdecay_5frate_16',['vegetative_bud_break_probability_decay_rate',['../struct_shoot_parameters.html#abe60e69a5cf66199d1dfd6688e4d4ced',1,'ShootParameters::vegetative_bud_break_probability_decay_rate'],['../_plant_architecture_doc.html#ShootParam_vegetative_prob',1,'vegetative_bud_break_probability_min and vegetative_bud_break_probability_decay_rate']]], + ['vegetative_5fbud_5fbreak_5fprobability_5fmin_20and_20vegetative_5fbud_5fbreak_5fprobability_5fdecay_5frate_17',['vegetative_bud_break_probability_min and vegetative_bud_break_probability_decay_rate',['../_plant_architecture_doc.html#ShootParam_vegetative_prob',1,'']]], + ['vegetativebud_18',['VegetativeBud',['../struct_vegetative_bud.html',1,'']]], + ['version_19',['Version',['../_choosing_c_u_d_a.html#chooseCUDA',1,'CUDA Version'],['../_choosing_c_u_d_a.html#chooseOptiX',1,'OptiX Version']]], + ['version_20',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], + ['version_20given_20in_20buckley_20turnbull_20and_20adams_202012_21',['Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)',['../_stomatal_doc.html#BMFTheory',1,'']]], + ['view_20controls_22',['View Controls',['../_visualizer_doc.html#ViewControls',1,'']]], + ['view_20options_23',['View Options',['../_visualizer_doc.html#Options',1,'']]], + ['visual_20studio_20c_20compiler_20tools_24',['Install Microsoft Visual Studio C++ compiler tools',['../_dependent_software.html#SetupPCMSVC',1,'']]], + ['visualization_25',['Visualization',['../visualizer_pdata.html#Tutorial8_vis',1,'']]], + ['visualization_20window_26',['Visualization Window',['../_visualizer_doc.html#Window',1,'']]], + ['visualizer_27',['Visualizer',['../visualizer_basics.html#vis_step2',1,'Step 2. Add geometry to the Visualizer'],['../class_visualizer.html',1,'Visualizer'],['../class_visualizer.html#a9277e99596d46d77d31a2249a1406983',1,'Visualizer::Visualizer(uint Wdisplay)'],['../class_visualizer.html#ac39e631c7d248c0e0f4f9ebba58a6dc4',1,'Visualizer::Visualizer(uint Wdisplay, uint Hdisplay)'],['../class_visualizer.html#a9c6edf93389fa78548f2024aec944b82',1,'Visualizer::Visualizer(uint Wdisplay, uint Hdisplay, int aliasing_samples, bool window_decorations)']]], + ['visualizer_20basics_28',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]], + ['visualizer_20class_29',['Step 1. Declare and initialize the Visualizer class',['../visualizer_basics.html#vis_step1',1,'']]], + ['visualizer_20options_30',['Step 3. Modify Visualizer options',['../visualizer_basics.html#vis_step3',1,'']]], + ['visualizer_20plug_20in_31',['Visualizer Plug In',['../_tutorials.html#VisualizerTuts',1,'Visualizer Plug-In'],['../_radiation_doc.html#RadVis',1,'Visualizing Model Outputs using the Visualizer Plug-In']]], + ['visualizer_20plug_20in_32',['Visualizer Plug in',['../_dependent_software.html#SetupLinuxVis',1,'Dependencies of the Visualizer Plug-in'],['../_visualizer_doc.html#UseVis',1,'Using the Visualizer Plug-in']]], + ['visualizer_20plugin_20documentation_33',['Visualizer Plugin Documentation',['../_visualizer_doc.html',1,'PlugIns']]], + ['visualizer_2ecpp_34',['Visualizer.cpp',['../_visualizer_8cpp.html',1,'']]], + ['visualizer_2eh_35',['Visualizer.h',['../_visualizer_8h.html',1,'']]], + ['visualizing_20model_20outputs_20using_20the_20visualizer_20plug_20in_36',['Visualizing Model Outputs using the Visualizer Plug-In',['../_radiation_doc.html#RadVis',1,'']]], + ['visualizing_20primitive_20data_20values_37',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], + ['visualizing_20results_38',['Visualizing results',['../_li_d_a_r_doc.html#LiDARvis',1,'']]], + ['von_20caemmerer_20berry_20model_20description_39',['Farquhar, von Caemmerer, Berry Model Description',['../_photosynthesis_doc.html#FarquharDescription',1,'']]], + ['voxel_20intersection_20plugin_20documentation_40',['Voxel Intersection Plugin Documentation',['../_voxel_intersection_doc.html',1,'PlugIns']]], + ['voxel_5fbounds_41',['voxel_bounds',['../primitive_intersection_8cu.html#a904cdd1733732aa1a8dbaf2e958176a9',1,'primitiveIntersection.cu']]], + ['voxel_5fintersect_42',['voxel_intersect',['../primitive_intersection_8cu.html#ac0a2a895d2e98227a3905e56939228fe',1,'primitiveIntersection.cu']]], + ['voxelintersection_43',['VoxelIntersection',['../class_voxel_intersection.html',1,'VoxelIntersection'],['../class_voxel_intersection.html#a45bf9a3a44c9373452753480c8e47c72',1,'VoxelIntersection::VoxelIntersection()']]], + ['voxelintersection_2ecpp_44',['VoxelIntersection.cpp',['../_voxel_intersection_8cpp.html',1,'']]], + ['voxelintersection_2ecu_45',['VoxelIntersection.cu',['../_voxel_intersection_8cu.html',1,'']]], + ['voxelintersection_2eh_46',['VoxelIntersection.h',['../_voxel_intersection_8h.html',1,'']]], + ['voxels_47',['Adding Voxels',['../_a_p_i.html#AddingVoxel',1,'']]], + ['vsp_20trellis_48',['VSP Trellis',['../_canopy_generator_doc.html#CGenUnilateral',1,'Grapevine Canopy with a Unilateral VSP Trellis'],['../_canopy_generator_doc.html#CGenVSP',1,'Grapevine Canopy with VSP Trellis']]], + ['vspgrapevineparameters_49',['VSPGrapevineParameters',['../struct_v_s_p_grapevine_parameters.html',1,'VSPGrapevineParameters'],['../struct_v_s_p_grapevine_parameters.html#af61690f86b14f0f6852e2c43b5549217',1,'VSPGrapevineParameters::VSPGrapevineParameters()'],['../struct_v_s_p_grapevine_parameters.html#a07cb2adfeec316d0cf5ce9ffb2266dc2',1,'VSPGrapevineParameters::VSPGrapevineParameters(const pugi::xml_node canopy_node)']]] ]; diff --git a/doc/html/search/all_1f.js b/doc/html/search/all_1f.js index da5459aaa..6a4e1384d 100644 --- a/doc/html/search/all_1f.js +++ b/doc/html/search/all_1f.js @@ -60,18 +60,19 @@ var searchData= ['writenormdepthimage_57',['writeNormDepthImage',['../class_radiation_model.html#a633d84a823ad4cd99495a06afc13d7a3',1,'RadiationModel']]], ['writeobj_58',['writeOBJ',['../classhelios_1_1_context.html#a8249b03fa781c9382863b7cf2caf0dd8',1,'helios::Context::writeOBJ(const std::string &filename) const'],['../classhelios_1_1_context.html#a8a5040ff4aaa061eddabe881ac668a01',1,'helios::Context::writeOBJ(const std::string &filename, const std::vector< uint > &UUIDs) const'],['../classhelios_1_1_context.html#ae976f6626930c925c8fdacb543e1e923',1,'helios::Context::writeOBJ(const std::string &filename, const std::vector< uint > &UUIDs, const std::vector< std::string > &primitive_dat_fields) const']]], ['writeobjectdatalabelmap_59',['writeObjectDataLabelMap',['../class_radiation_model.html#afdbe940b3c4ae5855a0fcbe5b0b7f708',1,'RadiationModel']]], - ['writeply_60',['writePLY',['../classhelios_1_1_context.html#aa47b8b6f8cefb3c9d55a3cda10d851d7',1,'helios::Context']]], - ['writepng_61',['writePNG',['../global_8h.html#afc2520441ef9a290c5221dd892ea9f01',1,'helios']]], - ['writeprimitivedata_62',['writePrimitiveData',['../classhelios_1_1_context.html#ab643fc787ea7b1a215605c369f446844',1,'helios::Context::writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, bool print_header=false) const'],['../classhelios_1_1_context.html#a97378b12bfaf42c2052960c54ff096d4',1,'helios::Context::writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, const std::vector< uint > &UUIDs, bool print_header=false) const']]], - ['writeprimitivedatalabelmap_63',['writePrimitiveDataLabelMap',['../class_radiation_model.html#a771c53fe19d75303c3f60017db8a2b50',1,'RadiationModel']]], - ['writespectralxmlfile_64',['writeSpectralXMLfile',['../struct_camera_calibration.html#a96b8a246adb36d20a09e3d527be9de25',1,'CameraCalibration']]], - ['writexml_65',['writeXML',['../classhelios_1_1_context.html#abfcac5a56c13e86298609ed3fccf354d',1,'helios::Context::writeXML(const char *filename, bool quiet=false) const'],['../classhelios_1_1_context.html#a499545512efe3645e2085e4815dcb94e',1,'helios::Context::writeXML(const char *filename, const std::vector< uint > &UUIDs, bool quiet=false) const']]], - ['writexml_5fbyobject_66',['writeXML_byobject',['../classhelios_1_1_context.html#ae2ada2bfdce5226cd970a6e6fa0ccc88',1,'helios::Context']]], - ['writing_20camera_20images_20to_20file_67',['Writing Camera Images to File',['../_radiation_doc.html#RadCamOut',1,'']]], - ['writing_20documentation_68',['Writing Documentation',['../_plugins.html#PluginWriting',1,'']]], - ['writing_20obj_20wavefront_20files_69',['Writing OBJ (Wavefront) Files',['../_i_o.html#OBJwrite',1,'']]], - ['writing_20plugins_70',['Writing Plugins',['../_plugins.html',1,'']]], - ['writing_20ply_20stanford_20polygon_20files_71',['Writing PLY (Stanford Polygon) Files',['../_i_o.html#PLYwrite',1,'']]], - ['writing_20results_20to_20file_72',['Writing results to file',['../_li_d_a_r_doc.html#LiDARoutput',1,'']]], - ['wsl_73',['Manually installing OptiX if using Windows Subsystem for Linux (WSL)',['../_dependent_software.html#OptiXWSL',1,'']]] + ['writeplantmeshvertices_60',['writePlantMeshVertices',['../class_plant_architecture.html#a1314accedeb4c376ee8283aa05c811c5',1,'PlantArchitecture']]], + ['writeply_61',['writePLY',['../classhelios_1_1_context.html#aa47b8b6f8cefb3c9d55a3cda10d851d7',1,'helios::Context']]], + ['writepng_62',['writePNG',['../global_8h.html#afc2520441ef9a290c5221dd892ea9f01',1,'helios']]], + ['writeprimitivedata_63',['writePrimitiveData',['../classhelios_1_1_context.html#ab643fc787ea7b1a215605c369f446844',1,'helios::Context::writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, bool print_header=false) const'],['../classhelios_1_1_context.html#a97378b12bfaf42c2052960c54ff096d4',1,'helios::Context::writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, const std::vector< uint > &UUIDs, bool print_header=false) const']]], + ['writeprimitivedatalabelmap_64',['writePrimitiveDataLabelMap',['../class_radiation_model.html#a771c53fe19d75303c3f60017db8a2b50',1,'RadiationModel']]], + ['writespectralxmlfile_65',['writeSpectralXMLfile',['../struct_camera_calibration.html#a96b8a246adb36d20a09e3d527be9de25',1,'CameraCalibration']]], + ['writexml_66',['writeXML',['../classhelios_1_1_context.html#abfcac5a56c13e86298609ed3fccf354d',1,'helios::Context::writeXML(const char *filename, bool quiet=false) const'],['../classhelios_1_1_context.html#a499545512efe3645e2085e4815dcb94e',1,'helios::Context::writeXML(const char *filename, const std::vector< uint > &UUIDs, bool quiet=false) const']]], + ['writexml_5fbyobject_67',['writeXML_byobject',['../classhelios_1_1_context.html#ae2ada2bfdce5226cd970a6e6fa0ccc88',1,'helios::Context']]], + ['writing_20camera_20images_20to_20file_68',['Writing Camera Images to File',['../_radiation_doc.html#RadCamOut',1,'']]], + ['writing_20documentation_69',['Writing Documentation',['../_plugins.html#PluginWriting',1,'']]], + ['writing_20obj_20wavefront_20files_70',['Writing OBJ (Wavefront) Files',['../_i_o.html#OBJwrite',1,'']]], + ['writing_20plugins_71',['Writing Plugins',['../_plugins.html',1,'']]], + ['writing_20ply_20stanford_20polygon_20files_72',['Writing PLY (Stanford Polygon) Files',['../_i_o.html#PLYwrite',1,'']]], + ['writing_20results_20to_20file_73',['Writing results to file',['../_li_d_a_r_doc.html#LiDARoutput',1,'']]], + ['wsl_74',['Manually installing OptiX if using Windows Subsystem for Linux (WSL)',['../_dependent_software.html#OptiXWSL',1,'']]] ]; diff --git a/doc/html/search/all_2.js b/doc/html/search/all_2.js index b986ccdab..a686eedf1 100644 --- a/doc/html/search/all_2.js +++ b/doc/html/search/all_2.js @@ -8,8 +8,7 @@ var searchData= ['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,'']]], - ['26_8',['Helios Documentation v1.3.26',['../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,'']]] + ['2_3a_20working_20with_20context_20geometry_8',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], + ['2d_20raster_20ground_20cover_20fraction_9',['2D raster ground cover fraction',['../_aerial_li_d_a_r_doc.html#AerialGroundCover',1,'']]], + ['2d_20raster_20height_20maps_10',['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 3f929cb36..6f881fbdc 100644 --- a/doc/html/search/all_3.js +++ b/doc/html/search/all_3.js @@ -1,9 +1,8 @@ var searchData= [ - ['3_2026_0',['Helios Documentation v1.3.26',['../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,'']]], - ['3_20removing_20the_20background_4',['3. Removing the background',['../_making_masks.html#Three',1,'']]], - ['3_20run_20the_20model_20and_20calculate_20par_20interception_5',['3. Run the model and calculate PAR interception',['../radiation_basics.html#Tutorial10_run',1,'']]] + ['3_20laminar_20flow_20around_20a_20sphere_0',['3. Laminar flow around a sphere',['../_b_l_conductance_doc.html#BLC3',1,'']]], + ['3_20modify_20visualizer_20options_1',['Step 3. Modify Visualizer options',['../visualizer_basics.html#vis_step3',1,'']]], + ['3_20radiation_20model_20set_20up_2',['3. Radiation model set-up',['../radiation__beers_law.html#tutorial11_rad',1,'']]], + ['3_20removing_20the_20background_3',['3. Removing the background',['../_making_masks.html#Three',1,'']]], + ['3_20run_20the_20model_20and_20calculate_20par_20interception_4',['3. Run the model and calculate PAR interception',['../radiation_basics.html#Tutorial10_run',1,'']]] ]; diff --git a/doc/html/search/all_c.js b/doc/html/search/all_c.js index ca2c7b80e..195e404e2 100644 --- a/doc/html/search/all_c.js +++ b/doc/html/search/all_c.js @@ -87,27 +87,26 @@ var searchData= ['distortimage_84',['distortImage',['../struct_camera_calibration.html#a75a0688aa37a6d7706cef4ee4b92dd7f',1,'CameraCalibration']]], ['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_2026_88',['Helios Documentation v1.3.26',['../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()']]], - ['doesobjectcontainprimitive_92',['doesObjectContainPrimitive',['../classhelios_1_1_compound_object.html#ae06ed1275c9ba5ed5ed59b08bdfd1216',1,'helios::CompoundObject::doesObjectContainPrimitive()'],['../classhelios_1_1_context.html#a60b571dd1cfd525caedcfd725162721e',1,'helios::Context::doesObjectContainPrimitive()']]], - ['doesobjectdataexist_93',['doesObjectDataExist',['../classhelios_1_1_compound_object.html#aac66c9dbdba0e7418051a9eb9c688618',1,'helios::CompoundObject::doesObjectDataExist()'],['../classhelios_1_1_context.html#a2834b9a6eee49d644f201f696ae5a4d5',1,'helios::Context::doesObjectDataExist(uint objID, const char *label) const']]], - ['doesobjectexist_94',['doesObjectExist',['../classhelios_1_1_context.html#a9b410e55075482b8cbc549f9bf571541',1,'helios::Context']]], - ['doesprimitivedataexist_95',['doesPrimitiveDataExist',['../classhelios_1_1_context.html#a780d83edd66f25cd38b5059359b48a7b',1,'helios::Context']]], - ['doesprimitiveexist_96',['doesPrimitiveExist',['../classhelios_1_1_context.html#acf4a7fa9ba97f03d0a9218e5c4b7bc66',1,'helios::Context::doesPrimitiveExist(uint UUID) const'],['../classhelios_1_1_context.html#a0c478e8ce47bfad4db16829f76305946',1,'helios::Context::doesPrimitiveExist(const std::vector< uint > &UUIDs) const']]], - ['doestimeseriesvariableexist_97',['doesTimeseriesVariableExist',['../group__timeseries.html#ga8beaa8454ad248064b74698f7f0534a2',1,'helios::Context']]], - ['doxygen_98',['Doxygen',['../_c_lion_i_d_e.html#CLionDox',1,'']]], - ['driver_20timeout_99',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], - ['dummy_20model_20plugin_20documentation_100',['Dummy Model Plugin Documentation',['../_dummy.html',1,'']]], - ['dummymodel_101',['DummyModel',['../class_dummy_model.html',1,'DummyModel'],['../class_dummy_model.html#ae48cd297d1bf8b94c296218e767b9f70',1,'DummyModel::DummyModel()']]], - ['dummymodel_2ecpp_102',['DummyModel.cpp',['../_dummy_model_8cpp.html',1,'']]], - ['dummymodel_2eh_103',['DummyModel.h',['../_dummy_model_8h.html',1,'']]], - ['dupex_104',['Dupex',['../struct_dupex.html',1,'']]], - ['duplicateglobaldata_105',['duplicateGlobalData',['../classhelios_1_1_context.html#ae89abaa03d7585e7f3abc6c5f16a0223',1,'helios::Context']]], - ['duplicateobjectdata_106',['duplicateObjectData',['../classhelios_1_1_context.html#a613366ab9fdbfd69428535d5c1867b73',1,'helios::Context']]], - ['duplicateplantinstance_107',['duplicatePlantInstance',['../class_plant_architecture.html#acd6de0d13dbc534992b94a203a16b76d',1,'PlantArchitecture']]], - ['duplicateprimitivedata_108',['duplicatePrimitiveData',['../classhelios_1_1_context.html#a86be37149a98b13141175da5793d053e',1,'helios::Context::duplicatePrimitiveData(uint UUID, const char *old_label, const char *new_label)'],['../classhelios_1_1_context.html#a3796eae362aec38408e40a3a83b3d8a4',1,'helios::Context::duplicatePrimitiveData(const char *existing_data_label, const char *copy_data_label)']]], - ['dynamic_20mode_109',['Running the Model in Dynamic Mode',['../_stomatal_doc.html#StomatalRunDyn',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'],['../index.html',1,'Helios 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']]], + ['doesbandexist_88',['doesBandExist',['../class_radiation_model.html#a966780925811e3a710a6d91f4ac852fb',1,'RadiationModel']]], + ['doesglobaldataexist_89',['doesGlobalDataExist',['../classhelios_1_1_context.html#a65ad9cb057b0cb2be3ef2734847608cc',1,'helios::Context']]], + ['doeshitdataexist_90',['doesHitDataExist',['../class_aerial_li_d_a_rcloud.html#a9b5aa652c94d4dee19a4f956a62f2ab1',1,'AerialLiDARcloud::doesHitDataExist()'],['../class_li_d_a_rcloud.html#aabb8d404b7f3fa00d8281cb6b74f90c0',1,'LiDARcloud::doesHitDataExist()']]], + ['doesobjectcontainprimitive_91',['doesObjectContainPrimitive',['../classhelios_1_1_compound_object.html#ae06ed1275c9ba5ed5ed59b08bdfd1216',1,'helios::CompoundObject::doesObjectContainPrimitive()'],['../classhelios_1_1_context.html#a60b571dd1cfd525caedcfd725162721e',1,'helios::Context::doesObjectContainPrimitive()']]], + ['doesobjectdataexist_92',['doesObjectDataExist',['../classhelios_1_1_compound_object.html#aac66c9dbdba0e7418051a9eb9c688618',1,'helios::CompoundObject::doesObjectDataExist()'],['../classhelios_1_1_context.html#a2834b9a6eee49d644f201f696ae5a4d5',1,'helios::Context::doesObjectDataExist(uint objID, const char *label) const']]], + ['doesobjectexist_93',['doesObjectExist',['../classhelios_1_1_context.html#a9b410e55075482b8cbc549f9bf571541',1,'helios::Context']]], + ['doesprimitivedataexist_94',['doesPrimitiveDataExist',['../classhelios_1_1_context.html#a780d83edd66f25cd38b5059359b48a7b',1,'helios::Context']]], + ['doesprimitiveexist_95',['doesPrimitiveExist',['../classhelios_1_1_context.html#acf4a7fa9ba97f03d0a9218e5c4b7bc66',1,'helios::Context::doesPrimitiveExist(uint UUID) const'],['../classhelios_1_1_context.html#a0c478e8ce47bfad4db16829f76305946',1,'helios::Context::doesPrimitiveExist(const std::vector< uint > &UUIDs) const']]], + ['doestimeseriesvariableexist_96',['doesTimeseriesVariableExist',['../group__timeseries.html#ga8beaa8454ad248064b74698f7f0534a2',1,'helios::Context']]], + ['doxygen_97',['Doxygen',['../_c_lion_i_d_e.html#CLionDox',1,'']]], + ['driver_20timeout_98',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], + ['dummy_20model_20plugin_20documentation_99',['Dummy Model Plugin Documentation',['../_dummy.html',1,'']]], + ['dummymodel_100',['DummyModel',['../class_dummy_model.html',1,'DummyModel'],['../class_dummy_model.html#ae48cd297d1bf8b94c296218e767b9f70',1,'DummyModel::DummyModel()']]], + ['dummymodel_2ecpp_101',['DummyModel.cpp',['../_dummy_model_8cpp.html',1,'']]], + ['dummymodel_2eh_102',['DummyModel.h',['../_dummy_model_8h.html',1,'']]], + ['dupex_103',['Dupex',['../struct_dupex.html',1,'']]], + ['duplicateglobaldata_104',['duplicateGlobalData',['../classhelios_1_1_context.html#ae89abaa03d7585e7f3abc6c5f16a0223',1,'helios::Context']]], + ['duplicateobjectdata_105',['duplicateObjectData',['../classhelios_1_1_context.html#a613366ab9fdbfd69428535d5c1867b73',1,'helios::Context']]], + ['duplicateplantinstance_106',['duplicatePlantInstance',['../class_plant_architecture.html#acd6de0d13dbc534992b94a203a16b76d',1,'PlantArchitecture']]], + ['duplicateprimitivedata_107',['duplicatePrimitiveData',['../classhelios_1_1_context.html#a86be37149a98b13141175da5793d053e',1,'helios::Context::duplicatePrimitiveData(uint UUID, const char *old_label, const char *new_label)'],['../classhelios_1_1_context.html#a3796eae362aec38408e40a3a83b3d8a4',1,'helios::Context::duplicatePrimitiveData(const char *existing_data_label, const char *copy_data_label)']]], + ['dynamic_20mode_108',['Running the Model in Dynamic Mode',['../_stomatal_doc.html#StomatalRunDyn',1,'']]] ]; diff --git a/doc/html/search/all_d.js b/doc/html/search/all_d.js index b5e6fe814..6f5525bb1 100644 --- a/doc/html/search/all_d.js +++ b/doc/html/search/all_d.js @@ -48,8 +48,9 @@ var searchData= ['exportpointcloud_45',['exportPointCloud',['../class_aerial_li_d_a_rcloud.html#a7f0992570b8535f687fd7067eb9f3593',1,'AerialLiDARcloud::exportPointCloud()'],['../class_li_d_a_rcloud.html#a2d0c11c6d8001171269232ff5d7f6322',1,'LiDARcloud::exportPointCloud(const char *filename)'],['../class_li_d_a_rcloud.html#ae9910fa1aae6b8b077d57417c130e753',1,'LiDARcloud::exportPointCloud(const char *filename, uint scanID)']]], ['exportpointcloudptx_46',['exportPointCloudPTX',['../class_li_d_a_rcloud.html#ac48fe9018f26664dd9abd8c100fccaa6',1,'LiDARcloud']]], ['exporttriangleareas_47',['exportTriangleAreas',['../class_li_d_a_rcloud.html#a416638f486c4fd2572a9589b69605fe7',1,'LiDARcloud::exportTriangleAreas(const char *filename)'],['../class_li_d_a_rcloud.html#adb93e3a16abc8100b2e5dac956c6cc3e',1,'LiDARcloud::exportTriangleAreas(const char *filename, int gridcell)']]], - ['exporttriangleinclinationdistribution_48',['exportTriangleInclinationDistribution',['../class_li_d_a_rcloud.html#aadeb8297b74a75fd003f6c96fe378043',1,'LiDARcloud']]], - ['exporttrianglenormals_49',['exportTriangleNormals',['../class_li_d_a_rcloud.html#ad030fdddcfa669d6af513eb66a9cbd1a',1,'LiDARcloud::exportTriangleNormals(const char *filename)'],['../class_li_d_a_rcloud.html#aa8376ce652d2e95e886d4d60d321c274',1,'LiDARcloud::exportTriangleNormals(const char *filename, int gridcell)']]], - ['extent_50',['extent',['../struct_aerial_scan_metadata.html#a5c51ed2d651b82502f0921bb52d80095',1,'AerialScanMetadata']]], - ['external_20radiation_20sources_51',['External Radiation Sources',['../_radiation_doc.html#RadSources',1,'']]] + ['exporttriangleazimuthdistribution_48',['exportTriangleAzimuthDistribution',['../class_li_d_a_rcloud.html#ab9a33b5d05470e8e0362de352fc09bf1',1,'LiDARcloud']]], + ['exporttriangleinclinationdistribution_49',['exportTriangleInclinationDistribution',['../class_li_d_a_rcloud.html#aadeb8297b74a75fd003f6c96fe378043',1,'LiDARcloud']]], + ['exporttrianglenormals_50',['exportTriangleNormals',['../class_li_d_a_rcloud.html#ad030fdddcfa669d6af513eb66a9cbd1a',1,'LiDARcloud::exportTriangleNormals(const char *filename)'],['../class_li_d_a_rcloud.html#aa8376ce652d2e95e886d4d60d321c274',1,'LiDARcloud::exportTriangleNormals(const char *filename, int gridcell)']]], + ['extent_51',['extent',['../struct_aerial_scan_metadata.html#a5c51ed2d651b82502f0921bb52d80095',1,'AerialScanMetadata']]], + ['external_20radiation_20sources_52',['External Radiation Sources',['../_radiation_doc.html#RadSources',1,'']]] ]; diff --git a/doc/html/search/all_f.js b/doc/html/search/all_f.js index 71af03b8b..cb6ac6d78 100644 --- a/doc/html/search/all_f.js +++ b/doc/html/search/all_f.js @@ -29,274 +29,279 @@ var searchData= ['getallobjectids_26',['getAllObjectIDs',['../classhelios_1_1_context.html#a2ef355a3298b21313700acec64232e22',1,'helios::Context::getAllObjectIDs()'],['../class_plant_architecture.html#a9069b1d637752f0a74ded148ae1706b0',1,'PlantArchitecture::getAllObjectIDs() const']]], ['getallpeduncleuuids_27',['getAllPeduncleUUIDs',['../class_plant_architecture.html#ad46693fc275721338c8f24cb764b2bf1',1,'PlantArchitecture']]], ['getallpetioleuuids_28',['getAllPetioleUUIDs',['../class_plant_architecture.html#afd1c00e6b5b6aa45e212aeb6b68cb825',1,'PlantArchitecture']]], - ['getallplantobjectids_29',['getAllPlantObjectIDs',['../class_plant_architecture.html#acf9855048c790d30d8d4de7fa1dc3550',1,'PlantArchitecture']]], - ['getallplantuuids_30',['getAllPlantUUIDs',['../class_plant_architecture.html#a3bdffb4e53fe0da836a40de80946d31f',1,'PlantArchitecture']]], - ['getalluuids_31',['getAllUUIDs',['../classhelios_1_1_context.html#a98516632daccf958cca6b5b6582310bb',1,'helios::Context::getAllUUIDs()'],['../class_canopy_generator.html#a8e395619077d656e206f4159f0bf8d34',1,'CanopyGenerator::getAllUUIDs()'],['../class_plant_architecture.html#afec06c56ae296984727c90413511cf6a',1,'PlantArchitecture::getAllUUIDs()'],['../class_weber_penn_tree.html#a19e16f9a51493680afebc38f3c434400',1,'WeberPennTree::getAllUUIDs()']]], - ['getambientlongwaveflux_32',['getAmbientLongwaveFlux',['../class_solar_position.html#a30ee555eedece8b7e19855877a74da71',1,'SolarPosition']]], - ['getarea_33',['getArea',['../classhelios_1_1_compound_object.html#a8bb518f6166e2a2831a68a7626787ac1',1,'helios::CompoundObject']]], - ['getaxisunitvector_34',['getAxisUnitVector',['../classhelios_1_1_cone.html#a60fc92fbb15149017956449123c0e4d0',1,'helios::Cone']]], - ['getbmfcoefficientsfromlibrary_35',['getBMFCoefficientsFromLibrary',['../class_stomatal_conductance_model.html#ada09940a1cc67dbfc0192f6e0a50c967',1,'StomatalConductanceModel']]], - ['getboxobjectcenter_36',['getBoxObjectCenter',['../classhelios_1_1_context.html#af73c44dace71ec805136b7d6ad6095a9',1,'helios::Context']]], - ['getboxobjectpointer_37',['getBoxObjectPointer',['../classhelios_1_1_context.html#a1ecbb5a8cfa6764bade6e0650d2f6990',1,'helios::Context']]], - ['getboxobjectsize_38',['getBoxObjectSize',['../classhelios_1_1_context.html#a4e5799ba4b6a0a889f446bef9e4d3dc0',1,'helios::Context']]], - ['getboxobjectsubdivisioncount_39',['getBoxObjectSubdivisionCount',['../classhelios_1_1_context.html#a258f524d38cdeb5f6c83a7f387608490',1,'helios::Context']]], - ['getboxobjectvolume_40',['getBoxObjectVolume',['../classhelios_1_1_context.html#ae31cc8855aacb6380a288a4b7fa8db82',1,'helios::Context']]], - ['getbranchuuids_41',['getBranchUUIDs',['../class_canopy_generator.html#ab7115aaa287346b9c8e7854bd66f8b5f',1,'CanopyGenerator::getBranchUUIDs(uint PlantID)'],['../class_canopy_generator.html#a7db6f05ab623b77de4e8a81dc132e914',1,'CanopyGenerator::getBranchUUIDs()'],['../class_weber_penn_tree.html#a813cb8959272b535050dc97aa49d3ed3',1,'WeberPennTree::getBranchUUIDs()']]], - ['getcameralookat_42',['getCameraLookat',['../class_radiation_model.html#a68c8736e58c7daf440ff9c93bb00522d',1,'RadiationModel']]], - ['getcameraorientation_43',['getCameraOrientation',['../class_radiation_model.html#a0b67b056aa1f2b5e6c42a06e358f4eb8',1,'RadiationModel']]], - ['getcameraposition_44',['getCameraPosition',['../class_radiation_model.html#a6785deae272a9464920030fc3f124bc3',1,'RadiationModel']]], - ['getcameraresponsescale_45',['getCameraResponseScale',['../struct_camera_calibration.html#a18eff4a7ecab1038f27b68c3963a5513',1,'CameraCalibration::getCameraResponseScale()'],['../class_radiation_model.html#adb5a74547d51a18018d3daeba0ec5f3c',1,'RadiationModel::getCameraResponseScale()']]], - ['getcellcenter_46',['getCellCenter',['../class_aerial_li_d_a_rcloud.html#a6e83c157d63d12253af3b81b995e1a33',1,'AerialLiDARcloud::getCellCenter()'],['../class_li_d_a_rcloud.html#a6e2ce01abb33cc0f80b2aa653ac6a445',1,'LiDARcloud::getCellCenter()']]], - ['getcellcoverfraction_47',['getCellCoverFraction',['../class_aerial_li_d_a_rcloud.html#ac714e2231b63d1455237662661590b16',1,'AerialLiDARcloud']]], - ['getcellglobalanchor_48',['getCellGlobalAnchor',['../class_li_d_a_rcloud.html#ad1ad4f851b5b7fcbf5b088b161aed83e',1,'LiDARcloud']]], - ['getcellgroundheight_49',['getCellGroundHeight',['../class_aerial_li_d_a_rcloud.html#a3b9d9ac013a041c30d58e68e5dc92bee',1,'AerialLiDARcloud']]], - ['getcellgtheta_50',['getCellGtheta',['../class_li_d_a_rcloud.html#a54351e18e3f4155e9d55eb02bd63c722',1,'LiDARcloud']]], - ['getcellleafarea_51',['getCellLeafArea',['../class_aerial_li_d_a_rcloud.html#a9f90891b20b8996e983e66640684b6cc',1,'AerialLiDARcloud::getCellLeafArea()'],['../class_li_d_a_rcloud.html#ac9d20a35bdb7ee2d45490ac1cd520117',1,'LiDARcloud::getCellLeafArea()']]], - ['getcellleafareadensity_52',['getCellLeafAreaDensity',['../class_aerial_li_d_a_rcloud.html#a4ca0903b642daffdff27e69a172c96b5',1,'AerialLiDARcloud::getCellLeafAreaDensity()'],['../class_li_d_a_rcloud.html#a3c1744984481f9629dc1371291fa397e',1,'LiDARcloud::getCellLeafAreaDensity()']]], - ['getcellmaximumhitheight_53',['getCellMaximumHitHeight',['../class_aerial_li_d_a_rcloud.html#a00f6479153ac2025031b70bd5637b65b',1,'AerialLiDARcloud']]], - ['getcellprimitives_54',['getCellPrimitives',['../class_voxel_intersection.html#a7d50123db71cf5cd7c7cc4582abd5cb2',1,'VoxelIntersection']]], - ['getcellrbar_55',['getCellRbar',['../class_aerial_li_d_a_rcloud.html#ae35261c7fc1553cb15fb318a2b14a3b2',1,'AerialLiDARcloud']]], - ['getcellrotation_56',['getCellRotation',['../class_li_d_a_rcloud.html#aa2cba1d0bcd9a2ae35d9a5be03832efc',1,'LiDARcloud']]], - ['getcellsize_57',['getCellSize',['../class_aerial_li_d_a_rcloud.html#a5bf5379ee229ebb51fdc8195af8cf3e7',1,'AerialLiDARcloud::getCellSize()'],['../class_li_d_a_rcloud.html#a6662330b95ee7ee77ea6647871695c55',1,'LiDARcloud::getCellSize()']]], - ['getcelltransmissionprobability_58',['getCellTransmissionProbability',['../class_aerial_li_d_a_rcloud.html#a98770b70c510e7611fb171d3fe920554',1,'AerialLiDARcloud']]], - ['getcellvegetationheight_59',['getCellVegetationHeight',['../class_aerial_li_d_a_rcloud.html#a12fe426a267cbef9982138537198558a',1,'AerialLiDARcloud']]], - ['getcenter_60',['getCenter',['../classhelios_1_1_tile.html#a18178d0280f8ecc1149663558947ca06',1,'helios::Tile::getCenter()'],['../classhelios_1_1_sphere.html#a48eada17c3dab899a91158f1424518d6',1,'helios::Sphere::getCenter()'],['../classhelios_1_1_box.html#a96e72a40ff113d6a6b463fe8c60b672a',1,'helios::Box::getCenter()'],['../classhelios_1_1_disk.html#ae8ed884a95cbfa2440e3bd9f8e3e4057',1,'helios::Disk::getCenter()']]], - ['getconeobjectaxisunitvector_61',['getConeObjectAxisUnitVector',['../classhelios_1_1_context.html#acaa3fb162b17cb7f912162f5d4be894e',1,'helios::Context']]], - ['getconeobjectlength_62',['getConeObjectLength',['../classhelios_1_1_context.html#ad2b045f361aa8e8596bcf325c1707a25',1,'helios::Context']]], - ['getconeobjectnode_63',['getConeObjectNode',['../classhelios_1_1_context.html#a54e9f0b7c5014a37cd9d5bf74e7d5935',1,'helios::Context']]], - ['getconeobjectnoderadii_64',['getConeObjectNodeRadii',['../classhelios_1_1_context.html#ade2608274b311c809d46bb13943b9e4e',1,'helios::Context']]], - ['getconeobjectnoderadius_65',['getConeObjectNodeRadius',['../classhelios_1_1_context.html#af5acc5647e6bf9cd1649da1dec677110',1,'helios::Context']]], - ['getconeobjectnodes_66',['getConeObjectNodes',['../classhelios_1_1_context.html#a8c4ec2d90ccd3d44a97597ecd80d78b6',1,'helios::Context']]], - ['getconeobjectpointer_67',['getConeObjectPointer',['../classhelios_1_1_context.html#a3221051ea9c1025e8fb00d9dec01839f',1,'helios::Context']]], - ['getconeobjectsubdivisioncount_68',['getConeObjectSubdivisionCount',['../classhelios_1_1_context.html#a1ff97eb95d5896e096156320f5bd5ff0',1,'helios::Context']]], - ['getconeobjectvolume_69',['getConeObjectVolume',['../classhelios_1_1_context.html#af6c1c571171be2604822a8df44d2349c',1,'helios::Context']]], - ['getcurrentcolormap_70',['getCurrentColormap',['../class_visualizer.html#ae2bba6102a283a31ec4f5780817a15da',1,'Visualizer']]], - ['getcurrentphytomerparameters_71',['getCurrentPhytomerParameters',['../class_plant_architecture.html#aaba5ecb6c069be56b3706a4060f5ff49',1,'PlantArchitecture']]], - ['getcurrentshootparameters_72',['getCurrentShootParameters',['../class_plant_architecture.html#aa696281e805e8879a78dacdf4354ff38',1,'PlantArchitecture::getCurrentShootParameters(const std::string &shoot_type_label)'],['../class_plant_architecture.html#a190d91f02c5cfcfad036879460b2e495',1,'PlantArchitecture::getCurrentShootParameters()']]], - ['getdate_73',['getDate',['../classhelios_1_1_context.html#a95dd5bc221cd8bcb4efabd0122d59b4f',1,'helios::Context']]], - ['getdepthmap_74',['getDepthMap',['../class_visualizer.html#a7c6362d7dc0f0bd4bba53195ce92b84e',1,'Visualizer']]], - ['getdiffuseflux_75',['getDiffuseFlux',['../class_radiation_model.html#af8450f2308aee38272b4aef87f0c547b',1,'RadiationModel']]], - ['getdiffusefraction_76',['getDiffuseFraction',['../class_solar_position.html#af8dbd15453ce775dab5b2c5a49b1c93b',1,'SolarPosition']]], - ['getdiskobjectcenter_77',['getDiskObjectCenter',['../classhelios_1_1_context.html#a213aea1539e0bb38965cf2953b1831df',1,'helios::Context']]], - ['getdiskobjectpointer_78',['getDiskObjectPointer',['../classhelios_1_1_context.html#a17c1256a1f57fbae1f34e04b66b76ca8',1,'helios::Context']]], - ['getdiskobjectsize_79',['getDiskObjectSize',['../classhelios_1_1_context.html#acee51918d3ee1d9892e5a51106a625d9',1,'helios::Context']]], - ['getdiskobjectsubdivisioncount_80',['getDiskObjectSubdivisionCount',['../classhelios_1_1_context.html#a86ffc9a6cdcd3851231c64dcc152123c',1,'helios::Context']]], - ['getdomainboundingbox_81',['getDomainBoundingBox',['../classhelios_1_1_context.html#a8690412a63d1eff69e679e48d03c9838',1,'helios::Context::getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const'],['../classhelios_1_1_context.html#ad4ac166bb01547d1cefb1ace7a9b966d',1,'helios::Context::getDomainBoundingBox(const std::vector< uint > &UUIDs, helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const'],['../class_visualizer.html#ae9c98dee278e9bcd5f85b871ff8ddfe5',1,'Visualizer::getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const']]], - ['getdomainboundingradius_82',['getDomainBoundingRadius',['../class_visualizer.html#a783739e072baeafc943a077dcb1cc3d5',1,'Visualizer']]], - ['getdomainboundingsphere_83',['getDomainBoundingSphere',['../classhelios_1_1_context.html#a3a6b0d25c5d9febb17787982c9f09d63',1,'helios::Context::getDomainBoundingSphere(helios::vec3 &center, float &radius) const'],['../classhelios_1_1_context.html#af3e048e969f06e3a0cf36ed3d76766ca',1,'helios::Context::getDomainBoundingSphere(const std::vector< uint > &UUIDs, helios::vec3 &center, float &radius) const']]], - ['getempiricalmodelcoefficients_84',['getEmpiricalModelCoefficients',['../class_photosynthesis_model.html#a86094d579852c2dc846acc2a97e6ac44',1,'PhotosynthesisModel']]], - ['getfarquharcoefficientsfromlibrary_85',['getFarquharCoefficientsFromLibrary',['../class_photosynthesis_model.html#ae40570ef642d5d4dc070dce9ba093f16',1,'PhotosynthesisModel']]], - ['getfarquharmodelcoefficients_86',['getFarquharModelCoefficients',['../class_photosynthesis_model.html#aeab92cd73298c5f89626b30ce8c41cf9',1,'PhotosynthesisModel']]], - ['getfileextension_87',['getFileExtension',['../global_8h.html#a58e660bb08e1ce13466825ae666467ef',1,'helios']]], - ['getfilename_88',['getFileName',['../global_8h.html#a63bd49091fdab0e262b051f61fb9a902',1,'helios']]], - ['getfilepath_89',['getFilePath',['../global_8h.html#ad76f15d03b511d1bf5123d64d804d6e8',1,'helios']]], - ['getfilestem_90',['getFileStem',['../global_8h.html#a9fff8cb6c3474de479f81c12f173d3ed',1,'helios']]], - ['getframebuffersize_91',['getFramebufferSize',['../class_visualizer.html#ab3b0261a21e7f552d55e4d2fda55f94f',1,'Visualizer']]], - ['getfruituuids_92',['getFruitUUIDs',['../class_canopy_generator.html#a8ab509f22c4bdffd57b44f67f43ce728',1,'CanopyGenerator::getFruitUUIDs(uint PlantID)'],['../class_canopy_generator.html#abdcc431929f98e57db4b9ed2dc26a616',1,'CanopyGenerator::getFruitUUIDs()']]], - ['getglobaldata_93',['getGlobalData',['../classhelios_1_1_context.html#a972fa4a45b2775f6047d41b88dc69d03',1,'helios::Context::getGlobalData(const char *label, int &data) const'],['../classhelios_1_1_context.html#a175d9a1955f428b0f2d6b11ab3b17659',1,'helios::Context::getGlobalData(const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#a98cbb0d37dc9fafaad14184cb889534f',1,'helios::Context::getGlobalData(const char *label, uint &data) const'],['../classhelios_1_1_context.html#a931a92ba7e9916c64d164bc1f29ff754',1,'helios::Context::getGlobalData(const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#ac1f5f6c3f24577cd5c4657c441483425',1,'helios::Context::getGlobalData(const char *label, float &data) const'],['../classhelios_1_1_context.html#a863264ab1339ba35c3754bfbf4c69eec',1,'helios::Context::getGlobalData(const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#a8ec49c820f10831b4b27059d4d1749d6',1,'helios::Context::getGlobalData(const char *label, double &data) const'],['../classhelios_1_1_context.html#a66e7d689b62d9ad47fb85ad45664c97f',1,'helios::Context::getGlobalData(const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#a6f4d6971c05d78aff30b92d277014b9f',1,'helios::Context::getGlobalData(const char *label, helios::vec2 &data) const'],['../classhelios_1_1_context.html#afc90a3d0143273e436541fc3bc9c5554',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec2 > &data) const'],['../classhelios_1_1_context.html#a990fdccf51979e235a1acba08e54583b',1,'helios::Context::getGlobalData(const char *label, helios::vec3 &data) const'],['../classhelios_1_1_context.html#a0376e2dc456e481bd055d5a84b7785f2',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec3 > &data) const'],['../classhelios_1_1_context.html#a3f621b536c3585d7f808698e2f0cd826',1,'helios::Context::getGlobalData(const char *label, helios::vec4 &data) const'],['../classhelios_1_1_context.html#ab0f329c8584b002dda2d77719073bf5d',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec4 > &data) const'],['../classhelios_1_1_context.html#aea16d4845e23fe44ae1da4c032ea57e3',1,'helios::Context::getGlobalData(const char *label, helios::int2 &data) const'],['../classhelios_1_1_context.html#a609563835616233b15fd263bb2e8857d',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int2 > &data) const'],['../classhelios_1_1_context.html#aba7c4fe63193509f40ca6682cddfa9a3',1,'helios::Context::getGlobalData(const char *label, helios::int3 &data) const'],['../classhelios_1_1_context.html#abbc6d463f6d722fca56ad219c8278c16',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int3 > &data) const'],['../classhelios_1_1_context.html#a2b2f0570e50711f34bb24dc01c8a7b43',1,'helios::Context::getGlobalData(const char *label, helios::int4 &data) const'],['../classhelios_1_1_context.html#ad08d9d2bea2c93b14ae2b3678aea2e29',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int4 > &data) const'],['../classhelios_1_1_context.html#a890583b0897bfcd730d137838fa7e155',1,'helios::Context::getGlobalData(const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a0572c1557ec60ae7389072e8ab3c2113',1,'helios::Context::getGlobalData(const char *label, std::vector< std::string > &data) const']]], - ['getglobaldatasize_94',['getGlobalDataSize',['../classhelios_1_1_context.html#a96d1060d1329dc467380ce2e5eafd559',1,'helios::Context']]], - ['getglobaldatatype_95',['getGlobalDataType',['../classhelios_1_1_context.html#a94bf0b919e5e6034fa45fbae2f575947',1,'helios::Context']]], - ['getgridboundingbox_96',['getGridBoundingBox',['../class_li_d_a_rcloud.html#a041ac4ba388c407a35b7f895029038e6',1,'LiDARcloud']]], - ['getgridcellcount_97',['getGridCellCount',['../class_li_d_a_rcloud.html#a28297a71becd69b30820d69b110fcc90',1,'LiDARcloud']]], - ['getgridcenter_98',['getGridCenter',['../class_aerial_li_d_a_rcloud.html#ad639b0d2337b74b1bd4949cc2aba88e0',1,'AerialLiDARcloud']]], - ['getgridextent_99',['getGridExtent',['../class_aerial_li_d_a_rcloud.html#a85ea1ea67ed12f2bbcfc28ef9a78dd77',1,'AerialLiDARcloud']]], - ['getgridresolution_100',['getGridResolution',['../class_aerial_li_d_a_rcloud.html#ae750e548d565d6305e600c5af8360fdb',1,'AerialLiDARcloud']]], - ['getgridrotation_101',['getGridRotation',['../class_aerial_li_d_a_rcloud.html#aace3b3baae4a75be461eb31f617ee695',1,'AerialLiDARcloud']]], - ['getgrounduuids_102',['getGroundUUIDs',['../class_canopy_generator.html#a6f0003d6ca29cbb56657442c7a48ad14',1,'CanopyGenerator']]], - ['gethitboundingbox_103',['getHitBoundingBox',['../class_aerial_li_d_a_rcloud.html#a74b0e833ecb6ee1b3ce3010f3d38d74d',1,'AerialLiDARcloud::getHitBoundingBox()'],['../class_li_d_a_rcloud.html#a45bc37a4d26eb74a944c594a7f3cb54b',1,'LiDARcloud::getHitBoundingBox()']]], - ['gethitcolor_104',['getHitColor',['../class_aerial_li_d_a_rcloud.html#af8f49444eb1d166837c322d03ea1cbfa',1,'AerialLiDARcloud::getHitColor()'],['../class_li_d_a_rcloud.html#aafafed9102966992d3cfb3772fa2ada1',1,'LiDARcloud::getHitColor()']]], - ['gethitcount_105',['getHitCount',['../class_aerial_li_d_a_rcloud.html#aaf287ef121543f10e9e73579bf77281a',1,'AerialLiDARcloud::getHitCount()'],['../class_li_d_a_rcloud.html#a691fd3bbd1262d80e10a674c82c6f568',1,'LiDARcloud::getHitCount()']]], - ['gethitdata_106',['getHitData',['../class_aerial_li_d_a_rcloud.html#a240af79b825bc886e886ff7ff0e0476c',1,'AerialLiDARcloud::getHitData()'],['../class_li_d_a_rcloud.html#a274ef68850afa3f288bb648d9fd6a59a',1,'LiDARcloud::getHitData()']]], - ['gethitgridcell_107',['getHitGridCell',['../class_aerial_li_d_a_rcloud.html#a26bc32e67d3195222f11fb72fb7d63da',1,'AerialLiDARcloud::getHitGridCell()'],['../class_li_d_a_rcloud.html#a251c4f3bbefdd07212cd8fe1037dc0d7',1,'LiDARcloud::getHitGridCell(uint index) const']]], - ['gethitindex_108',['getHitIndex',['../class_li_d_a_rcloud.html#a34eee980f365fdd5469a0cc6ee3a36f5',1,'LiDARcloud']]], - ['gethitraydir_109',['getHitRaydir',['../class_aerial_li_d_a_rcloud.html#ac0f8ba05e24d146d01ee2af0fb9ece7d',1,'AerialLiDARcloud::getHitRaydir()'],['../class_li_d_a_rcloud.html#aa91258bd97d6fcacd3313d8b55cceed4',1,'LiDARcloud::getHitRaydir()']]], - ['gethitscanid_110',['getHitScanID',['../class_aerial_li_d_a_rcloud.html#aaa2bbd15dad66355175fb733630456a4',1,'AerialLiDARcloud::getHitScanID()'],['../class_li_d_a_rcloud.html#a5510b2a0d0a878930e9f11331494bf41',1,'LiDARcloud::getHitScanID()']]], - ['gethitxyz_111',['getHitXYZ',['../class_aerial_li_d_a_rcloud.html#a3363ac3ffff1bbdd164b6074010d75ba',1,'AerialLiDARcloud::getHitXYZ()'],['../class_li_d_a_rcloud.html#ac5f234b6200419f10fe82c9abe409cbd',1,'LiDARcloud::getHitXYZ()']]], - ['getimageresolution_112',['getImageResolution',['../classhelios_1_1_texture.html#a4e106c0c80f0c4c065e5ff71193aaeab',1,'helios::Texture']]], - ['getimageresolutionjpeg_113',['getImageResolutionJPEG',['../global_8h.html#a94c80cbffdccaea7991b439acf8e9eb4',1,'helios']]], - ['getjuliandate_114',['getJulianDate',['../classhelios_1_1_context.html#a23f2611ed71eeefe8cf772cab98de4d4',1,'helios::Context']]], - ['getleafspectra_115',['getLeafSpectra',['../class_leaf_optics.html#a6b9fa9b6fb34fe7738e425b19118005a',1,'LeafOptics']]], - ['getleafuuids_116',['getLeafUUIDs',['../class_canopy_generator.html#a3509012720b5fd256a14bc2924a3b164',1,'CanopyGenerator::getLeafUUIDs(uint PlantID)'],['../class_canopy_generator.html#a73680976a2826f0b5dbf567551fd5593',1,'CanopyGenerator::getLeafUUIDs()'],['../class_weber_penn_tree.html#af4368c1f900503f6d72f0c0e569fe8e5',1,'WeberPennTree::getLeafUUIDs()']]], - ['getlength_117',['getLength',['../classhelios_1_1_tube.html#ad3c194a0f9977e212ac425aefe4032bf',1,'helios::Tube::getLength()'],['../classhelios_1_1_cone.html#ada36b3fe4850f16c4dfa58c38a8da80c',1,'helios::Cone::getLength()']]], - ['getloadedxmlfiles_118',['getLoadedXMLFiles',['../classhelios_1_1_context.html#a48a8a843b99c36ad357dba13ee6f1774',1,'helios::Context']]], - ['getlocation_119',['getLocation',['../classhelios_1_1_context.html#af4b1fa52419259a0c8a2faeb7484a439',1,'helios::Context']]], - ['getmonthstring_120',['getMonthString',['../classhelios_1_1_context.html#a6189f6ab35669f4fefde571ec362247c',1,'helios::Context']]], - ['getnodecolors_121',['getNodeColors',['../classhelios_1_1_tube.html#aae753418cb304e97c296240dc9919388',1,'helios::Tube']]], - ['getnodecoordinate_122',['getNodeCoordinate',['../classhelios_1_1_cone.html#a4f6ddd7fd23d61528ada9df1e333ad17',1,'helios::Cone']]], - ['getnodecoordinates_123',['getNodeCoordinates',['../classhelios_1_1_cone.html#a9eaab4331e325c85ce9f4c101135c966',1,'helios::Cone']]], - ['getnoderadii_124',['getNodeRadii',['../classhelios_1_1_tube.html#a29823b956371d22b35add97fc6831cab',1,'helios::Tube::getNodeRadii()'],['../classhelios_1_1_cone.html#adc5370734810e4b526bf0d42e143ecf8',1,'helios::Cone::getNodeRadii() const']]], - ['getnoderadius_125',['getNodeRadius',['../classhelios_1_1_cone.html#a2334ca87f6bb556b411c8a51476b523c',1,'helios::Cone']]], - ['getnodes_126',['getNodes',['../classhelios_1_1_tube.html#ab55e8f7d7a948941027f169d714e365b',1,'helios::Tube']]], - ['getnormal_127',['getNormal',['../classhelios_1_1_tile.html#ab8c70daf8c14bc60caf499b5adce301c',1,'helios::Tile']]], - ['getobjectarea_128',['getObjectArea',['../classhelios_1_1_context.html#aac46a608ec7719e4702cd861667925f1',1,'helios::Context']]], - ['getobjectboundingbox_129',['getObjectBoundingBox',['../classhelios_1_1_context.html#a1b9871bf670404adc1d952e59429ec38',1,'helios::Context::getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const'],['../classhelios_1_1_context.html#ab5aef932bd4b64b1cee932423172ab6f',1,'helios::Context::getObjectBoundingBox(const std::vector< uint > &ObjID, vec3 &min_corner, vec3 &max_corner) const']]], - ['getobjectcenter_130',['getObjectCenter',['../classhelios_1_1_compound_object.html#aff66ca85a22d7f8a2501039e2e7183a7',1,'helios::CompoundObject::getObjectCenter()'],['../classhelios_1_1_context.html#a4fe8ddd10f0d34bfe0b2a4aea648442a',1,'helios::Context::getObjectCenter(uint ObjID) const']]], - ['getobjectcount_131',['getObjectCount',['../classhelios_1_1_context.html#a54b9c5503ad33d1dcc8f6a5c74f7ea76',1,'helios::Context']]], - ['getobjectdata_132',['getObjectData',['../classhelios_1_1_compound_object.html#ac91c73ac495bc4a93cc9a89d0eb58f47',1,'helios::CompoundObject::getObjectData(const char *label, int &data) const'],['../classhelios_1_1_compound_object.html#aed77927b3d3fe0ea7ea674b20a8acce1',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int > &data) const'],['../classhelios_1_1_compound_object.html#ac91bb0e57aa261b003de76b3e008a762',1,'helios::CompoundObject::getObjectData(const char *label, uint &data) const'],['../classhelios_1_1_compound_object.html#a7be991a83ada928f25c23cf7ca3b1822',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_compound_object.html#ac222719662ca008014cdd045bedd3d96',1,'helios::CompoundObject::getObjectData(const char *label, float &data) const'],['../classhelios_1_1_compound_object.html#ac128057ff1d7cabb9dfbfb33216cb0c5',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< float > &data) const'],['../classhelios_1_1_compound_object.html#a6d99ef1cacec7471bb79b57601a7a6ee',1,'helios::CompoundObject::getObjectData(const char *label, double &data) const'],['../classhelios_1_1_compound_object.html#ac7af8838d7132683dd9fdbffd1288579',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< double > &data) const'],['../classhelios_1_1_compound_object.html#aef1aadca9de0e9a66500ca5879ab3755',1,'helios::CompoundObject::getObjectData(const char *label, vec2 &data) const'],['../classhelios_1_1_compound_object.html#af7574c29395681941d4d875e304b93de',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_compound_object.html#acea74a2c138c1e5d832df864a231e486',1,'helios::CompoundObject::getObjectData(const char *label, vec3 &data) const'],['../classhelios_1_1_compound_object.html#a797a5fd8f08ff7220b15ae1d5accb6cd',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_compound_object.html#a52661efba4b57415b073fcf839069623',1,'helios::CompoundObject::getObjectData(const char *label, vec4 &data) const'],['../classhelios_1_1_compound_object.html#a15ef0fda0196b4de933e4379d5f8234f',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_compound_object.html#a768a439ecb0d6e8449b31cd137317168',1,'helios::CompoundObject::getObjectData(const char *label, int2 &data) const'],['../classhelios_1_1_compound_object.html#af4d1accb01b8dd2f968296c43dfb6d97',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_compound_object.html#a95f20aead49e80032b0673273de436f2',1,'helios::CompoundObject::getObjectData(const char *label, int3 &data) const'],['../classhelios_1_1_compound_object.html#a6cb032fa5f5b6de86f234eb237980586',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_compound_object.html#a2c0dcefe9e05ec04b001ad94f475f34c',1,'helios::CompoundObject::getObjectData(const char *label, int4 &data) const'],['../classhelios_1_1_compound_object.html#aba75ef4dd5b01b02fc99f9a1d957d70b',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_compound_object.html#afa77a9712c207752cd56522f2dbca52b',1,'helios::CompoundObject::getObjectData(const char *label, std::string &data) const'],['../classhelios_1_1_compound_object.html#adfd1f35dc8785f223c02cc940360e6a5',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< std::string > &data) const'],['../classhelios_1_1_context.html#a3511ff568337b501ca878c99d97c9b52',1,'helios::Context::getObjectData(uint objID, const char *label, int &data) const'],['../classhelios_1_1_context.html#ae75ddc9a945ec876533211f52b8cd22e',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#abbd59cc4e7bcad35b43ea7240c4d5558',1,'helios::Context::getObjectData(uint objID, const char *label, uint &data) const'],['../classhelios_1_1_context.html#a22d510fad177ca319bdac0a94ee8f069',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#a8935a9cdf6e34e72bcb636a97043a474',1,'helios::Context::getObjectData(uint objID, const char *label, float &data) const'],['../classhelios_1_1_context.html#a293d899bb22cae1db8cf6c2cc813055d',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#ae222f3351535f3aea35e76cbe2ca2d67',1,'helios::Context::getObjectData(uint objID, const char *label, double &data) const'],['../classhelios_1_1_context.html#acda7f75e833791bcbd74ca8b37272a8b',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#af8fa05c716517966f7abcc2f4019c709',1,'helios::Context::getObjectData(uint objID, const char *label, vec2 &data) const'],['../classhelios_1_1_context.html#a2e691b7f0b630792f50b5423e23ebab1',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_context.html#a628cf051625e33549044cd20656519ac',1,'helios::Context::getObjectData(uint objID, const char *label, vec3 &data) const'],['../classhelios_1_1_context.html#a6606603899859e211de9f56cd49bf92d',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_context.html#ac2b7e667ec37c88868ba0752919da1c9',1,'helios::Context::getObjectData(uint objID, const char *label, vec4 &data) const'],['../classhelios_1_1_context.html#ace5025b962226a75c4984ee6ecc21356',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_context.html#ae56639e95fae8796545efde94fa84bcc',1,'helios::Context::getObjectData(uint objID, const char *label, int2 &data) const'],['../classhelios_1_1_context.html#a39b169b41cf94516afd863f580c2b772',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_context.html#ac58fc8f10c12dc54265491576650a0c6',1,'helios::Context::getObjectData(uint objID, const char *label, int3 &data) const'],['../classhelios_1_1_context.html#ac097e42620523f2d57d28eecd02954a4',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_context.html#aa393d7b0f24855b2e54480be71c09ad2',1,'helios::Context::getObjectData(uint objID, const char *label, int4 &data) const'],['../classhelios_1_1_context.html#a7ca032799776268d30fe185a76100e0e',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_context.html#a1eae737b91ec70ae6490a8c403936975',1,'helios::Context::getObjectData(uint objID, const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a158215e07c921d11e495b3805823b725',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< std::string > &data) const']]], - ['getobjectdatasize_133',['getObjectDataSize',['../classhelios_1_1_compound_object.html#a03b2516f8e7e8ae921ea61e4f571eb1d',1,'helios::CompoundObject::getObjectDataSize()'],['../classhelios_1_1_context.html#ac251e9be64f3a35b6d2e6441c2a46f40',1,'helios::Context::getObjectDataSize()']]], - ['getobjectdatatype_134',['getObjectDataType',['../classhelios_1_1_compound_object.html#abbcfd5c545991ee59cf3f77acf300b1e',1,'helios::CompoundObject::getObjectDataType()'],['../classhelios_1_1_context.html#af77ff3ea4a7668d2b5cb03bc6fc5f5b6',1,'helios::Context::getObjectDataType()']]], - ['getobjectid_135',['getObjectID',['../classhelios_1_1_compound_object.html#a28c85b0cf4dee51dd7997b7b78e4f442',1,'helios::CompoundObject']]], - ['getobjectpointer_136',['getObjectPointer',['../classhelios_1_1_context.html#a3d9493949db2c5d8ddeef30afd2a9a0a',1,'helios::Context']]], - ['getobjectprimitivecount_137',['getObjectPrimitiveCount',['../classhelios_1_1_context.html#a457ccd0bcf9870aef138b22c4a160aeb',1,'helios::Context']]], - ['getobjectprimitiveuuids_138',['getObjectPrimitiveUUIDs',['../classhelios_1_1_context.html#a7d0b3a6ca36b02702b06208a735a3b03',1,'helios::Context::getObjectPrimitiveUUIDs(uint ObjID) const'],['../classhelios_1_1_context.html#a09e60fbbd3c4be1f8345a9de3695ccdd',1,'helios::Context::getObjectPrimitiveUUIDs(const std::vector< uint > &ObjIDs) const'],['../classhelios_1_1_context.html#a266fba7ca4a0a1536c49f1e3ce918b1e',1,'helios::Context::getObjectPrimitiveUUIDs(const std::vector< std::vector< uint > > &ObjIDs) const']]], - ['getobjecttexturefile_139',['getObjectTextureFile',['../classhelios_1_1_context.html#aacd4cff3b170281516dcafb3fa83b84a',1,'helios::Context']]], - ['getobjecttransformationmatrix_140',['getObjectTransformationMatrix',['../classhelios_1_1_context.html#af9e972c138b0626cece9eea5f018b418',1,'helios::Context']]], - ['getobjecttype_141',['getObjectType',['../classhelios_1_1_compound_object.html#ab07473392ca1e4c439c909c83cc9730b',1,'helios::CompoundObject::getObjectType()'],['../classhelios_1_1_context.html#a75ae3ee4580c4420059fe95755dc22d2',1,'helios::Context::getObjectType(uint ObjID) const']]], - ['getpatchcenter_142',['getPatchCenter',['../classhelios_1_1_context.html#a4165df43e5ab752e81bc2b7d7caf19d5',1,'helios::Context']]], - ['getpatchsize_143',['getPatchSize',['../classhelios_1_1_context.html#ab3f802aca8dd1930127d9f76358e71cf',1,'helios::Context']]], - ['getplantcount_144',['getPlantCount',['../class_canopy_generator.html#aba9e186286ade3cd2ced0be80b3b8b89',1,'CanopyGenerator']]], - ['getplantflowerobjectids_145',['getPlantFlowerObjectIDs',['../class_plant_architecture.html#a1cb3e4ba93c7a94558c3c07496e550c2',1,'PlantArchitecture']]], - ['getplantfruitobjectids_146',['getPlantFruitObjectIDs',['../class_plant_architecture.html#aac602c603ac136c3aaffad052bd844d4',1,'PlantArchitecture']]], - ['getplantinternodeobjectids_147',['getPlantInternodeObjectIDs',['../class_plant_architecture.html#a53967340a1c9b88f4b804522f081ce62',1,'PlantArchitecture']]], - ['getplantleafobjectids_148',['getPlantLeafObjectIDs',['../class_plant_architecture.html#afcdea7f14c6ca722d39d94ff19ba87b4',1,'PlantArchitecture']]], - ['getplantpeduncleobjectids_149',['getPlantPeduncleObjectIDs',['../class_plant_architecture.html#af8a9f26212baf6695d71d44b982e6adf',1,'PlantArchitecture']]], - ['getplantpetioleobjectids_150',['getPlantPetioleObjectIDs',['../class_plant_architecture.html#aee2486b87dca29982dd1b380aa3510fb',1,'PlantArchitecture']]], - ['getpolymeshobjectpointer_151',['getPolymeshObjectPointer',['../classhelios_1_1_context.html#a5a10781f6c1e24b226a32b1e1369f5c1',1,'helios::Context']]], - ['getpolymeshobjectvolume_152',['getPolymeshObjectVolume',['../classhelios_1_1_context.html#aad71b3e493ab0e47c6d4496d14e89803',1,'helios::Context']]], - ['getprimitivearea_153',['getPrimitiveArea',['../classhelios_1_1_context.html#a1dafe58b3251d2ef9d09112258b2e85d',1,'helios::Context']]], - ['getprimitiveboundingbox_154',['getPrimitiveBoundingBox',['../classhelios_1_1_context.html#abf2e26ac2b32556878be6626a8876569',1,'helios::Context::getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const'],['../classhelios_1_1_context.html#a808527f76dec2683cbc168250c4f69be',1,'helios::Context::getPrimitiveBoundingBox(const std::vector< uint > &UUID, vec3 &min_corner, vec3 &max_corner) const']]], - ['getprimitivecolor_155',['getPrimitiveColor',['../classhelios_1_1_context.html#a1223205f1080b0b7024b8f97950779b8',1,'helios::Context']]], - ['getprimitivecolorrgb_156',['getPrimitiveColorRGB',['../classhelios_1_1_context.html#a8550633570ee91e4f09ec1464810bd7b',1,'helios::Context']]], - ['getprimitivecolorrgba_157',['getPrimitiveColorRGBA',['../classhelios_1_1_context.html#a4e29adcb908d55172efd239f294b49e5',1,'helios::Context']]], - ['getprimitivecount_158',['getPrimitiveCount',['../classhelios_1_1_compound_object.html#a0eb06d37710a7dc9f5b915fc33f191a0',1,'helios::CompoundObject::getPrimitiveCount()'],['../group__primitives.html#ga4d3447fb04c25e685bcc82599e2b173d',1,'helios::Context::getPrimitiveCount() const']]], - ['getprimitivedata_159',['getPrimitiveData',['../classhelios_1_1_context.html#a2144eea981e4030c973287ce2c38315e',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int &data) const'],['../classhelios_1_1_context.html#ad1f6453da61e8e64ba91f589b7cc4eb0',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#a420487af4a23ed5b527069c6471efd93',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, uint &data) const'],['../classhelios_1_1_context.html#add62ecdb7cc13510670c9c45bc8725a3',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#aa54fb6e8a942845010ae669505adc2e8',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, float &data) const'],['../classhelios_1_1_context.html#a466dea76918a4bd02e4a355ab70f161b',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#a802b10b84762052e52b9ff1861604c58',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, double &data) const'],['../classhelios_1_1_context.html#a65d1918df796575a5e5bc8c470ff3201',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#a2ac5198c45a57b7926f4dbd9129fcad5',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec2 &data) const'],['../classhelios_1_1_context.html#ab0fb70ff8b6e81901df14efe07ae7ff4',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_context.html#abbe503b705cfdeb903becdb7fb082dae',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec3 &data) const'],['../classhelios_1_1_context.html#a83619185959d1dae4570674a3855f808',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_context.html#a0e62c9bb97e4cbbcd56518b060e9cae5',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec4 &data) const'],['../classhelios_1_1_context.html#a29fed63e84bf5b5111b0e98f499da56e',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_context.html#a72ee49f503ff0c4937d9aa81b72689ed',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int2 &data) const'],['../classhelios_1_1_context.html#ae76119a1083016c2cffed9eb443aaa62',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_context.html#a18f0ede968126842068551834391e3ad',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int3 &data) const'],['../classhelios_1_1_context.html#a5c37491d4bc0a1d69ffcaf214e6c2fe7',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_context.html#afe292fdf1d3c7983427c699e4a2eca3a',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int4 &data) const'],['../classhelios_1_1_context.html#a8ebaded3f143fc9c673765ab3fda5366',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_context.html#ad1a2ca668fb5f5043f23f7a50c22483f',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a1d8cd543d68c2bc3b7ef876421284f15',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< std::string > &data) const']]], - ['getprimitivedatasize_160',['getPrimitiveDataSize',['../classhelios_1_1_context.html#a4b64585d356463ac759472f099660eca',1,'helios::Context']]], - ['getprimitivedatatype_161',['getPrimitiveDataType',['../classhelios_1_1_context.html#a9c894ecd12e0d893c53ffcfa9e90c0b6',1,'helios::Context']]], - ['getprimitivenormal_162',['getPrimitiveNormal',['../classhelios_1_1_context.html#abfeadf8e6a35eb97da1439abc21c434e',1,'helios::Context']]], - ['getprimitiveparentobjectid_163',['getPrimitiveParentObjectID',['../classhelios_1_1_context.html#a2d3e254d04f913e590a645b54886436e',1,'helios::Context']]], - ['getprimitivesolidfraction_164',['getPrimitiveSolidFraction',['../classhelios_1_1_context.html#a6e8a5e2044331158d69d6f9bd88fc0f7',1,'helios::Context']]], - ['getprimitivetexturefile_165',['getPrimitiveTextureFile',['../classhelios_1_1_context.html#a4fffad72d1ebb517d9c41837e448d4f5',1,'helios::Context']]], - ['getprimitivetexturesize_166',['getPrimitiveTextureSize',['../classhelios_1_1_context.html#a7fec62cbf2c2d56603b2750cbb4a4d9f',1,'helios::Context']]], - ['getprimitivetexturetransparencydata_167',['getPrimitiveTextureTransparencyData',['../classhelios_1_1_context.html#a98ad773979fff9efda47b44d71ac8e06',1,'helios::Context']]], - ['getprimitivetextureuv_168',['getPrimitiveTextureUV',['../classhelios_1_1_context.html#a5702f94aaba15bf6757aeb4d72d7774d',1,'helios::Context']]], - ['getprimitivetransformationmatrix_169',['getPrimitiveTransformationMatrix',['../classhelios_1_1_context.html#a046e855d15fa88088be01adea38a67fd',1,'helios::Context']]], - ['getprimitivetype_170',['getPrimitiveType',['../classhelios_1_1_context.html#a67bfd66f0a445f6485f1099f9eadc949',1,'helios::Context']]], - ['getprimitiveuuids_171',['getPrimitiveUUIDs',['../classhelios_1_1_compound_object.html#ab3973a7c8ccb1aa0ce3f21ffe461ef7b',1,'helios::CompoundObject']]], - ['getprimitivevertices_172',['getPrimitiveVertices',['../classhelios_1_1_context.html#ae8542fd1452150d3302675a0a3d991ed',1,'helios::Context']]], - ['getradius_173',['getRadius',['../classhelios_1_1_sphere.html#a38cf8b6959d22577a1a2f9a6c675bc8b',1,'helios::Sphere']]], - ['getrandomgenerator_174',['getRandomGenerator',['../classhelios_1_1_context.html#a96a928fa28d3d771ba310f798b56bd63',1,'helios::Context']]], - ['getscanbeamdivergence_175',['getScanBeamDivergence',['../class_aerial_li_d_a_rcloud.html#a4097c1d3994f57e0f0e2e602c7ca5c04',1,'AerialLiDARcloud::getScanBeamDivergence()'],['../class_li_d_a_rcloud.html#a9d93e6cd9decccf271fbf3fbd5c74a5a',1,'LiDARcloud::getScanBeamDivergence()']]], - ['getscanbeamexitdiameter_176',['getScanBeamExitDiameter',['../class_aerial_li_d_a_rcloud.html#ae6cbd6375be39129231233d66061afca',1,'AerialLiDARcloud::getScanBeamExitDiameter()'],['../class_li_d_a_rcloud.html#abab6b81a3d96226a766cc2450993407f',1,'LiDARcloud::getScanBeamExitDiameter()']]], - ['getscancenter_177',['getScanCenter',['../class_aerial_li_d_a_rcloud.html#a1ce1efbe6af71f54dcccd3743918aa72',1,'AerialLiDARcloud']]], - ['getscancolumnformat_178',['getScanColumnFormat',['../class_li_d_a_rcloud.html#abbe892f01508dc69bcc5b28bea5472bf',1,'LiDARcloud']]], - ['getscanconeangle_179',['getScanConeAngle',['../class_aerial_li_d_a_rcloud.html#a0dbf5535304d6d87d67a0d41c5d2310f',1,'AerialLiDARcloud']]], - ['getscancount_180',['getScanCount',['../class_aerial_li_d_a_rcloud.html#ab363717911dada3af4fdafa914532a6a',1,'AerialLiDARcloud::getScanCount()'],['../class_li_d_a_rcloud.html#aaa463ea1aaebb03abd8c3ec87091291a',1,'LiDARcloud::getScanCount()']]], - ['getscandensity_181',['getScanDensity',['../class_aerial_li_d_a_rcloud.html#a0c4627b15014ebe8c79053ed75f6cfb4',1,'AerialLiDARcloud']]], - ['getscanextent_182',['getScanExtent',['../class_aerial_li_d_a_rcloud.html#ad5bd68f06fef597d8c1f1aac3142acc6',1,'AerialLiDARcloud']]], - ['getscanorigin_183',['getScanOrigin',['../class_li_d_a_rcloud.html#aa657ed32a8831ebf4f2e4a9203b683ef',1,'LiDARcloud']]], - ['getscanrangephi_184',['getScanRangePhi',['../class_li_d_a_rcloud.html#ab314aac88834eb3938fc2f37e34807e3',1,'LiDARcloud']]], - ['getscanrangetheta_185',['getScanRangeTheta',['../class_li_d_a_rcloud.html#a7f0237a83da6997e973fde9939440979',1,'LiDARcloud']]], - ['getscansizephi_186',['getScanSizePhi',['../class_li_d_a_rcloud.html#aaf04cd04c2b1bc162106a0e47cff6d29',1,'LiDARcloud']]], - ['getscansizetheta_187',['getScanSizeTheta',['../class_li_d_a_rcloud.html#a40809c7a709a6c9ccb4beddca21f8ac9',1,'LiDARcloud']]], - ['getsegmentvolume_188',['getSegmentVolume',['../classhelios_1_1_tube.html#a2966ff764897904282082f23a76756b8',1,'helios::Tube']]], - ['getsize_189',['getSize',['../classhelios_1_1_tile.html#aa8daadd99bd57f647837e26890fcfeac',1,'helios::Tile::getSize()'],['../classhelios_1_1_box.html#afd79ee17402ab6367896fe8278800f34',1,'helios::Box::getSize()'],['../classhelios_1_1_disk.html#a23c03df1f2e351659a08420a41a74eb5',1,'helios::Disk::getSize()']]], - ['getskyenergy_190',['getSkyEnergy',['../class_radiation_model.html#a9c9a5f6cb6b0ba6e3780aba8a4da8a0d',1,'RadiationModel']]], - ['getsolarflux_191',['getSolarFlux',['../class_solar_position.html#a9701cb29a0336a11c445d285405b6956',1,'SolarPosition']]], - ['getsolarfluxnir_192',['getSolarFluxNIR',['../class_solar_position.html#a611461f700df9efa7c56b6f4ee7712b7',1,'SolarPosition']]], - ['getsolarfluxpar_193',['getSolarFluxPAR',['../class_solar_position.html#a5c6635160944b5b8202ea9965da6de9d',1,'SolarPosition']]], - ['getsolidfraction_194',['getSolidFraction',['../classhelios_1_1_texture.html#a685024e8394b49433f26a0dcd6665d86',1,'helios::Texture']]], - ['getsourceflux_195',['getSourceFlux',['../class_radiation_model.html#a9d4ea3e08514b90e617695ab2ee2fbf8',1,'RadiationModel']]], - ['getsourceposition_196',['getSourcePosition',['../class_radiation_model.html#ab8ec35514a0e4b53ce8a64d3f390427c',1,'RadiationModel']]], - ['getsphereobjectcenter_197',['getSphereObjectCenter',['../classhelios_1_1_context.html#a4f75af0785498d14eb3f5a3539cb16b1',1,'helios::Context']]], - ['getsphereobjectpointer_198',['getSphereObjectPointer',['../classhelios_1_1_context.html#a8ed7580efa323c0f5e53e97d00e16c85',1,'helios::Context']]], - ['getsphereobjectradius_199',['getSphereObjectRadius',['../classhelios_1_1_context.html#a5afb4fd92e9a726fb396779d1f2ae92b',1,'helios::Context']]], - ['getsphereobjectsubdivisioncount_200',['getSphereObjectSubdivisionCount',['../classhelios_1_1_context.html#adadbc5a5378a874cd6705ed681fb9e6a',1,'helios::Context']]], - ['getsphereobjectvolume_201',['getSphereObjectVolume',['../classhelios_1_1_context.html#ae92df5975ec7fa257e7633d6551e2a87',1,'helios::Context']]], - ['getsubdivisioncount_202',['getSubdivisionCount',['../classhelios_1_1_tile.html#a4f4198becfe3cafd989b5aa6cd21d5cf',1,'helios::Tile::getSubdivisionCount()'],['../classhelios_1_1_sphere.html#a152107e463d6765ba27ff8f3ab737711',1,'helios::Sphere::getSubdivisionCount()'],['../classhelios_1_1_tube.html#abf9bb1153b3607a5d616aafeee06e43e',1,'helios::Tube::getSubdivisionCount()'],['../classhelios_1_1_box.html#a6f25b211d8740257329f841cda737a4f',1,'helios::Box::getSubdivisionCount()'],['../classhelios_1_1_disk.html#a8dc2a195735ee3321b274274e7e0352e',1,'helios::Disk::getSubdivisionCount()'],['../classhelios_1_1_cone.html#a051a2c5760d53a6c0b95f66cab9cbf73',1,'helios::Cone::getSubdivisionCount()']]], - ['getsunazimuth_203',['getSunAzimuth',['../class_solar_position.html#a2b736578f75ecb8532556931b8263dc4',1,'SolarPosition']]], - ['getsundirectionspherical_204',['getSunDirectionSpherical',['../class_solar_position.html#adad5310db742ef9f2754e75095aeea92',1,'SolarPosition']]], - ['getsundirectionvector_205',['getSunDirectionVector',['../class_solar_position.html#af889756d5b3d7d3c366887fae1fb86ab',1,'SolarPosition']]], - ['getsunelevation_206',['getSunElevation',['../class_solar_position.html#a307e963d840abb9ee7867579fec69fa2',1,'SolarPosition']]], - ['getsunrisetime_207',['getSunriseTime',['../class_solar_position.html#a2d15fe2ca0d29adf33971916b1d8cd83',1,'SolarPosition']]], - ['getsunsettime_208',['getSunsetTime',['../class_solar_position.html#a4c58aa642b4fc2300d1c1447388bc0d8',1,'SolarPosition']]], - ['getsunzenith_209',['getSunZenith',['../class_solar_position.html#a4c4ba4931d13c6cc2ad69e8eab90ac14',1,'SolarPosition']]], - ['gettexturefile_210',['getTextureFile',['../classhelios_1_1_texture.html#a0371473a81deb9bb19b8274109b75ef8',1,'helios::Texture::getTextureFile()'],['../classhelios_1_1_compound_object.html#a3e43ebd386e7a6663fa877613b9d27fa',1,'helios::CompoundObject::getTextureFile()']]], - ['gettextureuv_211',['getTextureUV',['../classhelios_1_1_tile.html#a94deb25ac31abc1eb02dfe6913b4546f',1,'helios::Tile']]], - ['gettileobjectarearatio_212',['getTileObjectAreaRatio',['../classhelios_1_1_context.html#a9943834b21ccfb9ac1c519e47f959c92',1,'helios::Context::getTileObjectAreaRatio(uint ObjectID) const'],['../classhelios_1_1_context.html#afdebad3fd25bb8b9fa228020c3b11329',1,'helios::Context::getTileObjectAreaRatio(const std::vector< uint > &ObjectID) const']]], - ['gettileobjectcenter_213',['getTileObjectCenter',['../classhelios_1_1_context.html#aa60f87c9bc771e613f60db73188a149d',1,'helios::Context']]], - ['gettileobjectnormal_214',['getTileObjectNormal',['../classhelios_1_1_context.html#a64f4bcadff461357aa390d7f5dad2ba7',1,'helios::Context']]], - ['gettileobjectpointer_215',['getTileObjectPointer',['../classhelios_1_1_context.html#ad2b762dd7b31126150c6e6dc350a3914',1,'helios::Context']]], - ['gettileobjectsize_216',['getTileObjectSize',['../classhelios_1_1_context.html#a457654b4a1f96a4979f83299dd9752df',1,'helios::Context']]], - ['gettileobjectsubdivisioncount_217',['getTileObjectSubdivisionCount',['../classhelios_1_1_context.html#a9320e4577eb131e7efe05677d30591b3',1,'helios::Context']]], - ['gettileobjecttextureuv_218',['getTileObjectTextureUV',['../classhelios_1_1_context.html#a00718598a9c308dabe8fc24f85683210',1,'helios::Context']]], - ['gettileobjectvertices_219',['getTileObjectVertices',['../classhelios_1_1_context.html#ab77b708ac6b39c1c5e8ecaa4988403b0',1,'helios::Context']]], - ['gettime_220',['getTime',['../classhelios_1_1_context.html#a847ecbb2297e60220a23b67c39b0f6e2',1,'helios::Context']]], - ['gettimeserieslength_221',['getTimeseriesLength',['../group__timeseries.html#ga56d13f8c949e68137581a3c974790892',1,'helios::Context']]], - ['getting_20object_20ids_20and_20primitive_20uuids_20of_20model_20geometry_222',['Getting Object IDs and Primitive UUIDs of Model Geometry',['../_plant_architecture_doc.html#PlantArchQueryobjIDs',1,'']]], - ['getting_20primitive_20data_20values_223',['Getting Primitive Data Values',['../_a_p_i.html#GetPrimData',1,'']]], - ['getting_20primitive_20uuids_20for_20organ_20sub_20components_224',['Getting Primitive UUIDs for Organ Sub-Components',['../_plant_architecture_doc.html#PlantArchQueryUUIDs',1,'']]], - ['getting_20started_20with_20the_20existing_20plant_20library_225',['Getting Started with the Existing Plant Library',['../_plant_architecture_doc.html#PlantArchGettingStarted',1,'']]], - ['getting_20the_20direction_20of_20the_20sun_226',['Getting the Direction of the Sun',['../_solar_position_doc.html#SolarPos',1,'']]], - ['getting_20the_20sky_20longwave_20flux_227',['Getting the Sky Longwave Flux',['../_solar_position_doc.html#LWFlux',1,'']]], - ['getting_20the_20solar_20flux_228',['Getting the Solar Flux',['../_solar_position_doc.html#SolarFlux',1,'']]], - ['gettotalabsorbedflux_229',['getTotalAbsorbedFlux',['../class_radiation_model.html#a5e95e775550a2000798a97b00857bdd2',1,'RadiationModel']]], - ['gettransformationmatrix_230',['getTransformationMatrix',['../classhelios_1_1_compound_object.html#ac1e98d4f8098dadda345f9dc6dae73ca',1,'helios::CompoundObject']]], - ['gettransparencydata_231',['getTransparencyData',['../classhelios_1_1_texture.html#a798c3a24b21fc853db299d1f1f84a61c',1,'helios::Texture']]], - ['gettreeparameters_232',['getTreeParameters',['../class_weber_penn_tree.html#aac5619ac480517f8f01cb465d0dc4a6f',1,'WeberPennTree']]], - ['gettriangle_233',['getTriangle',['../class_li_d_a_rcloud.html#aa1a1af5eea22185e59c267c8e4d94c9e',1,'LiDARcloud']]], - ['gettrianglecount_234',['getTriangleCount',['../class_li_d_a_rcloud.html#abcdbf834959379a189a60efed41f3e52',1,'LiDARcloud']]], - ['gettrianglevertex_235',['getTriangleVertex',['../classhelios_1_1_context.html#a846f93175f8b45f44237e88155af8fde',1,'helios::Context']]], - ['gettrianglevertices_236',['getTriangleVertices',['../classhelios_1_1_tube.html#a6aedd14e533981bd79497ba13b33f2c9',1,'helios::Tube']]], - ['gettrunkuuids_237',['getTrunkUUIDs',['../class_canopy_generator.html#aa8e95a610c03588592acebbbba5d638e',1,'CanopyGenerator::getTrunkUUIDs(uint PlantID)'],['../class_canopy_generator.html#a44b2d0846bb08d331281a822df41daa6',1,'CanopyGenerator::getTrunkUUIDs()'],['../class_weber_penn_tree.html#ab247d9368368263dfdded18a43917f98',1,'WeberPennTree::getTrunkUUIDs()']]], - ['gettubeobjectnodecolors_238',['getTubeObjectNodeColors',['../classhelios_1_1_context.html#a7ad271dabb4291067f9a39d4c92e6ffd',1,'helios::Context']]], - ['gettubeobjectnoderadii_239',['getTubeObjectNodeRadii',['../classhelios_1_1_context.html#a6a58d8f1a8446a213d9a21e67ae8ed97',1,'helios::Context']]], - ['gettubeobjectnodes_240',['getTubeObjectNodes',['../classhelios_1_1_context.html#aa4650e7a0a16be12615870ff9a567ae3',1,'helios::Context']]], - ['gettubeobjectpointer_241',['getTubeObjectPointer',['../classhelios_1_1_context.html#ab26f963c75aa99d797a43860479910b0',1,'helios::Context']]], - ['gettubeobjectsegmentvolume_242',['getTubeObjectSegmentVolume',['../classhelios_1_1_context.html#a10928031db222e77e93ac8088f4b001d',1,'helios::Context']]], - ['gettubeobjectsubdivisioncount_243',['getTubeObjectSubdivisionCount',['../classhelios_1_1_context.html#a272ba030971b86c7d3da57ff90784e0f',1,'helios::Context']]], - ['gettubeobjectvolume_244',['getTubeObjectVolume',['../classhelios_1_1_context.html#a56b82c3f009084451225003b2b461b6f',1,'helios::Context']]], - ['getuniqueprimitiveparentobjectids_245',['getUniquePrimitiveParentObjectIDs',['../classhelios_1_1_context.html#a18a276db8d3c1d754bbd1ca475deec82',1,'helios::Context::getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs) const'],['../classhelios_1_1_context.html#a1f50af8c859a5b2ee0973c9ed5c10284',1,'helios::Context::getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs, bool include_ObjID_zero) const']]], - ['getvariation_246',['getVariation',['../_canopy_generator_8h.html#accfb46da54c7b0e83878a1331bbc94d1',1,'getVariation(float V, std::minstd_rand0 &generator, bool positive=false): CanopyGenerator.cpp'],['../_canopy_generator_8h.html#aa3a6e1a26b799f4a2006703314499fed',1,'getVariation(int V, std::minstd_rand0 &generator, bool positive=false): CanopyGenerator.cpp'],['../_canopy_generator_8h.html#a6cdee9cb4984f78c818e46eb2a5b62e6',1,'getVariation(uint V, std::minstd_rand0 &generator): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#aa0b21a2d6b9506b33d05047716d671e0',1,'getVariation(float V, std::minstd_rand0 &generator, bool positive): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#a9f90ba8fe8a074a822424ff748579f25',1,'getVariation(int V, std::minstd_rand0 &generator, bool positive): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#a6cdee9cb4984f78c818e46eb2a5b62e6',1,'getVariation(uint V, std::minstd_rand0 &generator): CanopyGenerator.cpp']]], - ['getvertices_247',['getVertices',['../classhelios_1_1_tile.html#aaea21403039646db33792c95be929afd',1,'helios::Tile']]], - ['getvolume_248',['getVolume',['../classhelios_1_1_sphere.html#a3d6a8e9f8c0daee1e093593d6006c906',1,'helios::Sphere::getVolume()'],['../classhelios_1_1_tube.html#aaa11cc27d6f704a989c3e5b0fe1b8055',1,'helios::Tube::getVolume()'],['../classhelios_1_1_box.html#a3d3d0b20e22aff306fde02bd7e2a4f84',1,'helios::Box::getVolume()'],['../classhelios_1_1_polymesh.html#ad901c4de0e202f44c16fc9af29481538',1,'helios::Polymesh::getVolume()'],['../classhelios_1_1_cone.html#aff2cb2fc89c68b75a038a9604ce73cd0',1,'helios::Cone::getVolume()']]], - ['getvoxelcenter_249',['getVoxelCenter',['../classhelios_1_1_context.html#acadf5206cbfed7b8eaa2835702349cd9',1,'helios::Context']]], - ['getvoxelsize_250',['getVoxelSize',['../classhelios_1_1_context.html#a6a3f85d4f29f8f7432b6ef605172a1cb',1,'helios::Context']]], - ['getwindowpixelsrgb_251',['getWindowPixelsRGB',['../class_visualizer.html#a15828ea9966b9729b56c9ddfccd4c117',1,'Visualizer']]], - ['getwindowsize_252',['getWindowSize',['../class_visualizer.html#ae6b83402c798f56334851f77b898de52',1,'Visualizer']]], - ['gimp_253',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['girth_5farea_5ffactor_254',['girth_area_factor',['../_plant_architecture_doc.html#ShootParam_girth_area_factor',1,'']]], - ['git_20github_20integration_255',['Git/GitHub integration',['../_c_lion_i_d_e.html#CLionGit',1,'']]], - ['github_20integration_256',['Git/GitHub integration',['../_c_lion_i_d_e.html#CLionGit',1,'']]], - ['given_20in_20buckley_20turnbull_20and_20adams_202012_257',['Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)',['../_stomatal_doc.html#BMFTheory',1,'']]], - ['global_20data_258',['Global Data',['../_a_p_i.html#GlobalData',1,'Global Data'],['../context_globaldata.html#context_globaldata_intro',1,'Introduction to Global Data'],['../context_globaldata.html',1,'Tutorial 6: Global Data']]], - ['global_20data_20arrays_259',['Creating Global Data (Arrays)',['../context_globaldata.html#context_globaldata_arrays',1,'']]], - ['global_20data_20scalars_260',['Creating Global Data (Scalars)',['../context_globaldata.html#context_globaldata_scalar',1,'']]], - ['global_2ecpp_261',['global.cpp',['../global_8cpp.html',1,'']]], - ['global_2eh_262',['global.h',['../global_8h.html',1,'']]], - ['globaldata_263',['GlobalData',['../structhelios_1_1_global_data.html',1,'helios']]], - ['glyph_264',['Glyph',['../class_glyph.html',1,'']]], - ['goblet_20trellis_265',['Grapevine Canopy with a Goblet Trellis',['../_canopy_generator_doc.html#CGenGoblet',1,'']]], - ['gobletgrapevineparameters_266',['GobletGrapevineParameters',['../struct_goblet_grapevine_parameters.html',1,'GobletGrapevineParameters'],['../struct_goblet_grapevine_parameters.html#a0274d6f6b1f13bbf7a383de5c2bc8726',1,'GobletGrapevineParameters::GobletGrapevineParameters()'],['../struct_goblet_grapevine_parameters.html#a498ce7f62d575b0bc914e9d48d94fbb2',1,'GobletGrapevineParameters::GobletGrapevineParameters(const pugi::xml_node canopy_node)']]], - ['gradientdescent_267',['GradientDescent',['../struct_camera_calibration.html#a5bfbb206b8271b406cda85eb5ae23a1b',1,'CameraCalibration']]], - ['gradientdescentparameters_268',['GradientDescentParameters',['../struct_camera_calibration_1_1_gradient_descent_parameters.html',1,'CameraCalibration']]], - ['grape_5fcolor_269',['grape_color',['../struct_base_grape_vine_parameters.html#ac90904eec34fa3e0dea393dd1c12faf6',1,'BaseGrapeVineParameters']]], - ['grape_5fradius_270',['grape_radius',['../struct_base_grape_vine_parameters.html#afa20674518acbb9fdfaafc893f362e01',1,'BaseGrapeVineParameters']]], - ['grape_5fradius_5fspread_271',['grape_radius_spread',['../struct_base_grape_vine_parameters.html#ace081969ad453ba66d60e394554d50b9',1,'BaseGrapeVineParameters']]], - ['grape_5fsubdivisions_272',['grape_subdivisions',['../struct_base_grape_vine_parameters.html#a510a2a5876fe8b3fb8ec70701c32df48',1,'BaseGrapeVineParameters']]], - ['grape_5fsubdivisions_5fspread_273',['grape_subdivisions_spread',['../struct_base_grape_vine_parameters.html#aa27b9934f658e9047462703e7d059d74',1,'BaseGrapeVineParameters']]], - ['grapevine_20canopy_20with_20a_20goblet_20trellis_274',['Grapevine Canopy with a Goblet Trellis',['../_canopy_generator_doc.html#CGenGoblet',1,'']]], - ['grapevine_20canopy_20with_20a_20split_20trellis_275',['Grapevine Canopy with a Split Trellis',['../_canopy_generator_doc.html#CGenSplit',1,'']]], - ['grapevine_20canopy_20with_20a_20unilateral_20vsp_20trellis_276',['Grapevine Canopy with a Unilateral VSP Trellis',['../_canopy_generator_doc.html#CGenUnilateral',1,'']]], - ['grapevine_20canopy_20with_20vsp_20trellis_277',['Grapevine Canopy with VSP Trellis',['../_canopy_generator_doc.html#CGenVSP',1,'']]], - ['grapevine_2ecpp_278',['grapevine.cpp',['../grapevine_8cpp.html',1,'']]], - ['grapevinegoblet_279',['grapevineGoblet',['../class_canopy_generator.html#a8f2d498637c464ee852109e6085cde8a',1,'CanopyGenerator']]], - ['grapevinesplit_280',['grapevineSplit',['../class_canopy_generator.html#a8747bad1af97214059c38043241f0b47',1,'CanopyGenerator']]], - ['grapevineunilateral_281',['grapevineUnilateral',['../class_canopy_generator.html#aac9104d7c6565e860737310de06981f8',1,'CanopyGenerator']]], - ['grapevinevsp_282',['grapevineVSP',['../class_canopy_generator.html#aaffe5cdb82a779785bc6d5e35e622812',1,'CanopyGenerator']]], - ['graphics_20driver_20timeout_283',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], - ['gravitropic_5fcurvature_284',['gravitropic_curvature',['../_plant_architecture_doc.html#ShootParam_gravitropic',1,'']]], - ['grid_20cell_285',['Calculating leaf area for each grid cell',['../_li_d_a_r_doc.html#LiDARleafarea',1,'']]], - ['grid_20cells_286',['grid cells',['../_aerial_li_d_a_r_doc.html#AerialLiDARgrid',1,'Establishing grid cells'],['../_li_d_a_r_doc.html#LiDARgrid',1,'Establishing grid cells']]], - ['gridcell_287',['GridCell',['../struct_grid_cell.html',1,'']]], - ['gridijk2index_288',['gridijk2index',['../class_aerial_li_d_a_rcloud.html#a35c81e8cda423b84c94fc33ee4163d47',1,'AerialLiDARcloud']]], - ['gridindex2ijk_289',['gridindex2ijk',['../class_aerial_li_d_a_rcloud.html#add78af9b69161c5c532a23c8df009d2e',1,'AerialLiDARcloud']]], - ['ground_290',['Building the Ground',['../_canopy_generator_doc.html#CGenBuildGround',1,'']]], - ['ground_291',['4. Flow over bare ground',['../_b_l_conductance_doc.html#BLC4',1,'']]], - ['ground_20area_20basis_292',['4b. Calculate radiation flux absorbed by the canopy on a ground area basis',['../radiation__beers_law.html#tutorial11_abs',1,'']]], - ['ground_20collision_20detection_293',['Ground Collision Detection',['../_plant_architecture_doc.html#PlantArchCollision',1,'']]], - ['ground_20cover_20fraction_294',['2D raster ground cover fraction',['../_aerial_li_d_a_r_doc.html#AerialGroundCover',1,'']]], - ['growing_20the_20model_20over_20time_295',['Growing the Model over Time',['../_plant_architecture_doc.html#PlantArchGrowth',1,'']]], - ['growth_20parameters_20of_20the_20shoot_296',['Growth Parameters of the Shoot',['../_plant_architecture_doc.html#ShootParametersGrowth',1,'']]], - ['growth_20phenology_297',['Growth Phenology',['../_plant_architecture_doc.html#PlantArchPheno',1,'']]], - ['guide_298',['User/API Guide',['../_a_p_i.html',1,'']]] + ['getallplantids_29',['getAllPlantIDs',['../class_plant_architecture.html#a73c43e42cc78a343279633842ea0aa07',1,'PlantArchitecture']]], + ['getallplantobjectids_30',['getAllPlantObjectIDs',['../class_plant_architecture.html#acf9855048c790d30d8d4de7fa1dc3550',1,'PlantArchitecture']]], + ['getallplantuuids_31',['getAllPlantUUIDs',['../class_plant_architecture.html#a3bdffb4e53fe0da836a40de80946d31f',1,'PlantArchitecture']]], + ['getalluuids_32',['getAllUUIDs',['../classhelios_1_1_context.html#a98516632daccf958cca6b5b6582310bb',1,'helios::Context::getAllUUIDs()'],['../class_canopy_generator.html#a8e395619077d656e206f4159f0bf8d34',1,'CanopyGenerator::getAllUUIDs()'],['../class_plant_architecture.html#afec06c56ae296984727c90413511cf6a',1,'PlantArchitecture::getAllUUIDs()'],['../class_weber_penn_tree.html#a19e16f9a51493680afebc38f3c434400',1,'WeberPennTree::getAllUUIDs()']]], + ['getambientlongwaveflux_33',['getAmbientLongwaveFlux',['../class_solar_position.html#a30ee555eedece8b7e19855877a74da71',1,'SolarPosition']]], + ['getarea_34',['getArea',['../classhelios_1_1_compound_object.html#a8bb518f6166e2a2831a68a7626787ac1',1,'helios::CompoundObject']]], + ['getaxisunitvector_35',['getAxisUnitVector',['../classhelios_1_1_cone.html#a60fc92fbb15149017956449123c0e4d0',1,'helios::Cone']]], + ['getbmfcoefficientsfromlibrary_36',['getBMFCoefficientsFromLibrary',['../class_stomatal_conductance_model.html#ada09940a1cc67dbfc0192f6e0a50c967',1,'StomatalConductanceModel']]], + ['getboxobjectcenter_37',['getBoxObjectCenter',['../classhelios_1_1_context.html#af73c44dace71ec805136b7d6ad6095a9',1,'helios::Context']]], + ['getboxobjectpointer_38',['getBoxObjectPointer',['../classhelios_1_1_context.html#a1ecbb5a8cfa6764bade6e0650d2f6990',1,'helios::Context']]], + ['getboxobjectsize_39',['getBoxObjectSize',['../classhelios_1_1_context.html#a4e5799ba4b6a0a889f446bef9e4d3dc0',1,'helios::Context']]], + ['getboxobjectsubdivisioncount_40',['getBoxObjectSubdivisionCount',['../classhelios_1_1_context.html#a258f524d38cdeb5f6c83a7f387608490',1,'helios::Context']]], + ['getboxobjectvolume_41',['getBoxObjectVolume',['../classhelios_1_1_context.html#ae31cc8855aacb6380a288a4b7fa8db82',1,'helios::Context']]], + ['getbranchuuids_42',['getBranchUUIDs',['../class_canopy_generator.html#ab7115aaa287346b9c8e7854bd66f8b5f',1,'CanopyGenerator::getBranchUUIDs(uint PlantID)'],['../class_canopy_generator.html#a7db6f05ab623b77de4e8a81dc132e914',1,'CanopyGenerator::getBranchUUIDs()'],['../class_weber_penn_tree.html#a813cb8959272b535050dc97aa49d3ed3',1,'WeberPennTree::getBranchUUIDs()']]], + ['getcameralookat_43',['getCameraLookat',['../class_radiation_model.html#a68c8736e58c7daf440ff9c93bb00522d',1,'RadiationModel']]], + ['getcameraorientation_44',['getCameraOrientation',['../class_radiation_model.html#a0b67b056aa1f2b5e6c42a06e358f4eb8',1,'RadiationModel']]], + ['getcameraposition_45',['getCameraPosition',['../class_radiation_model.html#a6785deae272a9464920030fc3f124bc3',1,'RadiationModel']]], + ['getcameraresponsescale_46',['getCameraResponseScale',['../struct_camera_calibration.html#a18eff4a7ecab1038f27b68c3963a5513',1,'CameraCalibration::getCameraResponseScale()'],['../class_radiation_model.html#adb5a74547d51a18018d3daeba0ec5f3c',1,'RadiationModel::getCameraResponseScale()']]], + ['getcellcenter_47',['getCellCenter',['../class_aerial_li_d_a_rcloud.html#a6e83c157d63d12253af3b81b995e1a33',1,'AerialLiDARcloud::getCellCenter()'],['../class_li_d_a_rcloud.html#a6e2ce01abb33cc0f80b2aa653ac6a445',1,'LiDARcloud::getCellCenter()']]], + ['getcellcoverfraction_48',['getCellCoverFraction',['../class_aerial_li_d_a_rcloud.html#ac714e2231b63d1455237662661590b16',1,'AerialLiDARcloud']]], + ['getcellglobalanchor_49',['getCellGlobalAnchor',['../class_li_d_a_rcloud.html#ad1ad4f851b5b7fcbf5b088b161aed83e',1,'LiDARcloud']]], + ['getcellgroundheight_50',['getCellGroundHeight',['../class_aerial_li_d_a_rcloud.html#a3b9d9ac013a041c30d58e68e5dc92bee',1,'AerialLiDARcloud']]], + ['getcellgtheta_51',['getCellGtheta',['../class_li_d_a_rcloud.html#a54351e18e3f4155e9d55eb02bd63c722',1,'LiDARcloud']]], + ['getcellleafarea_52',['getCellLeafArea',['../class_aerial_li_d_a_rcloud.html#a9f90891b20b8996e983e66640684b6cc',1,'AerialLiDARcloud::getCellLeafArea()'],['../class_li_d_a_rcloud.html#ac9d20a35bdb7ee2d45490ac1cd520117',1,'LiDARcloud::getCellLeafArea()']]], + ['getcellleafareadensity_53',['getCellLeafAreaDensity',['../class_aerial_li_d_a_rcloud.html#a4ca0903b642daffdff27e69a172c96b5',1,'AerialLiDARcloud::getCellLeafAreaDensity()'],['../class_li_d_a_rcloud.html#a3c1744984481f9629dc1371291fa397e',1,'LiDARcloud::getCellLeafAreaDensity()']]], + ['getcellmaximumhitheight_54',['getCellMaximumHitHeight',['../class_aerial_li_d_a_rcloud.html#a00f6479153ac2025031b70bd5637b65b',1,'AerialLiDARcloud']]], + ['getcellprimitives_55',['getCellPrimitives',['../class_voxel_intersection.html#a7d50123db71cf5cd7c7cc4582abd5cb2',1,'VoxelIntersection']]], + ['getcellrbar_56',['getCellRbar',['../class_aerial_li_d_a_rcloud.html#ae35261c7fc1553cb15fb318a2b14a3b2',1,'AerialLiDARcloud']]], + ['getcellrotation_57',['getCellRotation',['../class_li_d_a_rcloud.html#aa2cba1d0bcd9a2ae35d9a5be03832efc',1,'LiDARcloud']]], + ['getcellsize_58',['getCellSize',['../class_aerial_li_d_a_rcloud.html#a5bf5379ee229ebb51fdc8195af8cf3e7',1,'AerialLiDARcloud::getCellSize()'],['../class_li_d_a_rcloud.html#a6662330b95ee7ee77ea6647871695c55',1,'LiDARcloud::getCellSize()']]], + ['getcelltransmissionprobability_59',['getCellTransmissionProbability',['../class_aerial_li_d_a_rcloud.html#a98770b70c510e7611fb171d3fe920554',1,'AerialLiDARcloud']]], + ['getcellvegetationheight_60',['getCellVegetationHeight',['../class_aerial_li_d_a_rcloud.html#a12fe426a267cbef9982138537198558a',1,'AerialLiDARcloud']]], + ['getcenter_61',['getCenter',['../classhelios_1_1_tile.html#a18178d0280f8ecc1149663558947ca06',1,'helios::Tile::getCenter()'],['../classhelios_1_1_sphere.html#a48eada17c3dab899a91158f1424518d6',1,'helios::Sphere::getCenter()'],['../classhelios_1_1_box.html#a96e72a40ff113d6a6b463fe8c60b672a',1,'helios::Box::getCenter()'],['../classhelios_1_1_disk.html#ae8ed884a95cbfa2440e3bd9f8e3e4057',1,'helios::Disk::getCenter()']]], + ['getconeobjectaxisunitvector_62',['getConeObjectAxisUnitVector',['../classhelios_1_1_context.html#acaa3fb162b17cb7f912162f5d4be894e',1,'helios::Context']]], + ['getconeobjectlength_63',['getConeObjectLength',['../classhelios_1_1_context.html#ad2b045f361aa8e8596bcf325c1707a25',1,'helios::Context']]], + ['getconeobjectnode_64',['getConeObjectNode',['../classhelios_1_1_context.html#a54e9f0b7c5014a37cd9d5bf74e7d5935',1,'helios::Context']]], + ['getconeobjectnoderadii_65',['getConeObjectNodeRadii',['../classhelios_1_1_context.html#ade2608274b311c809d46bb13943b9e4e',1,'helios::Context']]], + ['getconeobjectnoderadius_66',['getConeObjectNodeRadius',['../classhelios_1_1_context.html#af5acc5647e6bf9cd1649da1dec677110',1,'helios::Context']]], + ['getconeobjectnodes_67',['getConeObjectNodes',['../classhelios_1_1_context.html#a8c4ec2d90ccd3d44a97597ecd80d78b6',1,'helios::Context']]], + ['getconeobjectpointer_68',['getConeObjectPointer',['../classhelios_1_1_context.html#a3221051ea9c1025e8fb00d9dec01839f',1,'helios::Context']]], + ['getconeobjectsubdivisioncount_69',['getConeObjectSubdivisionCount',['../classhelios_1_1_context.html#a1ff97eb95d5896e096156320f5bd5ff0',1,'helios::Context']]], + ['getconeobjectvolume_70',['getConeObjectVolume',['../classhelios_1_1_context.html#af6c1c571171be2604822a8df44d2349c',1,'helios::Context']]], + ['getcurrentcolormap_71',['getCurrentColormap',['../class_visualizer.html#ae2bba6102a283a31ec4f5780817a15da',1,'Visualizer']]], + ['getcurrentphytomerparameters_72',['getCurrentPhytomerParameters',['../class_plant_architecture.html#aaba5ecb6c069be56b3706a4060f5ff49',1,'PlantArchitecture']]], + ['getcurrentshootparameters_73',['getCurrentShootParameters',['../class_plant_architecture.html#aa696281e805e8879a78dacdf4354ff38',1,'PlantArchitecture::getCurrentShootParameters(const std::string &shoot_type_label)'],['../class_plant_architecture.html#a190d91f02c5cfcfad036879460b2e495',1,'PlantArchitecture::getCurrentShootParameters()']]], + ['getdate_74',['getDate',['../classhelios_1_1_context.html#a95dd5bc221cd8bcb4efabd0122d59b4f',1,'helios::Context']]], + ['getdepthmap_75',['getDepthMap',['../class_visualizer.html#a7c6362d7dc0f0bd4bba53195ce92b84e',1,'Visualizer']]], + ['getdiffuseflux_76',['getDiffuseFlux',['../class_radiation_model.html#af8450f2308aee38272b4aef87f0c547b',1,'RadiationModel']]], + ['getdiffusefraction_77',['getDiffuseFraction',['../class_solar_position.html#af8dbd15453ce775dab5b2c5a49b1c93b',1,'SolarPosition']]], + ['getdiskobjectcenter_78',['getDiskObjectCenter',['../classhelios_1_1_context.html#a213aea1539e0bb38965cf2953b1831df',1,'helios::Context']]], + ['getdiskobjectpointer_79',['getDiskObjectPointer',['../classhelios_1_1_context.html#a17c1256a1f57fbae1f34e04b66b76ca8',1,'helios::Context']]], + ['getdiskobjectsize_80',['getDiskObjectSize',['../classhelios_1_1_context.html#acee51918d3ee1d9892e5a51106a625d9',1,'helios::Context']]], + ['getdiskobjectsubdivisioncount_81',['getDiskObjectSubdivisionCount',['../classhelios_1_1_context.html#a86ffc9a6cdcd3851231c64dcc152123c',1,'helios::Context']]], + ['getdomainboundingbox_82',['getDomainBoundingBox',['../classhelios_1_1_context.html#a8690412a63d1eff69e679e48d03c9838',1,'helios::Context::getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const'],['../classhelios_1_1_context.html#ad4ac166bb01547d1cefb1ace7a9b966d',1,'helios::Context::getDomainBoundingBox(const std::vector< uint > &UUIDs, helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const'],['../class_visualizer.html#ae9c98dee278e9bcd5f85b871ff8ddfe5',1,'Visualizer::getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const']]], + ['getdomainboundingradius_83',['getDomainBoundingRadius',['../class_visualizer.html#a783739e072baeafc943a077dcb1cc3d5',1,'Visualizer']]], + ['getdomainboundingsphere_84',['getDomainBoundingSphere',['../classhelios_1_1_context.html#a3a6b0d25c5d9febb17787982c9f09d63',1,'helios::Context::getDomainBoundingSphere(helios::vec3 &center, float &radius) const'],['../classhelios_1_1_context.html#af3e048e969f06e3a0cf36ed3d76766ca',1,'helios::Context::getDomainBoundingSphere(const std::vector< uint > &UUIDs, helios::vec3 &center, float &radius) const']]], + ['getempiricalmodelcoefficients_85',['getEmpiricalModelCoefficients',['../class_photosynthesis_model.html#a86094d579852c2dc846acc2a97e6ac44',1,'PhotosynthesisModel']]], + ['getfarquharcoefficientsfromlibrary_86',['getFarquharCoefficientsFromLibrary',['../class_photosynthesis_model.html#ae40570ef642d5d4dc070dce9ba093f16',1,'PhotosynthesisModel']]], + ['getfarquharmodelcoefficients_87',['getFarquharModelCoefficients',['../class_photosynthesis_model.html#aeab92cd73298c5f89626b30ce8c41cf9',1,'PhotosynthesisModel']]], + ['getfileextension_88',['getFileExtension',['../global_8h.html#a58e660bb08e1ce13466825ae666467ef',1,'helios']]], + ['getfilename_89',['getFileName',['../global_8h.html#a63bd49091fdab0e262b051f61fb9a902',1,'helios']]], + ['getfilepath_90',['getFilePath',['../global_8h.html#ad76f15d03b511d1bf5123d64d804d6e8',1,'helios']]], + ['getfilestem_91',['getFileStem',['../global_8h.html#a9fff8cb6c3474de479f81c12f173d3ed',1,'helios']]], + ['getframebuffersize_92',['getFramebufferSize',['../class_visualizer.html#ab3b0261a21e7f552d55e4d2fda55f94f',1,'Visualizer']]], + ['getfruituuids_93',['getFruitUUIDs',['../class_canopy_generator.html#a8ab509f22c4bdffd57b44f67f43ce728',1,'CanopyGenerator::getFruitUUIDs(uint PlantID)'],['../class_canopy_generator.html#abdcc431929f98e57db4b9ed2dc26a616',1,'CanopyGenerator::getFruitUUIDs()']]], + ['getglobaldata_94',['getGlobalData',['../classhelios_1_1_context.html#a972fa4a45b2775f6047d41b88dc69d03',1,'helios::Context::getGlobalData(const char *label, int &data) const'],['../classhelios_1_1_context.html#a175d9a1955f428b0f2d6b11ab3b17659',1,'helios::Context::getGlobalData(const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#a98cbb0d37dc9fafaad14184cb889534f',1,'helios::Context::getGlobalData(const char *label, uint &data) const'],['../classhelios_1_1_context.html#a931a92ba7e9916c64d164bc1f29ff754',1,'helios::Context::getGlobalData(const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#ac1f5f6c3f24577cd5c4657c441483425',1,'helios::Context::getGlobalData(const char *label, float &data) const'],['../classhelios_1_1_context.html#a863264ab1339ba35c3754bfbf4c69eec',1,'helios::Context::getGlobalData(const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#a8ec49c820f10831b4b27059d4d1749d6',1,'helios::Context::getGlobalData(const char *label, double &data) const'],['../classhelios_1_1_context.html#a66e7d689b62d9ad47fb85ad45664c97f',1,'helios::Context::getGlobalData(const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#a6f4d6971c05d78aff30b92d277014b9f',1,'helios::Context::getGlobalData(const char *label, helios::vec2 &data) const'],['../classhelios_1_1_context.html#afc90a3d0143273e436541fc3bc9c5554',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec2 > &data) const'],['../classhelios_1_1_context.html#a990fdccf51979e235a1acba08e54583b',1,'helios::Context::getGlobalData(const char *label, helios::vec3 &data) const'],['../classhelios_1_1_context.html#a0376e2dc456e481bd055d5a84b7785f2',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec3 > &data) const'],['../classhelios_1_1_context.html#a3f621b536c3585d7f808698e2f0cd826',1,'helios::Context::getGlobalData(const char *label, helios::vec4 &data) const'],['../classhelios_1_1_context.html#ab0f329c8584b002dda2d77719073bf5d',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec4 > &data) const'],['../classhelios_1_1_context.html#aea16d4845e23fe44ae1da4c032ea57e3',1,'helios::Context::getGlobalData(const char *label, helios::int2 &data) const'],['../classhelios_1_1_context.html#a609563835616233b15fd263bb2e8857d',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int2 > &data) const'],['../classhelios_1_1_context.html#aba7c4fe63193509f40ca6682cddfa9a3',1,'helios::Context::getGlobalData(const char *label, helios::int3 &data) const'],['../classhelios_1_1_context.html#abbc6d463f6d722fca56ad219c8278c16',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int3 > &data) const'],['../classhelios_1_1_context.html#a2b2f0570e50711f34bb24dc01c8a7b43',1,'helios::Context::getGlobalData(const char *label, helios::int4 &data) const'],['../classhelios_1_1_context.html#ad08d9d2bea2c93b14ae2b3678aea2e29',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int4 > &data) const'],['../classhelios_1_1_context.html#a890583b0897bfcd730d137838fa7e155',1,'helios::Context::getGlobalData(const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a0572c1557ec60ae7389072e8ab3c2113',1,'helios::Context::getGlobalData(const char *label, std::vector< std::string > &data) const']]], + ['getglobaldatasize_95',['getGlobalDataSize',['../classhelios_1_1_context.html#a96d1060d1329dc467380ce2e5eafd559',1,'helios::Context']]], + ['getglobaldatatype_96',['getGlobalDataType',['../classhelios_1_1_context.html#a94bf0b919e5e6034fa45fbae2f575947',1,'helios::Context']]], + ['getgridboundingbox_97',['getGridBoundingBox',['../class_li_d_a_rcloud.html#a041ac4ba388c407a35b7f895029038e6',1,'LiDARcloud']]], + ['getgridcellcount_98',['getGridCellCount',['../class_li_d_a_rcloud.html#a28297a71becd69b30820d69b110fcc90',1,'LiDARcloud']]], + ['getgridcenter_99',['getGridCenter',['../class_aerial_li_d_a_rcloud.html#ad639b0d2337b74b1bd4949cc2aba88e0',1,'AerialLiDARcloud']]], + ['getgridextent_100',['getGridExtent',['../class_aerial_li_d_a_rcloud.html#a85ea1ea67ed12f2bbcfc28ef9a78dd77',1,'AerialLiDARcloud']]], + ['getgridresolution_101',['getGridResolution',['../class_aerial_li_d_a_rcloud.html#ae750e548d565d6305e600c5af8360fdb',1,'AerialLiDARcloud']]], + ['getgridrotation_102',['getGridRotation',['../class_aerial_li_d_a_rcloud.html#aace3b3baae4a75be461eb31f617ee695',1,'AerialLiDARcloud']]], + ['getgrounduuids_103',['getGroundUUIDs',['../class_canopy_generator.html#a6f0003d6ca29cbb56657442c7a48ad14',1,'CanopyGenerator']]], + ['gethitboundingbox_104',['getHitBoundingBox',['../class_aerial_li_d_a_rcloud.html#a74b0e833ecb6ee1b3ce3010f3d38d74d',1,'AerialLiDARcloud::getHitBoundingBox()'],['../class_li_d_a_rcloud.html#a45bc37a4d26eb74a944c594a7f3cb54b',1,'LiDARcloud::getHitBoundingBox()']]], + ['gethitcolor_105',['getHitColor',['../class_aerial_li_d_a_rcloud.html#af8f49444eb1d166837c322d03ea1cbfa',1,'AerialLiDARcloud::getHitColor()'],['../class_li_d_a_rcloud.html#aafafed9102966992d3cfb3772fa2ada1',1,'LiDARcloud::getHitColor()']]], + ['gethitcount_106',['getHitCount',['../class_aerial_li_d_a_rcloud.html#aaf287ef121543f10e9e73579bf77281a',1,'AerialLiDARcloud::getHitCount()'],['../class_li_d_a_rcloud.html#a691fd3bbd1262d80e10a674c82c6f568',1,'LiDARcloud::getHitCount()']]], + ['gethitdata_107',['getHitData',['../class_aerial_li_d_a_rcloud.html#a240af79b825bc886e886ff7ff0e0476c',1,'AerialLiDARcloud::getHitData()'],['../class_li_d_a_rcloud.html#a274ef68850afa3f288bb648d9fd6a59a',1,'LiDARcloud::getHitData()']]], + ['gethitgridcell_108',['getHitGridCell',['../class_aerial_li_d_a_rcloud.html#a26bc32e67d3195222f11fb72fb7d63da',1,'AerialLiDARcloud::getHitGridCell()'],['../class_li_d_a_rcloud.html#a251c4f3bbefdd07212cd8fe1037dc0d7',1,'LiDARcloud::getHitGridCell(uint index) const']]], + ['gethitindex_109',['getHitIndex',['../class_li_d_a_rcloud.html#a34eee980f365fdd5469a0cc6ee3a36f5',1,'LiDARcloud']]], + ['gethitraydir_110',['getHitRaydir',['../class_aerial_li_d_a_rcloud.html#ac0f8ba05e24d146d01ee2af0fb9ece7d',1,'AerialLiDARcloud::getHitRaydir()'],['../class_li_d_a_rcloud.html#aa91258bd97d6fcacd3313d8b55cceed4',1,'LiDARcloud::getHitRaydir()']]], + ['gethitscanid_111',['getHitScanID',['../class_aerial_li_d_a_rcloud.html#aaa2bbd15dad66355175fb733630456a4',1,'AerialLiDARcloud::getHitScanID()'],['../class_li_d_a_rcloud.html#a5510b2a0d0a878930e9f11331494bf41',1,'LiDARcloud::getHitScanID()']]], + ['gethitxyz_112',['getHitXYZ',['../class_aerial_li_d_a_rcloud.html#a3363ac3ffff1bbdd164b6074010d75ba',1,'AerialLiDARcloud::getHitXYZ()'],['../class_li_d_a_rcloud.html#ac5f234b6200419f10fe82c9abe409cbd',1,'LiDARcloud::getHitXYZ()']]], + ['getimageresolution_113',['getImageResolution',['../classhelios_1_1_texture.html#a4e106c0c80f0c4c065e5ff71193aaeab',1,'helios::Texture']]], + ['getimageresolutionjpeg_114',['getImageResolutionJPEG',['../global_8h.html#a94c80cbffdccaea7991b439acf8e9eb4',1,'helios']]], + ['getjuliandate_115',['getJulianDate',['../classhelios_1_1_context.html#a23f2611ed71eeefe8cf772cab98de4d4',1,'helios::Context']]], + ['getleafspectra_116',['getLeafSpectra',['../class_leaf_optics.html#a6b9fa9b6fb34fe7738e425b19118005a',1,'LeafOptics']]], + ['getleafuuids_117',['getLeafUUIDs',['../class_canopy_generator.html#a3509012720b5fd256a14bc2924a3b164',1,'CanopyGenerator::getLeafUUIDs(uint PlantID)'],['../class_canopy_generator.html#a73680976a2826f0b5dbf567551fd5593',1,'CanopyGenerator::getLeafUUIDs()'],['../class_weber_penn_tree.html#af4368c1f900503f6d72f0c0e569fe8e5',1,'WeberPennTree::getLeafUUIDs()']]], + ['getlength_118',['getLength',['../classhelios_1_1_tube.html#ad3c194a0f9977e212ac425aefe4032bf',1,'helios::Tube::getLength()'],['../classhelios_1_1_cone.html#ada36b3fe4850f16c4dfa58c38a8da80c',1,'helios::Cone::getLength()']]], + ['getloadedxmlfiles_119',['getLoadedXMLFiles',['../classhelios_1_1_context.html#a48a8a843b99c36ad357dba13ee6f1774',1,'helios::Context']]], + ['getlocation_120',['getLocation',['../classhelios_1_1_context.html#af4b1fa52419259a0c8a2faeb7484a439',1,'helios::Context']]], + ['getmonthstring_121',['getMonthString',['../classhelios_1_1_context.html#a6189f6ab35669f4fefde571ec362247c',1,'helios::Context']]], + ['getnodecolors_122',['getNodeColors',['../classhelios_1_1_tube.html#aae753418cb304e97c296240dc9919388',1,'helios::Tube']]], + ['getnodecoordinate_123',['getNodeCoordinate',['../classhelios_1_1_cone.html#a4f6ddd7fd23d61528ada9df1e333ad17',1,'helios::Cone']]], + ['getnodecoordinates_124',['getNodeCoordinates',['../classhelios_1_1_cone.html#a9eaab4331e325c85ce9f4c101135c966',1,'helios::Cone']]], + ['getnoderadii_125',['getNodeRadii',['../classhelios_1_1_tube.html#a29823b956371d22b35add97fc6831cab',1,'helios::Tube::getNodeRadii()'],['../classhelios_1_1_cone.html#adc5370734810e4b526bf0d42e143ecf8',1,'helios::Cone::getNodeRadii() const']]], + ['getnoderadius_126',['getNodeRadius',['../classhelios_1_1_cone.html#a2334ca87f6bb556b411c8a51476b523c',1,'helios::Cone']]], + ['getnodes_127',['getNodes',['../classhelios_1_1_tube.html#ab55e8f7d7a948941027f169d714e365b',1,'helios::Tube']]], + ['getnormal_128',['getNormal',['../classhelios_1_1_tile.html#ab8c70daf8c14bc60caf499b5adce301c',1,'helios::Tile']]], + ['getobjectarea_129',['getObjectArea',['../classhelios_1_1_context.html#aac46a608ec7719e4702cd861667925f1',1,'helios::Context']]], + ['getobjectboundingbox_130',['getObjectBoundingBox',['../classhelios_1_1_context.html#a1b9871bf670404adc1d952e59429ec38',1,'helios::Context::getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const'],['../classhelios_1_1_context.html#ab5aef932bd4b64b1cee932423172ab6f',1,'helios::Context::getObjectBoundingBox(const std::vector< uint > &ObjID, vec3 &min_corner, vec3 &max_corner) const']]], + ['getobjectcenter_131',['getObjectCenter',['../classhelios_1_1_compound_object.html#aff66ca85a22d7f8a2501039e2e7183a7',1,'helios::CompoundObject::getObjectCenter()'],['../classhelios_1_1_context.html#a4fe8ddd10f0d34bfe0b2a4aea648442a',1,'helios::Context::getObjectCenter(uint ObjID) const']]], + ['getobjectcount_132',['getObjectCount',['../classhelios_1_1_context.html#a54b9c5503ad33d1dcc8f6a5c74f7ea76',1,'helios::Context']]], + ['getobjectdata_133',['getObjectData',['../classhelios_1_1_compound_object.html#ac91c73ac495bc4a93cc9a89d0eb58f47',1,'helios::CompoundObject::getObjectData(const char *label, int &data) const'],['../classhelios_1_1_compound_object.html#aed77927b3d3fe0ea7ea674b20a8acce1',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int > &data) const'],['../classhelios_1_1_compound_object.html#ac91bb0e57aa261b003de76b3e008a762',1,'helios::CompoundObject::getObjectData(const char *label, uint &data) const'],['../classhelios_1_1_compound_object.html#a7be991a83ada928f25c23cf7ca3b1822',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_compound_object.html#ac222719662ca008014cdd045bedd3d96',1,'helios::CompoundObject::getObjectData(const char *label, float &data) const'],['../classhelios_1_1_compound_object.html#ac128057ff1d7cabb9dfbfb33216cb0c5',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< float > &data) const'],['../classhelios_1_1_compound_object.html#a6d99ef1cacec7471bb79b57601a7a6ee',1,'helios::CompoundObject::getObjectData(const char *label, double &data) const'],['../classhelios_1_1_compound_object.html#ac7af8838d7132683dd9fdbffd1288579',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< double > &data) const'],['../classhelios_1_1_compound_object.html#aef1aadca9de0e9a66500ca5879ab3755',1,'helios::CompoundObject::getObjectData(const char *label, vec2 &data) const'],['../classhelios_1_1_compound_object.html#af7574c29395681941d4d875e304b93de',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_compound_object.html#acea74a2c138c1e5d832df864a231e486',1,'helios::CompoundObject::getObjectData(const char *label, vec3 &data) const'],['../classhelios_1_1_compound_object.html#a797a5fd8f08ff7220b15ae1d5accb6cd',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_compound_object.html#a52661efba4b57415b073fcf839069623',1,'helios::CompoundObject::getObjectData(const char *label, vec4 &data) const'],['../classhelios_1_1_compound_object.html#a15ef0fda0196b4de933e4379d5f8234f',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_compound_object.html#a768a439ecb0d6e8449b31cd137317168',1,'helios::CompoundObject::getObjectData(const char *label, int2 &data) const'],['../classhelios_1_1_compound_object.html#af4d1accb01b8dd2f968296c43dfb6d97',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_compound_object.html#a95f20aead49e80032b0673273de436f2',1,'helios::CompoundObject::getObjectData(const char *label, int3 &data) const'],['../classhelios_1_1_compound_object.html#a6cb032fa5f5b6de86f234eb237980586',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_compound_object.html#a2c0dcefe9e05ec04b001ad94f475f34c',1,'helios::CompoundObject::getObjectData(const char *label, int4 &data) const'],['../classhelios_1_1_compound_object.html#aba75ef4dd5b01b02fc99f9a1d957d70b',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_compound_object.html#afa77a9712c207752cd56522f2dbca52b',1,'helios::CompoundObject::getObjectData(const char *label, std::string &data) const'],['../classhelios_1_1_compound_object.html#adfd1f35dc8785f223c02cc940360e6a5',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< std::string > &data) const'],['../classhelios_1_1_context.html#a3511ff568337b501ca878c99d97c9b52',1,'helios::Context::getObjectData(uint objID, const char *label, int &data) const'],['../classhelios_1_1_context.html#ae75ddc9a945ec876533211f52b8cd22e',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#abbd59cc4e7bcad35b43ea7240c4d5558',1,'helios::Context::getObjectData(uint objID, const char *label, uint &data) const'],['../classhelios_1_1_context.html#a22d510fad177ca319bdac0a94ee8f069',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#a8935a9cdf6e34e72bcb636a97043a474',1,'helios::Context::getObjectData(uint objID, const char *label, float &data) const'],['../classhelios_1_1_context.html#a293d899bb22cae1db8cf6c2cc813055d',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#ae222f3351535f3aea35e76cbe2ca2d67',1,'helios::Context::getObjectData(uint objID, const char *label, double &data) const'],['../classhelios_1_1_context.html#acda7f75e833791bcbd74ca8b37272a8b',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#af8fa05c716517966f7abcc2f4019c709',1,'helios::Context::getObjectData(uint objID, const char *label, vec2 &data) const'],['../classhelios_1_1_context.html#a2e691b7f0b630792f50b5423e23ebab1',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_context.html#a628cf051625e33549044cd20656519ac',1,'helios::Context::getObjectData(uint objID, const char *label, vec3 &data) const'],['../classhelios_1_1_context.html#a6606603899859e211de9f56cd49bf92d',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_context.html#ac2b7e667ec37c88868ba0752919da1c9',1,'helios::Context::getObjectData(uint objID, const char *label, vec4 &data) const'],['../classhelios_1_1_context.html#ace5025b962226a75c4984ee6ecc21356',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_context.html#ae56639e95fae8796545efde94fa84bcc',1,'helios::Context::getObjectData(uint objID, const char *label, int2 &data) const'],['../classhelios_1_1_context.html#a39b169b41cf94516afd863f580c2b772',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_context.html#ac58fc8f10c12dc54265491576650a0c6',1,'helios::Context::getObjectData(uint objID, const char *label, int3 &data) const'],['../classhelios_1_1_context.html#ac097e42620523f2d57d28eecd02954a4',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_context.html#aa393d7b0f24855b2e54480be71c09ad2',1,'helios::Context::getObjectData(uint objID, const char *label, int4 &data) const'],['../classhelios_1_1_context.html#a7ca032799776268d30fe185a76100e0e',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_context.html#a1eae737b91ec70ae6490a8c403936975',1,'helios::Context::getObjectData(uint objID, const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a158215e07c921d11e495b3805823b725',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< std::string > &data) const']]], + ['getobjectdatasize_134',['getObjectDataSize',['../classhelios_1_1_compound_object.html#a03b2516f8e7e8ae921ea61e4f571eb1d',1,'helios::CompoundObject::getObjectDataSize()'],['../classhelios_1_1_context.html#ac251e9be64f3a35b6d2e6441c2a46f40',1,'helios::Context::getObjectDataSize()']]], + ['getobjectdatatype_135',['getObjectDataType',['../classhelios_1_1_compound_object.html#abbcfd5c545991ee59cf3f77acf300b1e',1,'helios::CompoundObject::getObjectDataType()'],['../classhelios_1_1_context.html#af77ff3ea4a7668d2b5cb03bc6fc5f5b6',1,'helios::Context::getObjectDataType()']]], + ['getobjectid_136',['getObjectID',['../classhelios_1_1_compound_object.html#a28c85b0cf4dee51dd7997b7b78e4f442',1,'helios::CompoundObject']]], + ['getobjectpointer_137',['getObjectPointer',['../classhelios_1_1_context.html#a3d9493949db2c5d8ddeef30afd2a9a0a',1,'helios::Context']]], + ['getobjectprimitivecount_138',['getObjectPrimitiveCount',['../classhelios_1_1_context.html#a457ccd0bcf9870aef138b22c4a160aeb',1,'helios::Context']]], + ['getobjectprimitiveuuids_139',['getObjectPrimitiveUUIDs',['../classhelios_1_1_context.html#a7d0b3a6ca36b02702b06208a735a3b03',1,'helios::Context::getObjectPrimitiveUUIDs(uint ObjID) const'],['../classhelios_1_1_context.html#a09e60fbbd3c4be1f8345a9de3695ccdd',1,'helios::Context::getObjectPrimitiveUUIDs(const std::vector< uint > &ObjIDs) const'],['../classhelios_1_1_context.html#a266fba7ca4a0a1536c49f1e3ce918b1e',1,'helios::Context::getObjectPrimitiveUUIDs(const std::vector< std::vector< uint > > &ObjIDs) const']]], + ['getobjecttexturefile_140',['getObjectTextureFile',['../classhelios_1_1_context.html#aacd4cff3b170281516dcafb3fa83b84a',1,'helios::Context']]], + ['getobjecttransformationmatrix_141',['getObjectTransformationMatrix',['../classhelios_1_1_context.html#af9e972c138b0626cece9eea5f018b418',1,'helios::Context']]], + ['getobjecttype_142',['getObjectType',['../classhelios_1_1_compound_object.html#ab07473392ca1e4c439c909c83cc9730b',1,'helios::CompoundObject::getObjectType()'],['../classhelios_1_1_context.html#a75ae3ee4580c4420059fe95755dc22d2',1,'helios::Context::getObjectType(uint ObjID) const']]], + ['getpatchcenter_143',['getPatchCenter',['../classhelios_1_1_context.html#a4165df43e5ab752e81bc2b7d7caf19d5',1,'helios::Context']]], + ['getpatchsize_144',['getPatchSize',['../classhelios_1_1_context.html#ab3f802aca8dd1930127d9f76358e71cf',1,'helios::Context']]], + ['getplantcount_145',['getPlantCount',['../class_canopy_generator.html#aba9e186286ade3cd2ced0be80b3b8b89',1,'CanopyGenerator']]], + ['getplantflowerobjectids_146',['getPlantFlowerObjectIDs',['../class_plant_architecture.html#a1cb3e4ba93c7a94558c3c07496e550c2',1,'PlantArchitecture']]], + ['getplantfruitobjectids_147',['getPlantFruitObjectIDs',['../class_plant_architecture.html#aac602c603ac136c3aaffad052bd844d4',1,'PlantArchitecture']]], + ['getplantheight_148',['getPlantHeight',['../class_plant_architecture.html#a4d6e2ec9e60b12bc56e2ee753ba9f9cf',1,'PlantArchitecture']]], + ['getplantinternodeobjectids_149',['getPlantInternodeObjectIDs',['../class_plant_architecture.html#a53967340a1c9b88f4b804522f081ce62',1,'PlantArchitecture']]], + ['getplantleafcount_150',['getPlantLeafCount',['../class_plant_architecture.html#a74032e7973d410bf861e0c3448bee3ce',1,'PlantArchitecture']]], + ['getplantleafinclinationangledistribution_151',['getPlantLeafInclinationAngleDistribution',['../class_plant_architecture.html#a512ba39f59b0ebc35d8f699c136a00fe',1,'PlantArchitecture']]], + ['getplantleafobjectids_152',['getPlantLeafObjectIDs',['../class_plant_architecture.html#afcdea7f14c6ca722d39d94ff19ba87b4',1,'PlantArchitecture']]], + ['getplantpeduncleobjectids_153',['getPlantPeduncleObjectIDs',['../class_plant_architecture.html#af8a9f26212baf6695d71d44b982e6adf',1,'PlantArchitecture']]], + ['getplantpetioleobjectids_154',['getPlantPetioleObjectIDs',['../class_plant_architecture.html#aee2486b87dca29982dd1b380aa3510fb',1,'PlantArchitecture']]], + ['getplantstemheight_155',['getPlantStemHeight',['../class_plant_architecture.html#a7f34d9100299ca2d0d44984e9403915a',1,'PlantArchitecture']]], + ['getpolymeshobjectpointer_156',['getPolymeshObjectPointer',['../classhelios_1_1_context.html#a5a10781f6c1e24b226a32b1e1369f5c1',1,'helios::Context']]], + ['getpolymeshobjectvolume_157',['getPolymeshObjectVolume',['../classhelios_1_1_context.html#aad71b3e493ab0e47c6d4496d14e89803',1,'helios::Context']]], + ['getprimitivearea_158',['getPrimitiveArea',['../classhelios_1_1_context.html#a1dafe58b3251d2ef9d09112258b2e85d',1,'helios::Context']]], + ['getprimitiveboundingbox_159',['getPrimitiveBoundingBox',['../classhelios_1_1_context.html#abf2e26ac2b32556878be6626a8876569',1,'helios::Context::getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const'],['../classhelios_1_1_context.html#a808527f76dec2683cbc168250c4f69be',1,'helios::Context::getPrimitiveBoundingBox(const std::vector< uint > &UUID, vec3 &min_corner, vec3 &max_corner) const']]], + ['getprimitivecolor_160',['getPrimitiveColor',['../classhelios_1_1_context.html#a1223205f1080b0b7024b8f97950779b8',1,'helios::Context']]], + ['getprimitivecolorrgb_161',['getPrimitiveColorRGB',['../classhelios_1_1_context.html#a8550633570ee91e4f09ec1464810bd7b',1,'helios::Context']]], + ['getprimitivecolorrgba_162',['getPrimitiveColorRGBA',['../classhelios_1_1_context.html#a4e29adcb908d55172efd239f294b49e5',1,'helios::Context']]], + ['getprimitivecount_163',['getPrimitiveCount',['../classhelios_1_1_compound_object.html#a0eb06d37710a7dc9f5b915fc33f191a0',1,'helios::CompoundObject::getPrimitiveCount()'],['../group__primitives.html#ga4d3447fb04c25e685bcc82599e2b173d',1,'helios::Context::getPrimitiveCount() const']]], + ['getprimitivedata_164',['getPrimitiveData',['../classhelios_1_1_context.html#a2144eea981e4030c973287ce2c38315e',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int &data) const'],['../classhelios_1_1_context.html#ad1f6453da61e8e64ba91f589b7cc4eb0',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#a420487af4a23ed5b527069c6471efd93',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, uint &data) const'],['../classhelios_1_1_context.html#add62ecdb7cc13510670c9c45bc8725a3',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#aa54fb6e8a942845010ae669505adc2e8',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, float &data) const'],['../classhelios_1_1_context.html#a466dea76918a4bd02e4a355ab70f161b',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#a802b10b84762052e52b9ff1861604c58',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, double &data) const'],['../classhelios_1_1_context.html#a65d1918df796575a5e5bc8c470ff3201',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#a2ac5198c45a57b7926f4dbd9129fcad5',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec2 &data) const'],['../classhelios_1_1_context.html#ab0fb70ff8b6e81901df14efe07ae7ff4',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_context.html#abbe503b705cfdeb903becdb7fb082dae',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec3 &data) const'],['../classhelios_1_1_context.html#a83619185959d1dae4570674a3855f808',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_context.html#a0e62c9bb97e4cbbcd56518b060e9cae5',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec4 &data) const'],['../classhelios_1_1_context.html#a29fed63e84bf5b5111b0e98f499da56e',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_context.html#a72ee49f503ff0c4937d9aa81b72689ed',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int2 &data) const'],['../classhelios_1_1_context.html#ae76119a1083016c2cffed9eb443aaa62',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_context.html#a18f0ede968126842068551834391e3ad',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int3 &data) const'],['../classhelios_1_1_context.html#a5c37491d4bc0a1d69ffcaf214e6c2fe7',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_context.html#afe292fdf1d3c7983427c699e4a2eca3a',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int4 &data) const'],['../classhelios_1_1_context.html#a8ebaded3f143fc9c673765ab3fda5366',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_context.html#ad1a2ca668fb5f5043f23f7a50c22483f',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a1d8cd543d68c2bc3b7ef876421284f15',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< std::string > &data) const']]], + ['getprimitivedatasize_165',['getPrimitiveDataSize',['../classhelios_1_1_context.html#a4b64585d356463ac759472f099660eca',1,'helios::Context']]], + ['getprimitivedatatype_166',['getPrimitiveDataType',['../classhelios_1_1_context.html#a9c894ecd12e0d893c53ffcfa9e90c0b6',1,'helios::Context']]], + ['getprimitivenormal_167',['getPrimitiveNormal',['../classhelios_1_1_context.html#abfeadf8e6a35eb97da1439abc21c434e',1,'helios::Context']]], + ['getprimitiveparentobjectid_168',['getPrimitiveParentObjectID',['../classhelios_1_1_context.html#a2d3e254d04f913e590a645b54886436e',1,'helios::Context']]], + ['getprimitivesolidfraction_169',['getPrimitiveSolidFraction',['../classhelios_1_1_context.html#a6e8a5e2044331158d69d6f9bd88fc0f7',1,'helios::Context']]], + ['getprimitivetexturefile_170',['getPrimitiveTextureFile',['../classhelios_1_1_context.html#a4fffad72d1ebb517d9c41837e448d4f5',1,'helios::Context']]], + ['getprimitivetexturesize_171',['getPrimitiveTextureSize',['../classhelios_1_1_context.html#a7fec62cbf2c2d56603b2750cbb4a4d9f',1,'helios::Context']]], + ['getprimitivetexturetransparencydata_172',['getPrimitiveTextureTransparencyData',['../classhelios_1_1_context.html#a98ad773979fff9efda47b44d71ac8e06',1,'helios::Context']]], + ['getprimitivetextureuv_173',['getPrimitiveTextureUV',['../classhelios_1_1_context.html#a5702f94aaba15bf6757aeb4d72d7774d',1,'helios::Context']]], + ['getprimitivetransformationmatrix_174',['getPrimitiveTransformationMatrix',['../classhelios_1_1_context.html#a046e855d15fa88088be01adea38a67fd',1,'helios::Context']]], + ['getprimitivetype_175',['getPrimitiveType',['../classhelios_1_1_context.html#a67bfd66f0a445f6485f1099f9eadc949',1,'helios::Context']]], + ['getprimitiveuuids_176',['getPrimitiveUUIDs',['../classhelios_1_1_compound_object.html#ab3973a7c8ccb1aa0ce3f21ffe461ef7b',1,'helios::CompoundObject']]], + ['getprimitivevertices_177',['getPrimitiveVertices',['../classhelios_1_1_context.html#ae8542fd1452150d3302675a0a3d991ed',1,'helios::Context']]], + ['getradius_178',['getRadius',['../classhelios_1_1_sphere.html#a38cf8b6959d22577a1a2f9a6c675bc8b',1,'helios::Sphere']]], + ['getrandomgenerator_179',['getRandomGenerator',['../classhelios_1_1_context.html#a96a928fa28d3d771ba310f798b56bd63',1,'helios::Context']]], + ['getscanbeamdivergence_180',['getScanBeamDivergence',['../class_aerial_li_d_a_rcloud.html#a4097c1d3994f57e0f0e2e602c7ca5c04',1,'AerialLiDARcloud::getScanBeamDivergence()'],['../class_li_d_a_rcloud.html#a9d93e6cd9decccf271fbf3fbd5c74a5a',1,'LiDARcloud::getScanBeamDivergence()']]], + ['getscanbeamexitdiameter_181',['getScanBeamExitDiameter',['../class_aerial_li_d_a_rcloud.html#ae6cbd6375be39129231233d66061afca',1,'AerialLiDARcloud::getScanBeamExitDiameter()'],['../class_li_d_a_rcloud.html#abab6b81a3d96226a766cc2450993407f',1,'LiDARcloud::getScanBeamExitDiameter()']]], + ['getscancenter_182',['getScanCenter',['../class_aerial_li_d_a_rcloud.html#a1ce1efbe6af71f54dcccd3743918aa72',1,'AerialLiDARcloud']]], + ['getscancolumnformat_183',['getScanColumnFormat',['../class_li_d_a_rcloud.html#abbe892f01508dc69bcc5b28bea5472bf',1,'LiDARcloud']]], + ['getscanconeangle_184',['getScanConeAngle',['../class_aerial_li_d_a_rcloud.html#a0dbf5535304d6d87d67a0d41c5d2310f',1,'AerialLiDARcloud']]], + ['getscancount_185',['getScanCount',['../class_aerial_li_d_a_rcloud.html#ab363717911dada3af4fdafa914532a6a',1,'AerialLiDARcloud::getScanCount()'],['../class_li_d_a_rcloud.html#aaa463ea1aaebb03abd8c3ec87091291a',1,'LiDARcloud::getScanCount()']]], + ['getscandensity_186',['getScanDensity',['../class_aerial_li_d_a_rcloud.html#a0c4627b15014ebe8c79053ed75f6cfb4',1,'AerialLiDARcloud']]], + ['getscanextent_187',['getScanExtent',['../class_aerial_li_d_a_rcloud.html#ad5bd68f06fef597d8c1f1aac3142acc6',1,'AerialLiDARcloud']]], + ['getscanorigin_188',['getScanOrigin',['../class_li_d_a_rcloud.html#aa657ed32a8831ebf4f2e4a9203b683ef',1,'LiDARcloud']]], + ['getscanrangephi_189',['getScanRangePhi',['../class_li_d_a_rcloud.html#ab314aac88834eb3938fc2f37e34807e3',1,'LiDARcloud']]], + ['getscanrangetheta_190',['getScanRangeTheta',['../class_li_d_a_rcloud.html#a7f0237a83da6997e973fde9939440979',1,'LiDARcloud']]], + ['getscansizephi_191',['getScanSizePhi',['../class_li_d_a_rcloud.html#aaf04cd04c2b1bc162106a0e47cff6d29',1,'LiDARcloud']]], + ['getscansizetheta_192',['getScanSizeTheta',['../class_li_d_a_rcloud.html#a40809c7a709a6c9ccb4beddca21f8ac9',1,'LiDARcloud']]], + ['getsegmentvolume_193',['getSegmentVolume',['../classhelios_1_1_tube.html#a2966ff764897904282082f23a76756b8',1,'helios::Tube']]], + ['getsize_194',['getSize',['../classhelios_1_1_tile.html#aa8daadd99bd57f647837e26890fcfeac',1,'helios::Tile::getSize()'],['../classhelios_1_1_box.html#afd79ee17402ab6367896fe8278800f34',1,'helios::Box::getSize()'],['../classhelios_1_1_disk.html#a23c03df1f2e351659a08420a41a74eb5',1,'helios::Disk::getSize()']]], + ['getskyenergy_195',['getSkyEnergy',['../class_radiation_model.html#a9c9a5f6cb6b0ba6e3780aba8a4da8a0d',1,'RadiationModel']]], + ['getsolarflux_196',['getSolarFlux',['../class_solar_position.html#a9701cb29a0336a11c445d285405b6956',1,'SolarPosition']]], + ['getsolarfluxnir_197',['getSolarFluxNIR',['../class_solar_position.html#a611461f700df9efa7c56b6f4ee7712b7',1,'SolarPosition']]], + ['getsolarfluxpar_198',['getSolarFluxPAR',['../class_solar_position.html#a5c6635160944b5b8202ea9965da6de9d',1,'SolarPosition']]], + ['getsolidfraction_199',['getSolidFraction',['../classhelios_1_1_texture.html#a685024e8394b49433f26a0dcd6665d86',1,'helios::Texture']]], + ['getsourceflux_200',['getSourceFlux',['../class_radiation_model.html#a9d4ea3e08514b90e617695ab2ee2fbf8',1,'RadiationModel']]], + ['getsourceposition_201',['getSourcePosition',['../class_radiation_model.html#ab8ec35514a0e4b53ce8a64d3f390427c',1,'RadiationModel']]], + ['getsphereobjectcenter_202',['getSphereObjectCenter',['../classhelios_1_1_context.html#a4f75af0785498d14eb3f5a3539cb16b1',1,'helios::Context']]], + ['getsphereobjectpointer_203',['getSphereObjectPointer',['../classhelios_1_1_context.html#a8ed7580efa323c0f5e53e97d00e16c85',1,'helios::Context']]], + ['getsphereobjectradius_204',['getSphereObjectRadius',['../classhelios_1_1_context.html#a5afb4fd92e9a726fb396779d1f2ae92b',1,'helios::Context']]], + ['getsphereobjectsubdivisioncount_205',['getSphereObjectSubdivisionCount',['../classhelios_1_1_context.html#adadbc5a5378a874cd6705ed681fb9e6a',1,'helios::Context']]], + ['getsphereobjectvolume_206',['getSphereObjectVolume',['../classhelios_1_1_context.html#ae92df5975ec7fa257e7633d6551e2a87',1,'helios::Context']]], + ['getsubdivisioncount_207',['getSubdivisionCount',['../classhelios_1_1_tile.html#a4f4198becfe3cafd989b5aa6cd21d5cf',1,'helios::Tile::getSubdivisionCount()'],['../classhelios_1_1_sphere.html#a152107e463d6765ba27ff8f3ab737711',1,'helios::Sphere::getSubdivisionCount()'],['../classhelios_1_1_tube.html#abf9bb1153b3607a5d616aafeee06e43e',1,'helios::Tube::getSubdivisionCount()'],['../classhelios_1_1_box.html#a6f25b211d8740257329f841cda737a4f',1,'helios::Box::getSubdivisionCount()'],['../classhelios_1_1_disk.html#a8dc2a195735ee3321b274274e7e0352e',1,'helios::Disk::getSubdivisionCount()'],['../classhelios_1_1_cone.html#a051a2c5760d53a6c0b95f66cab9cbf73',1,'helios::Cone::getSubdivisionCount()']]], + ['getsunazimuth_208',['getSunAzimuth',['../class_solar_position.html#a2b736578f75ecb8532556931b8263dc4',1,'SolarPosition']]], + ['getsundirectionspherical_209',['getSunDirectionSpherical',['../class_solar_position.html#adad5310db742ef9f2754e75095aeea92',1,'SolarPosition']]], + ['getsundirectionvector_210',['getSunDirectionVector',['../class_solar_position.html#af889756d5b3d7d3c366887fae1fb86ab',1,'SolarPosition']]], + ['getsunelevation_211',['getSunElevation',['../class_solar_position.html#a307e963d840abb9ee7867579fec69fa2',1,'SolarPosition']]], + ['getsunrisetime_212',['getSunriseTime',['../class_solar_position.html#a2d15fe2ca0d29adf33971916b1d8cd83',1,'SolarPosition']]], + ['getsunsettime_213',['getSunsetTime',['../class_solar_position.html#a4c58aa642b4fc2300d1c1447388bc0d8',1,'SolarPosition']]], + ['getsunzenith_214',['getSunZenith',['../class_solar_position.html#a4c4ba4931d13c6cc2ad69e8eab90ac14',1,'SolarPosition']]], + ['gettexturefile_215',['getTextureFile',['../classhelios_1_1_texture.html#a0371473a81deb9bb19b8274109b75ef8',1,'helios::Texture::getTextureFile()'],['../classhelios_1_1_compound_object.html#a3e43ebd386e7a6663fa877613b9d27fa',1,'helios::CompoundObject::getTextureFile()']]], + ['gettextureuv_216',['getTextureUV',['../classhelios_1_1_tile.html#a94deb25ac31abc1eb02dfe6913b4546f',1,'helios::Tile']]], + ['gettileobjectarearatio_217',['getTileObjectAreaRatio',['../classhelios_1_1_context.html#a9943834b21ccfb9ac1c519e47f959c92',1,'helios::Context::getTileObjectAreaRatio(uint ObjectID) const'],['../classhelios_1_1_context.html#afdebad3fd25bb8b9fa228020c3b11329',1,'helios::Context::getTileObjectAreaRatio(const std::vector< uint > &ObjectID) const']]], + ['gettileobjectcenter_218',['getTileObjectCenter',['../classhelios_1_1_context.html#aa60f87c9bc771e613f60db73188a149d',1,'helios::Context']]], + ['gettileobjectnormal_219',['getTileObjectNormal',['../classhelios_1_1_context.html#a64f4bcadff461357aa390d7f5dad2ba7',1,'helios::Context']]], + ['gettileobjectpointer_220',['getTileObjectPointer',['../classhelios_1_1_context.html#ad2b762dd7b31126150c6e6dc350a3914',1,'helios::Context']]], + ['gettileobjectsize_221',['getTileObjectSize',['../classhelios_1_1_context.html#a457654b4a1f96a4979f83299dd9752df',1,'helios::Context']]], + ['gettileobjectsubdivisioncount_222',['getTileObjectSubdivisionCount',['../classhelios_1_1_context.html#a9320e4577eb131e7efe05677d30591b3',1,'helios::Context']]], + ['gettileobjecttextureuv_223',['getTileObjectTextureUV',['../classhelios_1_1_context.html#a00718598a9c308dabe8fc24f85683210',1,'helios::Context']]], + ['gettileobjectvertices_224',['getTileObjectVertices',['../classhelios_1_1_context.html#ab77b708ac6b39c1c5e8ecaa4988403b0',1,'helios::Context']]], + ['gettime_225',['getTime',['../classhelios_1_1_context.html#a847ecbb2297e60220a23b67c39b0f6e2',1,'helios::Context']]], + ['gettimeserieslength_226',['getTimeseriesLength',['../group__timeseries.html#ga56d13f8c949e68137581a3c974790892',1,'helios::Context']]], + ['getting_20object_20ids_20and_20primitive_20uuids_20of_20model_20geometry_227',['Getting Object IDs and Primitive UUIDs of Model Geometry',['../_plant_architecture_doc.html#PlantArchQueryobjIDs',1,'']]], + ['getting_20primitive_20data_20values_228',['Getting Primitive Data Values',['../_a_p_i.html#GetPrimData',1,'']]], + ['getting_20primitive_20uuids_20for_20organ_20sub_20components_229',['Getting Primitive UUIDs for Organ Sub-Components',['../_plant_architecture_doc.html#PlantArchQueryUUIDs',1,'']]], + ['getting_20started_20with_20the_20existing_20plant_20library_230',['Getting Started with the Existing Plant Library',['../_plant_architecture_doc.html#PlantArchGettingStarted',1,'']]], + ['getting_20the_20direction_20of_20the_20sun_231',['Getting the Direction of the Sun',['../_solar_position_doc.html#SolarPos',1,'']]], + ['getting_20the_20sky_20longwave_20flux_232',['Getting the Sky Longwave Flux',['../_solar_position_doc.html#LWFlux',1,'']]], + ['getting_20the_20solar_20flux_233',['Getting the Solar Flux',['../_solar_position_doc.html#SolarFlux',1,'']]], + ['gettotalabsorbedflux_234',['getTotalAbsorbedFlux',['../class_radiation_model.html#a5e95e775550a2000798a97b00857bdd2',1,'RadiationModel']]], + ['gettransformationmatrix_235',['getTransformationMatrix',['../classhelios_1_1_compound_object.html#ac1e98d4f8098dadda345f9dc6dae73ca',1,'helios::CompoundObject']]], + ['gettransparencydata_236',['getTransparencyData',['../classhelios_1_1_texture.html#a798c3a24b21fc853db299d1f1f84a61c',1,'helios::Texture']]], + ['gettreeparameters_237',['getTreeParameters',['../class_weber_penn_tree.html#aac5619ac480517f8f01cb465d0dc4a6f',1,'WeberPennTree']]], + ['gettriangle_238',['getTriangle',['../class_li_d_a_rcloud.html#aa1a1af5eea22185e59c267c8e4d94c9e',1,'LiDARcloud']]], + ['gettrianglecount_239',['getTriangleCount',['../class_li_d_a_rcloud.html#abcdbf834959379a189a60efed41f3e52',1,'LiDARcloud']]], + ['gettrianglevertex_240',['getTriangleVertex',['../classhelios_1_1_context.html#a846f93175f8b45f44237e88155af8fde',1,'helios::Context']]], + ['gettrianglevertices_241',['getTriangleVertices',['../classhelios_1_1_tube.html#a6aedd14e533981bd79497ba13b33f2c9',1,'helios::Tube']]], + ['gettrunkuuids_242',['getTrunkUUIDs',['../class_canopy_generator.html#aa8e95a610c03588592acebbbba5d638e',1,'CanopyGenerator::getTrunkUUIDs(uint PlantID)'],['../class_canopy_generator.html#a44b2d0846bb08d331281a822df41daa6',1,'CanopyGenerator::getTrunkUUIDs()'],['../class_weber_penn_tree.html#ab247d9368368263dfdded18a43917f98',1,'WeberPennTree::getTrunkUUIDs()']]], + ['gettubeobjectnodecolors_243',['getTubeObjectNodeColors',['../classhelios_1_1_context.html#a7ad271dabb4291067f9a39d4c92e6ffd',1,'helios::Context']]], + ['gettubeobjectnoderadii_244',['getTubeObjectNodeRadii',['../classhelios_1_1_context.html#a6a58d8f1a8446a213d9a21e67ae8ed97',1,'helios::Context']]], + ['gettubeobjectnodes_245',['getTubeObjectNodes',['../classhelios_1_1_context.html#aa4650e7a0a16be12615870ff9a567ae3',1,'helios::Context']]], + ['gettubeobjectpointer_246',['getTubeObjectPointer',['../classhelios_1_1_context.html#ab26f963c75aa99d797a43860479910b0',1,'helios::Context']]], + ['gettubeobjectsegmentvolume_247',['getTubeObjectSegmentVolume',['../classhelios_1_1_context.html#a10928031db222e77e93ac8088f4b001d',1,'helios::Context']]], + ['gettubeobjectsubdivisioncount_248',['getTubeObjectSubdivisionCount',['../classhelios_1_1_context.html#a272ba030971b86c7d3da57ff90784e0f',1,'helios::Context']]], + ['gettubeobjectvolume_249',['getTubeObjectVolume',['../classhelios_1_1_context.html#a56b82c3f009084451225003b2b461b6f',1,'helios::Context']]], + ['getuniqueprimitiveparentobjectids_250',['getUniquePrimitiveParentObjectIDs',['../classhelios_1_1_context.html#a18a276db8d3c1d754bbd1ca475deec82',1,'helios::Context::getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs) const'],['../classhelios_1_1_context.html#a1f50af8c859a5b2ee0973c9ed5c10284',1,'helios::Context::getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs, bool include_ObjID_zero) const']]], + ['getvariation_251',['getVariation',['../_canopy_generator_8h.html#accfb46da54c7b0e83878a1331bbc94d1',1,'getVariation(float V, std::minstd_rand0 &generator, bool positive=false): CanopyGenerator.cpp'],['../_canopy_generator_8h.html#aa3a6e1a26b799f4a2006703314499fed',1,'getVariation(int V, std::minstd_rand0 &generator, bool positive=false): CanopyGenerator.cpp'],['../_canopy_generator_8h.html#a6cdee9cb4984f78c818e46eb2a5b62e6',1,'getVariation(uint V, std::minstd_rand0 &generator): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#aa0b21a2d6b9506b33d05047716d671e0',1,'getVariation(float V, std::minstd_rand0 &generator, bool positive): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#a9f90ba8fe8a074a822424ff748579f25',1,'getVariation(int V, std::minstd_rand0 &generator, bool positive): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#a6cdee9cb4984f78c818e46eb2a5b62e6',1,'getVariation(uint V, std::minstd_rand0 &generator): CanopyGenerator.cpp']]], + ['getvertices_252',['getVertices',['../classhelios_1_1_tile.html#aaea21403039646db33792c95be929afd',1,'helios::Tile']]], + ['getvolume_253',['getVolume',['../classhelios_1_1_sphere.html#a3d6a8e9f8c0daee1e093593d6006c906',1,'helios::Sphere::getVolume()'],['../classhelios_1_1_tube.html#aaa11cc27d6f704a989c3e5b0fe1b8055',1,'helios::Tube::getVolume()'],['../classhelios_1_1_box.html#a3d3d0b20e22aff306fde02bd7e2a4f84',1,'helios::Box::getVolume()'],['../classhelios_1_1_polymesh.html#ad901c4de0e202f44c16fc9af29481538',1,'helios::Polymesh::getVolume()'],['../classhelios_1_1_cone.html#aff2cb2fc89c68b75a038a9604ce73cd0',1,'helios::Cone::getVolume()']]], + ['getvoxelcenter_254',['getVoxelCenter',['../classhelios_1_1_context.html#acadf5206cbfed7b8eaa2835702349cd9',1,'helios::Context']]], + ['getvoxelsize_255',['getVoxelSize',['../classhelios_1_1_context.html#a6a3f85d4f29f8f7432b6ef605172a1cb',1,'helios::Context']]], + ['getwindowpixelsrgb_256',['getWindowPixelsRGB',['../class_visualizer.html#a15828ea9966b9729b56c9ddfccd4c117',1,'Visualizer']]], + ['getwindowsize_257',['getWindowSize',['../class_visualizer.html#ae6b83402c798f56334851f77b898de52',1,'Visualizer']]], + ['gimp_258',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['girth_5farea_5ffactor_259',['girth_area_factor',['../_plant_architecture_doc.html#ShootParam_girth_area_factor',1,'']]], + ['git_20github_20integration_260',['Git/GitHub integration',['../_c_lion_i_d_e.html#CLionGit',1,'']]], + ['github_20integration_261',['Git/GitHub integration',['../_c_lion_i_d_e.html#CLionGit',1,'']]], + ['given_20in_20buckley_20turnbull_20and_20adams_202012_262',['Buckley, Mott, Farquhar (2003) Model (simplified version given in Buckley, Turnbull, and Adams 2012)',['../_stomatal_doc.html#BMFTheory',1,'']]], + ['global_20data_263',['Global Data',['../_a_p_i.html#GlobalData',1,'Global Data'],['../context_globaldata.html#context_globaldata_intro',1,'Introduction to Global Data'],['../context_globaldata.html',1,'Tutorial 6: Global Data']]], + ['global_20data_20arrays_264',['Creating Global Data (Arrays)',['../context_globaldata.html#context_globaldata_arrays',1,'']]], + ['global_20data_20scalars_265',['Creating Global Data (Scalars)',['../context_globaldata.html#context_globaldata_scalar',1,'']]], + ['global_2ecpp_266',['global.cpp',['../global_8cpp.html',1,'']]], + ['global_2eh_267',['global.h',['../global_8h.html',1,'']]], + ['globaldata_268',['GlobalData',['../structhelios_1_1_global_data.html',1,'helios']]], + ['glyph_269',['Glyph',['../class_glyph.html',1,'']]], + ['goblet_20trellis_270',['Grapevine Canopy with a Goblet Trellis',['../_canopy_generator_doc.html#CGenGoblet',1,'']]], + ['gobletgrapevineparameters_271',['GobletGrapevineParameters',['../struct_goblet_grapevine_parameters.html',1,'GobletGrapevineParameters'],['../struct_goblet_grapevine_parameters.html#a0274d6f6b1f13bbf7a383de5c2bc8726',1,'GobletGrapevineParameters::GobletGrapevineParameters()'],['../struct_goblet_grapevine_parameters.html#a498ce7f62d575b0bc914e9d48d94fbb2',1,'GobletGrapevineParameters::GobletGrapevineParameters(const pugi::xml_node canopy_node)']]], + ['gradientdescent_272',['GradientDescent',['../struct_camera_calibration.html#a5bfbb206b8271b406cda85eb5ae23a1b',1,'CameraCalibration']]], + ['gradientdescentparameters_273',['GradientDescentParameters',['../struct_camera_calibration_1_1_gradient_descent_parameters.html',1,'CameraCalibration']]], + ['grape_5fcolor_274',['grape_color',['../struct_base_grape_vine_parameters.html#ac90904eec34fa3e0dea393dd1c12faf6',1,'BaseGrapeVineParameters']]], + ['grape_5fradius_275',['grape_radius',['../struct_base_grape_vine_parameters.html#afa20674518acbb9fdfaafc893f362e01',1,'BaseGrapeVineParameters']]], + ['grape_5fradius_5fspread_276',['grape_radius_spread',['../struct_base_grape_vine_parameters.html#ace081969ad453ba66d60e394554d50b9',1,'BaseGrapeVineParameters']]], + ['grape_5fsubdivisions_277',['grape_subdivisions',['../struct_base_grape_vine_parameters.html#a510a2a5876fe8b3fb8ec70701c32df48',1,'BaseGrapeVineParameters']]], + ['grape_5fsubdivisions_5fspread_278',['grape_subdivisions_spread',['../struct_base_grape_vine_parameters.html#aa27b9934f658e9047462703e7d059d74',1,'BaseGrapeVineParameters']]], + ['grapevine_20canopy_20with_20a_20goblet_20trellis_279',['Grapevine Canopy with a Goblet Trellis',['../_canopy_generator_doc.html#CGenGoblet',1,'']]], + ['grapevine_20canopy_20with_20a_20split_20trellis_280',['Grapevine Canopy with a Split Trellis',['../_canopy_generator_doc.html#CGenSplit',1,'']]], + ['grapevine_20canopy_20with_20a_20unilateral_20vsp_20trellis_281',['Grapevine Canopy with a Unilateral VSP Trellis',['../_canopy_generator_doc.html#CGenUnilateral',1,'']]], + ['grapevine_20canopy_20with_20vsp_20trellis_282',['Grapevine Canopy with VSP Trellis',['../_canopy_generator_doc.html#CGenVSP',1,'']]], + ['grapevine_2ecpp_283',['grapevine.cpp',['../grapevine_8cpp.html',1,'']]], + ['grapevinegoblet_284',['grapevineGoblet',['../class_canopy_generator.html#a8f2d498637c464ee852109e6085cde8a',1,'CanopyGenerator']]], + ['grapevinesplit_285',['grapevineSplit',['../class_canopy_generator.html#a8747bad1af97214059c38043241f0b47',1,'CanopyGenerator']]], + ['grapevineunilateral_286',['grapevineUnilateral',['../class_canopy_generator.html#aac9104d7c6565e860737310de06981f8',1,'CanopyGenerator']]], + ['grapevinevsp_287',['grapevineVSP',['../class_canopy_generator.html#aaffe5cdb82a779785bc6d5e35e622812',1,'CanopyGenerator']]], + ['graphics_20driver_20timeout_288',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], + ['gravitropic_5fcurvature_289',['gravitropic_curvature',['../_plant_architecture_doc.html#ShootParam_gravitropic',1,'']]], + ['grid_20cell_290',['Calculating leaf area for each grid cell',['../_li_d_a_r_doc.html#LiDARleafarea',1,'']]], + ['grid_20cells_291',['grid cells',['../_aerial_li_d_a_r_doc.html#AerialLiDARgrid',1,'Establishing grid cells'],['../_li_d_a_r_doc.html#LiDARgrid',1,'Establishing grid cells']]], + ['gridcell_292',['GridCell',['../struct_grid_cell.html',1,'']]], + ['gridijk2index_293',['gridijk2index',['../class_aerial_li_d_a_rcloud.html#a35c81e8cda423b84c94fc33ee4163d47',1,'AerialLiDARcloud']]], + ['gridindex2ijk_294',['gridindex2ijk',['../class_aerial_li_d_a_rcloud.html#add78af9b69161c5c532a23c8df009d2e',1,'AerialLiDARcloud']]], + ['ground_295',['Building the Ground',['../_canopy_generator_doc.html#CGenBuildGround',1,'']]], + ['ground_296',['4. Flow over bare ground',['../_b_l_conductance_doc.html#BLC4',1,'']]], + ['ground_20area_20basis_297',['4b. Calculate radiation flux absorbed by the canopy on a ground area basis',['../radiation__beers_law.html#tutorial11_abs',1,'']]], + ['ground_20collision_20detection_298',['Ground Collision Detection',['../_plant_architecture_doc.html#PlantArchCollision',1,'']]], + ['ground_20cover_20fraction_299',['2D raster ground cover fraction',['../_aerial_li_d_a_r_doc.html#AerialGroundCover',1,'']]], + ['growing_20the_20model_20over_20time_300',['Growing the Model over Time',['../_plant_architecture_doc.html#PlantArchGrowth',1,'']]], + ['growth_20parameters_20of_20the_20shoot_301',['Growth Parameters of the Shoot',['../_plant_architecture_doc.html#ShootParametersGrowth',1,'']]], + ['growth_20phenology_302',['Growth Phenology',['../_plant_architecture_doc.html#PlantArchPheno',1,'']]], + ['guide_303',['User/API Guide',['../_a_p_i.html',1,'']]] ]; diff --git a/doc/html/search/functions_15.js b/doc/html/search/functions_15.js index 93f697955..9217ac2c2 100644 --- a/doc/html/search/functions_15.js +++ b/doc/html/search/functions_15.js @@ -18,11 +18,12 @@ var searchData= ['writenormdepthimage_15',['writeNormDepthImage',['../class_radiation_model.html#a633d84a823ad4cd99495a06afc13d7a3',1,'RadiationModel']]], ['writeobj_16',['writeOBJ',['../classhelios_1_1_context.html#a8249b03fa781c9382863b7cf2caf0dd8',1,'helios::Context::writeOBJ(const std::string &filename) const'],['../classhelios_1_1_context.html#a8a5040ff4aaa061eddabe881ac668a01',1,'helios::Context::writeOBJ(const std::string &filename, const std::vector< uint > &UUIDs) const'],['../classhelios_1_1_context.html#ae976f6626930c925c8fdacb543e1e923',1,'helios::Context::writeOBJ(const std::string &filename, const std::vector< uint > &UUIDs, const std::vector< std::string > &primitive_dat_fields) const']]], ['writeobjectdatalabelmap_17',['writeObjectDataLabelMap',['../class_radiation_model.html#afdbe940b3c4ae5855a0fcbe5b0b7f708',1,'RadiationModel']]], - ['writeply_18',['writePLY',['../classhelios_1_1_context.html#aa47b8b6f8cefb3c9d55a3cda10d851d7',1,'helios::Context']]], - ['writepng_19',['writePNG',['../global_8h.html#afc2520441ef9a290c5221dd892ea9f01',1,'helios']]], - ['writeprimitivedata_20',['writePrimitiveData',['../classhelios_1_1_context.html#ab643fc787ea7b1a215605c369f446844',1,'helios::Context::writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, bool print_header=false) const'],['../classhelios_1_1_context.html#a97378b12bfaf42c2052960c54ff096d4',1,'helios::Context::writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, const std::vector< uint > &UUIDs, bool print_header=false) const']]], - ['writeprimitivedatalabelmap_21',['writePrimitiveDataLabelMap',['../class_radiation_model.html#a771c53fe19d75303c3f60017db8a2b50',1,'RadiationModel']]], - ['writespectralxmlfile_22',['writeSpectralXMLfile',['../struct_camera_calibration.html#a96b8a246adb36d20a09e3d527be9de25',1,'CameraCalibration']]], - ['writexml_23',['writeXML',['../classhelios_1_1_context.html#abfcac5a56c13e86298609ed3fccf354d',1,'helios::Context::writeXML(const char *filename, bool quiet=false) const'],['../classhelios_1_1_context.html#a499545512efe3645e2085e4815dcb94e',1,'helios::Context::writeXML(const char *filename, const std::vector< uint > &UUIDs, bool quiet=false) const']]], - ['writexml_5fbyobject_24',['writeXML_byobject',['../classhelios_1_1_context.html#ae2ada2bfdce5226cd970a6e6fa0ccc88',1,'helios::Context']]] + ['writeplantmeshvertices_18',['writePlantMeshVertices',['../class_plant_architecture.html#a1314accedeb4c376ee8283aa05c811c5',1,'PlantArchitecture']]], + ['writeply_19',['writePLY',['../classhelios_1_1_context.html#aa47b8b6f8cefb3c9d55a3cda10d851d7',1,'helios::Context']]], + ['writepng_20',['writePNG',['../global_8h.html#afc2520441ef9a290c5221dd892ea9f01',1,'helios']]], + ['writeprimitivedata_21',['writePrimitiveData',['../classhelios_1_1_context.html#ab643fc787ea7b1a215605c369f446844',1,'helios::Context::writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, bool print_header=false) const'],['../classhelios_1_1_context.html#a97378b12bfaf42c2052960c54ff096d4',1,'helios::Context::writePrimitiveData(std::string filename, const std::vector< std::string > &column_format, const std::vector< uint > &UUIDs, bool print_header=false) const']]], + ['writeprimitivedatalabelmap_22',['writePrimitiveDataLabelMap',['../class_radiation_model.html#a771c53fe19d75303c3f60017db8a2b50',1,'RadiationModel']]], + ['writespectralxmlfile_23',['writeSpectralXMLfile',['../struct_camera_calibration.html#a96b8a246adb36d20a09e3d527be9de25',1,'CameraCalibration']]], + ['writexml_24',['writeXML',['../classhelios_1_1_context.html#abfcac5a56c13e86298609ed3fccf354d',1,'helios::Context::writeXML(const char *filename, bool quiet=false) const'],['../classhelios_1_1_context.html#a499545512efe3645e2085e4815dcb94e',1,'helios::Context::writeXML(const char *filename, const std::vector< uint > &UUIDs, bool quiet=false) const']]], + ['writexml_5fbyobject_25',['writeXML_byobject',['../classhelios_1_1_context.html#ae2ada2bfdce5226cd970a6e6fa0ccc88',1,'helios::Context']]] ]; diff --git a/doc/html/search/functions_4.js b/doc/html/search/functions_4.js index 61dbd3763..59b1d3edb 100644 --- a/doc/html/search/functions_4.js +++ b/doc/html/search/functions_4.js @@ -22,6 +22,7 @@ var searchData= ['exportpointcloud_19',['exportPointCloud',['../class_aerial_li_d_a_rcloud.html#a7f0992570b8535f687fd7067eb9f3593',1,'AerialLiDARcloud::exportPointCloud()'],['../class_li_d_a_rcloud.html#a2d0c11c6d8001171269232ff5d7f6322',1,'LiDARcloud::exportPointCloud(const char *filename)'],['../class_li_d_a_rcloud.html#ae9910fa1aae6b8b077d57417c130e753',1,'LiDARcloud::exportPointCloud(const char *filename, uint scanID)']]], ['exportpointcloudptx_20',['exportPointCloudPTX',['../class_li_d_a_rcloud.html#ac48fe9018f26664dd9abd8c100fccaa6',1,'LiDARcloud']]], ['exporttriangleareas_21',['exportTriangleAreas',['../class_li_d_a_rcloud.html#a416638f486c4fd2572a9589b69605fe7',1,'LiDARcloud::exportTriangleAreas(const char *filename)'],['../class_li_d_a_rcloud.html#adb93e3a16abc8100b2e5dac956c6cc3e',1,'LiDARcloud::exportTriangleAreas(const char *filename, int gridcell)']]], - ['exporttriangleinclinationdistribution_22',['exportTriangleInclinationDistribution',['../class_li_d_a_rcloud.html#aadeb8297b74a75fd003f6c96fe378043',1,'LiDARcloud']]], - ['exporttrianglenormals_23',['exportTriangleNormals',['../class_li_d_a_rcloud.html#ad030fdddcfa669d6af513eb66a9cbd1a',1,'LiDARcloud::exportTriangleNormals(const char *filename)'],['../class_li_d_a_rcloud.html#aa8376ce652d2e95e886d4d60d321c274',1,'LiDARcloud::exportTriangleNormals(const char *filename, int gridcell)']]] + ['exporttriangleazimuthdistribution_22',['exportTriangleAzimuthDistribution',['../class_li_d_a_rcloud.html#ab9a33b5d05470e8e0362de352fc09bf1',1,'LiDARcloud']]], + ['exporttriangleinclinationdistribution_23',['exportTriangleInclinationDistribution',['../class_li_d_a_rcloud.html#aadeb8297b74a75fd003f6c96fe378043',1,'LiDARcloud']]], + ['exporttrianglenormals_24',['exportTriangleNormals',['../class_li_d_a_rcloud.html#ad030fdddcfa669d6af513eb66a9cbd1a',1,'LiDARcloud::exportTriangleNormals(const char *filename)'],['../class_li_d_a_rcloud.html#aa8376ce652d2e95e886d4d60d321c274',1,'LiDARcloud::exportTriangleNormals(const char *filename, int gridcell)']]] ]; diff --git a/doc/html/search/functions_6.js b/doc/html/search/functions_6.js index a4f97d58a..a44ad4cd8 100644 --- a/doc/html/search/functions_6.js +++ b/doc/html/search/functions_6.js @@ -10,229 +10,234 @@ var searchData= ['getallobjectids_7',['getAllObjectIDs',['../classhelios_1_1_context.html#a2ef355a3298b21313700acec64232e22',1,'helios::Context::getAllObjectIDs()'],['../class_plant_architecture.html#a9069b1d637752f0a74ded148ae1706b0',1,'PlantArchitecture::getAllObjectIDs() const']]], ['getallpeduncleuuids_8',['getAllPeduncleUUIDs',['../class_plant_architecture.html#ad46693fc275721338c8f24cb764b2bf1',1,'PlantArchitecture']]], ['getallpetioleuuids_9',['getAllPetioleUUIDs',['../class_plant_architecture.html#afd1c00e6b5b6aa45e212aeb6b68cb825',1,'PlantArchitecture']]], - ['getallplantobjectids_10',['getAllPlantObjectIDs',['../class_plant_architecture.html#acf9855048c790d30d8d4de7fa1dc3550',1,'PlantArchitecture']]], - ['getallplantuuids_11',['getAllPlantUUIDs',['../class_plant_architecture.html#a3bdffb4e53fe0da836a40de80946d31f',1,'PlantArchitecture']]], - ['getalluuids_12',['getAllUUIDs',['../classhelios_1_1_context.html#a98516632daccf958cca6b5b6582310bb',1,'helios::Context::getAllUUIDs()'],['../class_canopy_generator.html#a8e395619077d656e206f4159f0bf8d34',1,'CanopyGenerator::getAllUUIDs()'],['../class_plant_architecture.html#afec06c56ae296984727c90413511cf6a',1,'PlantArchitecture::getAllUUIDs()'],['../class_weber_penn_tree.html#a19e16f9a51493680afebc38f3c434400',1,'WeberPennTree::getAllUUIDs()']]], - ['getambientlongwaveflux_13',['getAmbientLongwaveFlux',['../class_solar_position.html#a30ee555eedece8b7e19855877a74da71',1,'SolarPosition']]], - ['getarea_14',['getArea',['../classhelios_1_1_compound_object.html#a8bb518f6166e2a2831a68a7626787ac1',1,'helios::CompoundObject']]], - ['getaxisunitvector_15',['getAxisUnitVector',['../classhelios_1_1_cone.html#a60fc92fbb15149017956449123c0e4d0',1,'helios::Cone']]], - ['getbmfcoefficientsfromlibrary_16',['getBMFCoefficientsFromLibrary',['../class_stomatal_conductance_model.html#ada09940a1cc67dbfc0192f6e0a50c967',1,'StomatalConductanceModel']]], - ['getboxobjectcenter_17',['getBoxObjectCenter',['../classhelios_1_1_context.html#af73c44dace71ec805136b7d6ad6095a9',1,'helios::Context']]], - ['getboxobjectpointer_18',['getBoxObjectPointer',['../classhelios_1_1_context.html#a1ecbb5a8cfa6764bade6e0650d2f6990',1,'helios::Context']]], - ['getboxobjectsize_19',['getBoxObjectSize',['../classhelios_1_1_context.html#a4e5799ba4b6a0a889f446bef9e4d3dc0',1,'helios::Context']]], - ['getboxobjectsubdivisioncount_20',['getBoxObjectSubdivisionCount',['../classhelios_1_1_context.html#a258f524d38cdeb5f6c83a7f387608490',1,'helios::Context']]], - ['getboxobjectvolume_21',['getBoxObjectVolume',['../classhelios_1_1_context.html#ae31cc8855aacb6380a288a4b7fa8db82',1,'helios::Context']]], - ['getbranchuuids_22',['getBranchUUIDs',['../class_canopy_generator.html#ab7115aaa287346b9c8e7854bd66f8b5f',1,'CanopyGenerator::getBranchUUIDs(uint PlantID)'],['../class_canopy_generator.html#a7db6f05ab623b77de4e8a81dc132e914',1,'CanopyGenerator::getBranchUUIDs()'],['../class_weber_penn_tree.html#a813cb8959272b535050dc97aa49d3ed3',1,'WeberPennTree::getBranchUUIDs()']]], - ['getcameralookat_23',['getCameraLookat',['../class_radiation_model.html#a68c8736e58c7daf440ff9c93bb00522d',1,'RadiationModel']]], - ['getcameraorientation_24',['getCameraOrientation',['../class_radiation_model.html#a0b67b056aa1f2b5e6c42a06e358f4eb8',1,'RadiationModel']]], - ['getcameraposition_25',['getCameraPosition',['../class_radiation_model.html#a6785deae272a9464920030fc3f124bc3',1,'RadiationModel']]], - ['getcameraresponsescale_26',['getCameraResponseScale',['../struct_camera_calibration.html#a18eff4a7ecab1038f27b68c3963a5513',1,'CameraCalibration::getCameraResponseScale()'],['../class_radiation_model.html#adb5a74547d51a18018d3daeba0ec5f3c',1,'RadiationModel::getCameraResponseScale()']]], - ['getcellcenter_27',['getCellCenter',['../class_aerial_li_d_a_rcloud.html#a6e83c157d63d12253af3b81b995e1a33',1,'AerialLiDARcloud::getCellCenter()'],['../class_li_d_a_rcloud.html#a6e2ce01abb33cc0f80b2aa653ac6a445',1,'LiDARcloud::getCellCenter()']]], - ['getcellcoverfraction_28',['getCellCoverFraction',['../class_aerial_li_d_a_rcloud.html#ac714e2231b63d1455237662661590b16',1,'AerialLiDARcloud']]], - ['getcellglobalanchor_29',['getCellGlobalAnchor',['../class_li_d_a_rcloud.html#ad1ad4f851b5b7fcbf5b088b161aed83e',1,'LiDARcloud']]], - ['getcellgroundheight_30',['getCellGroundHeight',['../class_aerial_li_d_a_rcloud.html#a3b9d9ac013a041c30d58e68e5dc92bee',1,'AerialLiDARcloud']]], - ['getcellgtheta_31',['getCellGtheta',['../class_li_d_a_rcloud.html#a54351e18e3f4155e9d55eb02bd63c722',1,'LiDARcloud']]], - ['getcellleafarea_32',['getCellLeafArea',['../class_aerial_li_d_a_rcloud.html#a9f90891b20b8996e983e66640684b6cc',1,'AerialLiDARcloud::getCellLeafArea()'],['../class_li_d_a_rcloud.html#ac9d20a35bdb7ee2d45490ac1cd520117',1,'LiDARcloud::getCellLeafArea()']]], - ['getcellleafareadensity_33',['getCellLeafAreaDensity',['../class_aerial_li_d_a_rcloud.html#a4ca0903b642daffdff27e69a172c96b5',1,'AerialLiDARcloud::getCellLeafAreaDensity()'],['../class_li_d_a_rcloud.html#a3c1744984481f9629dc1371291fa397e',1,'LiDARcloud::getCellLeafAreaDensity()']]], - ['getcellmaximumhitheight_34',['getCellMaximumHitHeight',['../class_aerial_li_d_a_rcloud.html#a00f6479153ac2025031b70bd5637b65b',1,'AerialLiDARcloud']]], - ['getcellprimitives_35',['getCellPrimitives',['../class_voxel_intersection.html#a7d50123db71cf5cd7c7cc4582abd5cb2',1,'VoxelIntersection']]], - ['getcellrbar_36',['getCellRbar',['../class_aerial_li_d_a_rcloud.html#ae35261c7fc1553cb15fb318a2b14a3b2',1,'AerialLiDARcloud']]], - ['getcellrotation_37',['getCellRotation',['../class_li_d_a_rcloud.html#aa2cba1d0bcd9a2ae35d9a5be03832efc',1,'LiDARcloud']]], - ['getcellsize_38',['getCellSize',['../class_aerial_li_d_a_rcloud.html#a5bf5379ee229ebb51fdc8195af8cf3e7',1,'AerialLiDARcloud::getCellSize()'],['../class_li_d_a_rcloud.html#a6662330b95ee7ee77ea6647871695c55',1,'LiDARcloud::getCellSize()']]], - ['getcelltransmissionprobability_39',['getCellTransmissionProbability',['../class_aerial_li_d_a_rcloud.html#a98770b70c510e7611fb171d3fe920554',1,'AerialLiDARcloud']]], - ['getcellvegetationheight_40',['getCellVegetationHeight',['../class_aerial_li_d_a_rcloud.html#a12fe426a267cbef9982138537198558a',1,'AerialLiDARcloud']]], - ['getcenter_41',['getCenter',['../classhelios_1_1_tile.html#a18178d0280f8ecc1149663558947ca06',1,'helios::Tile::getCenter()'],['../classhelios_1_1_sphere.html#a48eada17c3dab899a91158f1424518d6',1,'helios::Sphere::getCenter()'],['../classhelios_1_1_box.html#a96e72a40ff113d6a6b463fe8c60b672a',1,'helios::Box::getCenter()'],['../classhelios_1_1_disk.html#ae8ed884a95cbfa2440e3bd9f8e3e4057',1,'helios::Disk::getCenter()']]], - ['getconeobjectaxisunitvector_42',['getConeObjectAxisUnitVector',['../classhelios_1_1_context.html#acaa3fb162b17cb7f912162f5d4be894e',1,'helios::Context']]], - ['getconeobjectlength_43',['getConeObjectLength',['../classhelios_1_1_context.html#ad2b045f361aa8e8596bcf325c1707a25',1,'helios::Context']]], - ['getconeobjectnode_44',['getConeObjectNode',['../classhelios_1_1_context.html#a54e9f0b7c5014a37cd9d5bf74e7d5935',1,'helios::Context']]], - ['getconeobjectnoderadii_45',['getConeObjectNodeRadii',['../classhelios_1_1_context.html#ade2608274b311c809d46bb13943b9e4e',1,'helios::Context']]], - ['getconeobjectnoderadius_46',['getConeObjectNodeRadius',['../classhelios_1_1_context.html#af5acc5647e6bf9cd1649da1dec677110',1,'helios::Context']]], - ['getconeobjectnodes_47',['getConeObjectNodes',['../classhelios_1_1_context.html#a8c4ec2d90ccd3d44a97597ecd80d78b6',1,'helios::Context']]], - ['getconeobjectpointer_48',['getConeObjectPointer',['../classhelios_1_1_context.html#a3221051ea9c1025e8fb00d9dec01839f',1,'helios::Context']]], - ['getconeobjectsubdivisioncount_49',['getConeObjectSubdivisionCount',['../classhelios_1_1_context.html#a1ff97eb95d5896e096156320f5bd5ff0',1,'helios::Context']]], - ['getconeobjectvolume_50',['getConeObjectVolume',['../classhelios_1_1_context.html#af6c1c571171be2604822a8df44d2349c',1,'helios::Context']]], - ['getcurrentcolormap_51',['getCurrentColormap',['../class_visualizer.html#ae2bba6102a283a31ec4f5780817a15da',1,'Visualizer']]], - ['getcurrentphytomerparameters_52',['getCurrentPhytomerParameters',['../class_plant_architecture.html#aaba5ecb6c069be56b3706a4060f5ff49',1,'PlantArchitecture']]], - ['getcurrentshootparameters_53',['getCurrentShootParameters',['../class_plant_architecture.html#aa696281e805e8879a78dacdf4354ff38',1,'PlantArchitecture::getCurrentShootParameters(const std::string &shoot_type_label)'],['../class_plant_architecture.html#a190d91f02c5cfcfad036879460b2e495',1,'PlantArchitecture::getCurrentShootParameters()']]], - ['getdate_54',['getDate',['../classhelios_1_1_context.html#a95dd5bc221cd8bcb4efabd0122d59b4f',1,'helios::Context']]], - ['getdepthmap_55',['getDepthMap',['../class_visualizer.html#a7c6362d7dc0f0bd4bba53195ce92b84e',1,'Visualizer']]], - ['getdiffuseflux_56',['getDiffuseFlux',['../class_radiation_model.html#af8450f2308aee38272b4aef87f0c547b',1,'RadiationModel']]], - ['getdiffusefraction_57',['getDiffuseFraction',['../class_solar_position.html#af8dbd15453ce775dab5b2c5a49b1c93b',1,'SolarPosition']]], - ['getdiskobjectcenter_58',['getDiskObjectCenter',['../classhelios_1_1_context.html#a213aea1539e0bb38965cf2953b1831df',1,'helios::Context']]], - ['getdiskobjectpointer_59',['getDiskObjectPointer',['../classhelios_1_1_context.html#a17c1256a1f57fbae1f34e04b66b76ca8',1,'helios::Context']]], - ['getdiskobjectsize_60',['getDiskObjectSize',['../classhelios_1_1_context.html#acee51918d3ee1d9892e5a51106a625d9',1,'helios::Context']]], - ['getdiskobjectsubdivisioncount_61',['getDiskObjectSubdivisionCount',['../classhelios_1_1_context.html#a86ffc9a6cdcd3851231c64dcc152123c',1,'helios::Context']]], - ['getdomainboundingbox_62',['getDomainBoundingBox',['../classhelios_1_1_context.html#a8690412a63d1eff69e679e48d03c9838',1,'helios::Context::getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const'],['../classhelios_1_1_context.html#ad4ac166bb01547d1cefb1ace7a9b966d',1,'helios::Context::getDomainBoundingBox(const std::vector< uint > &UUIDs, helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const'],['../class_visualizer.html#ae9c98dee278e9bcd5f85b871ff8ddfe5',1,'Visualizer::getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const']]], - ['getdomainboundingradius_63',['getDomainBoundingRadius',['../class_visualizer.html#a783739e072baeafc943a077dcb1cc3d5',1,'Visualizer']]], - ['getdomainboundingsphere_64',['getDomainBoundingSphere',['../classhelios_1_1_context.html#a3a6b0d25c5d9febb17787982c9f09d63',1,'helios::Context::getDomainBoundingSphere(helios::vec3 &center, float &radius) const'],['../classhelios_1_1_context.html#af3e048e969f06e3a0cf36ed3d76766ca',1,'helios::Context::getDomainBoundingSphere(const std::vector< uint > &UUIDs, helios::vec3 &center, float &radius) const']]], - ['getempiricalmodelcoefficients_65',['getEmpiricalModelCoefficients',['../class_photosynthesis_model.html#a86094d579852c2dc846acc2a97e6ac44',1,'PhotosynthesisModel']]], - ['getfarquharcoefficientsfromlibrary_66',['getFarquharCoefficientsFromLibrary',['../class_photosynthesis_model.html#ae40570ef642d5d4dc070dce9ba093f16',1,'PhotosynthesisModel']]], - ['getfarquharmodelcoefficients_67',['getFarquharModelCoefficients',['../class_photosynthesis_model.html#aeab92cd73298c5f89626b30ce8c41cf9',1,'PhotosynthesisModel']]], - ['getfileextension_68',['getFileExtension',['../global_8h.html#a58e660bb08e1ce13466825ae666467ef',1,'helios']]], - ['getfilename_69',['getFileName',['../global_8h.html#a63bd49091fdab0e262b051f61fb9a902',1,'helios']]], - ['getfilepath_70',['getFilePath',['../global_8h.html#ad76f15d03b511d1bf5123d64d804d6e8',1,'helios']]], - ['getfilestem_71',['getFileStem',['../global_8h.html#a9fff8cb6c3474de479f81c12f173d3ed',1,'helios']]], - ['getframebuffersize_72',['getFramebufferSize',['../class_visualizer.html#ab3b0261a21e7f552d55e4d2fda55f94f',1,'Visualizer']]], - ['getfruituuids_73',['getFruitUUIDs',['../class_canopy_generator.html#a8ab509f22c4bdffd57b44f67f43ce728',1,'CanopyGenerator::getFruitUUIDs(uint PlantID)'],['../class_canopy_generator.html#abdcc431929f98e57db4b9ed2dc26a616',1,'CanopyGenerator::getFruitUUIDs()']]], - ['getglobaldata_74',['getGlobalData',['../classhelios_1_1_context.html#a972fa4a45b2775f6047d41b88dc69d03',1,'helios::Context::getGlobalData(const char *label, int &data) const'],['../classhelios_1_1_context.html#a175d9a1955f428b0f2d6b11ab3b17659',1,'helios::Context::getGlobalData(const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#a98cbb0d37dc9fafaad14184cb889534f',1,'helios::Context::getGlobalData(const char *label, uint &data) const'],['../classhelios_1_1_context.html#a931a92ba7e9916c64d164bc1f29ff754',1,'helios::Context::getGlobalData(const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#ac1f5f6c3f24577cd5c4657c441483425',1,'helios::Context::getGlobalData(const char *label, float &data) const'],['../classhelios_1_1_context.html#a863264ab1339ba35c3754bfbf4c69eec',1,'helios::Context::getGlobalData(const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#a8ec49c820f10831b4b27059d4d1749d6',1,'helios::Context::getGlobalData(const char *label, double &data) const'],['../classhelios_1_1_context.html#a66e7d689b62d9ad47fb85ad45664c97f',1,'helios::Context::getGlobalData(const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#a6f4d6971c05d78aff30b92d277014b9f',1,'helios::Context::getGlobalData(const char *label, helios::vec2 &data) const'],['../classhelios_1_1_context.html#afc90a3d0143273e436541fc3bc9c5554',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec2 > &data) const'],['../classhelios_1_1_context.html#a990fdccf51979e235a1acba08e54583b',1,'helios::Context::getGlobalData(const char *label, helios::vec3 &data) const'],['../classhelios_1_1_context.html#a0376e2dc456e481bd055d5a84b7785f2',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec3 > &data) const'],['../classhelios_1_1_context.html#a3f621b536c3585d7f808698e2f0cd826',1,'helios::Context::getGlobalData(const char *label, helios::vec4 &data) const'],['../classhelios_1_1_context.html#ab0f329c8584b002dda2d77719073bf5d',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec4 > &data) const'],['../classhelios_1_1_context.html#aea16d4845e23fe44ae1da4c032ea57e3',1,'helios::Context::getGlobalData(const char *label, helios::int2 &data) const'],['../classhelios_1_1_context.html#a609563835616233b15fd263bb2e8857d',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int2 > &data) const'],['../classhelios_1_1_context.html#aba7c4fe63193509f40ca6682cddfa9a3',1,'helios::Context::getGlobalData(const char *label, helios::int3 &data) const'],['../classhelios_1_1_context.html#abbc6d463f6d722fca56ad219c8278c16',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int3 > &data) const'],['../classhelios_1_1_context.html#a2b2f0570e50711f34bb24dc01c8a7b43',1,'helios::Context::getGlobalData(const char *label, helios::int4 &data) const'],['../classhelios_1_1_context.html#ad08d9d2bea2c93b14ae2b3678aea2e29',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int4 > &data) const'],['../classhelios_1_1_context.html#a890583b0897bfcd730d137838fa7e155',1,'helios::Context::getGlobalData(const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a0572c1557ec60ae7389072e8ab3c2113',1,'helios::Context::getGlobalData(const char *label, std::vector< std::string > &data) const']]], - ['getglobaldatasize_75',['getGlobalDataSize',['../classhelios_1_1_context.html#a96d1060d1329dc467380ce2e5eafd559',1,'helios::Context']]], - ['getglobaldatatype_76',['getGlobalDataType',['../classhelios_1_1_context.html#a94bf0b919e5e6034fa45fbae2f575947',1,'helios::Context']]], - ['getgridboundingbox_77',['getGridBoundingBox',['../class_li_d_a_rcloud.html#a041ac4ba388c407a35b7f895029038e6',1,'LiDARcloud']]], - ['getgridcellcount_78',['getGridCellCount',['../class_li_d_a_rcloud.html#a28297a71becd69b30820d69b110fcc90',1,'LiDARcloud']]], - ['getgridcenter_79',['getGridCenter',['../class_aerial_li_d_a_rcloud.html#ad639b0d2337b74b1bd4949cc2aba88e0',1,'AerialLiDARcloud']]], - ['getgridextent_80',['getGridExtent',['../class_aerial_li_d_a_rcloud.html#a85ea1ea67ed12f2bbcfc28ef9a78dd77',1,'AerialLiDARcloud']]], - ['getgridresolution_81',['getGridResolution',['../class_aerial_li_d_a_rcloud.html#ae750e548d565d6305e600c5af8360fdb',1,'AerialLiDARcloud']]], - ['getgridrotation_82',['getGridRotation',['../class_aerial_li_d_a_rcloud.html#aace3b3baae4a75be461eb31f617ee695',1,'AerialLiDARcloud']]], - ['getgrounduuids_83',['getGroundUUIDs',['../class_canopy_generator.html#a6f0003d6ca29cbb56657442c7a48ad14',1,'CanopyGenerator']]], - ['gethitboundingbox_84',['getHitBoundingBox',['../class_aerial_li_d_a_rcloud.html#a74b0e833ecb6ee1b3ce3010f3d38d74d',1,'AerialLiDARcloud::getHitBoundingBox()'],['../class_li_d_a_rcloud.html#a45bc37a4d26eb74a944c594a7f3cb54b',1,'LiDARcloud::getHitBoundingBox()']]], - ['gethitcolor_85',['getHitColor',['../class_aerial_li_d_a_rcloud.html#af8f49444eb1d166837c322d03ea1cbfa',1,'AerialLiDARcloud::getHitColor()'],['../class_li_d_a_rcloud.html#aafafed9102966992d3cfb3772fa2ada1',1,'LiDARcloud::getHitColor()']]], - ['gethitcount_86',['getHitCount',['../class_aerial_li_d_a_rcloud.html#aaf287ef121543f10e9e73579bf77281a',1,'AerialLiDARcloud::getHitCount()'],['../class_li_d_a_rcloud.html#a691fd3bbd1262d80e10a674c82c6f568',1,'LiDARcloud::getHitCount()']]], - ['gethitdata_87',['getHitData',['../class_aerial_li_d_a_rcloud.html#a240af79b825bc886e886ff7ff0e0476c',1,'AerialLiDARcloud::getHitData()'],['../class_li_d_a_rcloud.html#a274ef68850afa3f288bb648d9fd6a59a',1,'LiDARcloud::getHitData()']]], - ['gethitgridcell_88',['getHitGridCell',['../class_aerial_li_d_a_rcloud.html#a26bc32e67d3195222f11fb72fb7d63da',1,'AerialLiDARcloud::getHitGridCell()'],['../class_li_d_a_rcloud.html#a251c4f3bbefdd07212cd8fe1037dc0d7',1,'LiDARcloud::getHitGridCell(uint index) const']]], - ['gethitindex_89',['getHitIndex',['../class_li_d_a_rcloud.html#a34eee980f365fdd5469a0cc6ee3a36f5',1,'LiDARcloud']]], - ['gethitraydir_90',['getHitRaydir',['../class_aerial_li_d_a_rcloud.html#ac0f8ba05e24d146d01ee2af0fb9ece7d',1,'AerialLiDARcloud::getHitRaydir()'],['../class_li_d_a_rcloud.html#aa91258bd97d6fcacd3313d8b55cceed4',1,'LiDARcloud::getHitRaydir()']]], - ['gethitscanid_91',['getHitScanID',['../class_aerial_li_d_a_rcloud.html#aaa2bbd15dad66355175fb733630456a4',1,'AerialLiDARcloud::getHitScanID()'],['../class_li_d_a_rcloud.html#a5510b2a0d0a878930e9f11331494bf41',1,'LiDARcloud::getHitScanID()']]], - ['gethitxyz_92',['getHitXYZ',['../class_aerial_li_d_a_rcloud.html#a3363ac3ffff1bbdd164b6074010d75ba',1,'AerialLiDARcloud::getHitXYZ()'],['../class_li_d_a_rcloud.html#ac5f234b6200419f10fe82c9abe409cbd',1,'LiDARcloud::getHitXYZ()']]], - ['getimageresolution_93',['getImageResolution',['../classhelios_1_1_texture.html#a4e106c0c80f0c4c065e5ff71193aaeab',1,'helios::Texture']]], - ['getimageresolutionjpeg_94',['getImageResolutionJPEG',['../global_8h.html#a94c80cbffdccaea7991b439acf8e9eb4',1,'helios']]], - ['getjuliandate_95',['getJulianDate',['../classhelios_1_1_context.html#a23f2611ed71eeefe8cf772cab98de4d4',1,'helios::Context']]], - ['getleafspectra_96',['getLeafSpectra',['../class_leaf_optics.html#a6b9fa9b6fb34fe7738e425b19118005a',1,'LeafOptics']]], - ['getleafuuids_97',['getLeafUUIDs',['../class_canopy_generator.html#a3509012720b5fd256a14bc2924a3b164',1,'CanopyGenerator::getLeafUUIDs(uint PlantID)'],['../class_canopy_generator.html#a73680976a2826f0b5dbf567551fd5593',1,'CanopyGenerator::getLeafUUIDs()'],['../class_weber_penn_tree.html#af4368c1f900503f6d72f0c0e569fe8e5',1,'WeberPennTree::getLeafUUIDs()']]], - ['getlength_98',['getLength',['../classhelios_1_1_tube.html#ad3c194a0f9977e212ac425aefe4032bf',1,'helios::Tube::getLength()'],['../classhelios_1_1_cone.html#ada36b3fe4850f16c4dfa58c38a8da80c',1,'helios::Cone::getLength()']]], - ['getloadedxmlfiles_99',['getLoadedXMLFiles',['../classhelios_1_1_context.html#a48a8a843b99c36ad357dba13ee6f1774',1,'helios::Context']]], - ['getlocation_100',['getLocation',['../classhelios_1_1_context.html#af4b1fa52419259a0c8a2faeb7484a439',1,'helios::Context']]], - ['getmonthstring_101',['getMonthString',['../classhelios_1_1_context.html#a6189f6ab35669f4fefde571ec362247c',1,'helios::Context']]], - ['getnodecolors_102',['getNodeColors',['../classhelios_1_1_tube.html#aae753418cb304e97c296240dc9919388',1,'helios::Tube']]], - ['getnodecoordinate_103',['getNodeCoordinate',['../classhelios_1_1_cone.html#a4f6ddd7fd23d61528ada9df1e333ad17',1,'helios::Cone']]], - ['getnodecoordinates_104',['getNodeCoordinates',['../classhelios_1_1_cone.html#a9eaab4331e325c85ce9f4c101135c966',1,'helios::Cone']]], - ['getnoderadii_105',['getNodeRadii',['../classhelios_1_1_tube.html#a29823b956371d22b35add97fc6831cab',1,'helios::Tube::getNodeRadii()'],['../classhelios_1_1_cone.html#adc5370734810e4b526bf0d42e143ecf8',1,'helios::Cone::getNodeRadii() const']]], - ['getnoderadius_106',['getNodeRadius',['../classhelios_1_1_cone.html#a2334ca87f6bb556b411c8a51476b523c',1,'helios::Cone']]], - ['getnodes_107',['getNodes',['../classhelios_1_1_tube.html#ab55e8f7d7a948941027f169d714e365b',1,'helios::Tube']]], - ['getnormal_108',['getNormal',['../classhelios_1_1_tile.html#ab8c70daf8c14bc60caf499b5adce301c',1,'helios::Tile']]], - ['getobjectarea_109',['getObjectArea',['../classhelios_1_1_context.html#aac46a608ec7719e4702cd861667925f1',1,'helios::Context']]], - ['getobjectboundingbox_110',['getObjectBoundingBox',['../classhelios_1_1_context.html#a1b9871bf670404adc1d952e59429ec38',1,'helios::Context::getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const'],['../classhelios_1_1_context.html#ab5aef932bd4b64b1cee932423172ab6f',1,'helios::Context::getObjectBoundingBox(const std::vector< uint > &ObjID, vec3 &min_corner, vec3 &max_corner) const']]], - ['getobjectcenter_111',['getObjectCenter',['../classhelios_1_1_compound_object.html#aff66ca85a22d7f8a2501039e2e7183a7',1,'helios::CompoundObject::getObjectCenter()'],['../classhelios_1_1_context.html#a4fe8ddd10f0d34bfe0b2a4aea648442a',1,'helios::Context::getObjectCenter(uint ObjID) const']]], - ['getobjectcount_112',['getObjectCount',['../classhelios_1_1_context.html#a54b9c5503ad33d1dcc8f6a5c74f7ea76',1,'helios::Context']]], - ['getobjectdata_113',['getObjectData',['../classhelios_1_1_compound_object.html#ac91c73ac495bc4a93cc9a89d0eb58f47',1,'helios::CompoundObject::getObjectData(const char *label, int &data) const'],['../classhelios_1_1_compound_object.html#aed77927b3d3fe0ea7ea674b20a8acce1',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int > &data) const'],['../classhelios_1_1_compound_object.html#ac91bb0e57aa261b003de76b3e008a762',1,'helios::CompoundObject::getObjectData(const char *label, uint &data) const'],['../classhelios_1_1_compound_object.html#a7be991a83ada928f25c23cf7ca3b1822',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_compound_object.html#ac222719662ca008014cdd045bedd3d96',1,'helios::CompoundObject::getObjectData(const char *label, float &data) const'],['../classhelios_1_1_compound_object.html#ac128057ff1d7cabb9dfbfb33216cb0c5',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< float > &data) const'],['../classhelios_1_1_compound_object.html#a6d99ef1cacec7471bb79b57601a7a6ee',1,'helios::CompoundObject::getObjectData(const char *label, double &data) const'],['../classhelios_1_1_compound_object.html#ac7af8838d7132683dd9fdbffd1288579',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< double > &data) const'],['../classhelios_1_1_compound_object.html#aef1aadca9de0e9a66500ca5879ab3755',1,'helios::CompoundObject::getObjectData(const char *label, vec2 &data) const'],['../classhelios_1_1_compound_object.html#af7574c29395681941d4d875e304b93de',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_compound_object.html#acea74a2c138c1e5d832df864a231e486',1,'helios::CompoundObject::getObjectData(const char *label, vec3 &data) const'],['../classhelios_1_1_compound_object.html#a797a5fd8f08ff7220b15ae1d5accb6cd',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_compound_object.html#a52661efba4b57415b073fcf839069623',1,'helios::CompoundObject::getObjectData(const char *label, vec4 &data) const'],['../classhelios_1_1_compound_object.html#a15ef0fda0196b4de933e4379d5f8234f',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_compound_object.html#a768a439ecb0d6e8449b31cd137317168',1,'helios::CompoundObject::getObjectData(const char *label, int2 &data) const'],['../classhelios_1_1_compound_object.html#af4d1accb01b8dd2f968296c43dfb6d97',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_compound_object.html#a95f20aead49e80032b0673273de436f2',1,'helios::CompoundObject::getObjectData(const char *label, int3 &data) const'],['../classhelios_1_1_compound_object.html#a6cb032fa5f5b6de86f234eb237980586',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_compound_object.html#a2c0dcefe9e05ec04b001ad94f475f34c',1,'helios::CompoundObject::getObjectData(const char *label, int4 &data) const'],['../classhelios_1_1_compound_object.html#aba75ef4dd5b01b02fc99f9a1d957d70b',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_compound_object.html#afa77a9712c207752cd56522f2dbca52b',1,'helios::CompoundObject::getObjectData(const char *label, std::string &data) const'],['../classhelios_1_1_compound_object.html#adfd1f35dc8785f223c02cc940360e6a5',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< std::string > &data) const'],['../classhelios_1_1_context.html#a3511ff568337b501ca878c99d97c9b52',1,'helios::Context::getObjectData(uint objID, const char *label, int &data) const'],['../classhelios_1_1_context.html#ae75ddc9a945ec876533211f52b8cd22e',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#abbd59cc4e7bcad35b43ea7240c4d5558',1,'helios::Context::getObjectData(uint objID, const char *label, uint &data) const'],['../classhelios_1_1_context.html#a22d510fad177ca319bdac0a94ee8f069',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#a8935a9cdf6e34e72bcb636a97043a474',1,'helios::Context::getObjectData(uint objID, const char *label, float &data) const'],['../classhelios_1_1_context.html#a293d899bb22cae1db8cf6c2cc813055d',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#ae222f3351535f3aea35e76cbe2ca2d67',1,'helios::Context::getObjectData(uint objID, const char *label, double &data) const'],['../classhelios_1_1_context.html#acda7f75e833791bcbd74ca8b37272a8b',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#af8fa05c716517966f7abcc2f4019c709',1,'helios::Context::getObjectData(uint objID, const char *label, vec2 &data) const'],['../classhelios_1_1_context.html#a2e691b7f0b630792f50b5423e23ebab1',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_context.html#a628cf051625e33549044cd20656519ac',1,'helios::Context::getObjectData(uint objID, const char *label, vec3 &data) const'],['../classhelios_1_1_context.html#a6606603899859e211de9f56cd49bf92d',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_context.html#ac2b7e667ec37c88868ba0752919da1c9',1,'helios::Context::getObjectData(uint objID, const char *label, vec4 &data) const'],['../classhelios_1_1_context.html#ace5025b962226a75c4984ee6ecc21356',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_context.html#ae56639e95fae8796545efde94fa84bcc',1,'helios::Context::getObjectData(uint objID, const char *label, int2 &data) const'],['../classhelios_1_1_context.html#a39b169b41cf94516afd863f580c2b772',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_context.html#ac58fc8f10c12dc54265491576650a0c6',1,'helios::Context::getObjectData(uint objID, const char *label, int3 &data) const'],['../classhelios_1_1_context.html#ac097e42620523f2d57d28eecd02954a4',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_context.html#aa393d7b0f24855b2e54480be71c09ad2',1,'helios::Context::getObjectData(uint objID, const char *label, int4 &data) const'],['../classhelios_1_1_context.html#a7ca032799776268d30fe185a76100e0e',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_context.html#a1eae737b91ec70ae6490a8c403936975',1,'helios::Context::getObjectData(uint objID, const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a158215e07c921d11e495b3805823b725',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< std::string > &data) const']]], - ['getobjectdatasize_114',['getObjectDataSize',['../classhelios_1_1_compound_object.html#a03b2516f8e7e8ae921ea61e4f571eb1d',1,'helios::CompoundObject::getObjectDataSize()'],['../classhelios_1_1_context.html#ac251e9be64f3a35b6d2e6441c2a46f40',1,'helios::Context::getObjectDataSize()']]], - ['getobjectdatatype_115',['getObjectDataType',['../classhelios_1_1_compound_object.html#abbcfd5c545991ee59cf3f77acf300b1e',1,'helios::CompoundObject::getObjectDataType()'],['../classhelios_1_1_context.html#af77ff3ea4a7668d2b5cb03bc6fc5f5b6',1,'helios::Context::getObjectDataType()']]], - ['getobjectid_116',['getObjectID',['../classhelios_1_1_compound_object.html#a28c85b0cf4dee51dd7997b7b78e4f442',1,'helios::CompoundObject']]], - ['getobjectpointer_117',['getObjectPointer',['../classhelios_1_1_context.html#a3d9493949db2c5d8ddeef30afd2a9a0a',1,'helios::Context']]], - ['getobjectprimitivecount_118',['getObjectPrimitiveCount',['../classhelios_1_1_context.html#a457ccd0bcf9870aef138b22c4a160aeb',1,'helios::Context']]], - ['getobjectprimitiveuuids_119',['getObjectPrimitiveUUIDs',['../classhelios_1_1_context.html#a7d0b3a6ca36b02702b06208a735a3b03',1,'helios::Context::getObjectPrimitiveUUIDs(uint ObjID) const'],['../classhelios_1_1_context.html#a09e60fbbd3c4be1f8345a9de3695ccdd',1,'helios::Context::getObjectPrimitiveUUIDs(const std::vector< uint > &ObjIDs) const'],['../classhelios_1_1_context.html#a266fba7ca4a0a1536c49f1e3ce918b1e',1,'helios::Context::getObjectPrimitiveUUIDs(const std::vector< std::vector< uint > > &ObjIDs) const']]], - ['getobjecttexturefile_120',['getObjectTextureFile',['../classhelios_1_1_context.html#aacd4cff3b170281516dcafb3fa83b84a',1,'helios::Context']]], - ['getobjecttransformationmatrix_121',['getObjectTransformationMatrix',['../classhelios_1_1_context.html#af9e972c138b0626cece9eea5f018b418',1,'helios::Context']]], - ['getobjecttype_122',['getObjectType',['../classhelios_1_1_compound_object.html#ab07473392ca1e4c439c909c83cc9730b',1,'helios::CompoundObject::getObjectType()'],['../classhelios_1_1_context.html#a75ae3ee4580c4420059fe95755dc22d2',1,'helios::Context::getObjectType(uint ObjID) const']]], - ['getpatchcenter_123',['getPatchCenter',['../classhelios_1_1_context.html#a4165df43e5ab752e81bc2b7d7caf19d5',1,'helios::Context']]], - ['getpatchsize_124',['getPatchSize',['../classhelios_1_1_context.html#ab3f802aca8dd1930127d9f76358e71cf',1,'helios::Context']]], - ['getplantcount_125',['getPlantCount',['../class_canopy_generator.html#aba9e186286ade3cd2ced0be80b3b8b89',1,'CanopyGenerator']]], - ['getplantflowerobjectids_126',['getPlantFlowerObjectIDs',['../class_plant_architecture.html#a1cb3e4ba93c7a94558c3c07496e550c2',1,'PlantArchitecture']]], - ['getplantfruitobjectids_127',['getPlantFruitObjectIDs',['../class_plant_architecture.html#aac602c603ac136c3aaffad052bd844d4',1,'PlantArchitecture']]], - ['getplantinternodeobjectids_128',['getPlantInternodeObjectIDs',['../class_plant_architecture.html#a53967340a1c9b88f4b804522f081ce62',1,'PlantArchitecture']]], - ['getplantleafobjectids_129',['getPlantLeafObjectIDs',['../class_plant_architecture.html#afcdea7f14c6ca722d39d94ff19ba87b4',1,'PlantArchitecture']]], - ['getplantpeduncleobjectids_130',['getPlantPeduncleObjectIDs',['../class_plant_architecture.html#af8a9f26212baf6695d71d44b982e6adf',1,'PlantArchitecture']]], - ['getplantpetioleobjectids_131',['getPlantPetioleObjectIDs',['../class_plant_architecture.html#aee2486b87dca29982dd1b380aa3510fb',1,'PlantArchitecture']]], - ['getpolymeshobjectpointer_132',['getPolymeshObjectPointer',['../classhelios_1_1_context.html#a5a10781f6c1e24b226a32b1e1369f5c1',1,'helios::Context']]], - ['getpolymeshobjectvolume_133',['getPolymeshObjectVolume',['../classhelios_1_1_context.html#aad71b3e493ab0e47c6d4496d14e89803',1,'helios::Context']]], - ['getprimitivearea_134',['getPrimitiveArea',['../classhelios_1_1_context.html#a1dafe58b3251d2ef9d09112258b2e85d',1,'helios::Context']]], - ['getprimitiveboundingbox_135',['getPrimitiveBoundingBox',['../classhelios_1_1_context.html#abf2e26ac2b32556878be6626a8876569',1,'helios::Context::getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const'],['../classhelios_1_1_context.html#a808527f76dec2683cbc168250c4f69be',1,'helios::Context::getPrimitiveBoundingBox(const std::vector< uint > &UUID, vec3 &min_corner, vec3 &max_corner) const']]], - ['getprimitivecolor_136',['getPrimitiveColor',['../classhelios_1_1_context.html#a1223205f1080b0b7024b8f97950779b8',1,'helios::Context']]], - ['getprimitivecolorrgb_137',['getPrimitiveColorRGB',['../classhelios_1_1_context.html#a8550633570ee91e4f09ec1464810bd7b',1,'helios::Context']]], - ['getprimitivecolorrgba_138',['getPrimitiveColorRGBA',['../classhelios_1_1_context.html#a4e29adcb908d55172efd239f294b49e5',1,'helios::Context']]], - ['getprimitivecount_139',['getPrimitiveCount',['../classhelios_1_1_compound_object.html#a0eb06d37710a7dc9f5b915fc33f191a0',1,'helios::CompoundObject::getPrimitiveCount()'],['../group__primitives.html#ga4d3447fb04c25e685bcc82599e2b173d',1,'helios::Context::getPrimitiveCount() const']]], - ['getprimitivedata_140',['getPrimitiveData',['../classhelios_1_1_context.html#a2144eea981e4030c973287ce2c38315e',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int &data) const'],['../classhelios_1_1_context.html#ad1f6453da61e8e64ba91f589b7cc4eb0',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#a420487af4a23ed5b527069c6471efd93',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, uint &data) const'],['../classhelios_1_1_context.html#add62ecdb7cc13510670c9c45bc8725a3',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#aa54fb6e8a942845010ae669505adc2e8',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, float &data) const'],['../classhelios_1_1_context.html#a466dea76918a4bd02e4a355ab70f161b',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#a802b10b84762052e52b9ff1861604c58',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, double &data) const'],['../classhelios_1_1_context.html#a65d1918df796575a5e5bc8c470ff3201',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#a2ac5198c45a57b7926f4dbd9129fcad5',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec2 &data) const'],['../classhelios_1_1_context.html#ab0fb70ff8b6e81901df14efe07ae7ff4',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_context.html#abbe503b705cfdeb903becdb7fb082dae',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec3 &data) const'],['../classhelios_1_1_context.html#a83619185959d1dae4570674a3855f808',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_context.html#a0e62c9bb97e4cbbcd56518b060e9cae5',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec4 &data) const'],['../classhelios_1_1_context.html#a29fed63e84bf5b5111b0e98f499da56e',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_context.html#a72ee49f503ff0c4937d9aa81b72689ed',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int2 &data) const'],['../classhelios_1_1_context.html#ae76119a1083016c2cffed9eb443aaa62',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_context.html#a18f0ede968126842068551834391e3ad',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int3 &data) const'],['../classhelios_1_1_context.html#a5c37491d4bc0a1d69ffcaf214e6c2fe7',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_context.html#afe292fdf1d3c7983427c699e4a2eca3a',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int4 &data) const'],['../classhelios_1_1_context.html#a8ebaded3f143fc9c673765ab3fda5366',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_context.html#ad1a2ca668fb5f5043f23f7a50c22483f',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a1d8cd543d68c2bc3b7ef876421284f15',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< std::string > &data) const']]], - ['getprimitivedatasize_141',['getPrimitiveDataSize',['../classhelios_1_1_context.html#a4b64585d356463ac759472f099660eca',1,'helios::Context']]], - ['getprimitivedatatype_142',['getPrimitiveDataType',['../classhelios_1_1_context.html#a9c894ecd12e0d893c53ffcfa9e90c0b6',1,'helios::Context']]], - ['getprimitivenormal_143',['getPrimitiveNormal',['../classhelios_1_1_context.html#abfeadf8e6a35eb97da1439abc21c434e',1,'helios::Context']]], - ['getprimitiveparentobjectid_144',['getPrimitiveParentObjectID',['../classhelios_1_1_context.html#a2d3e254d04f913e590a645b54886436e',1,'helios::Context']]], - ['getprimitivesolidfraction_145',['getPrimitiveSolidFraction',['../classhelios_1_1_context.html#a6e8a5e2044331158d69d6f9bd88fc0f7',1,'helios::Context']]], - ['getprimitivetexturefile_146',['getPrimitiveTextureFile',['../classhelios_1_1_context.html#a4fffad72d1ebb517d9c41837e448d4f5',1,'helios::Context']]], - ['getprimitivetexturesize_147',['getPrimitiveTextureSize',['../classhelios_1_1_context.html#a7fec62cbf2c2d56603b2750cbb4a4d9f',1,'helios::Context']]], - ['getprimitivetexturetransparencydata_148',['getPrimitiveTextureTransparencyData',['../classhelios_1_1_context.html#a98ad773979fff9efda47b44d71ac8e06',1,'helios::Context']]], - ['getprimitivetextureuv_149',['getPrimitiveTextureUV',['../classhelios_1_1_context.html#a5702f94aaba15bf6757aeb4d72d7774d',1,'helios::Context']]], - ['getprimitivetransformationmatrix_150',['getPrimitiveTransformationMatrix',['../classhelios_1_1_context.html#a046e855d15fa88088be01adea38a67fd',1,'helios::Context']]], - ['getprimitivetype_151',['getPrimitiveType',['../classhelios_1_1_context.html#a67bfd66f0a445f6485f1099f9eadc949',1,'helios::Context']]], - ['getprimitiveuuids_152',['getPrimitiveUUIDs',['../classhelios_1_1_compound_object.html#ab3973a7c8ccb1aa0ce3f21ffe461ef7b',1,'helios::CompoundObject']]], - ['getprimitivevertices_153',['getPrimitiveVertices',['../classhelios_1_1_context.html#ae8542fd1452150d3302675a0a3d991ed',1,'helios::Context']]], - ['getradius_154',['getRadius',['../classhelios_1_1_sphere.html#a38cf8b6959d22577a1a2f9a6c675bc8b',1,'helios::Sphere']]], - ['getrandomgenerator_155',['getRandomGenerator',['../classhelios_1_1_context.html#a96a928fa28d3d771ba310f798b56bd63',1,'helios::Context']]], - ['getscanbeamdivergence_156',['getScanBeamDivergence',['../class_aerial_li_d_a_rcloud.html#a4097c1d3994f57e0f0e2e602c7ca5c04',1,'AerialLiDARcloud::getScanBeamDivergence()'],['../class_li_d_a_rcloud.html#a9d93e6cd9decccf271fbf3fbd5c74a5a',1,'LiDARcloud::getScanBeamDivergence()']]], - ['getscanbeamexitdiameter_157',['getScanBeamExitDiameter',['../class_aerial_li_d_a_rcloud.html#ae6cbd6375be39129231233d66061afca',1,'AerialLiDARcloud::getScanBeamExitDiameter()'],['../class_li_d_a_rcloud.html#abab6b81a3d96226a766cc2450993407f',1,'LiDARcloud::getScanBeamExitDiameter()']]], - ['getscancenter_158',['getScanCenter',['../class_aerial_li_d_a_rcloud.html#a1ce1efbe6af71f54dcccd3743918aa72',1,'AerialLiDARcloud']]], - ['getscancolumnformat_159',['getScanColumnFormat',['../class_li_d_a_rcloud.html#abbe892f01508dc69bcc5b28bea5472bf',1,'LiDARcloud']]], - ['getscanconeangle_160',['getScanConeAngle',['../class_aerial_li_d_a_rcloud.html#a0dbf5535304d6d87d67a0d41c5d2310f',1,'AerialLiDARcloud']]], - ['getscancount_161',['getScanCount',['../class_aerial_li_d_a_rcloud.html#ab363717911dada3af4fdafa914532a6a',1,'AerialLiDARcloud::getScanCount()'],['../class_li_d_a_rcloud.html#aaa463ea1aaebb03abd8c3ec87091291a',1,'LiDARcloud::getScanCount()']]], - ['getscandensity_162',['getScanDensity',['../class_aerial_li_d_a_rcloud.html#a0c4627b15014ebe8c79053ed75f6cfb4',1,'AerialLiDARcloud']]], - ['getscanextent_163',['getScanExtent',['../class_aerial_li_d_a_rcloud.html#ad5bd68f06fef597d8c1f1aac3142acc6',1,'AerialLiDARcloud']]], - ['getscanorigin_164',['getScanOrigin',['../class_li_d_a_rcloud.html#aa657ed32a8831ebf4f2e4a9203b683ef',1,'LiDARcloud']]], - ['getscanrangephi_165',['getScanRangePhi',['../class_li_d_a_rcloud.html#ab314aac88834eb3938fc2f37e34807e3',1,'LiDARcloud']]], - ['getscanrangetheta_166',['getScanRangeTheta',['../class_li_d_a_rcloud.html#a7f0237a83da6997e973fde9939440979',1,'LiDARcloud']]], - ['getscansizephi_167',['getScanSizePhi',['../class_li_d_a_rcloud.html#aaf04cd04c2b1bc162106a0e47cff6d29',1,'LiDARcloud']]], - ['getscansizetheta_168',['getScanSizeTheta',['../class_li_d_a_rcloud.html#a40809c7a709a6c9ccb4beddca21f8ac9',1,'LiDARcloud']]], - ['getsegmentvolume_169',['getSegmentVolume',['../classhelios_1_1_tube.html#a2966ff764897904282082f23a76756b8',1,'helios::Tube']]], - ['getsize_170',['getSize',['../classhelios_1_1_tile.html#aa8daadd99bd57f647837e26890fcfeac',1,'helios::Tile::getSize()'],['../classhelios_1_1_box.html#afd79ee17402ab6367896fe8278800f34',1,'helios::Box::getSize()'],['../classhelios_1_1_disk.html#a23c03df1f2e351659a08420a41a74eb5',1,'helios::Disk::getSize()']]], - ['getskyenergy_171',['getSkyEnergy',['../class_radiation_model.html#a9c9a5f6cb6b0ba6e3780aba8a4da8a0d',1,'RadiationModel']]], - ['getsolarflux_172',['getSolarFlux',['../class_solar_position.html#a9701cb29a0336a11c445d285405b6956',1,'SolarPosition']]], - ['getsolarfluxnir_173',['getSolarFluxNIR',['../class_solar_position.html#a611461f700df9efa7c56b6f4ee7712b7',1,'SolarPosition']]], - ['getsolarfluxpar_174',['getSolarFluxPAR',['../class_solar_position.html#a5c6635160944b5b8202ea9965da6de9d',1,'SolarPosition']]], - ['getsolidfraction_175',['getSolidFraction',['../classhelios_1_1_texture.html#a685024e8394b49433f26a0dcd6665d86',1,'helios::Texture']]], - ['getsourceflux_176',['getSourceFlux',['../class_radiation_model.html#a9d4ea3e08514b90e617695ab2ee2fbf8',1,'RadiationModel']]], - ['getsourceposition_177',['getSourcePosition',['../class_radiation_model.html#ab8ec35514a0e4b53ce8a64d3f390427c',1,'RadiationModel']]], - ['getsphereobjectcenter_178',['getSphereObjectCenter',['../classhelios_1_1_context.html#a4f75af0785498d14eb3f5a3539cb16b1',1,'helios::Context']]], - ['getsphereobjectpointer_179',['getSphereObjectPointer',['../classhelios_1_1_context.html#a8ed7580efa323c0f5e53e97d00e16c85',1,'helios::Context']]], - ['getsphereobjectradius_180',['getSphereObjectRadius',['../classhelios_1_1_context.html#a5afb4fd92e9a726fb396779d1f2ae92b',1,'helios::Context']]], - ['getsphereobjectsubdivisioncount_181',['getSphereObjectSubdivisionCount',['../classhelios_1_1_context.html#adadbc5a5378a874cd6705ed681fb9e6a',1,'helios::Context']]], - ['getsphereobjectvolume_182',['getSphereObjectVolume',['../classhelios_1_1_context.html#ae92df5975ec7fa257e7633d6551e2a87',1,'helios::Context']]], - ['getsubdivisioncount_183',['getSubdivisionCount',['../classhelios_1_1_tile.html#a4f4198becfe3cafd989b5aa6cd21d5cf',1,'helios::Tile::getSubdivisionCount()'],['../classhelios_1_1_sphere.html#a152107e463d6765ba27ff8f3ab737711',1,'helios::Sphere::getSubdivisionCount()'],['../classhelios_1_1_tube.html#abf9bb1153b3607a5d616aafeee06e43e',1,'helios::Tube::getSubdivisionCount()'],['../classhelios_1_1_box.html#a6f25b211d8740257329f841cda737a4f',1,'helios::Box::getSubdivisionCount()'],['../classhelios_1_1_disk.html#a8dc2a195735ee3321b274274e7e0352e',1,'helios::Disk::getSubdivisionCount()'],['../classhelios_1_1_cone.html#a051a2c5760d53a6c0b95f66cab9cbf73',1,'helios::Cone::getSubdivisionCount()']]], - ['getsunazimuth_184',['getSunAzimuth',['../class_solar_position.html#a2b736578f75ecb8532556931b8263dc4',1,'SolarPosition']]], - ['getsundirectionspherical_185',['getSunDirectionSpherical',['../class_solar_position.html#adad5310db742ef9f2754e75095aeea92',1,'SolarPosition']]], - ['getsundirectionvector_186',['getSunDirectionVector',['../class_solar_position.html#af889756d5b3d7d3c366887fae1fb86ab',1,'SolarPosition']]], - ['getsunelevation_187',['getSunElevation',['../class_solar_position.html#a307e963d840abb9ee7867579fec69fa2',1,'SolarPosition']]], - ['getsunrisetime_188',['getSunriseTime',['../class_solar_position.html#a2d15fe2ca0d29adf33971916b1d8cd83',1,'SolarPosition']]], - ['getsunsettime_189',['getSunsetTime',['../class_solar_position.html#a4c58aa642b4fc2300d1c1447388bc0d8',1,'SolarPosition']]], - ['getsunzenith_190',['getSunZenith',['../class_solar_position.html#a4c4ba4931d13c6cc2ad69e8eab90ac14',1,'SolarPosition']]], - ['gettexturefile_191',['getTextureFile',['../classhelios_1_1_texture.html#a0371473a81deb9bb19b8274109b75ef8',1,'helios::Texture::getTextureFile()'],['../classhelios_1_1_compound_object.html#a3e43ebd386e7a6663fa877613b9d27fa',1,'helios::CompoundObject::getTextureFile()']]], - ['gettextureuv_192',['getTextureUV',['../classhelios_1_1_tile.html#a94deb25ac31abc1eb02dfe6913b4546f',1,'helios::Tile']]], - ['gettileobjectarearatio_193',['getTileObjectAreaRatio',['../classhelios_1_1_context.html#a9943834b21ccfb9ac1c519e47f959c92',1,'helios::Context::getTileObjectAreaRatio(uint ObjectID) const'],['../classhelios_1_1_context.html#afdebad3fd25bb8b9fa228020c3b11329',1,'helios::Context::getTileObjectAreaRatio(const std::vector< uint > &ObjectID) const']]], - ['gettileobjectcenter_194',['getTileObjectCenter',['../classhelios_1_1_context.html#aa60f87c9bc771e613f60db73188a149d',1,'helios::Context']]], - ['gettileobjectnormal_195',['getTileObjectNormal',['../classhelios_1_1_context.html#a64f4bcadff461357aa390d7f5dad2ba7',1,'helios::Context']]], - ['gettileobjectpointer_196',['getTileObjectPointer',['../classhelios_1_1_context.html#ad2b762dd7b31126150c6e6dc350a3914',1,'helios::Context']]], - ['gettileobjectsize_197',['getTileObjectSize',['../classhelios_1_1_context.html#a457654b4a1f96a4979f83299dd9752df',1,'helios::Context']]], - ['gettileobjectsubdivisioncount_198',['getTileObjectSubdivisionCount',['../classhelios_1_1_context.html#a9320e4577eb131e7efe05677d30591b3',1,'helios::Context']]], - ['gettileobjecttextureuv_199',['getTileObjectTextureUV',['../classhelios_1_1_context.html#a00718598a9c308dabe8fc24f85683210',1,'helios::Context']]], - ['gettileobjectvertices_200',['getTileObjectVertices',['../classhelios_1_1_context.html#ab77b708ac6b39c1c5e8ecaa4988403b0',1,'helios::Context']]], - ['gettime_201',['getTime',['../classhelios_1_1_context.html#a847ecbb2297e60220a23b67c39b0f6e2',1,'helios::Context']]], - ['gettimeserieslength_202',['getTimeseriesLength',['../group__timeseries.html#ga56d13f8c949e68137581a3c974790892',1,'helios::Context']]], - ['gettotalabsorbedflux_203',['getTotalAbsorbedFlux',['../class_radiation_model.html#a5e95e775550a2000798a97b00857bdd2',1,'RadiationModel']]], - ['gettransformationmatrix_204',['getTransformationMatrix',['../classhelios_1_1_compound_object.html#ac1e98d4f8098dadda345f9dc6dae73ca',1,'helios::CompoundObject']]], - ['gettransparencydata_205',['getTransparencyData',['../classhelios_1_1_texture.html#a798c3a24b21fc853db299d1f1f84a61c',1,'helios::Texture']]], - ['gettreeparameters_206',['getTreeParameters',['../class_weber_penn_tree.html#aac5619ac480517f8f01cb465d0dc4a6f',1,'WeberPennTree']]], - ['gettriangle_207',['getTriangle',['../class_li_d_a_rcloud.html#aa1a1af5eea22185e59c267c8e4d94c9e',1,'LiDARcloud']]], - ['gettrianglecount_208',['getTriangleCount',['../class_li_d_a_rcloud.html#abcdbf834959379a189a60efed41f3e52',1,'LiDARcloud']]], - ['gettrianglevertex_209',['getTriangleVertex',['../classhelios_1_1_context.html#a846f93175f8b45f44237e88155af8fde',1,'helios::Context']]], - ['gettrianglevertices_210',['getTriangleVertices',['../classhelios_1_1_tube.html#a6aedd14e533981bd79497ba13b33f2c9',1,'helios::Tube']]], - ['gettrunkuuids_211',['getTrunkUUIDs',['../class_canopy_generator.html#aa8e95a610c03588592acebbbba5d638e',1,'CanopyGenerator::getTrunkUUIDs(uint PlantID)'],['../class_canopy_generator.html#a44b2d0846bb08d331281a822df41daa6',1,'CanopyGenerator::getTrunkUUIDs()'],['../class_weber_penn_tree.html#ab247d9368368263dfdded18a43917f98',1,'WeberPennTree::getTrunkUUIDs()']]], - ['gettubeobjectnodecolors_212',['getTubeObjectNodeColors',['../classhelios_1_1_context.html#a7ad271dabb4291067f9a39d4c92e6ffd',1,'helios::Context']]], - ['gettubeobjectnoderadii_213',['getTubeObjectNodeRadii',['../classhelios_1_1_context.html#a6a58d8f1a8446a213d9a21e67ae8ed97',1,'helios::Context']]], - ['gettubeobjectnodes_214',['getTubeObjectNodes',['../classhelios_1_1_context.html#aa4650e7a0a16be12615870ff9a567ae3',1,'helios::Context']]], - ['gettubeobjectpointer_215',['getTubeObjectPointer',['../classhelios_1_1_context.html#ab26f963c75aa99d797a43860479910b0',1,'helios::Context']]], - ['gettubeobjectsegmentvolume_216',['getTubeObjectSegmentVolume',['../classhelios_1_1_context.html#a10928031db222e77e93ac8088f4b001d',1,'helios::Context']]], - ['gettubeobjectsubdivisioncount_217',['getTubeObjectSubdivisionCount',['../classhelios_1_1_context.html#a272ba030971b86c7d3da57ff90784e0f',1,'helios::Context']]], - ['gettubeobjectvolume_218',['getTubeObjectVolume',['../classhelios_1_1_context.html#a56b82c3f009084451225003b2b461b6f',1,'helios::Context']]], - ['getuniqueprimitiveparentobjectids_219',['getUniquePrimitiveParentObjectIDs',['../classhelios_1_1_context.html#a18a276db8d3c1d754bbd1ca475deec82',1,'helios::Context::getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs) const'],['../classhelios_1_1_context.html#a1f50af8c859a5b2ee0973c9ed5c10284',1,'helios::Context::getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs, bool include_ObjID_zero) const']]], - ['getvariation_220',['getVariation',['../_canopy_generator_8h.html#accfb46da54c7b0e83878a1331bbc94d1',1,'getVariation(float V, std::minstd_rand0 &generator, bool positive=false): CanopyGenerator.cpp'],['../_canopy_generator_8h.html#aa3a6e1a26b799f4a2006703314499fed',1,'getVariation(int V, std::minstd_rand0 &generator, bool positive=false): CanopyGenerator.cpp'],['../_canopy_generator_8h.html#a6cdee9cb4984f78c818e46eb2a5b62e6',1,'getVariation(uint V, std::minstd_rand0 &generator): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#aa0b21a2d6b9506b33d05047716d671e0',1,'getVariation(float V, std::minstd_rand0 &generator, bool positive): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#a9f90ba8fe8a074a822424ff748579f25',1,'getVariation(int V, std::minstd_rand0 &generator, bool positive): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#a6cdee9cb4984f78c818e46eb2a5b62e6',1,'getVariation(uint V, std::minstd_rand0 &generator): CanopyGenerator.cpp']]], - ['getvertices_221',['getVertices',['../classhelios_1_1_tile.html#aaea21403039646db33792c95be929afd',1,'helios::Tile']]], - ['getvolume_222',['getVolume',['../classhelios_1_1_sphere.html#a3d6a8e9f8c0daee1e093593d6006c906',1,'helios::Sphere::getVolume()'],['../classhelios_1_1_tube.html#aaa11cc27d6f704a989c3e5b0fe1b8055',1,'helios::Tube::getVolume()'],['../classhelios_1_1_box.html#a3d3d0b20e22aff306fde02bd7e2a4f84',1,'helios::Box::getVolume()'],['../classhelios_1_1_polymesh.html#ad901c4de0e202f44c16fc9af29481538',1,'helios::Polymesh::getVolume()'],['../classhelios_1_1_cone.html#aff2cb2fc89c68b75a038a9604ce73cd0',1,'helios::Cone::getVolume()']]], - ['getvoxelcenter_223',['getVoxelCenter',['../classhelios_1_1_context.html#acadf5206cbfed7b8eaa2835702349cd9',1,'helios::Context']]], - ['getvoxelsize_224',['getVoxelSize',['../classhelios_1_1_context.html#a6a3f85d4f29f8f7432b6ef605172a1cb',1,'helios::Context']]], - ['getwindowpixelsrgb_225',['getWindowPixelsRGB',['../class_visualizer.html#a15828ea9966b9729b56c9ddfccd4c117',1,'Visualizer']]], - ['getwindowsize_226',['getWindowSize',['../class_visualizer.html#ae6b83402c798f56334851f77b898de52',1,'Visualizer']]], - ['gobletgrapevineparameters_227',['GobletGrapevineParameters',['../struct_goblet_grapevine_parameters.html#a0274d6f6b1f13bbf7a383de5c2bc8726',1,'GobletGrapevineParameters::GobletGrapevineParameters()'],['../struct_goblet_grapevine_parameters.html#a498ce7f62d575b0bc914e9d48d94fbb2',1,'GobletGrapevineParameters::GobletGrapevineParameters(const pugi::xml_node canopy_node)']]], - ['gradientdescent_228',['GradientDescent',['../struct_camera_calibration.html#a5bfbb206b8271b406cda85eb5ae23a1b',1,'CameraCalibration']]], - ['grapevinegoblet_229',['grapevineGoblet',['../class_canopy_generator.html#a8f2d498637c464ee852109e6085cde8a',1,'CanopyGenerator']]], - ['grapevinesplit_230',['grapevineSplit',['../class_canopy_generator.html#a8747bad1af97214059c38043241f0b47',1,'CanopyGenerator']]], - ['grapevineunilateral_231',['grapevineUnilateral',['../class_canopy_generator.html#aac9104d7c6565e860737310de06981f8',1,'CanopyGenerator']]], - ['grapevinevsp_232',['grapevineVSP',['../class_canopy_generator.html#aaffe5cdb82a779785bc6d5e35e622812',1,'CanopyGenerator']]], - ['gridijk2index_233',['gridijk2index',['../class_aerial_li_d_a_rcloud.html#a35c81e8cda423b84c94fc33ee4163d47',1,'AerialLiDARcloud']]], - ['gridindex2ijk_234',['gridindex2ijk',['../class_aerial_li_d_a_rcloud.html#add78af9b69161c5c532a23c8df009d2e',1,'AerialLiDARcloud']]] + ['getallplantids_10',['getAllPlantIDs',['../class_plant_architecture.html#a73c43e42cc78a343279633842ea0aa07',1,'PlantArchitecture']]], + ['getallplantobjectids_11',['getAllPlantObjectIDs',['../class_plant_architecture.html#acf9855048c790d30d8d4de7fa1dc3550',1,'PlantArchitecture']]], + ['getallplantuuids_12',['getAllPlantUUIDs',['../class_plant_architecture.html#a3bdffb4e53fe0da836a40de80946d31f',1,'PlantArchitecture']]], + ['getalluuids_13',['getAllUUIDs',['../classhelios_1_1_context.html#a98516632daccf958cca6b5b6582310bb',1,'helios::Context::getAllUUIDs()'],['../class_canopy_generator.html#a8e395619077d656e206f4159f0bf8d34',1,'CanopyGenerator::getAllUUIDs()'],['../class_plant_architecture.html#afec06c56ae296984727c90413511cf6a',1,'PlantArchitecture::getAllUUIDs()'],['../class_weber_penn_tree.html#a19e16f9a51493680afebc38f3c434400',1,'WeberPennTree::getAllUUIDs()']]], + ['getambientlongwaveflux_14',['getAmbientLongwaveFlux',['../class_solar_position.html#a30ee555eedece8b7e19855877a74da71',1,'SolarPosition']]], + ['getarea_15',['getArea',['../classhelios_1_1_compound_object.html#a8bb518f6166e2a2831a68a7626787ac1',1,'helios::CompoundObject']]], + ['getaxisunitvector_16',['getAxisUnitVector',['../classhelios_1_1_cone.html#a60fc92fbb15149017956449123c0e4d0',1,'helios::Cone']]], + ['getbmfcoefficientsfromlibrary_17',['getBMFCoefficientsFromLibrary',['../class_stomatal_conductance_model.html#ada09940a1cc67dbfc0192f6e0a50c967',1,'StomatalConductanceModel']]], + ['getboxobjectcenter_18',['getBoxObjectCenter',['../classhelios_1_1_context.html#af73c44dace71ec805136b7d6ad6095a9',1,'helios::Context']]], + ['getboxobjectpointer_19',['getBoxObjectPointer',['../classhelios_1_1_context.html#a1ecbb5a8cfa6764bade6e0650d2f6990',1,'helios::Context']]], + ['getboxobjectsize_20',['getBoxObjectSize',['../classhelios_1_1_context.html#a4e5799ba4b6a0a889f446bef9e4d3dc0',1,'helios::Context']]], + ['getboxobjectsubdivisioncount_21',['getBoxObjectSubdivisionCount',['../classhelios_1_1_context.html#a258f524d38cdeb5f6c83a7f387608490',1,'helios::Context']]], + ['getboxobjectvolume_22',['getBoxObjectVolume',['../classhelios_1_1_context.html#ae31cc8855aacb6380a288a4b7fa8db82',1,'helios::Context']]], + ['getbranchuuids_23',['getBranchUUIDs',['../class_canopy_generator.html#ab7115aaa287346b9c8e7854bd66f8b5f',1,'CanopyGenerator::getBranchUUIDs(uint PlantID)'],['../class_canopy_generator.html#a7db6f05ab623b77de4e8a81dc132e914',1,'CanopyGenerator::getBranchUUIDs()'],['../class_weber_penn_tree.html#a813cb8959272b535050dc97aa49d3ed3',1,'WeberPennTree::getBranchUUIDs()']]], + ['getcameralookat_24',['getCameraLookat',['../class_radiation_model.html#a68c8736e58c7daf440ff9c93bb00522d',1,'RadiationModel']]], + ['getcameraorientation_25',['getCameraOrientation',['../class_radiation_model.html#a0b67b056aa1f2b5e6c42a06e358f4eb8',1,'RadiationModel']]], + ['getcameraposition_26',['getCameraPosition',['../class_radiation_model.html#a6785deae272a9464920030fc3f124bc3',1,'RadiationModel']]], + ['getcameraresponsescale_27',['getCameraResponseScale',['../struct_camera_calibration.html#a18eff4a7ecab1038f27b68c3963a5513',1,'CameraCalibration::getCameraResponseScale()'],['../class_radiation_model.html#adb5a74547d51a18018d3daeba0ec5f3c',1,'RadiationModel::getCameraResponseScale()']]], + ['getcellcenter_28',['getCellCenter',['../class_aerial_li_d_a_rcloud.html#a6e83c157d63d12253af3b81b995e1a33',1,'AerialLiDARcloud::getCellCenter()'],['../class_li_d_a_rcloud.html#a6e2ce01abb33cc0f80b2aa653ac6a445',1,'LiDARcloud::getCellCenter()']]], + ['getcellcoverfraction_29',['getCellCoverFraction',['../class_aerial_li_d_a_rcloud.html#ac714e2231b63d1455237662661590b16',1,'AerialLiDARcloud']]], + ['getcellglobalanchor_30',['getCellGlobalAnchor',['../class_li_d_a_rcloud.html#ad1ad4f851b5b7fcbf5b088b161aed83e',1,'LiDARcloud']]], + ['getcellgroundheight_31',['getCellGroundHeight',['../class_aerial_li_d_a_rcloud.html#a3b9d9ac013a041c30d58e68e5dc92bee',1,'AerialLiDARcloud']]], + ['getcellgtheta_32',['getCellGtheta',['../class_li_d_a_rcloud.html#a54351e18e3f4155e9d55eb02bd63c722',1,'LiDARcloud']]], + ['getcellleafarea_33',['getCellLeafArea',['../class_aerial_li_d_a_rcloud.html#a9f90891b20b8996e983e66640684b6cc',1,'AerialLiDARcloud::getCellLeafArea()'],['../class_li_d_a_rcloud.html#ac9d20a35bdb7ee2d45490ac1cd520117',1,'LiDARcloud::getCellLeafArea()']]], + ['getcellleafareadensity_34',['getCellLeafAreaDensity',['../class_aerial_li_d_a_rcloud.html#a4ca0903b642daffdff27e69a172c96b5',1,'AerialLiDARcloud::getCellLeafAreaDensity()'],['../class_li_d_a_rcloud.html#a3c1744984481f9629dc1371291fa397e',1,'LiDARcloud::getCellLeafAreaDensity()']]], + ['getcellmaximumhitheight_35',['getCellMaximumHitHeight',['../class_aerial_li_d_a_rcloud.html#a00f6479153ac2025031b70bd5637b65b',1,'AerialLiDARcloud']]], + ['getcellprimitives_36',['getCellPrimitives',['../class_voxel_intersection.html#a7d50123db71cf5cd7c7cc4582abd5cb2',1,'VoxelIntersection']]], + ['getcellrbar_37',['getCellRbar',['../class_aerial_li_d_a_rcloud.html#ae35261c7fc1553cb15fb318a2b14a3b2',1,'AerialLiDARcloud']]], + ['getcellrotation_38',['getCellRotation',['../class_li_d_a_rcloud.html#aa2cba1d0bcd9a2ae35d9a5be03832efc',1,'LiDARcloud']]], + ['getcellsize_39',['getCellSize',['../class_aerial_li_d_a_rcloud.html#a5bf5379ee229ebb51fdc8195af8cf3e7',1,'AerialLiDARcloud::getCellSize()'],['../class_li_d_a_rcloud.html#a6662330b95ee7ee77ea6647871695c55',1,'LiDARcloud::getCellSize()']]], + ['getcelltransmissionprobability_40',['getCellTransmissionProbability',['../class_aerial_li_d_a_rcloud.html#a98770b70c510e7611fb171d3fe920554',1,'AerialLiDARcloud']]], + ['getcellvegetationheight_41',['getCellVegetationHeight',['../class_aerial_li_d_a_rcloud.html#a12fe426a267cbef9982138537198558a',1,'AerialLiDARcloud']]], + ['getcenter_42',['getCenter',['../classhelios_1_1_tile.html#a18178d0280f8ecc1149663558947ca06',1,'helios::Tile::getCenter()'],['../classhelios_1_1_sphere.html#a48eada17c3dab899a91158f1424518d6',1,'helios::Sphere::getCenter()'],['../classhelios_1_1_box.html#a96e72a40ff113d6a6b463fe8c60b672a',1,'helios::Box::getCenter()'],['../classhelios_1_1_disk.html#ae8ed884a95cbfa2440e3bd9f8e3e4057',1,'helios::Disk::getCenter()']]], + ['getconeobjectaxisunitvector_43',['getConeObjectAxisUnitVector',['../classhelios_1_1_context.html#acaa3fb162b17cb7f912162f5d4be894e',1,'helios::Context']]], + ['getconeobjectlength_44',['getConeObjectLength',['../classhelios_1_1_context.html#ad2b045f361aa8e8596bcf325c1707a25',1,'helios::Context']]], + ['getconeobjectnode_45',['getConeObjectNode',['../classhelios_1_1_context.html#a54e9f0b7c5014a37cd9d5bf74e7d5935',1,'helios::Context']]], + ['getconeobjectnoderadii_46',['getConeObjectNodeRadii',['../classhelios_1_1_context.html#ade2608274b311c809d46bb13943b9e4e',1,'helios::Context']]], + ['getconeobjectnoderadius_47',['getConeObjectNodeRadius',['../classhelios_1_1_context.html#af5acc5647e6bf9cd1649da1dec677110',1,'helios::Context']]], + ['getconeobjectnodes_48',['getConeObjectNodes',['../classhelios_1_1_context.html#a8c4ec2d90ccd3d44a97597ecd80d78b6',1,'helios::Context']]], + ['getconeobjectpointer_49',['getConeObjectPointer',['../classhelios_1_1_context.html#a3221051ea9c1025e8fb00d9dec01839f',1,'helios::Context']]], + ['getconeobjectsubdivisioncount_50',['getConeObjectSubdivisionCount',['../classhelios_1_1_context.html#a1ff97eb95d5896e096156320f5bd5ff0',1,'helios::Context']]], + ['getconeobjectvolume_51',['getConeObjectVolume',['../classhelios_1_1_context.html#af6c1c571171be2604822a8df44d2349c',1,'helios::Context']]], + ['getcurrentcolormap_52',['getCurrentColormap',['../class_visualizer.html#ae2bba6102a283a31ec4f5780817a15da',1,'Visualizer']]], + ['getcurrentphytomerparameters_53',['getCurrentPhytomerParameters',['../class_plant_architecture.html#aaba5ecb6c069be56b3706a4060f5ff49',1,'PlantArchitecture']]], + ['getcurrentshootparameters_54',['getCurrentShootParameters',['../class_plant_architecture.html#aa696281e805e8879a78dacdf4354ff38',1,'PlantArchitecture::getCurrentShootParameters(const std::string &shoot_type_label)'],['../class_plant_architecture.html#a190d91f02c5cfcfad036879460b2e495',1,'PlantArchitecture::getCurrentShootParameters()']]], + ['getdate_55',['getDate',['../classhelios_1_1_context.html#a95dd5bc221cd8bcb4efabd0122d59b4f',1,'helios::Context']]], + ['getdepthmap_56',['getDepthMap',['../class_visualizer.html#a7c6362d7dc0f0bd4bba53195ce92b84e',1,'Visualizer']]], + ['getdiffuseflux_57',['getDiffuseFlux',['../class_radiation_model.html#af8450f2308aee38272b4aef87f0c547b',1,'RadiationModel']]], + ['getdiffusefraction_58',['getDiffuseFraction',['../class_solar_position.html#af8dbd15453ce775dab5b2c5a49b1c93b',1,'SolarPosition']]], + ['getdiskobjectcenter_59',['getDiskObjectCenter',['../classhelios_1_1_context.html#a213aea1539e0bb38965cf2953b1831df',1,'helios::Context']]], + ['getdiskobjectpointer_60',['getDiskObjectPointer',['../classhelios_1_1_context.html#a17c1256a1f57fbae1f34e04b66b76ca8',1,'helios::Context']]], + ['getdiskobjectsize_61',['getDiskObjectSize',['../classhelios_1_1_context.html#acee51918d3ee1d9892e5a51106a625d9',1,'helios::Context']]], + ['getdiskobjectsubdivisioncount_62',['getDiskObjectSubdivisionCount',['../classhelios_1_1_context.html#a86ffc9a6cdcd3851231c64dcc152123c',1,'helios::Context']]], + ['getdomainboundingbox_63',['getDomainBoundingBox',['../classhelios_1_1_context.html#a8690412a63d1eff69e679e48d03c9838',1,'helios::Context::getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const'],['../classhelios_1_1_context.html#ad4ac166bb01547d1cefb1ace7a9b966d',1,'helios::Context::getDomainBoundingBox(const std::vector< uint > &UUIDs, helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const'],['../class_visualizer.html#ae9c98dee278e9bcd5f85b871ff8ddfe5',1,'Visualizer::getDomainBoundingBox(helios::vec2 &xbounds, helios::vec2 &ybounds, helios::vec2 &zbounds) const']]], + ['getdomainboundingradius_64',['getDomainBoundingRadius',['../class_visualizer.html#a783739e072baeafc943a077dcb1cc3d5',1,'Visualizer']]], + ['getdomainboundingsphere_65',['getDomainBoundingSphere',['../classhelios_1_1_context.html#a3a6b0d25c5d9febb17787982c9f09d63',1,'helios::Context::getDomainBoundingSphere(helios::vec3 &center, float &radius) const'],['../classhelios_1_1_context.html#af3e048e969f06e3a0cf36ed3d76766ca',1,'helios::Context::getDomainBoundingSphere(const std::vector< uint > &UUIDs, helios::vec3 &center, float &radius) const']]], + ['getempiricalmodelcoefficients_66',['getEmpiricalModelCoefficients',['../class_photosynthesis_model.html#a86094d579852c2dc846acc2a97e6ac44',1,'PhotosynthesisModel']]], + ['getfarquharcoefficientsfromlibrary_67',['getFarquharCoefficientsFromLibrary',['../class_photosynthesis_model.html#ae40570ef642d5d4dc070dce9ba093f16',1,'PhotosynthesisModel']]], + ['getfarquharmodelcoefficients_68',['getFarquharModelCoefficients',['../class_photosynthesis_model.html#aeab92cd73298c5f89626b30ce8c41cf9',1,'PhotosynthesisModel']]], + ['getfileextension_69',['getFileExtension',['../global_8h.html#a58e660bb08e1ce13466825ae666467ef',1,'helios']]], + ['getfilename_70',['getFileName',['../global_8h.html#a63bd49091fdab0e262b051f61fb9a902',1,'helios']]], + ['getfilepath_71',['getFilePath',['../global_8h.html#ad76f15d03b511d1bf5123d64d804d6e8',1,'helios']]], + ['getfilestem_72',['getFileStem',['../global_8h.html#a9fff8cb6c3474de479f81c12f173d3ed',1,'helios']]], + ['getframebuffersize_73',['getFramebufferSize',['../class_visualizer.html#ab3b0261a21e7f552d55e4d2fda55f94f',1,'Visualizer']]], + ['getfruituuids_74',['getFruitUUIDs',['../class_canopy_generator.html#a8ab509f22c4bdffd57b44f67f43ce728',1,'CanopyGenerator::getFruitUUIDs(uint PlantID)'],['../class_canopy_generator.html#abdcc431929f98e57db4b9ed2dc26a616',1,'CanopyGenerator::getFruitUUIDs()']]], + ['getglobaldata_75',['getGlobalData',['../classhelios_1_1_context.html#a972fa4a45b2775f6047d41b88dc69d03',1,'helios::Context::getGlobalData(const char *label, int &data) const'],['../classhelios_1_1_context.html#a175d9a1955f428b0f2d6b11ab3b17659',1,'helios::Context::getGlobalData(const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#a98cbb0d37dc9fafaad14184cb889534f',1,'helios::Context::getGlobalData(const char *label, uint &data) const'],['../classhelios_1_1_context.html#a931a92ba7e9916c64d164bc1f29ff754',1,'helios::Context::getGlobalData(const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#ac1f5f6c3f24577cd5c4657c441483425',1,'helios::Context::getGlobalData(const char *label, float &data) const'],['../classhelios_1_1_context.html#a863264ab1339ba35c3754bfbf4c69eec',1,'helios::Context::getGlobalData(const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#a8ec49c820f10831b4b27059d4d1749d6',1,'helios::Context::getGlobalData(const char *label, double &data) const'],['../classhelios_1_1_context.html#a66e7d689b62d9ad47fb85ad45664c97f',1,'helios::Context::getGlobalData(const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#a6f4d6971c05d78aff30b92d277014b9f',1,'helios::Context::getGlobalData(const char *label, helios::vec2 &data) const'],['../classhelios_1_1_context.html#afc90a3d0143273e436541fc3bc9c5554',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec2 > &data) const'],['../classhelios_1_1_context.html#a990fdccf51979e235a1acba08e54583b',1,'helios::Context::getGlobalData(const char *label, helios::vec3 &data) const'],['../classhelios_1_1_context.html#a0376e2dc456e481bd055d5a84b7785f2',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec3 > &data) const'],['../classhelios_1_1_context.html#a3f621b536c3585d7f808698e2f0cd826',1,'helios::Context::getGlobalData(const char *label, helios::vec4 &data) const'],['../classhelios_1_1_context.html#ab0f329c8584b002dda2d77719073bf5d',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::vec4 > &data) const'],['../classhelios_1_1_context.html#aea16d4845e23fe44ae1da4c032ea57e3',1,'helios::Context::getGlobalData(const char *label, helios::int2 &data) const'],['../classhelios_1_1_context.html#a609563835616233b15fd263bb2e8857d',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int2 > &data) const'],['../classhelios_1_1_context.html#aba7c4fe63193509f40ca6682cddfa9a3',1,'helios::Context::getGlobalData(const char *label, helios::int3 &data) const'],['../classhelios_1_1_context.html#abbc6d463f6d722fca56ad219c8278c16',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int3 > &data) const'],['../classhelios_1_1_context.html#a2b2f0570e50711f34bb24dc01c8a7b43',1,'helios::Context::getGlobalData(const char *label, helios::int4 &data) const'],['../classhelios_1_1_context.html#ad08d9d2bea2c93b14ae2b3678aea2e29',1,'helios::Context::getGlobalData(const char *label, std::vector< helios::int4 > &data) const'],['../classhelios_1_1_context.html#a890583b0897bfcd730d137838fa7e155',1,'helios::Context::getGlobalData(const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a0572c1557ec60ae7389072e8ab3c2113',1,'helios::Context::getGlobalData(const char *label, std::vector< std::string > &data) const']]], + ['getglobaldatasize_76',['getGlobalDataSize',['../classhelios_1_1_context.html#a96d1060d1329dc467380ce2e5eafd559',1,'helios::Context']]], + ['getglobaldatatype_77',['getGlobalDataType',['../classhelios_1_1_context.html#a94bf0b919e5e6034fa45fbae2f575947',1,'helios::Context']]], + ['getgridboundingbox_78',['getGridBoundingBox',['../class_li_d_a_rcloud.html#a041ac4ba388c407a35b7f895029038e6',1,'LiDARcloud']]], + ['getgridcellcount_79',['getGridCellCount',['../class_li_d_a_rcloud.html#a28297a71becd69b30820d69b110fcc90',1,'LiDARcloud']]], + ['getgridcenter_80',['getGridCenter',['../class_aerial_li_d_a_rcloud.html#ad639b0d2337b74b1bd4949cc2aba88e0',1,'AerialLiDARcloud']]], + ['getgridextent_81',['getGridExtent',['../class_aerial_li_d_a_rcloud.html#a85ea1ea67ed12f2bbcfc28ef9a78dd77',1,'AerialLiDARcloud']]], + ['getgridresolution_82',['getGridResolution',['../class_aerial_li_d_a_rcloud.html#ae750e548d565d6305e600c5af8360fdb',1,'AerialLiDARcloud']]], + ['getgridrotation_83',['getGridRotation',['../class_aerial_li_d_a_rcloud.html#aace3b3baae4a75be461eb31f617ee695',1,'AerialLiDARcloud']]], + ['getgrounduuids_84',['getGroundUUIDs',['../class_canopy_generator.html#a6f0003d6ca29cbb56657442c7a48ad14',1,'CanopyGenerator']]], + ['gethitboundingbox_85',['getHitBoundingBox',['../class_aerial_li_d_a_rcloud.html#a74b0e833ecb6ee1b3ce3010f3d38d74d',1,'AerialLiDARcloud::getHitBoundingBox()'],['../class_li_d_a_rcloud.html#a45bc37a4d26eb74a944c594a7f3cb54b',1,'LiDARcloud::getHitBoundingBox()']]], + ['gethitcolor_86',['getHitColor',['../class_aerial_li_d_a_rcloud.html#af8f49444eb1d166837c322d03ea1cbfa',1,'AerialLiDARcloud::getHitColor()'],['../class_li_d_a_rcloud.html#aafafed9102966992d3cfb3772fa2ada1',1,'LiDARcloud::getHitColor()']]], + ['gethitcount_87',['getHitCount',['../class_aerial_li_d_a_rcloud.html#aaf287ef121543f10e9e73579bf77281a',1,'AerialLiDARcloud::getHitCount()'],['../class_li_d_a_rcloud.html#a691fd3bbd1262d80e10a674c82c6f568',1,'LiDARcloud::getHitCount()']]], + ['gethitdata_88',['getHitData',['../class_aerial_li_d_a_rcloud.html#a240af79b825bc886e886ff7ff0e0476c',1,'AerialLiDARcloud::getHitData()'],['../class_li_d_a_rcloud.html#a274ef68850afa3f288bb648d9fd6a59a',1,'LiDARcloud::getHitData()']]], + ['gethitgridcell_89',['getHitGridCell',['../class_aerial_li_d_a_rcloud.html#a26bc32e67d3195222f11fb72fb7d63da',1,'AerialLiDARcloud::getHitGridCell()'],['../class_li_d_a_rcloud.html#a251c4f3bbefdd07212cd8fe1037dc0d7',1,'LiDARcloud::getHitGridCell(uint index) const']]], + ['gethitindex_90',['getHitIndex',['../class_li_d_a_rcloud.html#a34eee980f365fdd5469a0cc6ee3a36f5',1,'LiDARcloud']]], + ['gethitraydir_91',['getHitRaydir',['../class_aerial_li_d_a_rcloud.html#ac0f8ba05e24d146d01ee2af0fb9ece7d',1,'AerialLiDARcloud::getHitRaydir()'],['../class_li_d_a_rcloud.html#aa91258bd97d6fcacd3313d8b55cceed4',1,'LiDARcloud::getHitRaydir()']]], + ['gethitscanid_92',['getHitScanID',['../class_aerial_li_d_a_rcloud.html#aaa2bbd15dad66355175fb733630456a4',1,'AerialLiDARcloud::getHitScanID()'],['../class_li_d_a_rcloud.html#a5510b2a0d0a878930e9f11331494bf41',1,'LiDARcloud::getHitScanID()']]], + ['gethitxyz_93',['getHitXYZ',['../class_aerial_li_d_a_rcloud.html#a3363ac3ffff1bbdd164b6074010d75ba',1,'AerialLiDARcloud::getHitXYZ()'],['../class_li_d_a_rcloud.html#ac5f234b6200419f10fe82c9abe409cbd',1,'LiDARcloud::getHitXYZ()']]], + ['getimageresolution_94',['getImageResolution',['../classhelios_1_1_texture.html#a4e106c0c80f0c4c065e5ff71193aaeab',1,'helios::Texture']]], + ['getimageresolutionjpeg_95',['getImageResolutionJPEG',['../global_8h.html#a94c80cbffdccaea7991b439acf8e9eb4',1,'helios']]], + ['getjuliandate_96',['getJulianDate',['../classhelios_1_1_context.html#a23f2611ed71eeefe8cf772cab98de4d4',1,'helios::Context']]], + ['getleafspectra_97',['getLeafSpectra',['../class_leaf_optics.html#a6b9fa9b6fb34fe7738e425b19118005a',1,'LeafOptics']]], + ['getleafuuids_98',['getLeafUUIDs',['../class_canopy_generator.html#a3509012720b5fd256a14bc2924a3b164',1,'CanopyGenerator::getLeafUUIDs(uint PlantID)'],['../class_canopy_generator.html#a73680976a2826f0b5dbf567551fd5593',1,'CanopyGenerator::getLeafUUIDs()'],['../class_weber_penn_tree.html#af4368c1f900503f6d72f0c0e569fe8e5',1,'WeberPennTree::getLeafUUIDs()']]], + ['getlength_99',['getLength',['../classhelios_1_1_tube.html#ad3c194a0f9977e212ac425aefe4032bf',1,'helios::Tube::getLength()'],['../classhelios_1_1_cone.html#ada36b3fe4850f16c4dfa58c38a8da80c',1,'helios::Cone::getLength()']]], + ['getloadedxmlfiles_100',['getLoadedXMLFiles',['../classhelios_1_1_context.html#a48a8a843b99c36ad357dba13ee6f1774',1,'helios::Context']]], + ['getlocation_101',['getLocation',['../classhelios_1_1_context.html#af4b1fa52419259a0c8a2faeb7484a439',1,'helios::Context']]], + ['getmonthstring_102',['getMonthString',['../classhelios_1_1_context.html#a6189f6ab35669f4fefde571ec362247c',1,'helios::Context']]], + ['getnodecolors_103',['getNodeColors',['../classhelios_1_1_tube.html#aae753418cb304e97c296240dc9919388',1,'helios::Tube']]], + ['getnodecoordinate_104',['getNodeCoordinate',['../classhelios_1_1_cone.html#a4f6ddd7fd23d61528ada9df1e333ad17',1,'helios::Cone']]], + ['getnodecoordinates_105',['getNodeCoordinates',['../classhelios_1_1_cone.html#a9eaab4331e325c85ce9f4c101135c966',1,'helios::Cone']]], + ['getnoderadii_106',['getNodeRadii',['../classhelios_1_1_tube.html#a29823b956371d22b35add97fc6831cab',1,'helios::Tube::getNodeRadii()'],['../classhelios_1_1_cone.html#adc5370734810e4b526bf0d42e143ecf8',1,'helios::Cone::getNodeRadii() const']]], + ['getnoderadius_107',['getNodeRadius',['../classhelios_1_1_cone.html#a2334ca87f6bb556b411c8a51476b523c',1,'helios::Cone']]], + ['getnodes_108',['getNodes',['../classhelios_1_1_tube.html#ab55e8f7d7a948941027f169d714e365b',1,'helios::Tube']]], + ['getnormal_109',['getNormal',['../classhelios_1_1_tile.html#ab8c70daf8c14bc60caf499b5adce301c',1,'helios::Tile']]], + ['getobjectarea_110',['getObjectArea',['../classhelios_1_1_context.html#aac46a608ec7719e4702cd861667925f1',1,'helios::Context']]], + ['getobjectboundingbox_111',['getObjectBoundingBox',['../classhelios_1_1_context.html#a1b9871bf670404adc1d952e59429ec38',1,'helios::Context::getObjectBoundingBox(uint ObjID, vec3 &min_corner, vec3 &max_corner) const'],['../classhelios_1_1_context.html#ab5aef932bd4b64b1cee932423172ab6f',1,'helios::Context::getObjectBoundingBox(const std::vector< uint > &ObjID, vec3 &min_corner, vec3 &max_corner) const']]], + ['getobjectcenter_112',['getObjectCenter',['../classhelios_1_1_compound_object.html#aff66ca85a22d7f8a2501039e2e7183a7',1,'helios::CompoundObject::getObjectCenter()'],['../classhelios_1_1_context.html#a4fe8ddd10f0d34bfe0b2a4aea648442a',1,'helios::Context::getObjectCenter(uint ObjID) const']]], + ['getobjectcount_113',['getObjectCount',['../classhelios_1_1_context.html#a54b9c5503ad33d1dcc8f6a5c74f7ea76',1,'helios::Context']]], + ['getobjectdata_114',['getObjectData',['../classhelios_1_1_compound_object.html#ac91c73ac495bc4a93cc9a89d0eb58f47',1,'helios::CompoundObject::getObjectData(const char *label, int &data) const'],['../classhelios_1_1_compound_object.html#aed77927b3d3fe0ea7ea674b20a8acce1',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int > &data) const'],['../classhelios_1_1_compound_object.html#ac91bb0e57aa261b003de76b3e008a762',1,'helios::CompoundObject::getObjectData(const char *label, uint &data) const'],['../classhelios_1_1_compound_object.html#a7be991a83ada928f25c23cf7ca3b1822',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_compound_object.html#ac222719662ca008014cdd045bedd3d96',1,'helios::CompoundObject::getObjectData(const char *label, float &data) const'],['../classhelios_1_1_compound_object.html#ac128057ff1d7cabb9dfbfb33216cb0c5',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< float > &data) const'],['../classhelios_1_1_compound_object.html#a6d99ef1cacec7471bb79b57601a7a6ee',1,'helios::CompoundObject::getObjectData(const char *label, double &data) const'],['../classhelios_1_1_compound_object.html#ac7af8838d7132683dd9fdbffd1288579',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< double > &data) const'],['../classhelios_1_1_compound_object.html#aef1aadca9de0e9a66500ca5879ab3755',1,'helios::CompoundObject::getObjectData(const char *label, vec2 &data) const'],['../classhelios_1_1_compound_object.html#af7574c29395681941d4d875e304b93de',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_compound_object.html#acea74a2c138c1e5d832df864a231e486',1,'helios::CompoundObject::getObjectData(const char *label, vec3 &data) const'],['../classhelios_1_1_compound_object.html#a797a5fd8f08ff7220b15ae1d5accb6cd',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_compound_object.html#a52661efba4b57415b073fcf839069623',1,'helios::CompoundObject::getObjectData(const char *label, vec4 &data) const'],['../classhelios_1_1_compound_object.html#a15ef0fda0196b4de933e4379d5f8234f',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_compound_object.html#a768a439ecb0d6e8449b31cd137317168',1,'helios::CompoundObject::getObjectData(const char *label, int2 &data) const'],['../classhelios_1_1_compound_object.html#af4d1accb01b8dd2f968296c43dfb6d97',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_compound_object.html#a95f20aead49e80032b0673273de436f2',1,'helios::CompoundObject::getObjectData(const char *label, int3 &data) const'],['../classhelios_1_1_compound_object.html#a6cb032fa5f5b6de86f234eb237980586',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_compound_object.html#a2c0dcefe9e05ec04b001ad94f475f34c',1,'helios::CompoundObject::getObjectData(const char *label, int4 &data) const'],['../classhelios_1_1_compound_object.html#aba75ef4dd5b01b02fc99f9a1d957d70b',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_compound_object.html#afa77a9712c207752cd56522f2dbca52b',1,'helios::CompoundObject::getObjectData(const char *label, std::string &data) const'],['../classhelios_1_1_compound_object.html#adfd1f35dc8785f223c02cc940360e6a5',1,'helios::CompoundObject::getObjectData(const char *label, std::vector< std::string > &data) const'],['../classhelios_1_1_context.html#a3511ff568337b501ca878c99d97c9b52',1,'helios::Context::getObjectData(uint objID, const char *label, int &data) const'],['../classhelios_1_1_context.html#ae75ddc9a945ec876533211f52b8cd22e',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#abbd59cc4e7bcad35b43ea7240c4d5558',1,'helios::Context::getObjectData(uint objID, const char *label, uint &data) const'],['../classhelios_1_1_context.html#a22d510fad177ca319bdac0a94ee8f069',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#a8935a9cdf6e34e72bcb636a97043a474',1,'helios::Context::getObjectData(uint objID, const char *label, float &data) const'],['../classhelios_1_1_context.html#a293d899bb22cae1db8cf6c2cc813055d',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#ae222f3351535f3aea35e76cbe2ca2d67',1,'helios::Context::getObjectData(uint objID, const char *label, double &data) const'],['../classhelios_1_1_context.html#acda7f75e833791bcbd74ca8b37272a8b',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#af8fa05c716517966f7abcc2f4019c709',1,'helios::Context::getObjectData(uint objID, const char *label, vec2 &data) const'],['../classhelios_1_1_context.html#a2e691b7f0b630792f50b5423e23ebab1',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_context.html#a628cf051625e33549044cd20656519ac',1,'helios::Context::getObjectData(uint objID, const char *label, vec3 &data) const'],['../classhelios_1_1_context.html#a6606603899859e211de9f56cd49bf92d',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_context.html#ac2b7e667ec37c88868ba0752919da1c9',1,'helios::Context::getObjectData(uint objID, const char *label, vec4 &data) const'],['../classhelios_1_1_context.html#ace5025b962226a75c4984ee6ecc21356',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_context.html#ae56639e95fae8796545efde94fa84bcc',1,'helios::Context::getObjectData(uint objID, const char *label, int2 &data) const'],['../classhelios_1_1_context.html#a39b169b41cf94516afd863f580c2b772',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_context.html#ac58fc8f10c12dc54265491576650a0c6',1,'helios::Context::getObjectData(uint objID, const char *label, int3 &data) const'],['../classhelios_1_1_context.html#ac097e42620523f2d57d28eecd02954a4',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_context.html#aa393d7b0f24855b2e54480be71c09ad2',1,'helios::Context::getObjectData(uint objID, const char *label, int4 &data) const'],['../classhelios_1_1_context.html#a7ca032799776268d30fe185a76100e0e',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_context.html#a1eae737b91ec70ae6490a8c403936975',1,'helios::Context::getObjectData(uint objID, const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a158215e07c921d11e495b3805823b725',1,'helios::Context::getObjectData(uint objID, const char *label, std::vector< std::string > &data) const']]], + ['getobjectdatasize_115',['getObjectDataSize',['../classhelios_1_1_compound_object.html#a03b2516f8e7e8ae921ea61e4f571eb1d',1,'helios::CompoundObject::getObjectDataSize()'],['../classhelios_1_1_context.html#ac251e9be64f3a35b6d2e6441c2a46f40',1,'helios::Context::getObjectDataSize()']]], + ['getobjectdatatype_116',['getObjectDataType',['../classhelios_1_1_compound_object.html#abbcfd5c545991ee59cf3f77acf300b1e',1,'helios::CompoundObject::getObjectDataType()'],['../classhelios_1_1_context.html#af77ff3ea4a7668d2b5cb03bc6fc5f5b6',1,'helios::Context::getObjectDataType()']]], + ['getobjectid_117',['getObjectID',['../classhelios_1_1_compound_object.html#a28c85b0cf4dee51dd7997b7b78e4f442',1,'helios::CompoundObject']]], + ['getobjectpointer_118',['getObjectPointer',['../classhelios_1_1_context.html#a3d9493949db2c5d8ddeef30afd2a9a0a',1,'helios::Context']]], + ['getobjectprimitivecount_119',['getObjectPrimitiveCount',['../classhelios_1_1_context.html#a457ccd0bcf9870aef138b22c4a160aeb',1,'helios::Context']]], + ['getobjectprimitiveuuids_120',['getObjectPrimitiveUUIDs',['../classhelios_1_1_context.html#a7d0b3a6ca36b02702b06208a735a3b03',1,'helios::Context::getObjectPrimitiveUUIDs(uint ObjID) const'],['../classhelios_1_1_context.html#a09e60fbbd3c4be1f8345a9de3695ccdd',1,'helios::Context::getObjectPrimitiveUUIDs(const std::vector< uint > &ObjIDs) const'],['../classhelios_1_1_context.html#a266fba7ca4a0a1536c49f1e3ce918b1e',1,'helios::Context::getObjectPrimitiveUUIDs(const std::vector< std::vector< uint > > &ObjIDs) const']]], + ['getobjecttexturefile_121',['getObjectTextureFile',['../classhelios_1_1_context.html#aacd4cff3b170281516dcafb3fa83b84a',1,'helios::Context']]], + ['getobjecttransformationmatrix_122',['getObjectTransformationMatrix',['../classhelios_1_1_context.html#af9e972c138b0626cece9eea5f018b418',1,'helios::Context']]], + ['getobjecttype_123',['getObjectType',['../classhelios_1_1_compound_object.html#ab07473392ca1e4c439c909c83cc9730b',1,'helios::CompoundObject::getObjectType()'],['../classhelios_1_1_context.html#a75ae3ee4580c4420059fe95755dc22d2',1,'helios::Context::getObjectType(uint ObjID) const']]], + ['getpatchcenter_124',['getPatchCenter',['../classhelios_1_1_context.html#a4165df43e5ab752e81bc2b7d7caf19d5',1,'helios::Context']]], + ['getpatchsize_125',['getPatchSize',['../classhelios_1_1_context.html#ab3f802aca8dd1930127d9f76358e71cf',1,'helios::Context']]], + ['getplantcount_126',['getPlantCount',['../class_canopy_generator.html#aba9e186286ade3cd2ced0be80b3b8b89',1,'CanopyGenerator']]], + ['getplantflowerobjectids_127',['getPlantFlowerObjectIDs',['../class_plant_architecture.html#a1cb3e4ba93c7a94558c3c07496e550c2',1,'PlantArchitecture']]], + ['getplantfruitobjectids_128',['getPlantFruitObjectIDs',['../class_plant_architecture.html#aac602c603ac136c3aaffad052bd844d4',1,'PlantArchitecture']]], + ['getplantheight_129',['getPlantHeight',['../class_plant_architecture.html#a4d6e2ec9e60b12bc56e2ee753ba9f9cf',1,'PlantArchitecture']]], + ['getplantinternodeobjectids_130',['getPlantInternodeObjectIDs',['../class_plant_architecture.html#a53967340a1c9b88f4b804522f081ce62',1,'PlantArchitecture']]], + ['getplantleafcount_131',['getPlantLeafCount',['../class_plant_architecture.html#a74032e7973d410bf861e0c3448bee3ce',1,'PlantArchitecture']]], + ['getplantleafinclinationangledistribution_132',['getPlantLeafInclinationAngleDistribution',['../class_plant_architecture.html#a512ba39f59b0ebc35d8f699c136a00fe',1,'PlantArchitecture']]], + ['getplantleafobjectids_133',['getPlantLeafObjectIDs',['../class_plant_architecture.html#afcdea7f14c6ca722d39d94ff19ba87b4',1,'PlantArchitecture']]], + ['getplantpeduncleobjectids_134',['getPlantPeduncleObjectIDs',['../class_plant_architecture.html#af8a9f26212baf6695d71d44b982e6adf',1,'PlantArchitecture']]], + ['getplantpetioleobjectids_135',['getPlantPetioleObjectIDs',['../class_plant_architecture.html#aee2486b87dca29982dd1b380aa3510fb',1,'PlantArchitecture']]], + ['getplantstemheight_136',['getPlantStemHeight',['../class_plant_architecture.html#a7f34d9100299ca2d0d44984e9403915a',1,'PlantArchitecture']]], + ['getpolymeshobjectpointer_137',['getPolymeshObjectPointer',['../classhelios_1_1_context.html#a5a10781f6c1e24b226a32b1e1369f5c1',1,'helios::Context']]], + ['getpolymeshobjectvolume_138',['getPolymeshObjectVolume',['../classhelios_1_1_context.html#aad71b3e493ab0e47c6d4496d14e89803',1,'helios::Context']]], + ['getprimitivearea_139',['getPrimitiveArea',['../classhelios_1_1_context.html#a1dafe58b3251d2ef9d09112258b2e85d',1,'helios::Context']]], + ['getprimitiveboundingbox_140',['getPrimitiveBoundingBox',['../classhelios_1_1_context.html#abf2e26ac2b32556878be6626a8876569',1,'helios::Context::getPrimitiveBoundingBox(uint UUID, vec3 &min_corner, vec3 &max_corner) const'],['../classhelios_1_1_context.html#a808527f76dec2683cbc168250c4f69be',1,'helios::Context::getPrimitiveBoundingBox(const std::vector< uint > &UUID, vec3 &min_corner, vec3 &max_corner) const']]], + ['getprimitivecolor_141',['getPrimitiveColor',['../classhelios_1_1_context.html#a1223205f1080b0b7024b8f97950779b8',1,'helios::Context']]], + ['getprimitivecolorrgb_142',['getPrimitiveColorRGB',['../classhelios_1_1_context.html#a8550633570ee91e4f09ec1464810bd7b',1,'helios::Context']]], + ['getprimitivecolorrgba_143',['getPrimitiveColorRGBA',['../classhelios_1_1_context.html#a4e29adcb908d55172efd239f294b49e5',1,'helios::Context']]], + ['getprimitivecount_144',['getPrimitiveCount',['../classhelios_1_1_compound_object.html#a0eb06d37710a7dc9f5b915fc33f191a0',1,'helios::CompoundObject::getPrimitiveCount()'],['../group__primitives.html#ga4d3447fb04c25e685bcc82599e2b173d',1,'helios::Context::getPrimitiveCount() const']]], + ['getprimitivedata_145',['getPrimitiveData',['../classhelios_1_1_context.html#a2144eea981e4030c973287ce2c38315e',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int &data) const'],['../classhelios_1_1_context.html#ad1f6453da61e8e64ba91f589b7cc4eb0',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int > &data) const'],['../classhelios_1_1_context.html#a420487af4a23ed5b527069c6471efd93',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, uint &data) const'],['../classhelios_1_1_context.html#add62ecdb7cc13510670c9c45bc8725a3',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< uint > &data) const'],['../classhelios_1_1_context.html#aa54fb6e8a942845010ae669505adc2e8',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, float &data) const'],['../classhelios_1_1_context.html#a466dea76918a4bd02e4a355ab70f161b',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< float > &data) const'],['../classhelios_1_1_context.html#a802b10b84762052e52b9ff1861604c58',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, double &data) const'],['../classhelios_1_1_context.html#a65d1918df796575a5e5bc8c470ff3201',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< double > &data) const'],['../classhelios_1_1_context.html#a2ac5198c45a57b7926f4dbd9129fcad5',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec2 &data) const'],['../classhelios_1_1_context.html#ab0fb70ff8b6e81901df14efe07ae7ff4',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec2 > &data) const'],['../classhelios_1_1_context.html#abbe503b705cfdeb903becdb7fb082dae',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec3 &data) const'],['../classhelios_1_1_context.html#a83619185959d1dae4570674a3855f808',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec3 > &data) const'],['../classhelios_1_1_context.html#a0e62c9bb97e4cbbcd56518b060e9cae5',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, vec4 &data) const'],['../classhelios_1_1_context.html#a29fed63e84bf5b5111b0e98f499da56e',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< vec4 > &data) const'],['../classhelios_1_1_context.html#a72ee49f503ff0c4937d9aa81b72689ed',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int2 &data) const'],['../classhelios_1_1_context.html#ae76119a1083016c2cffed9eb443aaa62',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int2 > &data) const'],['../classhelios_1_1_context.html#a18f0ede968126842068551834391e3ad',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int3 &data) const'],['../classhelios_1_1_context.html#a5c37491d4bc0a1d69ffcaf214e6c2fe7',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int3 > &data) const'],['../classhelios_1_1_context.html#afe292fdf1d3c7983427c699e4a2eca3a',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, int4 &data) const'],['../classhelios_1_1_context.html#a8ebaded3f143fc9c673765ab3fda5366',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< int4 > &data) const'],['../classhelios_1_1_context.html#ad1a2ca668fb5f5043f23f7a50c22483f',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::string &data) const'],['../classhelios_1_1_context.html#a1d8cd543d68c2bc3b7ef876421284f15',1,'helios::Context::getPrimitiveData(uint UUID, const char *label, std::vector< std::string > &data) const']]], + ['getprimitivedatasize_146',['getPrimitiveDataSize',['../classhelios_1_1_context.html#a4b64585d356463ac759472f099660eca',1,'helios::Context']]], + ['getprimitivedatatype_147',['getPrimitiveDataType',['../classhelios_1_1_context.html#a9c894ecd12e0d893c53ffcfa9e90c0b6',1,'helios::Context']]], + ['getprimitivenormal_148',['getPrimitiveNormal',['../classhelios_1_1_context.html#abfeadf8e6a35eb97da1439abc21c434e',1,'helios::Context']]], + ['getprimitiveparentobjectid_149',['getPrimitiveParentObjectID',['../classhelios_1_1_context.html#a2d3e254d04f913e590a645b54886436e',1,'helios::Context']]], + ['getprimitivesolidfraction_150',['getPrimitiveSolidFraction',['../classhelios_1_1_context.html#a6e8a5e2044331158d69d6f9bd88fc0f7',1,'helios::Context']]], + ['getprimitivetexturefile_151',['getPrimitiveTextureFile',['../classhelios_1_1_context.html#a4fffad72d1ebb517d9c41837e448d4f5',1,'helios::Context']]], + ['getprimitivetexturesize_152',['getPrimitiveTextureSize',['../classhelios_1_1_context.html#a7fec62cbf2c2d56603b2750cbb4a4d9f',1,'helios::Context']]], + ['getprimitivetexturetransparencydata_153',['getPrimitiveTextureTransparencyData',['../classhelios_1_1_context.html#a98ad773979fff9efda47b44d71ac8e06',1,'helios::Context']]], + ['getprimitivetextureuv_154',['getPrimitiveTextureUV',['../classhelios_1_1_context.html#a5702f94aaba15bf6757aeb4d72d7774d',1,'helios::Context']]], + ['getprimitivetransformationmatrix_155',['getPrimitiveTransformationMatrix',['../classhelios_1_1_context.html#a046e855d15fa88088be01adea38a67fd',1,'helios::Context']]], + ['getprimitivetype_156',['getPrimitiveType',['../classhelios_1_1_context.html#a67bfd66f0a445f6485f1099f9eadc949',1,'helios::Context']]], + ['getprimitiveuuids_157',['getPrimitiveUUIDs',['../classhelios_1_1_compound_object.html#ab3973a7c8ccb1aa0ce3f21ffe461ef7b',1,'helios::CompoundObject']]], + ['getprimitivevertices_158',['getPrimitiveVertices',['../classhelios_1_1_context.html#ae8542fd1452150d3302675a0a3d991ed',1,'helios::Context']]], + ['getradius_159',['getRadius',['../classhelios_1_1_sphere.html#a38cf8b6959d22577a1a2f9a6c675bc8b',1,'helios::Sphere']]], + ['getrandomgenerator_160',['getRandomGenerator',['../classhelios_1_1_context.html#a96a928fa28d3d771ba310f798b56bd63',1,'helios::Context']]], + ['getscanbeamdivergence_161',['getScanBeamDivergence',['../class_aerial_li_d_a_rcloud.html#a4097c1d3994f57e0f0e2e602c7ca5c04',1,'AerialLiDARcloud::getScanBeamDivergence()'],['../class_li_d_a_rcloud.html#a9d93e6cd9decccf271fbf3fbd5c74a5a',1,'LiDARcloud::getScanBeamDivergence()']]], + ['getscanbeamexitdiameter_162',['getScanBeamExitDiameter',['../class_aerial_li_d_a_rcloud.html#ae6cbd6375be39129231233d66061afca',1,'AerialLiDARcloud::getScanBeamExitDiameter()'],['../class_li_d_a_rcloud.html#abab6b81a3d96226a766cc2450993407f',1,'LiDARcloud::getScanBeamExitDiameter()']]], + ['getscancenter_163',['getScanCenter',['../class_aerial_li_d_a_rcloud.html#a1ce1efbe6af71f54dcccd3743918aa72',1,'AerialLiDARcloud']]], + ['getscancolumnformat_164',['getScanColumnFormat',['../class_li_d_a_rcloud.html#abbe892f01508dc69bcc5b28bea5472bf',1,'LiDARcloud']]], + ['getscanconeangle_165',['getScanConeAngle',['../class_aerial_li_d_a_rcloud.html#a0dbf5535304d6d87d67a0d41c5d2310f',1,'AerialLiDARcloud']]], + ['getscancount_166',['getScanCount',['../class_aerial_li_d_a_rcloud.html#ab363717911dada3af4fdafa914532a6a',1,'AerialLiDARcloud::getScanCount()'],['../class_li_d_a_rcloud.html#aaa463ea1aaebb03abd8c3ec87091291a',1,'LiDARcloud::getScanCount()']]], + ['getscandensity_167',['getScanDensity',['../class_aerial_li_d_a_rcloud.html#a0c4627b15014ebe8c79053ed75f6cfb4',1,'AerialLiDARcloud']]], + ['getscanextent_168',['getScanExtent',['../class_aerial_li_d_a_rcloud.html#ad5bd68f06fef597d8c1f1aac3142acc6',1,'AerialLiDARcloud']]], + ['getscanorigin_169',['getScanOrigin',['../class_li_d_a_rcloud.html#aa657ed32a8831ebf4f2e4a9203b683ef',1,'LiDARcloud']]], + ['getscanrangephi_170',['getScanRangePhi',['../class_li_d_a_rcloud.html#ab314aac88834eb3938fc2f37e34807e3',1,'LiDARcloud']]], + ['getscanrangetheta_171',['getScanRangeTheta',['../class_li_d_a_rcloud.html#a7f0237a83da6997e973fde9939440979',1,'LiDARcloud']]], + ['getscansizephi_172',['getScanSizePhi',['../class_li_d_a_rcloud.html#aaf04cd04c2b1bc162106a0e47cff6d29',1,'LiDARcloud']]], + ['getscansizetheta_173',['getScanSizeTheta',['../class_li_d_a_rcloud.html#a40809c7a709a6c9ccb4beddca21f8ac9',1,'LiDARcloud']]], + ['getsegmentvolume_174',['getSegmentVolume',['../classhelios_1_1_tube.html#a2966ff764897904282082f23a76756b8',1,'helios::Tube']]], + ['getsize_175',['getSize',['../classhelios_1_1_tile.html#aa8daadd99bd57f647837e26890fcfeac',1,'helios::Tile::getSize()'],['../classhelios_1_1_box.html#afd79ee17402ab6367896fe8278800f34',1,'helios::Box::getSize()'],['../classhelios_1_1_disk.html#a23c03df1f2e351659a08420a41a74eb5',1,'helios::Disk::getSize()']]], + ['getskyenergy_176',['getSkyEnergy',['../class_radiation_model.html#a9c9a5f6cb6b0ba6e3780aba8a4da8a0d',1,'RadiationModel']]], + ['getsolarflux_177',['getSolarFlux',['../class_solar_position.html#a9701cb29a0336a11c445d285405b6956',1,'SolarPosition']]], + ['getsolarfluxnir_178',['getSolarFluxNIR',['../class_solar_position.html#a611461f700df9efa7c56b6f4ee7712b7',1,'SolarPosition']]], + ['getsolarfluxpar_179',['getSolarFluxPAR',['../class_solar_position.html#a5c6635160944b5b8202ea9965da6de9d',1,'SolarPosition']]], + ['getsolidfraction_180',['getSolidFraction',['../classhelios_1_1_texture.html#a685024e8394b49433f26a0dcd6665d86',1,'helios::Texture']]], + ['getsourceflux_181',['getSourceFlux',['../class_radiation_model.html#a9d4ea3e08514b90e617695ab2ee2fbf8',1,'RadiationModel']]], + ['getsourceposition_182',['getSourcePosition',['../class_radiation_model.html#ab8ec35514a0e4b53ce8a64d3f390427c',1,'RadiationModel']]], + ['getsphereobjectcenter_183',['getSphereObjectCenter',['../classhelios_1_1_context.html#a4f75af0785498d14eb3f5a3539cb16b1',1,'helios::Context']]], + ['getsphereobjectpointer_184',['getSphereObjectPointer',['../classhelios_1_1_context.html#a8ed7580efa323c0f5e53e97d00e16c85',1,'helios::Context']]], + ['getsphereobjectradius_185',['getSphereObjectRadius',['../classhelios_1_1_context.html#a5afb4fd92e9a726fb396779d1f2ae92b',1,'helios::Context']]], + ['getsphereobjectsubdivisioncount_186',['getSphereObjectSubdivisionCount',['../classhelios_1_1_context.html#adadbc5a5378a874cd6705ed681fb9e6a',1,'helios::Context']]], + ['getsphereobjectvolume_187',['getSphereObjectVolume',['../classhelios_1_1_context.html#ae92df5975ec7fa257e7633d6551e2a87',1,'helios::Context']]], + ['getsubdivisioncount_188',['getSubdivisionCount',['../classhelios_1_1_tile.html#a4f4198becfe3cafd989b5aa6cd21d5cf',1,'helios::Tile::getSubdivisionCount()'],['../classhelios_1_1_sphere.html#a152107e463d6765ba27ff8f3ab737711',1,'helios::Sphere::getSubdivisionCount()'],['../classhelios_1_1_tube.html#abf9bb1153b3607a5d616aafeee06e43e',1,'helios::Tube::getSubdivisionCount()'],['../classhelios_1_1_box.html#a6f25b211d8740257329f841cda737a4f',1,'helios::Box::getSubdivisionCount()'],['../classhelios_1_1_disk.html#a8dc2a195735ee3321b274274e7e0352e',1,'helios::Disk::getSubdivisionCount()'],['../classhelios_1_1_cone.html#a051a2c5760d53a6c0b95f66cab9cbf73',1,'helios::Cone::getSubdivisionCount()']]], + ['getsunazimuth_189',['getSunAzimuth',['../class_solar_position.html#a2b736578f75ecb8532556931b8263dc4',1,'SolarPosition']]], + ['getsundirectionspherical_190',['getSunDirectionSpherical',['../class_solar_position.html#adad5310db742ef9f2754e75095aeea92',1,'SolarPosition']]], + ['getsundirectionvector_191',['getSunDirectionVector',['../class_solar_position.html#af889756d5b3d7d3c366887fae1fb86ab',1,'SolarPosition']]], + ['getsunelevation_192',['getSunElevation',['../class_solar_position.html#a307e963d840abb9ee7867579fec69fa2',1,'SolarPosition']]], + ['getsunrisetime_193',['getSunriseTime',['../class_solar_position.html#a2d15fe2ca0d29adf33971916b1d8cd83',1,'SolarPosition']]], + ['getsunsettime_194',['getSunsetTime',['../class_solar_position.html#a4c58aa642b4fc2300d1c1447388bc0d8',1,'SolarPosition']]], + ['getsunzenith_195',['getSunZenith',['../class_solar_position.html#a4c4ba4931d13c6cc2ad69e8eab90ac14',1,'SolarPosition']]], + ['gettexturefile_196',['getTextureFile',['../classhelios_1_1_texture.html#a0371473a81deb9bb19b8274109b75ef8',1,'helios::Texture::getTextureFile()'],['../classhelios_1_1_compound_object.html#a3e43ebd386e7a6663fa877613b9d27fa',1,'helios::CompoundObject::getTextureFile()']]], + ['gettextureuv_197',['getTextureUV',['../classhelios_1_1_tile.html#a94deb25ac31abc1eb02dfe6913b4546f',1,'helios::Tile']]], + ['gettileobjectarearatio_198',['getTileObjectAreaRatio',['../classhelios_1_1_context.html#a9943834b21ccfb9ac1c519e47f959c92',1,'helios::Context::getTileObjectAreaRatio(uint ObjectID) const'],['../classhelios_1_1_context.html#afdebad3fd25bb8b9fa228020c3b11329',1,'helios::Context::getTileObjectAreaRatio(const std::vector< uint > &ObjectID) const']]], + ['gettileobjectcenter_199',['getTileObjectCenter',['../classhelios_1_1_context.html#aa60f87c9bc771e613f60db73188a149d',1,'helios::Context']]], + ['gettileobjectnormal_200',['getTileObjectNormal',['../classhelios_1_1_context.html#a64f4bcadff461357aa390d7f5dad2ba7',1,'helios::Context']]], + ['gettileobjectpointer_201',['getTileObjectPointer',['../classhelios_1_1_context.html#ad2b762dd7b31126150c6e6dc350a3914',1,'helios::Context']]], + ['gettileobjectsize_202',['getTileObjectSize',['../classhelios_1_1_context.html#a457654b4a1f96a4979f83299dd9752df',1,'helios::Context']]], + ['gettileobjectsubdivisioncount_203',['getTileObjectSubdivisionCount',['../classhelios_1_1_context.html#a9320e4577eb131e7efe05677d30591b3',1,'helios::Context']]], + ['gettileobjecttextureuv_204',['getTileObjectTextureUV',['../classhelios_1_1_context.html#a00718598a9c308dabe8fc24f85683210',1,'helios::Context']]], + ['gettileobjectvertices_205',['getTileObjectVertices',['../classhelios_1_1_context.html#ab77b708ac6b39c1c5e8ecaa4988403b0',1,'helios::Context']]], + ['gettime_206',['getTime',['../classhelios_1_1_context.html#a847ecbb2297e60220a23b67c39b0f6e2',1,'helios::Context']]], + ['gettimeserieslength_207',['getTimeseriesLength',['../group__timeseries.html#ga56d13f8c949e68137581a3c974790892',1,'helios::Context']]], + ['gettotalabsorbedflux_208',['getTotalAbsorbedFlux',['../class_radiation_model.html#a5e95e775550a2000798a97b00857bdd2',1,'RadiationModel']]], + ['gettransformationmatrix_209',['getTransformationMatrix',['../classhelios_1_1_compound_object.html#ac1e98d4f8098dadda345f9dc6dae73ca',1,'helios::CompoundObject']]], + ['gettransparencydata_210',['getTransparencyData',['../classhelios_1_1_texture.html#a798c3a24b21fc853db299d1f1f84a61c',1,'helios::Texture']]], + ['gettreeparameters_211',['getTreeParameters',['../class_weber_penn_tree.html#aac5619ac480517f8f01cb465d0dc4a6f',1,'WeberPennTree']]], + ['gettriangle_212',['getTriangle',['../class_li_d_a_rcloud.html#aa1a1af5eea22185e59c267c8e4d94c9e',1,'LiDARcloud']]], + ['gettrianglecount_213',['getTriangleCount',['../class_li_d_a_rcloud.html#abcdbf834959379a189a60efed41f3e52',1,'LiDARcloud']]], + ['gettrianglevertex_214',['getTriangleVertex',['../classhelios_1_1_context.html#a846f93175f8b45f44237e88155af8fde',1,'helios::Context']]], + ['gettrianglevertices_215',['getTriangleVertices',['../classhelios_1_1_tube.html#a6aedd14e533981bd79497ba13b33f2c9',1,'helios::Tube']]], + ['gettrunkuuids_216',['getTrunkUUIDs',['../class_canopy_generator.html#aa8e95a610c03588592acebbbba5d638e',1,'CanopyGenerator::getTrunkUUIDs(uint PlantID)'],['../class_canopy_generator.html#a44b2d0846bb08d331281a822df41daa6',1,'CanopyGenerator::getTrunkUUIDs()'],['../class_weber_penn_tree.html#ab247d9368368263dfdded18a43917f98',1,'WeberPennTree::getTrunkUUIDs()']]], + ['gettubeobjectnodecolors_217',['getTubeObjectNodeColors',['../classhelios_1_1_context.html#a7ad271dabb4291067f9a39d4c92e6ffd',1,'helios::Context']]], + ['gettubeobjectnoderadii_218',['getTubeObjectNodeRadii',['../classhelios_1_1_context.html#a6a58d8f1a8446a213d9a21e67ae8ed97',1,'helios::Context']]], + ['gettubeobjectnodes_219',['getTubeObjectNodes',['../classhelios_1_1_context.html#aa4650e7a0a16be12615870ff9a567ae3',1,'helios::Context']]], + ['gettubeobjectpointer_220',['getTubeObjectPointer',['../classhelios_1_1_context.html#ab26f963c75aa99d797a43860479910b0',1,'helios::Context']]], + ['gettubeobjectsegmentvolume_221',['getTubeObjectSegmentVolume',['../classhelios_1_1_context.html#a10928031db222e77e93ac8088f4b001d',1,'helios::Context']]], + ['gettubeobjectsubdivisioncount_222',['getTubeObjectSubdivisionCount',['../classhelios_1_1_context.html#a272ba030971b86c7d3da57ff90784e0f',1,'helios::Context']]], + ['gettubeobjectvolume_223',['getTubeObjectVolume',['../classhelios_1_1_context.html#a56b82c3f009084451225003b2b461b6f',1,'helios::Context']]], + ['getuniqueprimitiveparentobjectids_224',['getUniquePrimitiveParentObjectIDs',['../classhelios_1_1_context.html#a18a276db8d3c1d754bbd1ca475deec82',1,'helios::Context::getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs) const'],['../classhelios_1_1_context.html#a1f50af8c859a5b2ee0973c9ed5c10284',1,'helios::Context::getUniquePrimitiveParentObjectIDs(const std::vector< uint > &UUIDs, bool include_ObjID_zero) const']]], + ['getvariation_225',['getVariation',['../_canopy_generator_8h.html#accfb46da54c7b0e83878a1331bbc94d1',1,'getVariation(float V, std::minstd_rand0 &generator, bool positive=false): CanopyGenerator.cpp'],['../_canopy_generator_8h.html#aa3a6e1a26b799f4a2006703314499fed',1,'getVariation(int V, std::minstd_rand0 &generator, bool positive=false): CanopyGenerator.cpp'],['../_canopy_generator_8h.html#a6cdee9cb4984f78c818e46eb2a5b62e6',1,'getVariation(uint V, std::minstd_rand0 &generator): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#aa0b21a2d6b9506b33d05047716d671e0',1,'getVariation(float V, std::minstd_rand0 &generator, bool positive): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#a9f90ba8fe8a074a822424ff748579f25',1,'getVariation(int V, std::minstd_rand0 &generator, bool positive): CanopyGenerator.cpp'],['../_canopy_generator_8cpp.html#a6cdee9cb4984f78c818e46eb2a5b62e6',1,'getVariation(uint V, std::minstd_rand0 &generator): CanopyGenerator.cpp']]], + ['getvertices_226',['getVertices',['../classhelios_1_1_tile.html#aaea21403039646db33792c95be929afd',1,'helios::Tile']]], + ['getvolume_227',['getVolume',['../classhelios_1_1_sphere.html#a3d6a8e9f8c0daee1e093593d6006c906',1,'helios::Sphere::getVolume()'],['../classhelios_1_1_tube.html#aaa11cc27d6f704a989c3e5b0fe1b8055',1,'helios::Tube::getVolume()'],['../classhelios_1_1_box.html#a3d3d0b20e22aff306fde02bd7e2a4f84',1,'helios::Box::getVolume()'],['../classhelios_1_1_polymesh.html#ad901c4de0e202f44c16fc9af29481538',1,'helios::Polymesh::getVolume()'],['../classhelios_1_1_cone.html#aff2cb2fc89c68b75a038a9604ce73cd0',1,'helios::Cone::getVolume()']]], + ['getvoxelcenter_228',['getVoxelCenter',['../classhelios_1_1_context.html#acadf5206cbfed7b8eaa2835702349cd9',1,'helios::Context']]], + ['getvoxelsize_229',['getVoxelSize',['../classhelios_1_1_context.html#a6a3f85d4f29f8f7432b6ef605172a1cb',1,'helios::Context']]], + ['getwindowpixelsrgb_230',['getWindowPixelsRGB',['../class_visualizer.html#a15828ea9966b9729b56c9ddfccd4c117',1,'Visualizer']]], + ['getwindowsize_231',['getWindowSize',['../class_visualizer.html#ae6b83402c798f56334851f77b898de52',1,'Visualizer']]], + ['gobletgrapevineparameters_232',['GobletGrapevineParameters',['../struct_goblet_grapevine_parameters.html#a0274d6f6b1f13bbf7a383de5c2bc8726',1,'GobletGrapevineParameters::GobletGrapevineParameters()'],['../struct_goblet_grapevine_parameters.html#a498ce7f62d575b0bc914e9d48d94fbb2',1,'GobletGrapevineParameters::GobletGrapevineParameters(const pugi::xml_node canopy_node)']]], + ['gradientdescent_233',['GradientDescent',['../struct_camera_calibration.html#a5bfbb206b8271b406cda85eb5ae23a1b',1,'CameraCalibration']]], + ['grapevinegoblet_234',['grapevineGoblet',['../class_canopy_generator.html#a8f2d498637c464ee852109e6085cde8a',1,'CanopyGenerator']]], + ['grapevinesplit_235',['grapevineSplit',['../class_canopy_generator.html#a8747bad1af97214059c38043241f0b47',1,'CanopyGenerator']]], + ['grapevineunilateral_236',['grapevineUnilateral',['../class_canopy_generator.html#aac9104d7c6565e860737310de06981f8',1,'CanopyGenerator']]], + ['grapevinevsp_237',['grapevineVSP',['../class_canopy_generator.html#aaffe5cdb82a779785bc6d5e35e622812',1,'CanopyGenerator']]], + ['gridijk2index_238',['gridijk2index',['../class_aerial_li_d_a_rcloud.html#a35c81e8cda423b84c94fc33ee4163d47',1,'AerialLiDARcloud']]], + ['gridindex2ijk_239',['gridindex2ijk',['../class_aerial_li_d_a_rcloud.html#add78af9b69161c5c532a23c8df009d2e',1,'AerialLiDARcloud']]] ]; diff --git a/doc/html/search/functions_e.js b/doc/html/search/functions_e.js index ca504f988..bcfbc8abc 100644 --- a/doc/html/search/functions_e.js +++ b/doc/html/search/functions_e.js @@ -51,5 +51,6 @@ var searchData= ['printobjectinfo_48',['printObjectInfo',['../classhelios_1_1_context.html#a963fbdd1d4c3d270d2eb8f49a22b274a',1,'helios::Context']]], ['printprimitiveinfo_49',['printPrimitiveInfo',['../classhelios_1_1_context.html#a355617da1f3faa4d01ca4d95425e9c0b',1,'helios::Context']]], ['printwindow_50',['printWindow',['../class_visualizer.html#a2db00c518bf610fdcb70e0ec5a5a0e32',1,'Visualizer::printWindow()'],['../class_visualizer.html#a1840b4285caa645e6b8b28144478cfe1',1,'Visualizer::printWindow(const char *outfile)']]], - ['prospect_51',['PROSPECT',['../class_leaf_optics.html#a8af86e8cce4d721230ddc746580b7dcf',1,'LeafOptics']]] + ['prospect_51',['PROSPECT',['../class_leaf_optics.html#a8af86e8cce4d721230ddc746580b7dcf',1,'LeafOptics']]], + ['prunetubenodes_52',['pruneTubeNodes',['../classhelios_1_1_tube.html#a4d8bc6d05dab160f3e0fbee48ad3fd2c',1,'helios::Tube::pruneTubeNodes()'],['../classhelios_1_1_context.html#a7e47d13895d9e65ae719e2afce8d1d54',1,'helios::Context::pruneTubeNodes()']]] ]; diff --git a/doc/html/search/pages_10.js b/doc/html/search/pages_10.js index 370548609..e0395a9c1 100644 --- a/doc/html/search/pages_10.js +++ b/doc/html/search/pages_10.js @@ -1,11 +1,8 @@ var searchData= [ - ['ide_20with_20helios_0',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], - ['increasing_20graphics_20driver_20timeout_1',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], - ['input_20output_2',['File Input/Output',['../_i_o.html',1,'']]], - ['ins_3',['Plug-ins',['../_plug_ins.html',1,'']]], - ['install_20and_20set_20up_4',['Install and Set-up',['../_dependent_software.html',1,'']]], - ['interception_5',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], - ['interception_20and_20fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_6',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['intersection_20plugin_20documentation_7',['Voxel Intersection Plugin Documentation',['../_voxel_intersection_doc.html',1,'PlugIns']]] + ['layer_20conductance_20model_20plugin_20documentation_0',['Boundary-Layer Conductance Model Plugin Documentation',['../_b_l_conductance_doc.html',1,'PlugIns']]], + ['leaf_20area_20for_20a_20homogeneous_20canopy_1',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['lidar_20point_20cloud_20plugin_20documentation_2',['LiDAR Point Cloud Plugin Documentation',['../_aerial_li_d_a_r_doc.html',1,'Aerial LiDAR Point Cloud Plugin Documentation'],['../_li_d_a_r_doc.html',1,'LiDAR Point Cloud Plugin Documentation']]], + ['light_20interception_3',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], + ['light_20interception_20and_20fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_4',['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/search/pages_11.js b/doc/html/search/pages_11.js index e0395a9c1..48220f176 100644 --- a/doc/html/search/pages_11.js +++ b/doc/html/search/pages_11.js @@ -1,8 +1,7 @@ var searchData= [ - ['layer_20conductance_20model_20plugin_20documentation_0',['Boundary-Layer Conductance Model Plugin Documentation',['../_b_l_conductance_doc.html',1,'PlugIns']]], - ['leaf_20area_20for_20a_20homogeneous_20canopy_1',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['lidar_20point_20cloud_20plugin_20documentation_2',['LiDAR Point Cloud Plugin Documentation',['../_aerial_li_d_a_r_doc.html',1,'Aerial LiDAR Point Cloud Plugin Documentation'],['../_li_d_a_r_doc.html',1,'LiDAR Point Cloud Plugin Documentation']]], - ['light_20interception_3',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], - ['light_20interception_20and_20fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_4',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]] + ['making_20texture_20mask_20files_20with_20transparency_20using_20gimp_0',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['mask_20files_20with_20transparency_20using_20gimp_1',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['model_20basics_20tree_20light_20interception_2',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], + ['model_20plugin_20documentation_3',['Model Plugin Documentation',['../_b_l_conductance_doc.html',1,'Boundary-Layer Conductance Model Plugin Documentation'],['../_dummy.html',1,'Dummy Model Plugin Documentation'],['../_energy_balance_doc.html',1,'Energy Balance Model 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'],['../_stomatal_doc.html',1,'Stomatal Conductance Model Plugin Documentation']]] ]; diff --git a/doc/html/search/pages_12.js b/doc/html/search/pages_12.js index 48220f176..d1d10c0a6 100644 --- a/doc/html/search/pages_12.js +++ b/doc/html/search/pages_12.js @@ -1,7 +1,7 @@ var searchData= [ - ['making_20texture_20mask_20files_20with_20transparency_20using_20gimp_0',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['mask_20files_20with_20transparency_20using_20gimp_1',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['model_20basics_20tree_20light_20interception_2',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], - ['model_20plugin_20documentation_3',['Model Plugin Documentation',['../_b_l_conductance_doc.html',1,'Boundary-Layer Conductance Model Plugin Documentation'],['../_dummy.html',1,'Dummy Model Plugin Documentation'],['../_energy_balance_doc.html',1,'Energy Balance Model 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'],['../_stomatal_doc.html',1,'Stomatal Conductance Model Plugin Documentation']]] + ['of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_0',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['optix_20version_1',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], + ['output_2',['File Input/Output',['../_i_o.html',1,'']]], + ['overview_3',['Overview',['../_overview.html',1,'']]] ]; diff --git a/doc/html/search/pages_13.js b/doc/html/search/pages_13.js index d1d10c0a6..19c025143 100644 --- a/doc/html/search/pages_13.js +++ b/doc/html/search/pages_13.js @@ -1,7 +1,15 @@ var searchData= [ - ['of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_0',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['optix_20version_1',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], - ['output_2',['File Input/Output',['../_i_o.html',1,'']]], - ['overview_3',['Overview',['../_overview.html',1,'']]] + ['penn_20tree_20plugin_20documentation_0',['Weber-Penn Tree Plugin Documentation',['../_weber_penn_doc.html',1,'PlugIns']]], + ['photosynthesis_20model_20plugin_20documentation_1',['Photosynthesis Model Plugin Documentation',['../_photosynthesis_doc.html',1,'PlugIns']]], + ['plant_20architecture_20model_20plugin_20documentation_2',['Plant Architecture Model Plugin Documentation',['../_plant_architecture_doc.html',1,'PlugIns']]], + ['plug_20ins_3',['Plug-ins',['../_plug_ins.html',1,'']]], + ['plugin_20documentation_4',['Plugin 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']]], + ['plugins_5',['Writing Plugins',['../_plugins.html',1,'']]], + ['ply_20using_20blender_6',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], + ['point_20cloud_20plugin_20documentation_7',['Point Cloud Plugin Documentation',['../_aerial_li_d_a_r_doc.html',1,'Aerial LiDAR Point Cloud Plugin Documentation'],['../_li_d_a_r_doc.html',1,'LiDAR Point Cloud Plugin Documentation']]], + ['polygon_20file_20formats_20to_20ply_20using_20blender_8',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], + ['position_20plugin_20documentation_9',['Solar Position Plugin Documentation',['../_solar_position_doc.html',1,'PlugIns']]], + ['primitive_20data_10',['Tutorial 5: Primitive Data',['../context_primdata.html',1,'Tutorials']]], + ['primitive_20data_20values_11',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]] ]; diff --git a/doc/html/search/pages_14.js b/doc/html/search/pages_14.js index 19c025143..7db5e9b1d 100644 --- a/doc/html/search/pages_14.js +++ b/doc/html/search/pages_14.js @@ -1,15 +1,6 @@ var searchData= [ - ['penn_20tree_20plugin_20documentation_0',['Weber-Penn Tree Plugin Documentation',['../_weber_penn_doc.html',1,'PlugIns']]], - ['photosynthesis_20model_20plugin_20documentation_1',['Photosynthesis Model Plugin Documentation',['../_photosynthesis_doc.html',1,'PlugIns']]], - ['plant_20architecture_20model_20plugin_20documentation_2',['Plant Architecture Model Plugin Documentation',['../_plant_architecture_doc.html',1,'PlugIns']]], - ['plug_20ins_3',['Plug-ins',['../_plug_ins.html',1,'']]], - ['plugin_20documentation_4',['Plugin 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']]], - ['plugins_5',['Writing Plugins',['../_plugins.html',1,'']]], - ['ply_20using_20blender_6',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], - ['point_20cloud_20plugin_20documentation_7',['Point Cloud Plugin Documentation',['../_aerial_li_d_a_r_doc.html',1,'Aerial LiDAR Point Cloud Plugin Documentation'],['../_li_d_a_r_doc.html',1,'LiDAR Point Cloud Plugin Documentation']]], - ['polygon_20file_20formats_20to_20ply_20using_20blender_8',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], - ['position_20plugin_20documentation_9',['Solar Position Plugin Documentation',['../_solar_position_doc.html',1,'PlugIns']]], - ['primitive_20data_10',['Tutorial 5: Primitive Data',['../context_primdata.html',1,'Tutorials']]], - ['primitive_20data_20values_11',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]] + ['radiation_20model_20basics_20tree_20light_20interception_0',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], + ['radiation_20model_20plugin_20documentation_1',['Radiation Model Plugin Documentation',['../_radiation_doc.html',1,'PlugIns']]], + ['right_20cuda_20and_20optix_20version_2',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]] ]; diff --git a/doc/html/search/pages_15.js b/doc/html/search/pages_15.js index 7db5e9b1d..cc7611ea1 100644 --- a/doc/html/search/pages_15.js +++ b/doc/html/search/pages_15.js @@ -1,6 +1,9 @@ var searchData= [ - ['radiation_20model_20basics_20tree_20light_20interception_0',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], - ['radiation_20model_20plugin_20documentation_1',['Radiation Model Plugin Documentation',['../_radiation_doc.html',1,'PlugIns']]], - ['right_20cuda_20and_20optix_20version_2',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]] + ['self_20test_20tutorial_0',['Tutorial 0: Context Self-Test Tutorial',['../context_selftest.html',1,'Tutorials']]], + ['set_20up_1',['Install and Set-up',['../_dependent_software.html',1,'']]], + ['shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_2',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['solar_20position_20plugin_20documentation_3',['Solar Position Plugin Documentation',['../_solar_position_doc.html',1,'PlugIns']]], + ['stomatal_20conductance_20model_20plugin_20documentation_4',['Stomatal Conductance Model Plugin Documentation',['../_stomatal_doc.html',1,'PlugIns']]], + ['sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_5',['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/search/pages_16.js b/doc/html/search/pages_16.js index cc7611ea1..941cc70be 100644 --- a/doc/html/search/pages_16.js +++ b/doc/html/search/pages_16.js @@ -1,9 +1,24 @@ var searchData= [ - ['self_20test_20tutorial_0',['Tutorial 0: Context Self-Test Tutorial',['../context_selftest.html',1,'Tutorials']]], - ['set_20up_1',['Install and Set-up',['../_dependent_software.html',1,'']]], - ['shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_2',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['solar_20position_20plugin_20documentation_3',['Solar Position Plugin Documentation',['../_solar_position_doc.html',1,'PlugIns']]], - ['stomatal_20conductance_20model_20plugin_20documentation_4',['Stomatal Conductance Model Plugin Documentation',['../_stomatal_doc.html',1,'PlugIns']]], - ['sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_5',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]] + ['test_20tutorial_0',['Tutorial 0: Context Self-Test Tutorial',['../context_selftest.html',1,'Tutorials']]], + ['texture_20mask_20files_20with_20transparency_20using_20gimp_1',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['the_20clion_20ide_20with_20helios_2',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], + ['the_20right_20cuda_20and_20optix_20version_3',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], + ['timeout_4',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], + ['to_20ply_20using_20blender_5',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], + ['transparency_20using_20gimp_6',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['tree_20light_20interception_7',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], + ['tree_20plugin_20documentation_8',['Weber-Penn Tree Plugin Documentation',['../_weber_penn_doc.html',1,'PlugIns']]], + ['tutorial_9',['Tutorial',['../context_selftest.html',1,'Tutorial 0: Context Self-Test Tutorial'],['../context_vectors.html',1,'Tutorial 1: Helios Vector Types Tutorial']]], + ['tutorial_200_3a_20context_20self_20test_20tutorial_10',['Tutorial 0: Context Self-Test Tutorial',['../context_selftest.html',1,'Tutorials']]], + ['tutorial_2010_3a_20radiation_20model_20basics_20tree_20light_20interception_11',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], + ['tutorial_2011_3a_20light_20interception_20and_20fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_12',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['tutorial_201_3a_20helios_20vector_20types_20tutorial_13',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], + ['tutorial_202_3a_20working_20with_20context_20geometry_14',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], + ['tutorial_205_3a_20primitive_20data_15',['Tutorial 5: Primitive Data',['../context_primdata.html',1,'Tutorials']]], + ['tutorial_206_3a_20global_20data_16',['Tutorial 6: Global Data',['../context_globaldata.html',1,'Tutorials']]], + ['tutorial_207_3a_20visualizer_20basics_17',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]], + ['tutorial_208_3a_20visualizing_20primitive_20data_20values_18',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], + ['tutorials_19',['Tutorials',['../_tutorials.html',1,'']]], + ['types_20tutorial_20',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]] ]; diff --git a/doc/html/search/pages_17.js b/doc/html/search/pages_17.js index 941cc70be..683011bc6 100644 --- a/doc/html/search/pages_17.js +++ b/doc/html/search/pages_17.js @@ -1,24 +1,8 @@ var searchData= [ - ['test_20tutorial_0',['Tutorial 0: Context Self-Test Tutorial',['../context_selftest.html',1,'Tutorials']]], - ['texture_20mask_20files_20with_20transparency_20using_20gimp_1',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['the_20clion_20ide_20with_20helios_2',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], - ['the_20right_20cuda_20and_20optix_20version_3',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], - ['timeout_4',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], - ['to_20ply_20using_20blender_5',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], - ['transparency_20using_20gimp_6',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['tree_20light_20interception_7',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], - ['tree_20plugin_20documentation_8',['Weber-Penn Tree Plugin Documentation',['../_weber_penn_doc.html',1,'PlugIns']]], - ['tutorial_9',['Tutorial',['../context_selftest.html',1,'Tutorial 0: Context Self-Test Tutorial'],['../context_vectors.html',1,'Tutorial 1: Helios Vector Types Tutorial']]], - ['tutorial_200_3a_20context_20self_20test_20tutorial_10',['Tutorial 0: Context Self-Test Tutorial',['../context_selftest.html',1,'Tutorials']]], - ['tutorial_2010_3a_20radiation_20model_20basics_20tree_20light_20interception_11',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], - ['tutorial_2011_3a_20light_20interception_20and_20fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_12',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['tutorial_201_3a_20helios_20vector_20types_20tutorial_13',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], - ['tutorial_202_3a_20working_20with_20context_20geometry_14',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], - ['tutorial_205_3a_20primitive_20data_15',['Tutorial 5: Primitive Data',['../context_primdata.html',1,'Tutorials']]], - ['tutorial_206_3a_20global_20data_16',['Tutorial 6: Global Data',['../context_globaldata.html',1,'Tutorials']]], - ['tutorial_207_3a_20visualizer_20basics_17',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]], - ['tutorial_208_3a_20visualizing_20primitive_20data_20values_18',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], - ['tutorials_19',['Tutorials',['../_tutorials.html',1,'']]], - ['types_20tutorial_20',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]] + ['up_0',['Install and Set-up',['../_dependent_software.html',1,'']]], + ['user_20api_20guide_1',['User/API Guide',['../_a_p_i.html',1,'']]], + ['using_20blender_2',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], + ['using_20gimp_3',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['using_20the_20clion_20ide_20with_20helios_4',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]] ]; diff --git a/doc/html/search/pages_18.js b/doc/html/search/pages_18.js index 683011bc6..8c7a8c498 100644 --- a/doc/html/search/pages_18.js +++ b/doc/html/search/pages_18.js @@ -1,8 +1,10 @@ var searchData= [ - ['up_0',['Install and Set-up',['../_dependent_software.html',1,'']]], - ['user_20api_20guide_1',['User/API Guide',['../_a_p_i.html',1,'']]], - ['using_20blender_2',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], - ['using_20gimp_3',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['using_20the_20clion_20ide_20with_20helios_4',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]] + ['values_0',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], + ['vector_20types_20tutorial_1',['Tutorial 1: Helios Vector Types Tutorial',['../context_vectors.html',1,'Tutorials']]], + ['version_2',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], + ['visualizer_20basics_3',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]], + ['visualizer_20plugin_20documentation_4',['Visualizer Plugin Documentation',['../_visualizer_doc.html',1,'PlugIns']]], + ['visualizing_20primitive_20data_20values_5',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], + ['voxel_20intersection_20plugin_20documentation_6',['Voxel Intersection Plugin Documentation',['../_voxel_intersection_doc.html',1,'PlugIns']]] ]; diff --git a/doc/html/search/pages_19.js b/doc/html/search/pages_19.js index 37d584909..2d37f211e 100644 --- a/doc/html/search/pages_19.js +++ b/doc/html/search/pages_19.js @@ -1,11 +1,9 @@ var searchData= [ - ['v1_203_2026_0',['Helios Documentation v1.3.26',['../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,'']]], - ['visualizer_20basics_4',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]], - ['visualizer_20plugin_20documentation_5',['Visualizer Plugin Documentation',['../_visualizer_doc.html',1,'PlugIns']]], - ['visualizing_20primitive_20data_20values_6',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]], - ['voxel_20intersection_20plugin_20documentation_7',['Voxel Intersection Plugin Documentation',['../_voxel_intersection_doc.html',1,'PlugIns']]] + ['weber_20penn_20tree_20plugin_20documentation_0',['Weber-Penn Tree Plugin Documentation',['../_weber_penn_doc.html',1,'PlugIns']]], + ['with_20context_20geometry_1',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], + ['with_20helios_2',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], + ['with_20transparency_20using_20gimp_3',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['working_20with_20context_20geometry_4',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], + ['writing_20plugins_5',['Writing Plugins',['../_plugins.html',1,'']]] ]; diff --git a/doc/html/search/pages_1a.js b/doc/html/search/pages_1a.js deleted file mode 100644 index 2d37f211e..000000000 --- a/doc/html/search/pages_1a.js +++ /dev/null @@ -1,9 +0,0 @@ -var searchData= -[ - ['weber_20penn_20tree_20plugin_20documentation_0',['Weber-Penn Tree Plugin Documentation',['../_weber_penn_doc.html',1,'PlugIns']]], - ['with_20context_20geometry_1',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], - ['with_20helios_2',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], - ['with_20transparency_20using_20gimp_3',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['working_20with_20context_20geometry_4',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], - ['writing_20plugins_5',['Writing Plugins',['../_plugins.html',1,'']]] -]; diff --git a/doc/html/search/pages_2.js b/doc/html/search/pages_2.js index b89682b8d..19bdd782d 100644 --- a/doc/html/search/pages_2.js +++ b/doc/html/search/pages_2.js @@ -1,5 +1,4 @@ var searchData= [ - ['26_0',['Helios Documentation v1.3.26',['../index.html',1,'']]], - ['2_3a_20working_20with_20context_20geometry_1',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]] + ['2_3a_20working_20with_20context_20geometry_0',['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 c16a1d4fd..a4833130f 100644 --- a/doc/html/search/pages_3.js +++ b/doc/html/search/pages_3.js @@ -1,4 +1,4 @@ var searchData= [ - ['3_2026_0',['Helios Documentation v1.3.26',['../index.html',1,'']]] + ['5_3a_20primitive_20data_0',['Tutorial 5: Primitive Data',['../context_primdata.html',1,'Tutorials']]] ]; diff --git a/doc/html/search/pages_4.js b/doc/html/search/pages_4.js index a4833130f..24ffab6ff 100644 --- a/doc/html/search/pages_4.js +++ b/doc/html/search/pages_4.js @@ -1,4 +1,4 @@ var searchData= [ - ['5_3a_20primitive_20data_0',['Tutorial 5: Primitive Data',['../context_primdata.html',1,'Tutorials']]] + ['6_3a_20global_20data_0',['Tutorial 6: Global Data',['../context_globaldata.html',1,'Tutorials']]] ]; diff --git a/doc/html/search/pages_5.js b/doc/html/search/pages_5.js index 24ffab6ff..5a8ca5087 100644 --- a/doc/html/search/pages_5.js +++ b/doc/html/search/pages_5.js @@ -1,4 +1,4 @@ var searchData= [ - ['6_3a_20global_20data_0',['Tutorial 6: Global Data',['../context_globaldata.html',1,'Tutorials']]] + ['7_3a_20visualizer_20basics_0',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]] ]; diff --git a/doc/html/search/pages_6.js b/doc/html/search/pages_6.js index 5a8ca5087..2c7084b8a 100644 --- a/doc/html/search/pages_6.js +++ b/doc/html/search/pages_6.js @@ -1,4 +1,4 @@ var searchData= [ - ['7_3a_20visualizer_20basics_0',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]] + ['8_3a_20visualizing_20primitive_20data_20values_0',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]] ]; diff --git a/doc/html/search/pages_7.js b/doc/html/search/pages_7.js index 2c7084b8a..ac3d26691 100644 --- a/doc/html/search/pages_7.js +++ b/doc/html/search/pages_7.js @@ -1,4 +1,11 @@ var searchData= [ - ['8_3a_20visualizing_20primitive_20data_20values_0',['Tutorial 8: Visualizing primitive data values',['../visualizer_pdata.html',1,'Tutorials']]] + ['a_20homogeneous_20canopy_0',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['aerial_20lidar_20point_20cloud_20plugin_20documentation_1',['Aerial LiDAR Point Cloud Plugin Documentation',['../_aerial_li_d_a_r_doc.html',1,'PlugIns']]], + ['and_20fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_2',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['and_20optix_20version_3',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], + ['and_20set_20up_4',['Install and Set-up',['../_dependent_software.html',1,'']]], + ['api_20guide_5',['User/API Guide',['../_a_p_i.html',1,'']]], + ['architecture_20model_20plugin_20documentation_6',['Plant Architecture Model Plugin Documentation',['../_plant_architecture_doc.html',1,'PlugIns']]], + ['area_20for_20a_20homogeneous_20canopy_7',['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/search/pages_8.js b/doc/html/search/pages_8.js index ac3d26691..8094fdf2a 100644 --- a/doc/html/search/pages_8.js +++ b/doc/html/search/pages_8.js @@ -1,11 +1,8 @@ var searchData= [ - ['a_20homogeneous_20canopy_0',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['aerial_20lidar_20point_20cloud_20plugin_20documentation_1',['Aerial LiDAR Point Cloud Plugin Documentation',['../_aerial_li_d_a_r_doc.html',1,'PlugIns']]], - ['and_20fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_2',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['and_20optix_20version_3',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], - ['and_20set_20up_4',['Install and Set-up',['../_dependent_software.html',1,'']]], - ['api_20guide_5',['User/API Guide',['../_a_p_i.html',1,'']]], - ['architecture_20model_20plugin_20documentation_6',['Plant Architecture Model Plugin Documentation',['../_plant_architecture_doc.html',1,'PlugIns']]], - ['area_20for_20a_20homogeneous_20canopy_7',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]] + ['balance_20model_20plugin_20documentation_0',['Energy Balance Model Plugin Documentation',['../_energy_balance_doc.html',1,'PlugIns']]], + ['basics_1',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]], + ['basics_20tree_20light_20interception_2',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], + ['blender_3',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], + ['boundary_20layer_20conductance_20model_20plugin_20documentation_4',['Boundary-Layer Conductance Model Plugin Documentation',['../_b_l_conductance_doc.html',1,'PlugIns']]] ]; diff --git a/doc/html/search/pages_9.js b/doc/html/search/pages_9.js index 8094fdf2a..de06516d9 100644 --- a/doc/html/search/pages_9.js +++ b/doc/html/search/pages_9.js @@ -1,8 +1,13 @@ var searchData= [ - ['balance_20model_20plugin_20documentation_0',['Energy Balance Model Plugin Documentation',['../_energy_balance_doc.html',1,'PlugIns']]], - ['basics_1',['Tutorial 7: Visualizer Basics',['../visualizer_basics.html',1,'Tutorials']]], - ['basics_20tree_20light_20interception_2',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], - ['blender_3',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], - ['boundary_20layer_20conductance_20model_20plugin_20documentation_4',['Boundary-Layer Conductance Model Plugin Documentation',['../_b_l_conductance_doc.html',1,'PlugIns']]] + ['canopy_0',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['canopy_20generator_20plugin_20documentation_1',['Canopy Generator Plugin Documentation',['../_canopy_generator_doc.html',1,'PlugIns']]], + ['choosing_20the_20right_20cuda_20and_20optix_20version_2',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], + ['clion_20ide_20with_20helios_3',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], + ['cloud_20plugin_20documentation_4',['Cloud Plugin Documentation',['../_aerial_li_d_a_r_doc.html',1,'Aerial LiDAR Point Cloud Plugin Documentation'],['../_li_d_a_r_doc.html',1,'LiDAR Point Cloud Plugin Documentation']]], + ['conductance_20model_20plugin_20documentation_5',['Conductance Model Plugin Documentation',['../_b_l_conductance_doc.html',1,'Boundary-Layer Conductance Model Plugin Documentation'],['../_stomatal_doc.html',1,'Stomatal Conductance Model Plugin Documentation']]], + ['context_20geometry_6',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], + ['context_20self_20test_20tutorial_7',['Tutorial 0: Context Self-Test Tutorial',['../context_selftest.html',1,'Tutorials']]], + ['converting_20polygon_20file_20formats_20to_20ply_20using_20blender_8',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], + ['cuda_20and_20optix_20version_9',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]] ]; diff --git a/doc/html/search/pages_a.js b/doc/html/search/pages_a.js index de06516d9..9f1400c21 100644 --- a/doc/html/search/pages_a.js +++ b/doc/html/search/pages_a.js @@ -1,13 +1,8 @@ var searchData= [ - ['canopy_0',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['canopy_20generator_20plugin_20documentation_1',['Canopy Generator Plugin Documentation',['../_canopy_generator_doc.html',1,'PlugIns']]], - ['choosing_20the_20right_20cuda_20and_20optix_20version_2',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]], - ['clion_20ide_20with_20helios_3',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], - ['cloud_20plugin_20documentation_4',['Cloud Plugin Documentation',['../_aerial_li_d_a_r_doc.html',1,'Aerial LiDAR Point Cloud Plugin Documentation'],['../_li_d_a_r_doc.html',1,'LiDAR Point Cloud Plugin Documentation']]], - ['conductance_20model_20plugin_20documentation_5',['Conductance Model Plugin Documentation',['../_b_l_conductance_doc.html',1,'Boundary-Layer Conductance Model Plugin Documentation'],['../_stomatal_doc.html',1,'Stomatal Conductance Model Plugin Documentation']]], - ['context_20geometry_6',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], - ['context_20self_20test_20tutorial_7',['Tutorial 0: Context Self-Test Tutorial',['../context_selftest.html',1,'Tutorials']]], - ['converting_20polygon_20file_20formats_20to_20ply_20using_20blender_8',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], - ['cuda_20and_20optix_20version_9',['Choosing the right CUDA and OptiX version',['../_choosing_c_u_d_a.html',1,'']]] + ['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'],['../index.html',1,'Helios 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']]], + ['driver_20timeout_3',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], + ['dummy_20model_20plugin_20documentation_4',['Dummy Model Plugin Documentation',['../_dummy.html',1,'']]] ]; diff --git a/doc/html/search/pages_b.js b/doc/html/search/pages_b.js index a36505f2a..80b36297d 100644 --- a/doc/html/search/pages_b.js +++ b/doc/html/search/pages_b.js @@ -1,9 +1,4 @@ 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_2026_3',['Helios Documentation v1.3.26',['../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,'']]] + ['energy_20balance_20model_20plugin_20documentation_0',['Energy Balance Model Plugin Documentation',['../_energy_balance_doc.html',1,'PlugIns']]] ]; diff --git a/doc/html/search/pages_c.js b/doc/html/search/pages_c.js index 80b36297d..c63717ad6 100644 --- a/doc/html/search/pages_c.js +++ b/doc/html/search/pages_c.js @@ -1,4 +1,9 @@ var searchData= [ - ['energy_20balance_20model_20plugin_20documentation_0',['Energy Balance Model Plugin Documentation',['../_energy_balance_doc.html',1,'PlugIns']]] + ['file_20formats_20to_20ply_20using_20blender_0',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], + ['file_20input_20output_1',['File Input/Output',['../_i_o.html',1,'']]], + ['files_20with_20transparency_20using_20gimp_2',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['for_20a_20homogeneous_20canopy_3',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['formats_20to_20ply_20using_20blender_4',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], + ['fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_5',['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/search/pages_d.js b/doc/html/search/pages_d.js index c63717ad6..9e100670f 100644 --- a/doc/html/search/pages_d.js +++ b/doc/html/search/pages_d.js @@ -1,9 +1,9 @@ var searchData= [ - ['file_20formats_20to_20ply_20using_20blender_0',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], - ['file_20input_20output_1',['File Input/Output',['../_i_o.html',1,'']]], - ['files_20with_20transparency_20using_20gimp_2',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['for_20a_20homogeneous_20canopy_3',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], - ['formats_20to_20ply_20using_20blender_4',['Converting polygon file formats to .ply using Blender',['../_convert_p_l_y.html',1,'']]], - ['fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_5',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]] + ['generator_20plugin_20documentation_0',['Canopy Generator Plugin Documentation',['../_canopy_generator_doc.html',1,'PlugIns']]], + ['geometry_1',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], + ['gimp_2',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], + ['global_20data_3',['Tutorial 6: Global Data',['../context_globaldata.html',1,'Tutorials']]], + ['graphics_20driver_20timeout_4',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], + ['guide_5',['User/API Guide',['../_a_p_i.html',1,'']]] ]; diff --git a/doc/html/search/pages_e.js b/doc/html/search/pages_e.js index 9e100670f..ad9efad6f 100644 --- a/doc/html/search/pages_e.js +++ b/doc/html/search/pages_e.js @@ -1,9 +1,7 @@ var searchData= [ - ['generator_20plugin_20documentation_0',['Canopy Generator Plugin Documentation',['../_canopy_generator_doc.html',1,'PlugIns']]], - ['geometry_1',['Tutorial 2: Working with Context Geometry',['../context_primitives.html',1,'Tutorials']]], - ['gimp_2',['Making texture mask files with transparency using GIMP',['../_making_masks.html',1,'']]], - ['global_20data_3',['Tutorial 6: Global Data',['../context_globaldata.html',1,'Tutorials']]], - ['graphics_20driver_20timeout_4',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], - ['guide_5',['User/API Guide',['../_a_p_i.html',1,'']]] + ['helios_0',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], + ['helios_20documentation_1',['Helios Documentation',['../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/search/pages_f.js b/doc/html/search/pages_f.js index 3b631c953..370548609 100644 --- a/doc/html/search/pages_f.js +++ b/doc/html/search/pages_f.js @@ -1,7 +1,11 @@ var searchData= [ - ['helios_0',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], - ['helios_20documentation_20v1_203_2026_1',['Helios Documentation v1.3.26',['../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']]] + ['ide_20with_20helios_0',['Using the CLion IDE with Helios',['../_c_lion_i_d_e.html',1,'']]], + ['increasing_20graphics_20driver_20timeout_1',['Increasing graphics driver timeout',['../_p_c_g_p_u_timeout.html',1,'']]], + ['input_20output_2',['File Input/Output',['../_i_o.html',1,'']]], + ['ins_3',['Plug-ins',['../_plug_ins.html',1,'']]], + ['install_20and_20set_20up_4',['Install and Set-up',['../_dependent_software.html',1,'']]], + ['interception_5',['Tutorial 10: Radiation model basics - tree light interception',['../radiation_basics.html',1,'Tutorials']]], + ['interception_20and_20fraction_20of_20sunlit_20shaded_20leaf_20area_20for_20a_20homogeneous_20canopy_6',['Tutorial 11: Light interception and fraction of sunlit/shaded leaf area for a homogeneous canopy',['../radiation__beers_law.html',1,'Tutorials']]], + ['intersection_20plugin_20documentation_7',['Voxel Intersection Plugin Documentation',['../_voxel_intersection_doc.html',1,'PlugIns']]] ]; diff --git a/doc/html/search/related_0.js b/doc/html/search/related_0.js index 228621233..a1f73e50e 100644 --- a/doc/html/search/related_0.js +++ b/doc/html/search/related_0.js @@ -1,4 +1,4 @@ var searchData= [ - ['operator_3c_3c_0',['operator<<',['../structhelios_1_1int2.html#aa70779f707686be8b004587a4220a153',1,'helios::int2::operator<<'],['../structhelios_1_1int3.html#a6f576c885af0d781aadda850a2ca77af',1,'helios::int3::operator<<'],['../structhelios_1_1int4.html#ac6b32d39d92de0b8585c64048040f0f9',1,'helios::int4::operator<<'],['../structhelios_1_1vec2.html#a5e585083b0cf16b2e73958747390e152',1,'helios::vec2::operator<<'],['../structhelios_1_1vec3.html#a87277dd90e0869e2e8e7ce376dfc7033',1,'helios::vec3::operator<<'],['../structhelios_1_1vec4.html#a32f014dbb41084ece2ad85f19c540874',1,'helios::vec4::operator<<'],['../structhelios_1_1_r_g_bcolor.html#a47b1d94ed5f6fa0c8ae897e02a06435c',1,'helios::RGBcolor::operator<<'],['../structhelios_1_1_r_g_b_acolor.html#aaa76985ee048b321703f78175e2b87b7',1,'helios::RGBAcolor::operator<<'],['../structhelios_1_1_date.html#a189b8537a2e0696e2f38da34e0f13eec',1,'helios::Date::operator<<'],['../structhelios_1_1_time.html#a5d53ebf9a42b3aa2d959a3cd5023c71a',1,'helios::Time::operator<<'],['../structhelios_1_1_location.html#a60375cac034fe50880b47569df6e8f69',1,'helios::Location::operator<<'],['../structhelios_1_1_spherical_coord.html#ad9381fdcb8448d8834b4ce43465b5335',1,'helios::SphericalCoord::operator<<']]] + ['operator_3c_3c_0',['operator<<',['../structhelios_1_1int2.html#aa70779f707686be8b004587a4220a153',1,'helios::int2::operator<<()'],['../structhelios_1_1int3.html#a6f576c885af0d781aadda850a2ca77af',1,'helios::int3::operator<<()'],['../structhelios_1_1int4.html#ac6b32d39d92de0b8585c64048040f0f9',1,'helios::int4::operator<<()'],['../structhelios_1_1vec2.html#a5e585083b0cf16b2e73958747390e152',1,'helios::vec2::operator<<()'],['../structhelios_1_1vec3.html#a87277dd90e0869e2e8e7ce376dfc7033',1,'helios::vec3::operator<<()'],['../structhelios_1_1vec4.html#a32f014dbb41084ece2ad85f19c540874',1,'helios::vec4::operator<<()'],['../structhelios_1_1_r_g_bcolor.html#a47b1d94ed5f6fa0c8ae897e02a06435c',1,'helios::RGBcolor::operator<<()'],['../structhelios_1_1_r_g_b_acolor.html#aaa76985ee048b321703f78175e2b87b7',1,'helios::RGBAcolor::operator<<()'],['../structhelios_1_1_date.html#a189b8537a2e0696e2f38da34e0f13eec',1,'helios::Date::operator<<()'],['../structhelios_1_1_time.html#a5d53ebf9a42b3aa2d959a3cd5023c71a',1,'helios::Time::operator<<()'],['../structhelios_1_1_location.html#a60375cac034fe50880b47569df6e8f69',1,'helios::Location::operator<<()'],['../structhelios_1_1_spherical_coord.html#ad9381fdcb8448d8834b4ce43465b5335',1,'helios::SphericalCoord::operator<<()']]] ]; diff --git a/doc/html/search/searchdata.js b/doc/html/search/searchdata.js index 1a4f96998..79ce81682 100644 --- a/doc/html/search/searchdata.js +++ b/doc/html/search/searchdata.js @@ -9,7 +9,7 @@ var indexSectionsWithContent = 6: "chlop", 7: "o", 8: "cfgoptuv", - 9: "01235678abcdefghilmoprstuvw" + 9: "0125678abcdefghilmoprstuvw" }; var indexSectionNames = diff --git a/doc/html/sorghum_8cpp_source.html b/doc/html/sorghum_8cpp_source.html index 18e76a80b..12d84d231 100644 --- a/doc/html/sorghum_8cpp_source.html +++ b/doc/html/sorghum_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
sorghum.cpp
@@ -136,19 +142,19 @@
29
30 std::vector<std::vector<uint> > s1_UUID_stem_plant;
31 s1_UUID_stem_plant.resize(1);
-
32 std::vector<uint> UUID_stem= context->addTube(params.s1_stem_subdivisions, node_stem, radius_stem, Color_stem);
-
33 std::vector<uint> UUID_stem_top = context->addDisk(params.s1_stem_subdivisions,make_vec3(0,0,0),make_vec2(params.s1_stem_radius,params.s1_stem_radius),make_SphericalCoord( 0, 0, 0),RGBcolor(0.44,0.58,0.19));
+
32 std::vector<uint> UUID_stem= context->addTube(params.s1_stem_subdivisions, node_stem, radius_stem, Color_stem);
+
33 std::vector<uint> UUID_stem_top = context->addDisk(params.s1_stem_subdivisions,make_vec3(0,0,0),make_vec2(params.s1_stem_radius,params.s1_stem_radius),make_SphericalCoord( 0, 0, 0),RGBcolor(0.44,0.58,0.19));
34
35 vec3 base_top = interpolateTube(node_stem, 1);
-
36 context->translatePrimitive(UUID_stem_top, base_top);
+
36 context->translatePrimitive(UUID_stem_top, base_top);
37
-
38 s1_UUID_stem_plant.push_back(context->copyPrimitive(UUID_stem));
-
39 s1_UUID_stem_plant.push_back(context->copyPrimitive(UUID_stem_top));
-
40 context->deletePrimitive(UUID_stem);
-
41 context->deletePrimitive(UUID_stem_top);
+
38 s1_UUID_stem_plant.push_back(context->copyPrimitive(UUID_stem));
+
39 s1_UUID_stem_plant.push_back(context->copyPrimitive(UUID_stem_top));
+
40 context->deletePrimitive(UUID_stem);
+
41 context->deletePrimitive(UUID_stem_top);
42
43
-
44 float angle = ((context->randu(0, 90) * PI_F) / float(180));
+
44 float angle = ((context->randu(0, 90) * PI_F) / float(180));
45 for (float i = 1; i < 4; i++){
46 float leaf_length, leaf_width,rotation_value1, leaf_bend, rotation_value2,frac, leaf_curve, x_adj;
47
@@ -273,14 +279,14 @@
166 vec2 uv2((x + sx) /(Nx * dx), (y + sy) / (leaf_width));
167 vec2 uv3(x / (Nx * dx), (y + sy) /(leaf_width));
168
-
169 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s1_leaf_texture_file.c_str(), uv0, uv1, uv2));
-
170 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s1_leaf_texture_file.c_str(), uv0, uv2, uv3));
+
169 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s1_leaf_texture_file.c_str(), uv0, uv1, uv2));
+
170 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s1_leaf_texture_file.c_str(), uv0, uv2, uv3));
171 }
172 }
173
174 std::vector<std::vector<uint> > s1_UUID_leaf_plant;
-
175 s1_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
-
176 context->deletePrimitive(UUIDs4);
+
175 s1_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
+
176 context->deletePrimitive(UUIDs4);
177
178 vec3 translation(-x_adj, -leaf_width*0.5, 0);
179 float rotation_1 = -rotation_value2 * PI_F / float(180);
@@ -288,10 +294,10 @@
181 float rotation_2 = angle + rotation_value1;
182 vec3 base = interpolateTube(node_stem, frac);
183
-
184 context->translatePrimitive(s1_UUID_leaf_plant.back(), translation);
-
185 context->rotatePrimitive(s1_UUID_leaf_plant.back(), rotation_1, "y");
-
186 context->rotatePrimitive(s1_UUID_leaf_plant.back(), rotation_2, "z");
-
187 context->translatePrimitive(s1_UUID_leaf_plant.back(), base);
+
184 context->translatePrimitive(s1_UUID_leaf_plant.back(), translation);
+
185 context->rotatePrimitive(s1_UUID_leaf_plant.back(), rotation_1, "y");
+
186 context->rotatePrimitive(s1_UUID_leaf_plant.back(), rotation_2, "z");
+
187 context->translatePrimitive(s1_UUID_leaf_plant.back(), base);
188
189
190 vector<vector<vector<uint>>> s1_UUID_panicle_plant; // empty vector
@@ -328,18 +334,18 @@
221
222 std::vector<std::vector<uint> > s2_UUID_stem_plant;
223 s2_UUID_stem_plant.resize(1);
-
224 std::vector<uint> UUID_stem= context->addTube(50, node_stem, radius_stem, Color_stem);
-
225 std::vector<uint> UUID_stem_top = context->addDisk(50,make_vec3(0,0,0),make_vec2(params.s2_stem_radius,params.s2_stem_radius),make_SphericalCoord( 0, 0, 0),RGBcolor(0.302,0.4314,0.2392));
+
224 std::vector<uint> UUID_stem= context->addTube(50, node_stem, radius_stem, Color_stem);
+
225 std::vector<uint> UUID_stem_top = context->addDisk(50,make_vec3(0,0,0),make_vec2(params.s2_stem_radius,params.s2_stem_radius),make_SphericalCoord( 0, 0, 0),RGBcolor(0.302,0.4314,0.2392));
226
227 vec3 base_top = interpolateTube(node_stem, 1);
-
228 context->translatePrimitive(UUID_stem_top, base_top);
+
228 context->translatePrimitive(UUID_stem_top, base_top);
229
-
230 s2_UUID_stem_plant.push_back(context->copyPrimitive(UUID_stem));
-
231 s2_UUID_stem_plant.push_back(context->copyPrimitive(UUID_stem_top));
-
232 context->deletePrimitive(UUID_stem);
-
233 context->deletePrimitive(UUID_stem_top);
+
230 s2_UUID_stem_plant.push_back(context->copyPrimitive(UUID_stem));
+
231 s2_UUID_stem_plant.push_back(context->copyPrimitive(UUID_stem_top));
+
232 context->deletePrimitive(UUID_stem);
+
233 context->deletePrimitive(UUID_stem_top);
234
-
235 float angle = ((context->randu(0, 90) * PI_F) / float(180));
+
235 float angle = ((context->randu(0, 90) * PI_F) / float(180));
236 for (float i = 1; i < 6; i++){
237 float leaf_length, leaf_width,rotation_value1, leaf_bend,rotation_value2,frac, leaf_curve, leaf_wave_no, leaf_wave;
238
@@ -368,7 +374,7 @@
261 }else if (i == 3) {
262 leaf_length = params.s2_leaf_size3.x;
263 leaf_width = params.s2_leaf_size3.y;
-
264 rotation_value1 = PI_F + ((context->randu(0, 45) * PI_F) / float(180));
+
264 rotation_value1 = PI_F + ((context->randu(0, 45) * PI_F) / float(180));
265 leaf_bend = leaf_length * 0.3;
266 rotation_value2 = 15;
267 frac = 0.75;
@@ -379,7 +385,7 @@
272 }else if (i == 4){
273 leaf_length = params.s2_leaf_size4.x;
274 leaf_width = params.s2_leaf_size4.y;
-
275 rotation_value1 = ((context->randu(0, 45) * PI_F) / float(180));
+
275 rotation_value1 = ((context->randu(0, 45) * PI_F) / float(180));
276 leaf_bend = leaf_length * 0.3;
277 rotation_value2 = 25;
278 frac= 0.5;
@@ -390,7 +396,7 @@
283 }else{
284 leaf_length = params.s2_leaf_size5.x;
285 leaf_width = params.s2_leaf_size5.y;
-
286 rotation_value1 = PI_F + ((context->randu(0, 45) * PI_F) / float(180));
+
286 rotation_value1 = PI_F + ((context->randu(0, 45) * PI_F) / float(180));
287 leaf_bend = leaf_length * 0.3;
288 rotation_value2 = 10;
289 frac= 0.25;
@@ -490,13 +496,13 @@
383 vec2 uv2((x + sx) /(Nx * dx), (y + sy) /(leaf_width));
384 vec2 uv3(x /(Nx * dx), (y + sy) /(leaf_width));
385
-
386 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s2_leaf_texture_file.c_str(), uv0, uv1, uv2));
-
387 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s2_leaf_texture_file.c_str(), uv0, uv2, uv3));
+
386 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s2_leaf_texture_file.c_str(), uv0, uv1, uv2));
+
387 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s2_leaf_texture_file.c_str(), uv0, uv2, uv3));
388 }
389 }
390
-
391 s2_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
-
392 context->deletePrimitive(UUIDs4);
+
391 s2_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
+
392 context->deletePrimitive(UUIDs4);
393
394 vec3 translation(- 0.00015* rotation_value2, -leaf_width*0.5, 0); // adjustment v0 amplitude,v1 radius v2 leaf_length
395 float rotation_1 = -rotation_value2 * PI_F / float(180);
@@ -504,10 +510,10 @@
397 float rotation_2 = angle + rotation_value1;
398 vec3 base = interpolateTube(node_stem, frac);
399
-
400 context->translatePrimitive(s2_UUID_leaf_plant.back(), translation);
-
401 context->rotatePrimitive(s2_UUID_leaf_plant.back(), rotation_1, "y");
-
402 context->rotatePrimitive(s2_UUID_leaf_plant.back(), rotation_2, "z");
-
403 context->translatePrimitive(s2_UUID_leaf_plant.back(), base);
+
400 context->translatePrimitive(s2_UUID_leaf_plant.back(), translation);
+
401 context->rotatePrimitive(s2_UUID_leaf_plant.back(), rotation_1, "y");
+
402 context->rotatePrimitive(s2_UUID_leaf_plant.back(), rotation_2, "z");
+
403 context->translatePrimitive(s2_UUID_leaf_plant.back(), base);
404
405 vector<vector<vector<uint>>> s2_UUID_panicle_plant; // empty vector
406 std::vector<uint> s2_UUID_branch_plant; // empty vector
@@ -541,13 +547,13 @@
434 Color_stem.push_back(make_RGBcolor(0.302,0.4314,0.2392));
435 }
436
-
437 std::vector<uint> s3_UUID_stem_plant = context->addTube(params.s3_stem_subdivisions, node_stem, radius_stem, Color_stem);
+
437 std::vector<uint> s3_UUID_stem_plant = context->addTube(params.s3_stem_subdivisions, node_stem, radius_stem, Color_stem);
438
439// THE LEAVES
440
441 int nodes_no = params.s3_number_of_leaves;
442
-
443 float rotation_x1 = (context->randu(0, 360) * PI_F) / float(180);// inclination rotation, different for each plant
+
443 float rotation_x1 = (context->randu(0, 360) * PI_F) / float(180);// inclination rotation, different for each plant
444 std::vector<std::vector<uint> > s3_UUID_leaf_plant;
445
446 for (int i = 1; i < (nodes_no + 1); i++) {
@@ -650,14 +656,14 @@
543 vec2 uv2((x + sx) /(Nx * dx), (y + sy) /(params.s3_leaf_size.y));
544 vec2 uv3(x /(Nx * dx), (y + sy) /(params.s3_leaf_size.y));
545
-
546 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s3_leaf_texture_file.c_str(), uv0, uv1, uv2));
-
547 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s3_leaf_texture_file.c_str(), uv0, uv2, uv3));
+
546 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s3_leaf_texture_file.c_str(), uv0, uv1, uv2));
+
547 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s3_leaf_texture_file.c_str(), uv0, uv2, uv3));
548 }
549 }
550
551
-
552 s3_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
-
553 context->deletePrimitive(UUIDs4);
+
552 s3_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
+
553 context->deletePrimitive(UUIDs4);
554
555 float frac;
556
@@ -666,27 +672,27 @@
559 frac = 1;
560 } else {
561
-
562 frac = 1 - ((i - (context->randu() / float(2))) / float((nodes_no + 1)));
+
562 frac = 1 - ((i - (context->randu() / float(2))) / float((nodes_no + 1)));
563 }
564
565 vec3 base = interpolateTube(node_stem, frac);
-
566 float rotation_1 = - (params.s3_mean_leaf_angle * PI_F / float(180)) - (context->randu(0, 5) * PI_F) / float(180);
-
567 float rotation_x2 = (context->randu(0, 45) * PI_F) / float(180);
+
566 float rotation_1 = - (params.s3_mean_leaf_angle * PI_F / float(180)) - (context->randu(0, 5) * PI_F) / float(180);
+
567 float rotation_x2 = (context->randu(0, 45) * PI_F) / float(180);
568 float rotation_2 = rotation_x1 + rotation_x2;
569 float rotation_3 = rotation_2 + PI_F; //
570 vec3 translation(-params.s3_stem_radius * 2.8, -0.9 / (2 / float(params.s3_leaf_size.y)), 0); // adjustment
571
572 if (i % 2 != 0) {
-
573 context->translatePrimitive(s3_UUID_leaf_plant.back(), translation);
-
574 context->rotatePrimitive(s3_UUID_leaf_plant.back(), rotation_1, "y");
-
575 context->rotatePrimitive(s3_UUID_leaf_plant.back(), rotation_2, "z");
-
576 context->translatePrimitive(s3_UUID_leaf_plant.back(), base);
+
573 context->translatePrimitive(s3_UUID_leaf_plant.back(), translation);
+
574 context->rotatePrimitive(s3_UUID_leaf_plant.back(), rotation_1, "y");
+
575 context->rotatePrimitive(s3_UUID_leaf_plant.back(), rotation_2, "z");
+
576 context->translatePrimitive(s3_UUID_leaf_plant.back(), base);
577
578 } else {
-
579 context->translatePrimitive(s3_UUID_leaf_plant.back(), translation);
-
580 context->rotatePrimitive(s3_UUID_leaf_plant.back(), rotation_1, "y");
-
581 context->rotatePrimitive(s3_UUID_leaf_plant.back(), rotation_3, "z");
-
582 context->translatePrimitive(s3_UUID_leaf_plant.back(), base);
+
579 context->translatePrimitive(s3_UUID_leaf_plant.back(), translation);
+
580 context->rotatePrimitive(s3_UUID_leaf_plant.back(), rotation_1, "y");
+
581 context->rotatePrimitive(s3_UUID_leaf_plant.back(), rotation_3, "z");
+
582 context->translatePrimitive(s3_UUID_leaf_plant.back(), base);
583 }
584
585 }
@@ -723,7 +729,7 @@
616
617 }
618
-
619 std::vector<uint> s4_UUID_stem_plant = context->addTube(params.s4_stem_subdivisions, node_stem, radius_stem, Color_stem); // 50
+
619 std::vector<uint> s4_UUID_stem_plant = context->addTube(params.s4_stem_subdivisions, node_stem, radius_stem, Color_stem); // 50
620
621 // THE PANICLE
622
@@ -747,10 +753,10 @@
640
641 }
642
-
643 std::vector<uint> UUID1 = context->addTube(params.s4_stem_subdivisions, nodes_panicle_stalk, radius_panicle_stalk, Color_panicle_stalk);
+
643 std::vector<uint> UUID1 = context->addTube(params.s4_stem_subdivisions, nodes_panicle_stalk, radius_panicle_stalk, Color_panicle_stalk);
644
-
645 s4_UUID_panicle_plant.front().push_back(context->copyPrimitive(UUID1));
-
646 context->deletePrimitive(UUID1);
+
645 s4_UUID_panicle_plant.front().push_back(context->copyPrimitive(UUID1));
+
646 context->deletePrimitive(UUID1);
647
648 // now the panicle
649 std::vector<vec3> nodes_panicle;
@@ -771,13 +777,13 @@
664
665 }
666
-
667 std::vector<uint> UUIDs2 = context->addTube(params.s4_panicle_subdivisions, nodes_panicle, radius_panicle, params.s4_seed_texture_file.c_str());
+
667 std::vector<uint> UUIDs2 = context->addTube(params.s4_panicle_subdivisions, nodes_panicle, radius_panicle, params.s4_seed_texture_file.c_str());
668
669 float z_value = 0;
670 float di = 0;
671
672 for (int i = (params.s4_panicle_size.x * adj) + 2; i > -1; i--) {
-
673 std::vector<uint> UUIDs2_copy = context->copyPrimitive(UUIDs2);
+
673 std::vector<uint> UUIDs2_copy = context->copyPrimitive(UUIDs2);
674
675 float rotation_angle;
676
@@ -793,9 +799,9 @@
686 vec3 base = interpolateTube(nodes_panicle_stalk, 0.05);
687 float rot1 = rotation_angle;
688
-
689 context->rotatePrimitive(UUIDs2_copy, rot1, "y");
-
690 context->translatePrimitive(UUIDs2_copy, base);
-
691 context->translatePrimitive(UUIDs2_copy, tra1);
+
689 context->rotatePrimitive(UUIDs2_copy, rot1, "y");
+
690 context->translatePrimitive(UUIDs2_copy, base);
+
691 context->translatePrimitive(UUIDs2_copy, tra1);
692 s4_UUID_panicle_plant.front().push_back(UUIDs2_copy);
693
694 float i_value_1, i_value_2;
@@ -811,7 +817,7 @@
704 }
705
706 for (int ii = 0; ii < i_value_1; ii++) {
-
707 s4_UUID_panicle_plant.front().push_back(context->copyPrimitive(UUIDs2_copy));
+
707 s4_UUID_panicle_plant.front().push_back(context->copyPrimitive(UUIDs2_copy));
708 float rot2 = ii * i_value_2 * PI_F / float(180);
709 context -> rotatePrimitive(s4_UUID_panicle_plant.front().back(), rot2, "z");
710
@@ -819,15 +825,15 @@
712
713 };
714
-
715 context->deletePrimitive(UUIDs2);
+
715 context->deletePrimitive(UUIDs2);
716 vec3 V_1 = interpolateTube(node_stem, 1);
-
717 context->translatePrimitive(flatten(s4_UUID_panicle_plant), V_1);
+
717 context->translatePrimitive(flatten(s4_UUID_panicle_plant), V_1);
718
719// THE LEAVES
720
721 int nodes_no = params.s4_number_of_leaves;
722
-
723 float rotation_x1 = (context->randu(0, 360) * PI_F) / float(180);// inclination rotation, different for each plant
+
723 float rotation_x1 = (context->randu(0, 360) * PI_F) / float(180);// inclination rotation, different for each plant
724 std::vector<std::vector<uint> > s4_UUID_leaf_plant;
725
726 for (int i = 1; i < (nodes_no + 1); i++) {
@@ -932,41 +938,41 @@
825 vec2 uv2((x + sx) /(Nx * dx), (y + sy) / float(params.s4_leaf_size.y));
826 vec2 uv3(x /(Nx * dx), (y + sy) / float(params.s4_leaf_size.y));
827
-
828 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s4_leaf_texture_file.c_str(), uv0, uv1, uv2));
-
829 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s4_leaf_texture_file.c_str(), uv0, uv2, uv3));
+
828 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s4_leaf_texture_file.c_str(), uv0, uv1, uv2));
+
829 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s4_leaf_texture_file.c_str(), uv0, uv2, uv3));
830 }
831 }
832
833
-
834 s4_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
-
835 context->deletePrimitive(UUIDs4);
+
834 s4_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
+
835 context->deletePrimitive(UUIDs4);
836
837 float frac;
838
839 if (i == 1) {
840 frac = 0.9;
841 } else {
-
842 frac = (1 - ((i - (context->randu() / float(2))) / float((nodes_no + 1)*1.2))) - 0.15;
+
842 frac = (1 - ((i - (context->randu() / float(2))) / float((nodes_no + 1)*1.2))) - 0.15;
843 }
844
845 vec3 base = interpolateTube(node_stem, frac);
-
846 float rotation_1 = - (params.s4_mean_leaf_angle * PI_F / float(180)) - (context->randu(0, 5) * PI_F) / float(180);
-
847 float rotation_x2 = (context->randu(0, 45) * PI_F) / float(180);
+
846 float rotation_1 = - (params.s4_mean_leaf_angle * PI_F / float(180)) - (context->randu(0, 5) * PI_F) / float(180);
+
847 float rotation_x2 = (context->randu(0, 45) * PI_F) / float(180);
848 float rotation_2 = rotation_x1 + rotation_x2;
849 float rotation_3 = rotation_2 + PI_F; //
850 vec3 translation(-params.s4_stem_radius * 2, -0.9 / (2 / float(params.s4_leaf_size.y)), 0); // adjustment
851
852 if (i % 2 != 0) {
-
853 context->translatePrimitive(s4_UUID_leaf_plant.back(), translation);
-
854 context->rotatePrimitive(s4_UUID_leaf_plant.back(), rotation_1, "y");
-
855 context->rotatePrimitive(s4_UUID_leaf_plant.back(), rotation_2, "z");
-
856 context->translatePrimitive(s4_UUID_leaf_plant.back(), base);
+
853 context->translatePrimitive(s4_UUID_leaf_plant.back(), translation);
+
854 context->rotatePrimitive(s4_UUID_leaf_plant.back(), rotation_1, "y");
+
855 context->rotatePrimitive(s4_UUID_leaf_plant.back(), rotation_2, "z");
+
856 context->translatePrimitive(s4_UUID_leaf_plant.back(), base);
857
858 } else {
-
859 context->translatePrimitive(s4_UUID_leaf_plant.back(), translation);
-
860 context->rotatePrimitive(s4_UUID_leaf_plant.back(), rotation_1, "y");
-
861 context->rotatePrimitive(s4_UUID_leaf_plant.back(), rotation_3, "z");
-
862 context->translatePrimitive(s4_UUID_leaf_plant.back(), base);
+
859 context->translatePrimitive(s4_UUID_leaf_plant.back(), translation);
+
860 context->rotatePrimitive(s4_UUID_leaf_plant.back(), rotation_1, "y");
+
861 context->rotatePrimitive(s4_UUID_leaf_plant.back(), rotation_3, "z");
+
862 context->translatePrimitive(s4_UUID_leaf_plant.back(), base);
863 }
864
865 }
@@ -1015,7 +1021,7 @@
908
909 }
910
-
911 std::vector<uint> s5_UUID_stem_plant = context->addTube(params.s5_stem_subdivisions, nodes_stem, radius_stem,
+
911 std::vector<uint> s5_UUID_stem_plant = context->addTube(params.s5_stem_subdivisions, nodes_stem, radius_stem,
912 Color_stem); // 50
913
914
@@ -1043,10 +1049,10 @@
936
937 }
938
-
939 std::vector<uint> UUID1 = context->addTube(params.s5_stem_subdivisions, nodes_panicle_stalk, radius_panicle_stalk, Color_panicle_stalk);
+
939 std::vector<uint> UUID1 = context->addTube(params.s5_stem_subdivisions, nodes_panicle_stalk, radius_panicle_stalk, Color_panicle_stalk);
940
-
941 s5_UUID_panicle_plant.front().push_back(context->copyPrimitive(UUID1));
-
942 context->deletePrimitive(UUID1);
+
941 s5_UUID_panicle_plant.front().push_back(context->copyPrimitive(UUID1));
+
942 context->deletePrimitive(UUID1);
943
944 // now the panicle
945 std::vector<vec3> nodes_panicle;
@@ -1067,7 +1073,7 @@
960
961 }
962
-
963 std::vector<uint> UUIDs2 = context->addTube(params.s5_panicle_subdivisions, nodes_panicle, radius_panicle,params.s5_seed_texture_file.c_str());
+
963 std::vector<uint> UUIDs2 = context->addTube(params.s5_panicle_subdivisions, nodes_panicle, radius_panicle,params.s5_seed_texture_file.c_str());
964
965 float z_value = 0;
966
@@ -1076,7 +1082,7 @@
969 for (int i = (params.s5_panicle_size.x*adj) + 2; i > -1; i--) {
970
971
-
972 std::vector<uint> UUIDs_copy = context->copyPrimitive(UUIDs2);
+
972 std::vector<uint> UUIDs_copy = context->copyPrimitive(UUIDs2);
973
974 float rotation_angle;
975
@@ -1092,9 +1098,9 @@
985 vec3 base = interpolateTube(nodes_panicle_stalk, 0.05);
986 float rot1 = rotation_angle;
987
-
988 context->rotatePrimitive(UUIDs_copy, rot1, "y");
-
989 context->translatePrimitive(UUIDs_copy, base);
-
990 context->translatePrimitive(UUIDs_copy, tra1);
+
988 context->rotatePrimitive(UUIDs_copy, rot1, "y");
+
989 context->translatePrimitive(UUIDs_copy, base);
+
990 context->translatePrimitive(UUIDs_copy, tra1);
991
992
993 s5_UUID_panicle_plant.front().push_back(UUIDs_copy);
@@ -1112,7 +1118,7 @@
1005 }
1006
1007 for (int ii = 0; ii < i_value_1; ii++) {
-
1008 s5_UUID_panicle_plant.front().push_back(context->copyPrimitive(UUIDs_copy));
+
1008 s5_UUID_panicle_plant.front().push_back(context->copyPrimitive(UUIDs_copy));
1009 float rot2 = ii * i_value_2 * PI_F / float(180);
1010 context -> rotatePrimitive(s5_UUID_panicle_plant.front().back(), rot2, "z");
1011
@@ -1121,7 +1127,7 @@
1014 };
1015
1016
-
1017 context->deletePrimitive(UUIDs2);
+
1017 context->deletePrimitive(UUIDs2);
1018 ;
1019 vec3 V_1 = interpolateTube(nodes_stem, 1);
1020 vec3 V_2 = interpolateTube(nodes_stem, 0.95);
@@ -1129,9 +1135,9 @@
1022
1023 float Z = cart2sphere(V_3).zenith;
1024
-
1025 context->rotatePrimitive(flatten(s5_UUID_panicle_plant), Z, "y");
+
1025 context->rotatePrimitive(flatten(s5_UUID_panicle_plant), Z, "y");
1026
-
1027 context->translatePrimitive(flatten(s5_UUID_panicle_plant), V_1);
+
1027 context->translatePrimitive(flatten(s5_UUID_panicle_plant), V_1);
1028
1029
1030// THE LEAVES
@@ -1139,7 +1145,7 @@
1032 int nodes_no = params.s5_number_of_leaves;
1033
1034
-
1035 float rotation_x1 = (context->randu(0, 360) * PI_F) / float(180);// inclination rotation, different for each plant
+
1035 float rotation_x1 = (context->randu(0, 360) * PI_F) / float(180);// inclination rotation, different for each plant
1036 std::vector<std::vector<uint> > s5_UUID_leaf_plant;
1037
1038 for (int i = 1; i < (nodes_no + 1); i++) {
@@ -1227,13 +1233,13 @@
1120 vec2 uv2((x + sx) / (Nx * dx), (y + sy) / float(params.s5_leaf_size.y));
1121 vec2 uv3(x /(Nx * dx), (y + sy) / float(params.s5_leaf_size.y));
1122
-
1123 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s5_leaf_texture_file.c_str(), uv0, uv1, uv2));
-
1124 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s5_leaf_texture_file.c_str(), uv0, uv2, uv3));
+
1123 UUIDs4.push_back(context->addTriangle(v0, v1, v2, params.s5_leaf_texture_file.c_str(), uv0, uv1, uv2));
+
1124 UUIDs4.push_back(context->addTriangle(v0, v2, v3, params.s5_leaf_texture_file.c_str(), uv0, uv2, uv3));
1125 }
1126 }
1127
-
1128 s5_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
-
1129 context->deletePrimitive(UUIDs4);
+
1128 s5_UUID_leaf_plant.push_back(context->copyPrimitive(UUIDs4));
+
1129 context->deletePrimitive(UUIDs4);
1130
1131 float frac;
1132
@@ -1242,36 +1248,36 @@
1135 frac = 0.9;
1136 } else {
1137
-
1138 frac = (1 - ((i - (context->randu() / float(2))) / float((nodes_no + 1)*1.2))) - 0.15;
+
1138 frac = (1 - ((i - (context->randu() / float(2))) / float((nodes_no + 1)*1.2))) - 0.15;
1139 }
1140
1141 vec3 base = interpolateTube(nodes_stem, frac);
-
1142 float rotation_1 = - (params.s5_mean_leaf_angle * PI_F / float(180)) - (context->randu(0, 10) * PI_F) / float(180);
-
1143 float rotation_x2 = (context->randu(0, 45) * PI_F) / float(180);
+
1142 float rotation_1 = - (params.s5_mean_leaf_angle * PI_F / float(180)) - (context->randu(0, 10) * PI_F) / float(180);
+
1143 float rotation_x2 = (context->randu(0, 45) * PI_F) / float(180);
1144 float rotation_2 = rotation_x1 + rotation_x2;
1145 float rotation_3 = rotation_2 + PI_F; //
1146 vec3 translation(0, -0.9 / (2 / float(params.s5_leaf_size.y)), 0); // adjustment
1147
1148 if (i % 2 != 0) {
-
1149 context->translatePrimitive(s5_UUID_leaf_plant.back(), translation);
-
1150 context->rotatePrimitive(s5_UUID_leaf_plant.back(), rotation_1, "y");
-
1151 context->rotatePrimitive(s5_UUID_leaf_plant.back(), rotation_2, "z");
-
1152 context->translatePrimitive(s5_UUID_leaf_plant.back(), base);
+
1149 context->translatePrimitive(s5_UUID_leaf_plant.back(), translation);
+
1150 context->rotatePrimitive(s5_UUID_leaf_plant.back(), rotation_1, "y");
+
1151 context->rotatePrimitive(s5_UUID_leaf_plant.back(), rotation_2, "z");
+
1152 context->translatePrimitive(s5_UUID_leaf_plant.back(), base);
1153
1154 } else {
-
1155 context->translatePrimitive(s5_UUID_leaf_plant.back(), translation);
-
1156 context->rotatePrimitive(s5_UUID_leaf_plant.back(), rotation_1, "y");
-
1157 context->rotatePrimitive(s5_UUID_leaf_plant.back(), rotation_3, "z");
-
1158 context->translatePrimitive(s5_UUID_leaf_plant.back(), base);
+
1155 context->translatePrimitive(s5_UUID_leaf_plant.back(), translation);
+
1156 context->rotatePrimitive(s5_UUID_leaf_plant.back(), rotation_1, "y");
+
1157 context->rotatePrimitive(s5_UUID_leaf_plant.back(), rotation_3, "z");
+
1158 context->translatePrimitive(s5_UUID_leaf_plant.back(), base);
1159 }
1160
1161 }
1162
-
1163 float plant_rotation = (context->randu(0, 360) * PI_F) / float(180);
+
1163 float plant_rotation = (context->randu(0, 360) * PI_F) / float(180);
1164
-
1165 context->rotatePrimitive( s5_UUID_stem_plant,plant_rotation,origin, make_vec3(0,0,1));
-
1166 context->rotatePrimitive( flatten(s5_UUID_panicle_plant),plant_rotation,origin, make_vec3(0,0,1));
-
1167 context->rotatePrimitive( flatten(s5_UUID_leaf_plant),plant_rotation,origin, make_vec3(0,0,1));
+
1165 context->rotatePrimitive( s5_UUID_stem_plant,plant_rotation,origin, make_vec3(0,0,1));
+
1166 context->rotatePrimitive( flatten(s5_UUID_panicle_plant),plant_rotation,origin, make_vec3(0,0,1));
+
1167 context->rotatePrimitive( flatten(s5_UUID_leaf_plant),plant_rotation,origin, make_vec3(0,0,1));
1168
1169 std::vector<uint> s5_UUID_branch_plant; // empty vector
1170
@@ -1292,16 +1298,8 @@
helios::vec3 interpolateTube(const std::vector< helios::vec3 > &P, float frac)
Interpolate the position of a point along a tube.
uint sorghum(const SorghumCanopyParameters &params, const helios::vec3 &origin)
Function to add an individual sorghum plant.
Definition sorghum.cpp:8
-
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
-
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
-
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
-
std::vector< uint > addDisk(uint Ndivs, const helios::vec3 &center, const helios::vec2 &size)
Add new Disk geometric primitive to the Context given its center, and size.
Definition Context.cpp:6356
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
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:1943
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
-
uint addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
Add new Triangle geometric primitive.
Definition Context.cpp:1328
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
RGBcolor make_RGBcolor(float r, float g, float b)
Make an RGBcolor vector.
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
@@ -1363,15 +1361,18 @@
const float & zenith
Zenithal angle (radians)
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
+
Vector of two elements of type 'float'.
float x
First element in vector.
float y
Second element in vector.
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
- - + + diff --git a/doc/html/sponsors.jpg b/doc/html/sponsors.jpg deleted file mode 100644 index da71038d351a03cf800bb3f8328ae205e0acf204..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 63422 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 Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
strawberry.cpp
@@ -329,19 +335,19 @@
222
223 for( int i=0; i<params.stems_per_plant; i++ ){
224
-
225 vec3 position = origin + sphere2cart( make_SphericalCoord(0.1*context->randu()*params.plant_height,0,2*PI_F*context->randu()) ) ;
+
225 vec3 position = origin + sphere2cart( make_SphericalCoord(0.1*context->randu()*params.plant_height,0,2*PI_F*context->randu()) ) ;
226
-
227 vec3 base_direction = sphere2cart( make_SphericalCoord( 0.45*PI_F-0.15*PI_F*float(i)/float(params.stems_per_plant-1), 2*PI_F*context->randu()) );
+
227 vec3 base_direction = sphere2cart( make_SphericalCoord( 0.45*PI_F-0.15*PI_F*float(i)/float(params.stems_per_plant-1), 2*PI_F*context->randu()) );
228
229 float tip_angle = 0.3*PI_F*float(i)/float(params.stems_per_plant-1);
230
-
231 float length = (0.75+0.25*float(params.stems_per_plant-1-i)/float(params.stems_per_plant-1))*params.plant_height*(0.9+0.2*context->randu());
+
231 float length = (0.75+0.25*float(params.stems_per_plant-1-i)/float(params.stems_per_plant-1))*params.plant_height*(0.9+0.2*context->randu());
232
233 strawberryShoot(params, position, base_direction, length, tip_angle, leaf_prototype, leaf_UUIDs, branch_UUIDs, fruit_UUIDs, context);
234
235 }
236
-
237 context->deletePrimitive( leaf_prototype );
+
237 context->deletePrimitive( leaf_prototype );
238
239 UUID_leaf.push_back( leaf_UUIDs );
240 UUID_branch.push_back( branch_UUIDs );
@@ -354,14 +360,13 @@
helios::vec3 interpolateTube(const std::vector< helios::vec3 > &P, float frac)
Interpolate the position of a point along a tube.
uint strawberry(const StrawberryParameters &params, const helios::vec3 &origin)
Function to add an individual strawberry plant.
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
void scalePrimitive(uint UUID, const helios::vec3 &S)
Scale a primitive using its UUID relative to the origin (0,0,0)
Definition Context.cpp:1491
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
+
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5957
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
uint addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
Add new Triangle geometric primitive.
Definition Context.cpp:1328
@@ -386,14 +391,17 @@
float azimuth
Azimuthal angle (radians)
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
- - + + diff --git a/doc/html/struct_aerial_hit_point.html b/doc/html/struct_aerial_hit_point.html index cbc1f3712..d055ec1a1 100644 --- a/doc/html/struct_aerial_hit_point.html +++ b/doc/html/struct_aerial_hit_point.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_aerial_scan_metadata.html b/doc/html/struct_aerial_scan_metadata.html index 0be530d0e..6d39c92f6 100644 --- a/doc/html/struct_aerial_scan_metadata.html +++ b/doc/html/struct_aerial_scan_metadata.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Public Member Functions | @@ -332,10 +342,13 @@

AerialLiDAR.cpp

- -
+ + diff --git a/doc/html/struct_aerial_scan_metadata.js b/doc/html/struct_aerial_scan_metadata.js new file mode 100644 index 000000000..ed1886749 --- /dev/null +++ b/doc/html/struct_aerial_scan_metadata.js @@ -0,0 +1,11 @@ +var struct_aerial_scan_metadata = +[ + [ "AerialScanMetadata", "struct_aerial_scan_metadata.html#a7335ab6e76b88c50520e3fd205d4c575", null ], + [ "beamDivergence", "struct_aerial_scan_metadata.html#a8572a62a5c28d56c69e55737272d07b4", null ], + [ "center", "struct_aerial_scan_metadata.html#a8aaa9b231aca939a27d438bdf203699c", null ], + [ "coneangle", "struct_aerial_scan_metadata.html#a5fbcc96d692e7be7e52c983eb9d242fd", null ], + [ "exitDiameter", "struct_aerial_scan_metadata.html#aa42ea7d97c0d88bedea8ebeab10c4c84", null ], + [ "extent", "struct_aerial_scan_metadata.html#a5c51ed2d651b82502f0921bb52d80095", null ], + [ "Nrays", "struct_aerial_scan_metadata.html#a14b34575b0c5f8de6e1e203667a1d8a6", null ], + [ "scandensity", "struct_aerial_scan_metadata.html#ab6e7d1152e1b122a4751c733f04a3803", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_axis_rotation.html b/doc/html/struct_axis_rotation.html index bf4f03d02..a87d9f216 100644 --- a/doc/html/struct_axis_rotation.html +++ b/doc/html/struct_axis_rotation.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_b_b_lcoefficients.html b/doc/html/struct_b_b_lcoefficients.html index 759fa9b3b..e38fe3045 100644 --- a/doc/html/struct_b_b_lcoefficients.html +++ b/doc/html/struct_b_b_lcoefficients.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_b_bcoefficients.html b/doc/html/struct_b_bcoefficients.html index dc2152c3c..720d59f54 100644 --- a/doc/html/struct_b_bcoefficients.html +++ b/doc/html/struct_b_bcoefficients.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_b_m_fcoefficients.html b/doc/html/struct_b_m_fcoefficients.html index ed4eec88d..6e17dfbd9 100644 --- a/doc/html/struct_b_m_fcoefficients.html +++ b/doc/html/struct_b_m_fcoefficients.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_b_w_bcoefficients.html b/doc/html/struct_b_w_bcoefficients.html index 043804d7e..f6b3d8b71 100644 --- a/doc/html/struct_b_w_bcoefficients.html +++ b/doc/html/struct_b_w_bcoefficients.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_base_canopy_parameters.html b/doc/html/struct_base_canopy_parameters.html index e608f2cfe..f4e6adcda 100644 --- a/doc/html/struct_base_canopy_parameters.html +++ b/doc/html/struct_base_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
-
BaseCanopyParameters Struct Referenceabstract
+
BaseCanopyParameters Struct Referenceabstract
@@ -223,7 +233,7 @@

-pure virtual +pure virtual

- -
+ + diff --git a/doc/html/struct_base_canopy_parameters.js b/doc/html/struct_base_canopy_parameters.js new file mode 100644 index 000000000..f70152b2b --- /dev/null +++ b/doc/html/struct_base_canopy_parameters.js @@ -0,0 +1,10 @@ +var struct_base_canopy_parameters = +[ + [ "BaseCanopyParameters", "struct_base_canopy_parameters.html#a164f6d2b463a7ff7bf58551f1295e1f5", null ], + [ "BaseCanopyParameters", "struct_base_canopy_parameters.html#a22b341ef9edf0edcd95030aec4bf0a3a", null ], + [ "buildCanopy", "struct_base_canopy_parameters.html#a741a7c822b8f84d8f658cebd54e23eed", null ], + [ "buildPlant", "struct_base_canopy_parameters.html#afcbe470fe8e3e7106f0da0a93e540cce", null ], + [ "readParametersFromXML", "struct_base_canopy_parameters.html#a929e1fee86e6408cf42ca398510fc672", null ], + [ "canopy_origin", "struct_base_canopy_parameters.html#a0b5eb48ff33aaab57a3ea0616bc8d5eb", null ], + [ "canopy_rotation", "struct_base_canopy_parameters.html#afb6abc2b3cf2cf3283261915be329117", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_base_grape_vine_parameters.html b/doc/html/struct_base_grape_vine_parameters.html index 949fe0ff0..728575108 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_base_grape_vine_parameters.js b/doc/html/struct_base_grape_vine_parameters.js new file mode 100644 index 000000000..7cb57b2b5 --- /dev/null +++ b/doc/html/struct_base_grape_vine_parameters.js @@ -0,0 +1,50 @@ +var struct_base_grape_vine_parameters = +[ + [ "BaseGrapeVineParameters", "struct_base_grape_vine_parameters.html#a422125376a63e56695eb9f58581217b0", null ], + [ "BaseGrapeVineParameters", "struct_base_grape_vine_parameters.html#a7f439fd0f30ce24900ae9a299e28aa3c", null ], + [ "buildCanopy", "struct_base_grape_vine_parameters.html#a8251daae21fcd0cfccffab9f23812c18", null ], + [ "buildPlant", "struct_base_grape_vine_parameters.html#a7577cb650adee17f4343f30af8e3179d", null ], + [ "readParametersFromXML", "struct_base_grape_vine_parameters.html#a39fd838f1f07fca0f8c5b38619379167", null ], + [ "canopy_rotation_spread", "struct_base_grape_vine_parameters.html#a7a4245a8a58c9342f83544f4c4fbe84c", null ], + [ "cluster_height_max", "struct_base_grape_vine_parameters.html#a400d6647ac782d95810095028b3fc896", null ], + [ "cluster_height_max_spread", "struct_base_grape_vine_parameters.html#a953ff61ba4aafb94fea7965b9034595d", null ], + [ "cluster_radius", "struct_base_grape_vine_parameters.html#a33068ecf3f8ab89c8b427f9496c5c887", null ], + [ "cluster_radius_spread", "struct_base_grape_vine_parameters.html#ac2be7d544dc5b8a4362eff523532445a", null ], + [ "cordon_height", "struct_base_grape_vine_parameters.html#ae0039b667a66a05e79bc4391c33fea85", null ], + [ "cordon_height_spread", "struct_base_grape_vine_parameters.html#a7987cea6f3fa47a7bd6c3e26985f27f9", null ], + [ "cordon_length", "struct_base_grape_vine_parameters.html#ac1b85687c9d616cecbcd5669cc306f6f", null ], + [ "cordon_length_spread", "struct_base_grape_vine_parameters.html#aff36939081dff4eb93a98a06d3453fde", null ], + [ "cordon_radius", "struct_base_grape_vine_parameters.html#a6d1ddbd96a217d8d744058cd4edca266", null ], + [ "cordon_radius_spread", "struct_base_grape_vine_parameters.html#ac9906e333606068b757f6a5bf0b529ad", null ], + [ "dead_probability", "struct_base_grape_vine_parameters.html#a23c655ac5643e9d9d4a0ad1e4d989e8e", null ], + [ "grape_color", "struct_base_grape_vine_parameters.html#ac90904eec34fa3e0dea393dd1c12faf6", null ], + [ "grape_radius", "struct_base_grape_vine_parameters.html#afa20674518acbb9fdfaafc893f362e01", null ], + [ "grape_radius_spread", "struct_base_grape_vine_parameters.html#ace081969ad453ba66d60e394554d50b9", null ], + [ "grape_subdivisions", "struct_base_grape_vine_parameters.html#a510a2a5876fe8b3fb8ec70701c32df48", null ], + [ "grape_subdivisions_spread", "struct_base_grape_vine_parameters.html#aa27b9934f658e9047462703e7d059d74", null ], + [ "leaf_spacing_fraction", "struct_base_grape_vine_parameters.html#a55cc37c53fdd62e586f836129bde9a45", null ], + [ "leaf_spacing_fraction_spread", "struct_base_grape_vine_parameters.html#a4406907ab0df63e9aa3f11416b79dd17", null ], + [ "leaf_subdivisions", "struct_base_grape_vine_parameters.html#a93f3e632f8d7dd45f17559ca5a131091", null ], + [ "leaf_texture_file", "struct_base_grape_vine_parameters.html#a436f25d4bd25818fe97592b5feadce80", null ], + [ "leaf_width", "struct_base_grape_vine_parameters.html#a75f9ad83c0f7d963e9f528fcd3ba23b9", null ], + [ "leaf_width_spread", "struct_base_grape_vine_parameters.html#aca739e4edc970f7ef36ac4913279b656", null ], + [ "missing_plant_probability", "struct_base_grape_vine_parameters.html#a1d9460b443217dccd867a587c5bf57f7", null ], + [ "plant_count", "struct_base_grape_vine_parameters.html#ad8aa5493feef5a08a5d2ff1b9ce9f513", null ], + [ "plant_spacing", "struct_base_grape_vine_parameters.html#a0904dc05cf1becdeaaa46d9361893506", null ], + [ "plant_spacing_spread", "struct_base_grape_vine_parameters.html#a53486547ca872fbad9335c7c612a6c28", null ], + [ "row_spacing", "struct_base_grape_vine_parameters.html#a4c2005587aecf5648ca2bf6fcf57b5a7", null ], + [ "row_spacing_spread", "struct_base_grape_vine_parameters.html#adc793dabe989efe16fbca06821eaf11f", null ], + [ "shoot_length", "struct_base_grape_vine_parameters.html#a93f5db8eb3001cdc8a5d84c0addd6b2b", null ], + [ "shoot_length_spread", "struct_base_grape_vine_parameters.html#a53fe3fa053a5aa71ca4ea22956e554ec", null ], + [ "shoot_radius", "struct_base_grape_vine_parameters.html#ab849b6c742cec6ae33db7aeb4d94b6dd", null ], + [ "shoot_radius_spread", "struct_base_grape_vine_parameters.html#a0988985e1efda816cbee5273f67fcb28", null ], + [ "shoots_per_cordon", "struct_base_grape_vine_parameters.html#a80a0060ddd5de6e77e9071d320f49702", null ], + [ "shoots_per_cordon_spread", "struct_base_grape_vine_parameters.html#a5b20278772fcefb3ecace03fda12885e", null ], + [ "trunk_height", "struct_base_grape_vine_parameters.html#a85d8f22abdda39c464a48e1fc60bd064", null ], + [ "trunk_height_spread", "struct_base_grape_vine_parameters.html#a5980a12f332f92c2d084d1a1120a8dd3", null ], + [ "trunk_radius", "struct_base_grape_vine_parameters.html#ab842729ff885c8d8476e5c2c204e2979", null ], + [ "trunk_radius_spread", "struct_base_grape_vine_parameters.html#a6f2bca2ded24fa8da8f71d9b7ae5e033", null ], + [ "wood_subdivisions", "struct_base_grape_vine_parameters.html#a49d391b42c6aafd088bb89f29a3f8d5e", null ], + [ "wood_subdivisions_spread", "struct_base_grape_vine_parameters.html#a7d1ef566d2bdbd0495f95bc6b1938e17", null ], + [ "wood_texture_file", "struct_base_grape_vine_parameters.html#ae28d9e75240a23e0c534af9b884ce41d", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_bean_parameters.html b/doc/html/struct_bean_parameters.html index 2792da552..71bfdb112 100644 --- a/doc/html/struct_bean_parameters.html +++ b/doc/html/struct_bean_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_bean_parameters.js b/doc/html/struct_bean_parameters.js new file mode 100644 index 000000000..71ce55533 --- /dev/null +++ b/doc/html/struct_bean_parameters.js @@ -0,0 +1,23 @@ +var struct_bean_parameters = +[ + [ "BeanParameters", "struct_bean_parameters.html#a2fdf7cbadfebd5c8494ad9bbdb0e8bf5", null ], + [ "BeanParameters", "struct_bean_parameters.html#a901e474f4df9ef7639832c9359e21e0a", null ], + [ "buildCanopy", "struct_bean_parameters.html#ab9c791e070fc12c5ddb185de38a96097", null ], + [ "buildPlant", "struct_bean_parameters.html#a8be910632031fbec98a6185a0aab6efb", null ], + [ "readParametersFromXML", "struct_bean_parameters.html#ac37cccbcb4b68058724f2c09bde4007e", null ], + [ "germination_probability", "struct_bean_parameters.html#a9bec1a611d5100e6e7417b70a47cbe06", null ], + [ "leaf_length", "struct_bean_parameters.html#a1c21ac308fa92de4fa722701e714b473", null ], + [ "leaf_subdivisions", "struct_bean_parameters.html#a3e033c07426c9626a9d465c1113b3667", null ], + [ "leaf_texture_file", "struct_bean_parameters.html#ab07f50052e6f91914239d6bbe4e3608a", null ], + [ "leaflet_length", "struct_bean_parameters.html#a0ba15d0731c1116186120d1b365438e8", null ], + [ "plant_count", "struct_bean_parameters.html#af11292adc0e3c6835e6de7f79bf9f58f", null ], + [ "plant_spacing", "struct_bean_parameters.html#a0b814b2a7af5e252859183bdb951d95c", null ], + [ "pod_color", "struct_bean_parameters.html#a3b485cb8999c93db10fb30b21826b5be", null ], + [ "pod_length", "struct_bean_parameters.html#a143874bf6130c1e02315f745dfac5f13", null ], + [ "pod_subdivisions", "struct_bean_parameters.html#a7f447a601152e1428ad752b6f3417fc9", null ], + [ "row_spacing", "struct_bean_parameters.html#ad1b0816e394a4d7f5f848d99ef4d8527", null ], + [ "shoot_color", "struct_bean_parameters.html#ac98b67b586790c21f7c78a53829a62da", null ], + [ "shoot_subdivisions", "struct_bean_parameters.html#a35e44fe9bff11ba69c7d1dce97fa2883", null ], + [ "stem_length", "struct_bean_parameters.html#a68612ab1ea804835e5fd7c1723144e4f", null ], + [ "stem_radius", "struct_bean_parameters.html#a9636c5c02d104a795fa06b759df1f888", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_camera_calibration.html b/doc/html/struct_camera_calibration.html index fc12b056e..002176f5a 100644 --- a/doc/html/struct_camera_calibration.html +++ b/doc/html/struct_camera_calibration.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_camera_calibration.js b/doc/html/struct_camera_calibration.js new file mode 100644 index 000000000..fb391e08c --- /dev/null +++ b/doc/html/struct_camera_calibration.js @@ -0,0 +1,17 @@ +var struct_camera_calibration = +[ + [ "GradientDescentParameters", "struct_camera_calibration_1_1_gradient_descent_parameters.html", null ], + [ "addCheckerboard", "struct_camera_calibration.html#ab101fe425760d29aab58073d626be460", null ], + [ "addColorboard", "struct_camera_calibration.html#ad1c0a4605b3b3ea355b9f3dee1706ec9", null ], + [ "addDefaultCheckerboard", "struct_camera_calibration.html#a73e6dfb0a8a3a68beeed498797310702", null ], + [ "addDefaultColorboard", "struct_camera_calibration.html#a4b1c43adcd27bc075327a239f31f03b8", null ], + [ "distortImage", "struct_camera_calibration.html#a75a0688aa37a6d7706cef4ee4b92dd7f", null ], + [ "getCameraResponseScale", "struct_camera_calibration.html#a18eff4a7ecab1038f27b68c3963a5513", null ], + [ "GradientDescent", "struct_camera_calibration.html#a5bfbb206b8271b406cda85eb5ae23a1b", null ], + [ "loadXMLlabeldata", "struct_camera_calibration.html#a0e689ece69868c47a8d6f392dac06d19", null ], + [ "preprocessSpectra", "struct_camera_calibration.html#a7f11687ea932b11dd32efb4a5a2d79e8", null ], + [ "readROMCCanopy", "struct_camera_calibration.html#ae4f513355e7095b19417ad62d6f9f89f", null ], + [ "updateCameraResponseSpectra", "struct_camera_calibration.html#a900b08896dc2c3bf892311478d895883", null ], + [ "writeCalibratedCameraResponses", "struct_camera_calibration.html#a148bdc83d9f7a3d564a3aa10793a5d70", null ], + [ "writeSpectralXMLfile", "struct_camera_calibration.html#a96b8a246adb36d20a09e3d527be9de25", null ] +]; \ No newline at end of file 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 64493ba6c..58351cc2e 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+ -
@@ -196,10 +202,13 @@

CameraCalibration.h

- -
+ + diff --git a/doc/html/struct_camera_properties.html b/doc/html/struct_camera_properties.html index b611c9273..65b0f785d 100644 --- a/doc/html/struct_camera_properties.html +++ b/doc/html/struct_camera_properties.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Public Member Functions | @@ -131,7 +141,7 @@  Camera horizontal field of view in degrees.
  float FOV_aspect_ratio = 1.f - Physical dimensions of the pixel array sensor in the horizontal (.x) and vertical (.y) directions.
+ Ratio of horizontal to vertical camera field of view.
 

Detailed Description

@@ -157,7 +167,7 @@

-inline +inline

- -
+ + diff --git a/doc/html/struct_camera_properties.js b/doc/html/struct_camera_properties.js new file mode 100644 index 000000000..6aa68bb81 --- /dev/null +++ b/doc/html/struct_camera_properties.js @@ -0,0 +1,8 @@ +var struct_camera_properties = +[ + [ "camera_resolution", "struct_camera_properties.html#a2806b640deeab5fbcd9dda8ea240f345", null ], + [ "focal_plane_distance", "struct_camera_properties.html#a7eae760b6f6729b2e391d0b96d07b209", null ], + [ "FOV_aspect_ratio", "struct_camera_properties.html#ae1e4df4d4612fd652ccd1e57fc71d104", null ], + [ "HFOV", "struct_camera_properties.html#ac1419dfa651f1f8343f5fb5a2fad2148", null ], + [ "lens_diameter", "struct_camera_properties.html#acf2d9d32a978b027658045c8068c7d1a", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_colormap.html b/doc/html/struct_colormap.html index 6f6d26a7e..0111ffc46 100644 --- a/doc/html/struct_colormap.html +++ b/doc/html/struct_colormap.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_conical_crowns_canopy_parameters.html b/doc/html/struct_conical_crowns_canopy_parameters.html index 0ec43ec06..da29b93b3 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_conical_crowns_canopy_parameters.js b/doc/html/struct_conical_crowns_canopy_parameters.js new file mode 100644 index 000000000..7c0510951 --- /dev/null +++ b/doc/html/struct_conical_crowns_canopy_parameters.js @@ -0,0 +1,19 @@ +var struct_conical_crowns_canopy_parameters = +[ + [ "ConicalCrownsCanopyParameters", "struct_conical_crowns_canopy_parameters.html#a14c7ca248edf64af6b1882aea58d7d74", null ], + [ "ConicalCrownsCanopyParameters", "struct_conical_crowns_canopy_parameters.html#a687c4bb375077d6eb1fbe96ff438fb0f", null ], + [ "buildCanopy", "struct_conical_crowns_canopy_parameters.html#a71bba52f726b16ac52e3d44c41cc7b03", null ], + [ "buildPlant", "struct_conical_crowns_canopy_parameters.html#adabbdff81275869121f3308bf31aa4cc", null ], + [ "readParametersFromXML", "struct_conical_crowns_canopy_parameters.html#adcca81e7a3f0f5791d83cf38317603d3", null ], + [ "canopy_configuration", "struct_conical_crowns_canopy_parameters.html#a72eaaa43483eb64d79780418e726f749", null ], + [ "crown_height", "struct_conical_crowns_canopy_parameters.html#a40b24b7e99ad96e967bc4d3d9af277e2", null ], + [ "crown_radius", "struct_conical_crowns_canopy_parameters.html#ab8ad6dd9a6bdb0ccfbccb268a58e3275", null ], + [ "leaf_angle_distribution", "struct_conical_crowns_canopy_parameters.html#a071b3d2e2ebaa9921702b483682fb6d6", null ], + [ "leaf_area_density", "struct_conical_crowns_canopy_parameters.html#ac15b062cb9d964163b49f7590e3804a8", null ], + [ "leaf_color", "struct_conical_crowns_canopy_parameters.html#a3ace8715f3b5e0b91272e9a718642ee4", null ], + [ "leaf_size", "struct_conical_crowns_canopy_parameters.html#a914f22b9bd8d046d5c2d661ddacbfb69", null ], + [ "leaf_subdivisions", "struct_conical_crowns_canopy_parameters.html#a1871e049c234ab2237ccf1fa717d632b", null ], + [ "leaf_texture_file", "struct_conical_crowns_canopy_parameters.html#a3d54bb0c814adced34e4e1f3b26bf41f", null ], + [ "plant_count", "struct_conical_crowns_canopy_parameters.html#a001d43bc659ec5ee0ca8204a7b0d07e3", null ], + [ "plant_spacing", "struct_conical_crowns_canopy_parameters.html#a605e547c57f08fc248fa39a42cb64877", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_dupex.html b/doc/html/struct_dupex.html index 675d20de4..eb98afeb4 100644 --- a/doc/html/struct_dupex.html +++ b/doc/html/struct_dupex.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_empirical_model_coefficients.html b/doc/html/struct_empirical_model_coefficients.html index 109ff3316..83c56ebdf 100644 --- a/doc/html/struct_empirical_model_coefficients.html +++ b/doc/html/struct_empirical_model_coefficients.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
@@ -148,7 +158,7 @@

-inline +inline

- -
+ + diff --git a/doc/html/struct_farquhar_model_coefficients.html b/doc/html/struct_farquhar_model_coefficients.html index b4ebd8b8a..d23911f2c 100644 --- a/doc/html/struct_farquhar_model_coefficients.html +++ b/doc/html/struct_farquhar_model_coefficients.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_floral_bud.html b/doc/html/struct_floral_bud.html index 4ba038b25..31cc39cc6 100644 --- a/doc/html/struct_floral_bud.html +++ b/doc/html/struct_floral_bud.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
@@ -348,10 +358,13 @@

PlantArchitecture.h

- -
+ + diff --git a/doc/html/struct_goblet_grapevine_parameters.html b/doc/html/struct_goblet_grapevine_parameters.html index cd45837c9..bccbbb886 100644 --- a/doc/html/struct_goblet_grapevine_parameters.html +++ b/doc/html/struct_goblet_grapevine_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_goblet_grapevine_parameters.js b/doc/html/struct_goblet_grapevine_parameters.js new file mode 100644 index 000000000..bf186a6f4 --- /dev/null +++ b/doc/html/struct_goblet_grapevine_parameters.js @@ -0,0 +1,8 @@ +var struct_goblet_grapevine_parameters = +[ + [ "GobletGrapevineParameters", "struct_goblet_grapevine_parameters.html#a0274d6f6b1f13bbf7a383de5c2bc8726", null ], + [ "GobletGrapevineParameters", "struct_goblet_grapevine_parameters.html#a498ce7f62d575b0bc914e9d48d94fbb2", null ], + [ "buildCanopy", "struct_goblet_grapevine_parameters.html#a462a7445a2ceb304db57c507a5a0e9b7", null ], + [ "buildPlant", "struct_goblet_grapevine_parameters.html#a410a1bc232e9c55829ef493096e387f3", null ], + [ "readParametersFromXML", "struct_goblet_grapevine_parameters.html#a79f3f790ebb458d89fdb26d485d718da", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_grid_cell.html b/doc/html/struct_grid_cell.html index fcb760359..f98da2d15 100644 --- a/doc/html/struct_grid_cell.html +++ b/doc/html/struct_grid_cell.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
- -
+ + diff --git a/doc/html/struct_hit_point.html b/doc/html/struct_hit_point.html index bc5e741be..d5adf8f6f 100644 --- a/doc/html/struct_hit_point.html +++ b/doc/html/struct_hit_point.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_homogeneous_canopy_parameters.html b/doc/html/struct_homogeneous_canopy_parameters.html index 010c885d6..3231c820d 100644 --- a/doc/html/struct_homogeneous_canopy_parameters.html +++ b/doc/html/struct_homogeneous_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_homogeneous_canopy_parameters.js b/doc/html/struct_homogeneous_canopy_parameters.js new file mode 100644 index 000000000..310216fd4 --- /dev/null +++ b/doc/html/struct_homogeneous_canopy_parameters.js @@ -0,0 +1,17 @@ +var struct_homogeneous_canopy_parameters = +[ + [ "HomogeneousCanopyParameters", "struct_homogeneous_canopy_parameters.html#ad5f583b7f483df9fdaf86bbdaf0e5a92", null ], + [ "HomogeneousCanopyParameters", "struct_homogeneous_canopy_parameters.html#aac168c38c41f7c11830c36707a744620", null ], + [ "buildCanopy", "struct_homogeneous_canopy_parameters.html#a45be1a4822a85324643eee2612dda1b5", null ], + [ "buildPlant", "struct_homogeneous_canopy_parameters.html#a4204162f4c57227e9328b8fcff59cb4d", null ], + [ "readParametersFromXML", "struct_homogeneous_canopy_parameters.html#a199c70328138eb4af32e22fb974b8783", null ], + [ "buffer", "struct_homogeneous_canopy_parameters.html#a1b6de173fb1f5e71f4d8e7ff9ae99881", null ], + [ "canopy_extent", "struct_homogeneous_canopy_parameters.html#a68c488e6bd2f209af3a46ce8aca4bf60", null ], + [ "canopy_height", "struct_homogeneous_canopy_parameters.html#a80df27cc13e2b7f113d52e405ddb2737", null ], + [ "leaf_angle_distribution", "struct_homogeneous_canopy_parameters.html#a9d22fee5250b0fc616acdd91e5cb34b2", null ], + [ "leaf_area_index", "struct_homogeneous_canopy_parameters.html#ae8880f6cbbdd6c69caee3cedba4ef542", null ], + [ "leaf_color", "struct_homogeneous_canopy_parameters.html#a3fc69732f3f0790dc858fe4ed8abf3fd", null ], + [ "leaf_size", "struct_homogeneous_canopy_parameters.html#a2edb9f81abc15976ca0d338677105b06", null ], + [ "leaf_subdivisions", "struct_homogeneous_canopy_parameters.html#a7e385ca3b257c8012d8336c03a617b31", null ], + [ "leaf_texture_file", "struct_homogeneous_canopy_parameters.html#ada090628a7e4d792005768eef445658d", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_leaf_optics_properties.html b/doc/html/struct_leaf_optics_properties.html index a43088466..a0630f963 100644 --- a/doc/html/struct_leaf_optics_properties.html +++ b/doc/html/struct_leaf_optics_properties.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_leaf_prototype.html b/doc/html/struct_leaf_prototype.html index 102c80382..0890c0840 100644 --- a/doc/html/struct_leaf_prototype.html +++ b/doc/html/struct_leaf_prototype.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_leaf_prototype.js b/doc/html/struct_leaf_prototype.js new file mode 100644 index 000000000..9bd7fbea2 --- /dev/null +++ b/doc/html/struct_leaf_prototype.js @@ -0,0 +1,21 @@ +var struct_leaf_prototype = +[ + [ "LeafPrototype", "struct_leaf_prototype.html#af29d0b590d0c675ff43134797d4ade6b", null ], + [ "LeafPrototype", "struct_leaf_prototype.html#a1ad2dbbc6bf4c55f598f7060d8d436cd", null ], + [ "operator=", "struct_leaf_prototype.html#a2dc8e0e35313b52c69cb7076d0392c2a", null ], + [ "build_petiolule", "struct_leaf_prototype.html#a97e0456a85a039b8c7c318a0cd57663e", null ], + [ "lateral_curvature", "struct_leaf_prototype.html#a6ccef984c87ae4203d7b620d3ac4e177", null ], + [ "leaf_buckle_angle", "struct_leaf_prototype.html#ab24b8cb372c52a7cd2c138d415fc9622", null ], + [ "leaf_buckle_length", "struct_leaf_prototype.html#ab628d133df921861f8db3d36f4fc6496", null ], + [ "leaf_offset", "struct_leaf_prototype.html#aa8fc5dd4868a81ef7c8d34d4aa255daf", null ], + [ "leaf_texture_file", "struct_leaf_prototype.html#a418960ee0b7f6c6693d09cd5f0d2ba59", null ], + [ "longitudinal_curvature", "struct_leaf_prototype.html#af14f092796a2c241521be4f50cad1552", null ], + [ "midrib_fold_fraction", "struct_leaf_prototype.html#ab6a5584fbf19ee9c61f979e020eeb834", null ], + [ "OBJ_model_file", "struct_leaf_prototype.html#abf799f4b6c6a0eb64ddccb0e310c6259", null ], + [ "petiole_roll", "struct_leaf_prototype.html#a8719e0541fc2360c8f9d889df70642a9", null ], + [ "prototype_function", "struct_leaf_prototype.html#ab709ab7749bf4ad562946441bc7a937e", null ], + [ "subdivisions", "struct_leaf_prototype.html#a2a90483933ca70d5bd87079e607d5d38", null ], + [ "unique_prototypes", "struct_leaf_prototype.html#a900f658b122d42dc24a42838fb16f189", null ], + [ "wave_amplitude", "struct_leaf_prototype.html#ab86a62f2f03c638481bfdd28997c74d1", null ], + [ "wave_period", "struct_leaf_prototype.html#aa62b74d58f6a490473f3e30c5e5aa01a", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_m_o_p_tcoefficients.html b/doc/html/struct_m_o_p_tcoefficients.html index ed85c6950..95877ceb7 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_per_ray_data.html b/doc/html/struct_per_ray_data.html index cadeba755..15226aed5 100644 --- a/doc/html/struct_per_ray_data.html +++ b/doc/html/struct_per_ray_data.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
@@ -265,10 +275,13 @@

RayTracing.cu.h

- -
+ + diff --git a/doc/html/struct_per_ray_data.js b/doc/html/struct_per_ray_data.js new file mode 100644 index 000000000..cd65764c1 --- /dev/null +++ b/doc/html/struct_per_ray_data.js @@ -0,0 +1,10 @@ +var struct_per_ray_data = +[ + [ "area", "struct_per_ray_data.html#a3bf336505e26e0fe714a4347524f7407", null ], + [ "face", "struct_per_ray_data.html#afc61137cf7b0e132eeb05b908b899790", null ], + [ "origin_UUID", "struct_per_ray_data.html#a6eb01aac11b5c8d4cfe02f15330dd868", null ], + [ "periodic_depth", "struct_per_ray_data.html#ad10350ee3268a1f18cca466d764247a5", null ], + [ "seed", "struct_per_ray_data.html#a757f60a4367093c4aa8bf21e6042c1dd", null ], + [ "source_ID", "struct_per_ray_data.html#a1c5097650f40749e55c984db780e1b1a", null ], + [ "strength", "struct_per_ray_data.html#a3510f98e1f2a49183edf5173a2d9f935", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_photosynthetic_temperature_response_parameters.html b/doc/html/struct_photosynthetic_temperature_response_parameters.html index d4c2588bb..9075900e0 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_phytomer.html b/doc/html/struct_phytomer.html index ce703013d..82d535039 100644 --- a/doc/html/struct_phytomer.html +++ b/doc/html/struct_phytomer.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Public Member Functions | @@ -173,6 +183,8 @@   void removeLeaf ()   +void deletePhytomer () +  @@ -260,7 +272,7 @@

Static Public Member Functions

Detailed Description

-

Definition at line 799 of file PlantArchitecture.h.

+

Definition at line 797 of file PlantArchitecture.h.

Constructor & Destructor Documentation

◆ Phytomer()

@@ -341,7 +353,7 @@

-

Definition at line 776 of file PlantArchitecture.cpp.

+

Definition at line 803 of file PlantArchitecture.cpp.

@@ -361,7 +373,7 @@

-

Definition at line 1756 of file PlantArchitecture.cpp.

+

Definition at line 1831 of file PlantArchitecture.cpp.

@@ -380,7 +392,26 @@

-

Definition at line 265 of file CarbohydrateModel.cpp.

+

Definition at line 303 of file CarbohydrateModel.cpp.

+ + + + +

◆ deletePhytomer()

+ +
+
+ + + + + + + +
void Phytomer::deletePhytomer ()
+
+ +

Definition at line 1779 of file PlantArchitecture.cpp.

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

-static +static @@ -624,7 +655,7 @@

-

Definition at line 1730 of file PlantArchitecture.cpp.

+

Definition at line 1757 of file PlantArchitecture.cpp.

@@ -652,7 +683,7 @@

-

Definition at line 1491 of file PlantArchitecture.cpp.

+

Definition at line 1518 of file PlantArchitecture.cpp.

@@ -679,7 +710,7 @@

Definition at line 1586 of file PlantArchitecture.cpp.

+

Definition at line 1613 of file PlantArchitecture.cpp.

@@ -698,7 +729,7 @@

-

Definition at line 1690 of file PlantArchitecture.cpp.

+

Definition at line 1717 of file PlantArchitecture.cpp.

@@ -791,7 +822,7 @@

-

Definition at line 1713 of file PlantArchitecture.cpp.

+

Definition at line 1740 of file PlantArchitecture.cpp.

@@ -814,7 +845,7 @@

-

Definition at line 1544 of file PlantArchitecture.cpp.

+

Definition at line 1571 of file PlantArchitecture.cpp.

@@ -841,7 +872,7 @@

Definition at line 1597 of file PlantArchitecture.cpp.

+

Definition at line 1624 of file PlantArchitecture.cpp.

@@ -868,7 +899,7 @@

Definition at line 1602 of file PlantArchitecture.cpp.

+

Definition at line 1629 of file PlantArchitecture.cpp.

@@ -895,7 +926,7 @@

Definition at line 1670 of file PlantArchitecture.cpp.

+

Definition at line 1697 of file PlantArchitecture.cpp.

@@ -922,7 +953,7 @@

Definition at line 1606 of file PlantArchitecture.cpp.

+

Definition at line 1633 of file PlantArchitecture.cpp.

@@ -941,7 +972,7 @@

-

Definition at line 1457 of file PlantArchitecture.cpp.

+

Definition at line 1484 of file PlantArchitecture.cpp.

@@ -1031,7 +1062,7 @@

-friend +friend @@ -1605,10 +1636,13 @@

PlantArchitecture.cpp - - + + diff --git a/doc/html/struct_phytomer.js b/doc/html/struct_phytomer.js new file mode 100644 index 000000000..b33a7b810 --- /dev/null +++ b/doc/html/struct_phytomer.js @@ -0,0 +1,11 @@ +var struct_phytomer = +[ + [ "scaleInternodeMaxLength", "struct_phytomer.html#aecc6f52f3490562f4daf581bec7f4260", null ], + [ "setInternodeMaxLength", "struct_phytomer.html#a25a09ac7a2eb07d34fed5c6d9fad213e", null ], + [ "setInternodeMaxRadius", "struct_phytomer.html#a70aa0f62afdf829d9f2af6167d30f8ca", null ], + [ "setLeafPrototypeScale", "struct_phytomer.html#ae6bbbd7dcf85fb3b11062e2b0cb415e3", null ], + [ "setLeafScaleFraction", "struct_phytomer.html#ab089057c5102fd40a09a92d5a424bfdb", null ], + [ "age", "struct_phytomer.html#adca1542efc0d16f0117d533f86c849e5", null ], + [ "petiole_vertices", "struct_phytomer.html#a63c1deff7ef09e41bddc155cb4e22861", null ], + [ "shoot_index", "struct_phytomer.html#aa35d5da6c2d3ae761d1b4ce491db2e17", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_phytomer_parameters.html b/doc/html/struct_phytomer_parameters.html index 2e693218f..6ef66ddbc 100644 --- a/doc/html/struct_phytomer_parameters.html +++ b/doc/html/struct_phytomer_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_phytomer_parameters.js b/doc/html/struct_phytomer_parameters.js new file mode 100644 index 000000000..dae570d5e --- /dev/null +++ b/doc/html/struct_phytomer_parameters.js @@ -0,0 +1,7 @@ +var struct_phytomer_parameters = +[ + [ "PhytomerParameters", "struct_phytomer_parameters.html#a00985415187962da3e18fbc024595277", null ], + [ "PhytomerParameters", "struct_phytomer_parameters.html#a23034eb00d8036aad3177e752cf4d8e7", null ], + [ "phytomer_callback_function", "struct_phytomer_parameters.html#a4460d1a8a04f27ad90908a4752c33cfb", null ], + [ "phytomer_creation_function", "struct_phytomer_parameters.html#ab97ce4b897b2ec905235ca2efbf8545d", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_plant_instance.html b/doc/html/struct_plant_instance.html index cac30c78d..db76a93ad 100644 --- a/doc/html/struct_plant_instance.html +++ b/doc/html/struct_plant_instance.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Public Member Functions | @@ -106,8 +116,8 @@ - - + +

Public Member Functions

 PlantInstance (const helios::vec3 &a_base_position, float a_current_age, helios::Context *a_context_ptr)
 
 PlantInstance (const helios::vec3 &a_base_position, float a_current_age, const std::string &a_plant_name, helios::Context *a_context_ptr)
 
@@ -121,6 +131,8 @@ + + @@ -144,10 +156,10 @@

Data Fields

 
helios::Contextcontext_ptr
 
std::string plant_name
 
std::pair< std::string, float > epicormic_shoot_probability_perlength_per_day
 
float dd_to_dormancy_break = 0

Detailed Description

-

Definition at line 1075 of file PlantArchitecture.h.

+

Definition at line 1088 of file PlantArchitecture.h.

Constructor & Destructor Documentation

- -

◆ PlantInstance()

+ +

◆ PlantInstance()

@@ -195,7 +212,7 @@

-

Definition at line 1079 of file PlantArchitecture.h.

+

Definition at line 1092 of file PlantArchitecture.h.

@@ -211,7 +228,7 @@

-

Definition at line 1082 of file PlantArchitecture.h.

+

Definition at line 1095 of file PlantArchitecture.h.

@@ -227,7 +244,7 @@

-

Definition at line 1080 of file PlantArchitecture.h.

+

Definition at line 1093 of file PlantArchitecture.h.

@@ -243,7 +260,7 @@

-

Definition at line 1091 of file PlantArchitecture.h.

+

Definition at line 1105 of file PlantArchitecture.h.

@@ -259,7 +276,7 @@

-

Definition at line 1086 of file PlantArchitecture.h.

+

Definition at line 1100 of file PlantArchitecture.h.

@@ -275,7 +292,7 @@

-

Definition at line 1087 of file PlantArchitecture.h.

+

Definition at line 1101 of file PlantArchitecture.h.

@@ -291,7 +308,7 @@

-

Definition at line 1088 of file PlantArchitecture.h.

+

Definition at line 1102 of file PlantArchitecture.h.

@@ -307,7 +324,7 @@

-

Definition at line 1090 of file PlantArchitecture.h.

+

Definition at line 1104 of file PlantArchitecture.h.

@@ -323,7 +340,7 @@

-

Definition at line 1089 of file PlantArchitecture.h.

+

Definition at line 1103 of file PlantArchitecture.h.

@@ -339,7 +356,7 @@

-

Definition at line 1083 of file PlantArchitecture.h.

+

Definition at line 1097 of file PlantArchitecture.h.

@@ -355,7 +372,7 @@

-

Definition at line 1093 of file PlantArchitecture.h.

+

Definition at line 1107 of file PlantArchitecture.h.

@@ -371,7 +388,7 @@

-

Definition at line 1095 of file PlantArchitecture.h.

+

Definition at line 1109 of file PlantArchitecture.h.

@@ -387,7 +404,23 @@

-

Definition at line 1092 of file PlantArchitecture.h.

+

Definition at line 1106 of file PlantArchitecture.h.

+ + + + +

◆ plant_name

+ +
+
+ + + + +
std::string PlantInstance::plant_name
+
+ +

Definition at line 1096 of file PlantArchitecture.h.

@@ -403,7 +436,7 @@

-

Definition at line 1078 of file PlantArchitecture.h.

+

Definition at line 1091 of file PlantArchitecture.h.

@@ -419,7 +452,7 @@

-

Definition at line 1081 of file PlantArchitecture.h.

+

Definition at line 1094 of file PlantArchitecture.h.

@@ -427,10 +460,13 @@

PlantArchitecture.h - - + + diff --git a/doc/html/struct_radiation_band.html b/doc/html/struct_radiation_band.html index 66c5aab5f..2fc4bacef 100644 --- a/doc/html/struct_radiation_band.html +++ b/doc/html/struct_radiation_band.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_radiation_band.js b/doc/html/struct_radiation_band.js new file mode 100644 index 000000000..513543759 --- /dev/null +++ b/doc/html/struct_radiation_band.js @@ -0,0 +1,17 @@ +var struct_radiation_band = +[ + [ "RadiationBand", "struct_radiation_band.html#a24a8c605f4553fd80e47f8cb7dd77744", null ], + [ "diffuse_spectrum", "struct_radiation_band.html#a24a0753d9bc91d02db11046a7278220b", null ], + [ "diffuseDistNorm", "struct_radiation_band.html#a774ee8eb75fc96a086688fe4c643cdec", null ], + [ "diffuseExtinction", "struct_radiation_band.html#a8d765b32b7feb274d2e4b19c46256454", null ], + [ "diffuseFlux", "struct_radiation_band.html#a8eab113387b2e1435640b0e5eb7cc0ce", null ], + [ "diffusePeakDir", "struct_radiation_band.html#a640846a7f7b0b525ff33ea0d8143e866", null ], + [ "diffuseRayCount", "struct_radiation_band.html#ad96ca3a5bd5aa77844ac2c9fe16e042d", null ], + [ "directRayCount", "struct_radiation_band.html#aff62997df11af06fad82b946b298ee90", null ], + [ "emissionFlag", "struct_radiation_band.html#ace749bf8f3e89cf3ea93fb58d3e28e1b", null ], + [ "label", "struct_radiation_band.html#a2929fde6f333f2aeba923886fc84887f", null ], + [ "minScatterEnergy", "struct_radiation_band.html#a2f54d84dc4a82db6bdd50ba3648cae59", null ], + [ "radiativepropertiesinitialized", "struct_radiation_band.html#ac4e08f643cd7c5d85a02a475c7c9bdbf", null ], + [ "scatteringDepth", "struct_radiation_band.html#a1e6751a77faec064c49aba70539865de", null ], + [ "wavebandBounds", "struct_radiation_band.html#a11a0c1b2fe1f6be6efb8052fa247b396", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_radiation_camera.html b/doc/html/struct_radiation_camera.html index b0849bcc6..19a575a6e 100644 --- a/doc/html/struct_radiation_camera.html +++ b/doc/html/struct_radiation_camera.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_radiation_source.html b/doc/html/struct_radiation_source.html index 1c430e480..b1323bfc8 100644 --- a/doc/html/struct_radiation_source.html +++ b/doc/html/struct_radiation_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_radiation_source.js b/doc/html/struct_radiation_source.js new file mode 100644 index 000000000..8adb9400a --- /dev/null +++ b/doc/html/struct_radiation_source.js @@ -0,0 +1,16 @@ +var struct_radiation_source = +[ + [ "RadiationSource", "struct_radiation_source.html#a1d16744d95956e385117f14a10597985", null ], + [ "RadiationSource", "struct_radiation_source.html#a6b8bd173e37c83e1534580ab919d5446", null ], + [ "RadiationSource", "struct_radiation_source.html#a13db4b713a7fa670799c426676bc771f", null ], + [ "RadiationSource", "struct_radiation_source.html#a858a27adea32f97904b4bceb3eb253ce", null ], + [ "RadiationSource", "struct_radiation_source.html#aedecf6adc5056dc241007993e375f260", null ], + [ "source_flux_scaling_factor", "struct_radiation_source.html#a96bb8f5309cd171067e2693a6fb0118f", null ], + [ "source_fluxes", "struct_radiation_source.html#af57db9db9cd4f389eecd547e474644d3", null ], + [ "source_position", "struct_radiation_source.html#a7b6944d5b003d2001d4e0a096c2d72c2", null ], + [ "source_position_scaling_factor", "struct_radiation_source.html#a1a48a8fce4d1edba23aba7490fd1a6f7", null ], + [ "source_rotation", "struct_radiation_source.html#ac436b7a30a4f1a614df2d4b4fa5a4b5a", null ], + [ "source_spectrum", "struct_radiation_source.html#a2a5320be3f9facc5863928f81dbc8823", null ], + [ "source_type", "struct_radiation_source.html#ad6e32df75c976c45dbf00b6f76eb1c48", null ], + [ "source_width", "struct_radiation_source.html#a6135f3233535ed8dbbf0075d4123dc07", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_random_parameter__float.html b/doc/html/struct_random_parameter__float.html index 27addcb28..b6ca5cbf5 100644 --- a/doc/html/struct_random_parameter__float.html +++ b/doc/html/struct_random_parameter__float.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_random_parameter__float.js b/doc/html/struct_random_parameter__float.js new file mode 100644 index 000000000..f2640c6e4 --- /dev/null +++ b/doc/html/struct_random_parameter__float.js @@ -0,0 +1,6 @@ +var struct_random_parameter__float = +[ + [ "RandomParameter_float", "struct_random_parameter__float.html#a7a817ca20cc05025ce5d84fc0603d41b", null ], + [ "RandomParameter_float", "struct_random_parameter__float.html#ab0d3df0a653e4325a6485b7a31450365", null ], + [ "RandomParameter_float", "struct_random_parameter__float.html#aaf1fc58b78ae982d6065c5cfbd87a1dd", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_random_parameter__int.html b/doc/html/struct_random_parameter__int.html index a0a502f17..f1a3a085c 100644 --- a/doc/html/struct_random_parameter__int.html +++ b/doc/html/struct_random_parameter__int.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_scan_metadata.html b/doc/html/struct_scan_metadata.html index a2fa744b2..34213011d 100644 --- a/doc/html/struct_scan_metadata.html +++ b/doc/html/struct_scan_metadata.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Public Member Functions | @@ -133,8 +143,7 @@  Number of zenithal angles in scan (rows)
  float thetaMin - Minimum zenithal angle of scan in radians
-
+ Minimum zenithal angle of scan in radians.
  float thetaMax  Maximum zenithal angle of scan in radians.
@@ -523,8 +532,7 @@

-

Minimum zenithal angle of scan in radians
-

+

Minimum zenithal angle of scan in radians.

Note
Zenithal angles range from -pi/2 (downward) to +pi/2 (upward).

Definition at line 214 of file LiDAR.h.

@@ -536,10 +544,13 @@

LiDAR.cpp

- -
+ + diff --git a/doc/html/struct_scan_metadata.js b/doc/html/struct_scan_metadata.js new file mode 100644 index 000000000..454f76fb7 --- /dev/null +++ b/doc/html/struct_scan_metadata.js @@ -0,0 +1,18 @@ +var struct_scan_metadata = +[ + [ "ScanMetadata", "struct_scan_metadata.html#a2f625c96f54068fb8de34b528e7f770d", null ], + [ "ScanMetadata", "struct_scan_metadata.html#a6aa59ee9ecf89c9c6a2ae3a734c5ccd4", null ], + [ "direction2rc", "struct_scan_metadata.html#aab2db5e4c22f1eb7979294a7f8993611", null ], + [ "rc2direction", "struct_scan_metadata.html#ae28f6042e5eae2adaaacbeaaa6109a8c", null ], + [ "beamDivergence", "struct_scan_metadata.html#acec69b1556a96236c0702f03b231d008", null ], + [ "columnFormat", "struct_scan_metadata.html#accc2b308821e99b3e9aeed5d0a797130", null ], + [ "data_file", "struct_scan_metadata.html#a9314565da4824fbee86ced28382cc1dc", null ], + [ "exitDiameter", "struct_scan_metadata.html#a86d36162498a4de96a04ce83976c8e22", null ], + [ "Nphi", "struct_scan_metadata.html#a8d9273e0fccbfc20916c284ab6c573ac", null ], + [ "Ntheta", "struct_scan_metadata.html#a8432ab0ab545a0027bb47ce84f0a6704", null ], + [ "origin", "struct_scan_metadata.html#a200bf65b728866855ace6456365d66a3", null ], + [ "phiMax", "struct_scan_metadata.html#a29f41bdfbec57a32c60755944b4c0a7f", null ], + [ "phiMin", "struct_scan_metadata.html#a019acfcaf7a3ba3fe062af1a59c24513", null ], + [ "thetaMax", "struct_scan_metadata.html#a2654da6ef2d7d383ba912cbc6cbfeedf", null ], + [ "thetaMin", "struct_scan_metadata.html#a1b5a4f80f3d64d54755d2b6499f3863f", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_shader.html b/doc/html/struct_shader.html index aa711c6f6..bc078f3e7 100644 --- a/doc/html/struct_shader.html +++ b/doc/html/struct_shader.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
Public Member Functions | @@ -194,7 +204,7 @@

-

Definition at line 4082 of file Visualizer.cpp.

+

Definition at line 4083 of file Visualizer.cpp.

@@ -216,7 +226,7 @@

Definition at line 4087 of file Visualizer.cpp.

+

Definition at line 4088 of file Visualizer.cpp.

@@ -237,7 +247,7 @@

Definition at line 4171 of file Visualizer.cpp.

+

Definition at line 4172 of file Visualizer.cpp.

@@ -258,7 +268,7 @@

Definition at line 4291 of file Visualizer.cpp.

+

Definition at line 4292 of file Visualizer.cpp.

@@ -290,7 +300,7 @@

Definition at line 3931 of file Visualizer.cpp.

+

Definition at line 3932 of file Visualizer.cpp.

@@ -311,7 +321,7 @@

Definition at line 4310 of file Visualizer.cpp.

+

Definition at line 4311 of file Visualizer.cpp.

@@ -332,7 +342,7 @@

Definition at line 4314 of file Visualizer.cpp.

+

Definition at line 4315 of file Visualizer.cpp.

@@ -353,7 +363,7 @@

Definition at line 4318 of file Visualizer.cpp.

+

Definition at line 4319 of file Visualizer.cpp.

@@ -374,7 +384,7 @@

Definition at line 4322 of file Visualizer.cpp.

+

Definition at line 4323 of file Visualizer.cpp.

@@ -412,7 +422,7 @@

Definition at line 4092 of file Visualizer.cpp.

+

Definition at line 4093 of file Visualizer.cpp.

@@ -450,7 +460,7 @@

Definition at line 4231 of file Visualizer.cpp.

+

Definition at line 4232 of file Visualizer.cpp.

@@ -482,7 +492,7 @@

Definition at line 4187 of file Visualizer.cpp.

+

Definition at line 4188 of file Visualizer.cpp.

@@ -503,7 +513,7 @@

Definition at line 4306 of file Visualizer.cpp.

+

Definition at line 4307 of file Visualizer.cpp.

@@ -524,7 +534,7 @@

Definition at line 4326 of file Visualizer.cpp.

+

Definition at line 4327 of file Visualizer.cpp.

@@ -694,10 +704,13 @@

Visualizer.cpp - - + + diff --git a/doc/html/struct_shader.js b/doc/html/struct_shader.js new file mode 100644 index 000000000..52eb4a29c --- /dev/null +++ b/doc/html/struct_shader.js @@ -0,0 +1,16 @@ +var struct_shader = +[ + [ "disableTextures", "struct_shader.html#a487913973657c8817a5aa03422c43be5", null ], + [ "enableTextureMaps", "struct_shader.html#a7a7ec6989dd0c90dcf290b07fab781a7", null ], + [ "enableTextureMasks", "struct_shader.html#a1da903f6c4f0aabd7df4e1cbcb67137c", null ], + [ "initialize", "struct_shader.html#a168524d306867180df143651ed73ce3b", null ], + [ "setDepthBiasMatrix", "struct_shader.html#a0efa9af9639f9dc4b2c119a8b3a3981b", null ], + [ "setLightDirection", "struct_shader.html#a197c0e45d7c831ffb337b892b3e29594", null ], + [ "setLightingModel", "struct_shader.html#a08f9e96dbdea98bf178f902549c8096b", null ], + [ "setLightIntensity", "struct_shader.html#adb7e2c4c14638b056e39b6b9827bef97", null ], + [ "setTextureMap", "struct_shader.html#ab2e9dda74f59acd1bfa0bbfb6d405526", null ], + [ "setTextureMask", "struct_shader.html#acabe2ce63e1a7fc5773803e3174de7ac", null ], + [ "setTextureMask", "struct_shader.html#a7800ac33a9f3fdaefad983d6fe851fa7", null ], + [ "setTransformationMatrix", "struct_shader.html#af0ef553d486d1c50da7e2a96ec048ba9", null ], + [ "useShader", "struct_shader.html#a07520fd004cb1fd118597151d00e2c24", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_shoot.html b/doc/html/struct_shoot.html index df8ed3cdc..3405eb682 100644 --- a/doc/html/struct_shoot.html +++ b/doc/html/struct_shoot.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
Public Member Functions | @@ -139,6 +149,8 @@   float sumShootLeafArea (uint start_node_index=0) const   +float sumChildVolume (uint start_node_index=0) const +  void propagateDownstreamLeafArea (Shoot *shoot, uint node_index, float leaf_area)   void breakDormancy () @@ -170,10 +182,18 @@   const uint parent_petiole_index   -float carbohydrate_pool_molC = 0.01 +float carbohydrate_pool_molC = 0   -float old_shoot_volume = 0 +float old_shoot_volume   +float phyllochron_increase = 2 +  +float phyllochron_recovery = phyllochron_increase * 1.5 +  +float elongation_decay = 0.5 +  +float elongation_recovery = elongation_decay /1.5 +  uint days_with_negative_carbon_balance = 0   bool isdormant @@ -184,6 +204,10 @@   float phyllochron_counter = 0   +float phyllochron_min = 6 +  +float elongation_max = .25 +  float curvature_perturbation = 0   float yaw_perturbation = 0 @@ -206,6 +230,10 @@   std::string shoot_type_label   +float phyllochron_instantaneous +  +float elongation_rate_instantaneous +  std::vector< std::shared_ptr< Phytomer > > phytomers   PlantArchitectureplantarchitecture_ptr @@ -291,7 +319,7 @@

-

Definition at line 1760 of file PlantArchitecture.cpp.

+

Definition at line 1835 of file PlantArchitecture.cpp.

@@ -311,7 +339,7 @@

-

Definition at line 634 of file PlantArchitecture.cpp.

+

Definition at line 638 of file PlantArchitecture.cpp.

@@ -361,7 +389,7 @@

Returns
Number of phytomers in the shoot after the new phytomer is appended
-

Definition at line 427 of file PlantArchitecture.cpp.

+

Definition at line 429 of file PlantArchitecture.cpp.

@@ -380,7 +408,7 @@

-

Definition at line 552 of file PlantArchitecture.cpp.

+

Definition at line 556 of file PlantArchitecture.cpp.

@@ -418,7 +446,7 @@

-

Definition at line 1774 of file PlantArchitecture.cpp.

+

Definition at line 1851 of file PlantArchitecture.cpp.

@@ -437,7 +465,7 @@

-

Definition at line 657 of file PlantArchitecture.cpp.

+

Definition at line 661 of file PlantArchitecture.cpp.

@@ -456,7 +484,7 @@

-

Definition at line 667 of file PlantArchitecture.cpp.

+

Definition at line 671 of file PlantArchitecture.cpp.

@@ -475,7 +503,7 @@

-

Definition at line 720 of file PlantArchitecture.cpp.

+

Definition at line 724 of file PlantArchitecture.cpp.

@@ -494,7 +522,7 @@

-

Definition at line 587 of file PlantArchitecture.cpp.

+

Definition at line 591 of file PlantArchitecture.cpp.

@@ -522,7 +550,7 @@

-

Definition at line 733 of file PlantArchitecture.cpp.

+

Definition at line 737 of file PlantArchitecture.cpp.

@@ -544,7 +572,7 @@

Returns
Label of the randomly selected child shoot type.
-

Definition at line 1797 of file PlantArchitecture.cpp.

+

Definition at line 1874 of file PlantArchitecture.cpp.

@@ -577,7 +605,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 1861 of file PlantArchitecture.cpp.

+

Definition at line 1938 of file PlantArchitecture.cpp.

@@ -605,7 +633,26 @@

Returns
True if the vegetative bud should break into a new shoot
-

Definition at line 1832 of file PlantArchitecture.cpp.

+

Definition at line 1909 of file PlantArchitecture.cpp.

+ + + + +

◆ sumChildVolume()

+ +
+
+ + + + + + + +
float Shoot::sumChildVolume (uint start_node_index = 0) const
+
+ +

Definition at line 781 of file PlantArchitecture.cpp.

@@ -624,7 +671,7 @@

-

Definition at line 747 of file PlantArchitecture.cpp.

+

Definition at line 751 of file PlantArchitecture.cpp.

@@ -643,7 +690,7 @@

-

Definition at line 620 of file PlantArchitecture.cpp.

+

Definition at line 624 of file PlantArchitecture.cpp.

@@ -662,7 +709,7 @@

-

Definition at line 624 of file PlantArchitecture.cpp.

+

Definition at line 628 of file PlantArchitecture.cpp.

@@ -683,7 +730,7 @@

Definition at line 675 of file PlantArchitecture.cpp.

+

Definition at line 679 of file PlantArchitecture.cpp.

@@ -700,7 +747,7 @@

-

Definition at line 1020 of file PlantArchitecture.h.

+

Definition at line 1022 of file PlantArchitecture.h.

@@ -716,7 +763,7 @@

-

Definition at line 1021 of file PlantArchitecture.h.

+

Definition at line 1023 of file PlantArchitecture.h.

@@ -732,7 +779,7 @@

-

Definition at line 1058 of file PlantArchitecture.h.

+

Definition at line 1068 of file PlantArchitecture.h.

@@ -743,12 +790,12 @@

- +
float Shoot::carbohydrate_pool_molC = 0.01float Shoot::carbohydrate_pool_molC = 0
@@ -764,7 +811,7 @@

-

Definition at line 1061 of file PlantArchitecture.h.

+

Definition at line 1071 of file PlantArchitecture.h.

@@ -780,7 +827,7 @@

-

Definition at line 1071 of file PlantArchitecture.h.

+

Definition at line 1084 of file PlantArchitecture.h.

@@ -796,7 +843,7 @@

-

Definition at line 1017 of file PlantArchitecture.h.

+

Definition at line 1019 of file PlantArchitecture.h.

@@ -812,7 +859,7 @@

-

Definition at line 1046 of file PlantArchitecture.h.

+

Definition at line 1056 of file PlantArchitecture.h.

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

-

Definition at line 1034 of file PlantArchitecture.h.

+

Definition at line 1042 of file PlantArchitecture.h.

@@ -844,6 +891,70 @@

+

Definition at line 1048 of file PlantArchitecture.h.

+ + + + +

◆ elongation_decay

+ +
+
+ + + + +
float Shoot::elongation_decay = 0.5
+
+ +

Definition at line 1039 of file PlantArchitecture.h.

+ +
+
+ +

◆ elongation_max

+ +
+
+ + + + +
float Shoot::elongation_max = .25
+
+ +

Definition at line 1054 of file PlantArchitecture.h.

+ +
+
+ +

◆ elongation_rate_instantaneous

+ +
+
+ + + + +
float Shoot::elongation_rate_instantaneous
+
+ +

Definition at line 1078 of file PlantArchitecture.h.

+ +
+
+ +

◆ elongation_recovery

+ +
+
+ + + + +
float Shoot::elongation_recovery = elongation_decay /1.5
+
+

Definition at line 1040 of file PlantArchitecture.h.

@@ -860,7 +971,7 @@

-

Definition at line 1049 of file PlantArchitecture.h.

+

Definition at line 1059 of file PlantArchitecture.h.

@@ -876,7 +987,7 @@

-

Definition at line 1024 of file PlantArchitecture.h.

+

Definition at line 1026 of file PlantArchitecture.h.

@@ -892,7 +1003,7 @@

-

Definition at line 1051 of file PlantArchitecture.h.

+

Definition at line 1061 of file PlantArchitecture.h.

@@ -908,7 +1019,7 @@

-

Definition at line 1053 of file PlantArchitecture.h.

+

Definition at line 1063 of file PlantArchitecture.h.

@@ -924,7 +1035,7 @@

-

Definition at line 1039 of file PlantArchitecture.h.

+

Definition at line 1047 of file PlantArchitecture.h.

@@ -940,7 +1051,7 @@

-

Definition at line 1042 of file PlantArchitecture.h.

+

Definition at line 1050 of file PlantArchitecture.h.

@@ -956,7 +1067,7 @@

-

Definition at line 1018 of file PlantArchitecture.h.

+

Definition at line 1020 of file PlantArchitecture.h.

@@ -967,12 +1078,12 @@

- +
float Shoot::old_shoot_volume = 0float Shoot::old_shoot_volume
@@ -988,7 +1099,7 @@

-

Definition at line 1027 of file PlantArchitecture.h.

+

Definition at line 1029 of file PlantArchitecture.h.

@@ -1004,7 +1115,7 @@

-

Definition at line 1029 of file PlantArchitecture.h.

+

Definition at line 1031 of file PlantArchitecture.h.

@@ -1020,7 +1131,7 @@

-

Definition at line 1025 of file PlantArchitecture.h.

+

Definition at line 1027 of file PlantArchitecture.h.

@@ -1036,7 +1147,71 @@

-

Definition at line 1044 of file PlantArchitecture.h.

+

Definition at line 1052 of file PlantArchitecture.h.

+ + + + +

◆ phyllochron_increase

+ +
+
+ + + + +
float Shoot::phyllochron_increase = 2
+
+ +

Definition at line 1036 of file PlantArchitecture.h.

+ +
+
+ +

◆ phyllochron_instantaneous

+ +
+
+ + + + +
float Shoot::phyllochron_instantaneous
+
+ +

Definition at line 1077 of file PlantArchitecture.h.

+ +
+
+ +

◆ phyllochron_min

+ +
+
+ + + + +
float Shoot::phyllochron_min = 6
+
+ +

Definition at line 1053 of file PlantArchitecture.h.

+ +
+
+ +

◆ phyllochron_recovery

+ +
+
+ + + + +
float Shoot::phyllochron_recovery = phyllochron_increase * 1.5
+
+ +

Definition at line 1037 of file PlantArchitecture.h.

@@ -1052,7 +1227,7 @@

-

Definition at line 1067 of file PlantArchitecture.h.

+

Definition at line 1080 of file PlantArchitecture.h.

@@ -1068,7 +1243,7 @@

-

Definition at line 1069 of file PlantArchitecture.h.

+

Definition at line 1082 of file PlantArchitecture.h.

@@ -1084,7 +1259,7 @@

-

Definition at line 1026 of file PlantArchitecture.h.

+

Definition at line 1028 of file PlantArchitecture.h.

@@ -1100,7 +1275,7 @@

-

Definition at line 1022 of file PlantArchitecture.h.

+

Definition at line 1024 of file PlantArchitecture.h.

@@ -1116,7 +1291,7 @@

-

Definition at line 1028 of file PlantArchitecture.h.

+

Definition at line 1030 of file PlantArchitecture.h.

@@ -1132,7 +1307,7 @@

-

Definition at line 1056 of file PlantArchitecture.h.

+

Definition at line 1066 of file PlantArchitecture.h.

@@ -1148,7 +1323,7 @@

-

Definition at line 1055 of file PlantArchitecture.h.

+

Definition at line 1065 of file PlantArchitecture.h.

@@ -1164,7 +1339,7 @@

-

Definition at line 1063 of file PlantArchitecture.h.

+

Definition at line 1073 of file PlantArchitecture.h.

@@ -1180,7 +1355,7 @@

-

Definition at line 1065 of file PlantArchitecture.h.

+

Definition at line 1075 of file PlantArchitecture.h.

@@ -1196,7 +1371,7 @@

-

Definition at line 1047 of file PlantArchitecture.h.

+

Definition at line 1057 of file PlantArchitecture.h.

@@ -1205,10 +1380,13 @@

PlantArchitecture.cpp - - + + diff --git a/doc/html/struct_shoot.js b/doc/html/struct_shoot.js new file mode 100644 index 000000000..5cfd6a761 --- /dev/null +++ b/doc/html/struct_shoot.js @@ -0,0 +1,8 @@ +var struct_shoot = +[ + [ "appendPhytomer", "struct_shoot.html#a624619a8a5106774aa25dc99ba06cd41", null ], + [ "sampleChildShootType", "struct_shoot.html#aab304a4f16758e32927dba357f6fb775", null ], + [ "sampleEpicormicShoot", "struct_shoot.html#afe4fa0bc2d46f94087c88b658d8aef13", null ], + [ "sampleVegetativeBudBreak", "struct_shoot.html#a79c44586c03664cfe2e7e8e114821f4f", null ], + [ "updateShootNodes", "struct_shoot.html#a19eb5d6e3248c45de08774d11cbf329b", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_shoot_parameters.html b/doc/html/struct_shoot_parameters.html index b0bf6b815..69749fb82 100644 --- a/doc/html/struct_shoot_parameters.html +++ b/doc/html/struct_shoot_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- @@ -379,14 +389,14 @@

-

◆ elongation_rate

+ +

◆ elongation_rate_max

- +
RandomParameter_float ShootParameters::elongation_rateRandomParameter_float ShootParameters::elongation_rate_max
@@ -721,10 +731,13 @@

PlantArchitecture.cpp

- -
+ + diff --git a/doc/html/struct_shoot_parameters.js b/doc/html/struct_shoot_parameters.js new file mode 100644 index 000000000..112a8ecef --- /dev/null +++ b/doc/html/struct_shoot_parameters.js @@ -0,0 +1,6 @@ +var struct_shoot_parameters = +[ + [ "ShootParameters", "struct_shoot_parameters.html#ab3003af230c520f6ff26010ca3ef850e", null ], + [ "ShootParameters", "struct_shoot_parameters.html#ab02d5fb11149500aae2d2480c3a75b6e", null ], + [ "vegetative_bud_break_probability_decay_rate", "struct_shoot_parameters.html#abe60e69a5cf66199d1dfd6688e4d4ced", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_shx.html b/doc/html/struct_shx.html index 7de360608..a9887eca8 100644 --- a/doc/html/struct_shx.html +++ b/doc/html/struct_shx.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_sorghum_canopy_parameters.html b/doc/html/struct_sorghum_canopy_parameters.html index 248168a52..fd6910dba 100644 --- a/doc/html/struct_sorghum_canopy_parameters.html +++ b/doc/html/struct_sorghum_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_sorghum_canopy_parameters.js b/doc/html/struct_sorghum_canopy_parameters.js new file mode 100644 index 000000000..8c653eb09 --- /dev/null +++ b/doc/html/struct_sorghum_canopy_parameters.js @@ -0,0 +1,69 @@ +var struct_sorghum_canopy_parameters = +[ + [ "SorghumCanopyParameters", "struct_sorghum_canopy_parameters.html#a5d06ca3cd236193ada9662f0787abd40", null ], + [ "SorghumCanopyParameters", "struct_sorghum_canopy_parameters.html#a135111963ff4580035611f3af2babe37", null ], + [ "buildCanopy", "struct_sorghum_canopy_parameters.html#ae21bba784a6af20966ba7a87e9c283dc", null ], + [ "buildPlant", "struct_sorghum_canopy_parameters.html#a1139c684da4cde5c7b34500da0e87bb5", null ], + [ "readParametersFromXML", "struct_sorghum_canopy_parameters.html#a616f622ac8a7387b0ec94509340ccd18", null ], + [ "plant_count", "struct_sorghum_canopy_parameters.html#a66cb3200529a5b83416a43267ade724e", null ], + [ "plant_spacing", "struct_sorghum_canopy_parameters.html#a4d2e359bc3e33b9e04019575e8e4e30f", null ], + [ "row_spacing", "struct_sorghum_canopy_parameters.html#ad03798a817bc923891357b0298050b6a", null ], + [ "s1_leaf1_angle", "struct_sorghum_canopy_parameters.html#a055da9b13d5d33b8b62e3fb9d8432f08", null ], + [ "s1_leaf2_angle", "struct_sorghum_canopy_parameters.html#adaf3271852908daf8b55121ce7fffd7c", null ], + [ "s1_leaf3_angle", "struct_sorghum_canopy_parameters.html#aed23ed04b3ddca133071f74f4a6c4aad", null ], + [ "s1_leaf_size1", "struct_sorghum_canopy_parameters.html#a5f043e646e579018dfa6fec8fb458368", null ], + [ "s1_leaf_size2", "struct_sorghum_canopy_parameters.html#a1f43b856d67a2d0d827445d898f7527c", null ], + [ "s1_leaf_size3", "struct_sorghum_canopy_parameters.html#a7e30b11a0539a22e26b5ba0b62e74c89", null ], + [ "s1_leaf_subdivisions", "struct_sorghum_canopy_parameters.html#ac84f20cc1f137d8969c1166d78589161", null ], + [ "s1_leaf_texture_file", "struct_sorghum_canopy_parameters.html#a1ba7822b8d7b621236d3fb26339f3b80", null ], + [ "s1_stem_length", "struct_sorghum_canopy_parameters.html#ae2e5589dba50b2dc31be67b2b27582a2", null ], + [ "s1_stem_radius", "struct_sorghum_canopy_parameters.html#aa6f75372512d2cbbe72091f90b416c8c", null ], + [ "s1_stem_subdivisions", "struct_sorghum_canopy_parameters.html#ac18297754bb4664c4b06917edea77a82", null ], + [ "s2_leaf1_angle", "struct_sorghum_canopy_parameters.html#a35058e0b3485d531348a82d0fcbfb92f", null ], + [ "s2_leaf2_angle", "struct_sorghum_canopy_parameters.html#af96017371615c50147f5ac71cead2b6d", null ], + [ "s2_leaf3_angle", "struct_sorghum_canopy_parameters.html#a546b3ffb7e55a1f3050d914b3cf3fb0c", null ], + [ "s2_leaf4_angle", "struct_sorghum_canopy_parameters.html#a42b6683f425584df7d87da2b096ac901", null ], + [ "s2_leaf5_angle", "struct_sorghum_canopy_parameters.html#a4b5828b945f8f2ab30855bee3aabc9c5", null ], + [ "s2_leaf_size1", "struct_sorghum_canopy_parameters.html#aedaf27d8e335d46e89d8f3f960a5fdd5", null ], + [ "s2_leaf_size2", "struct_sorghum_canopy_parameters.html#ace2b6a18a80e6f53d4459f4233d329c1", null ], + [ "s2_leaf_size3", "struct_sorghum_canopy_parameters.html#a92fda41cc4d33cc1bbda5647b2b85116", null ], + [ "s2_leaf_size4", "struct_sorghum_canopy_parameters.html#ac69d718bffad7c7586615440de9f4339", null ], + [ "s2_leaf_size5", "struct_sorghum_canopy_parameters.html#ab1722a2d04435a3d9ebeefdffde6d3dd", null ], + [ "s2_leaf_subdivisions", "struct_sorghum_canopy_parameters.html#a4cc923591186631e81670cba369764f5", null ], + [ "s2_leaf_texture_file", "struct_sorghum_canopy_parameters.html#a3d4def312245c9351ed27b6e4e2ccedd", null ], + [ "s2_stem_length", "struct_sorghum_canopy_parameters.html#adab00887989b76b54f6fe5cbe0b00fa4", null ], + [ "s2_stem_radius", "struct_sorghum_canopy_parameters.html#a566d945dca39d9064e76349db76b3b6e", null ], + [ "s2_stem_subdivisions", "struct_sorghum_canopy_parameters.html#a02d288c3ce64c16aa3ed35bbde1a3e72", null ], + [ "s3_leaf_size", "struct_sorghum_canopy_parameters.html#ad6dc4e8e1c43d9e85cc303c4270b995d", null ], + [ "s3_leaf_subdivisions", "struct_sorghum_canopy_parameters.html#a13cd4f9fa100a7f945549d215f8e2dd7", null ], + [ "s3_leaf_texture_file", "struct_sorghum_canopy_parameters.html#a87f1e1ec6df26337ea31b9d235bfa6f4", null ], + [ "s3_mean_leaf_angle", "struct_sorghum_canopy_parameters.html#a2d470fce2f09d835c48d5f8a04e6a0f3", null ], + [ "s3_number_of_leaves", "struct_sorghum_canopy_parameters.html#aadb0291f1b07d6de354e2bf86050ab76", null ], + [ "s3_stem_length", "struct_sorghum_canopy_parameters.html#a874045edcb46926aaddeb3588061a275", null ], + [ "s3_stem_radius", "struct_sorghum_canopy_parameters.html#a6862b2e046366ce852896fca526a8857", null ], + [ "s3_stem_subdivisions", "struct_sorghum_canopy_parameters.html#ae0a4609f94d4e1104ff5a411c8e1b28e", null ], + [ "s4_leaf_size", "struct_sorghum_canopy_parameters.html#a542b812d6c48b3c41cab4111261ee242", null ], + [ "s4_leaf_subdivisions", "struct_sorghum_canopy_parameters.html#a55fdb0febc1cc573d59bcad2db07d6a7", null ], + [ "s4_leaf_texture_file", "struct_sorghum_canopy_parameters.html#acc23aed799e76667167f474ecd29af4b", null ], + [ "s4_mean_leaf_angle", "struct_sorghum_canopy_parameters.html#a4ab179de4931853476bb68cf9cccfb57", null ], + [ "s4_number_of_leaves", "struct_sorghum_canopy_parameters.html#a823d78f11ca9b5d8f8f3a5dfe9c3ab8f", null ], + [ "s4_panicle_size", "struct_sorghum_canopy_parameters.html#af6380b91e8a559b711e0b973ef862bc2", null ], + [ "s4_panicle_subdivisions", "struct_sorghum_canopy_parameters.html#a83893b5e61c2501509fc2f0c9d7b7634", null ], + [ "s4_seed_texture_file", "struct_sorghum_canopy_parameters.html#a0e592b9ddd3bdaf213c154dd3865c710", null ], + [ "s4_stem_length", "struct_sorghum_canopy_parameters.html#a11feead673b9e86c4559a8670c290257", null ], + [ "s4_stem_radius", "struct_sorghum_canopy_parameters.html#a2a80af374f3d050df6ecf568e831a739", null ], + [ "s4_stem_subdivisions", "struct_sorghum_canopy_parameters.html#a321d838cea5a50a7131e71c3c732367a", null ], + [ "s5_leaf_size", "struct_sorghum_canopy_parameters.html#ab6c381612b2ca76fc409401dc75bab3f", null ], + [ "s5_leaf_subdivisions", "struct_sorghum_canopy_parameters.html#a78ef9c1a644caad89f52d759630d9a0b", null ], + [ "s5_leaf_texture_file", "struct_sorghum_canopy_parameters.html#a6ad429a68501b5a1fecb795a73d943d8", null ], + [ "s5_mean_leaf_angle", "struct_sorghum_canopy_parameters.html#a10c15107111fdd0b73cfef24d45d3ab4", null ], + [ "s5_number_of_leaves", "struct_sorghum_canopy_parameters.html#a0fd7a4e7d5f5a2fa419e738a35d368e1", null ], + [ "s5_panicle_size", "struct_sorghum_canopy_parameters.html#aad64258f9ac6ec9df2f86c5ff9bb8d0d", null ], + [ "s5_panicle_subdivisions", "struct_sorghum_canopy_parameters.html#a3dd303738e509f6b67e423f303b39e13", null ], + [ "s5_seed_texture_file", "struct_sorghum_canopy_parameters.html#af5ce42735f214b47e215759c8c6b02ee", null ], + [ "s5_stem_bend", "struct_sorghum_canopy_parameters.html#a5d8dcff59a7cb1604c67595efaa04b36", null ], + [ "s5_stem_length", "struct_sorghum_canopy_parameters.html#a09aa6e060ca74d672d20742ff6f330dc", null ], + [ "s5_stem_radius", "struct_sorghum_canopy_parameters.html#a667cefb6b9b105d58c3bef82db61c52f", null ], + [ "s5_stem_subdivisions", "struct_sorghum_canopy_parameters.html#a016f6dbe9526e4411d9b7f1480e562b6", null ], + [ "sorghum_stage", "struct_sorghum_canopy_parameters.html#ae438f61b66b95f9ada7f9f34a7162e2c", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_spherical_crowns_canopy_parameters.html b/doc/html/struct_spherical_crowns_canopy_parameters.html index 399b05b8f..beea2a39b 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_spherical_crowns_canopy_parameters.js b/doc/html/struct_spherical_crowns_canopy_parameters.js new file mode 100644 index 000000000..435bc389a --- /dev/null +++ b/doc/html/struct_spherical_crowns_canopy_parameters.js @@ -0,0 +1,18 @@ +var struct_spherical_crowns_canopy_parameters = +[ + [ "SphericalCrownsCanopyParameters", "struct_spherical_crowns_canopy_parameters.html#a9f4c0922be93c14cbeefcf816a392077", null ], + [ "SphericalCrownsCanopyParameters", "struct_spherical_crowns_canopy_parameters.html#a6109ceebfa172d0a452c67bd4add93da", null ], + [ "buildCanopy", "struct_spherical_crowns_canopy_parameters.html#ae1670d0366828f06f04936530e94af89", null ], + [ "buildPlant", "struct_spherical_crowns_canopy_parameters.html#af127df26f4a93e6422e23720f5b0a136", null ], + [ "readParametersFromXML", "struct_spherical_crowns_canopy_parameters.html#addf82e2fd57315136b747531ecb4200a", null ], + [ "canopy_configuration", "struct_spherical_crowns_canopy_parameters.html#acb6042ba8355cae63a24a1b98ca3aa58", null ], + [ "crown_radius", "struct_spherical_crowns_canopy_parameters.html#a1695b7794ffb1c8ab8618ebb701fbb6d", null ], + [ "leaf_angle_distribution", "struct_spherical_crowns_canopy_parameters.html#ab11d57364434c44388b83a7a04dc9bd0", null ], + [ "leaf_area_density", "struct_spherical_crowns_canopy_parameters.html#ab625b07dbc7f73b11d4af2932e96158d", null ], + [ "leaf_color", "struct_spherical_crowns_canopy_parameters.html#a7d08f35ed3ce045b74bd4479ca4cb5b4", null ], + [ "leaf_size", "struct_spherical_crowns_canopy_parameters.html#a48c2ab4110bc38b4f412250d8e3e8051", null ], + [ "leaf_subdivisions", "struct_spherical_crowns_canopy_parameters.html#aa7ddee04ae15e0aa0814702a0ef4a034", null ], + [ "leaf_texture_file", "struct_spherical_crowns_canopy_parameters.html#a6b01f45dcaefadaf8bb4ebd67b92197b", null ], + [ "plant_count", "struct_spherical_crowns_canopy_parameters.html#a8ac3d5fbeee86db6289693aa5e14a76f", null ], + [ "plant_spacing", "struct_spherical_crowns_canopy_parameters.html#a9be21b26afb7d32b61a236bbe5372acd", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_split_grapevine_parameters.html b/doc/html/struct_split_grapevine_parameters.html index 672d1376d..04a7fd929 100644 --- a/doc/html/struct_split_grapevine_parameters.html +++ b/doc/html/struct_split_grapevine_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_split_grapevine_parameters.js b/doc/html/struct_split_grapevine_parameters.js new file mode 100644 index 000000000..d13b49c75 --- /dev/null +++ b/doc/html/struct_split_grapevine_parameters.js @@ -0,0 +1,14 @@ +var struct_split_grapevine_parameters = +[ + [ "SplitGrapevineParameters", "struct_split_grapevine_parameters.html#a63c5f4e090194bc74f35c1099b5520d4", null ], + [ "SplitGrapevineParameters", "struct_split_grapevine_parameters.html#a9f1e4d3e220effa2eccc0f4040ce15db", null ], + [ "buildCanopy", "struct_split_grapevine_parameters.html#a0e1bad7d21a9d1e2f2be2fc9b1a4a135", null ], + [ "buildPlant", "struct_split_grapevine_parameters.html#a6116fc97e1f19bcdb9b0c49714413c1c", null ], + [ "readParametersFromXML", "struct_split_grapevine_parameters.html#a3263eaf412ecd633ef785b96a65f6bec", null ], + [ "cordon_spacing", "struct_split_grapevine_parameters.html#a6d65cd7d6a101ce083020c08f7237dcb", null ], + [ "cordon_spacing_spread", "struct_split_grapevine_parameters.html#abe4c3510d79f5543ea86ec9d4c5baf81", null ], + [ "shoot_angle_base", "struct_split_grapevine_parameters.html#a37ae8efcf5324eed693d79ebd33edb91", null ], + [ "shoot_angle_base_spread", "struct_split_grapevine_parameters.html#a17998fb21f60d03be7f2c7844deaec3d", null ], + [ "shoot_angle_tip", "struct_split_grapevine_parameters.html#af4c2209be803fc0118328b97eeb50ab3", null ], + [ "shoot_angle_tip_spread", "struct_split_grapevine_parameters.html#ad8b40619cc10ce5d1a71077972658084", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_strawberry_parameters.html b/doc/html/struct_strawberry_parameters.html index 83eb3fc4c..ccf835609 100644 --- a/doc/html/struct_strawberry_parameters.html +++ b/doc/html/struct_strawberry_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_strawberry_parameters.js b/doc/html/struct_strawberry_parameters.js new file mode 100644 index 000000000..302732b8d --- /dev/null +++ b/doc/html/struct_strawberry_parameters.js @@ -0,0 +1,23 @@ +var struct_strawberry_parameters = +[ + [ "StrawberryParameters", "struct_strawberry_parameters.html#a4eb336cbf5135adf114135c958fdb41e", null ], + [ "StrawberryParameters", "struct_strawberry_parameters.html#aa58f8ff7655ded0ad470c81a3b34d718", null ], + [ "buildCanopy", "struct_strawberry_parameters.html#a9487c5f22f2dc3dce45a853c6c88c553", null ], + [ "buildPlant", "struct_strawberry_parameters.html#a739703fbc934574475585466357292a3", null ], + [ "readParametersFromXML", "struct_strawberry_parameters.html#a621e67abb2a43aac9714f6e8fde5aa96", null ], + [ "clusters_per_stem", "struct_strawberry_parameters.html#aac9b43d90dcf4883834708376c5514c9", null ], + [ "fruit_radius", "struct_strawberry_parameters.html#a4dd66f8aa042b1815999674beb9015e6", null ], + [ "fruit_subdivisions", "struct_strawberry_parameters.html#a5834190bacb193cf1fba6a1c68aa4116", null ], + [ "fruit_texture_file", "struct_strawberry_parameters.html#aa15e29acb98b00a55cada2dfaca847ac", null ], + [ "leaf_length", "struct_strawberry_parameters.html#afcfe4fd8f2cdba4df2d031e048ff18cb", null ], + [ "leaf_subdivisions", "struct_strawberry_parameters.html#a863f21593c3e36c1a43730e8a1594e9d", null ], + [ "leaf_texture_file", "struct_strawberry_parameters.html#ad19120d86ed515a1bfe29be284c0fbd1", null ], + [ "plant_count", "struct_strawberry_parameters.html#a5c4fc3e9da6d07f98bc4116f56be8916", null ], + [ "plant_height", "struct_strawberry_parameters.html#a612148d98514861b02a4def15489206d", null ], + [ "plant_spacing", "struct_strawberry_parameters.html#a4df2a5b0e030df75e54f2d519a7b87bf", null ], + [ "row_spacing", "struct_strawberry_parameters.html#ae2383458132397e4bbe111d4b4fc38b9", null ], + [ "stem_color", "struct_strawberry_parameters.html#aef7973d815b5bfb9c09e27130681d857", null ], + [ "stem_radius", "struct_strawberry_parameters.html#ac774348e3a59b3a79cf21e1b4634489f", null ], + [ "stem_subdivisions", "struct_strawberry_parameters.html#a07bd64fa21e059f5db73fbfb9d4c9607", null ], + [ "stems_per_plant", "struct_strawberry_parameters.html#a26ecd0d74e8339a2c40f05a7de926ef9", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_tomato_parameters.html b/doc/html/struct_tomato_parameters.html index 9c68425c3..a5f66c780 100644 --- a/doc/html/struct_tomato_parameters.html +++ b/doc/html/struct_tomato_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_tomato_parameters.js b/doc/html/struct_tomato_parameters.js new file mode 100644 index 000000000..46c5da0f3 --- /dev/null +++ b/doc/html/struct_tomato_parameters.js @@ -0,0 +1,20 @@ +var struct_tomato_parameters = +[ + [ "TomatoParameters", "struct_tomato_parameters.html#ab799d673013e4ef5c257293d9951a462", null ], + [ "TomatoParameters", "struct_tomato_parameters.html#ab687e0d3051c1c94fff2c61e5db971b4", null ], + [ "buildCanopy", "struct_tomato_parameters.html#adc34c3b3dcb59f81fb3d0f21059e8b9a", null ], + [ "buildPlant", "struct_tomato_parameters.html#a0915f161732f561e479d9eea9a375254", null ], + [ "readParametersFromXML", "struct_tomato_parameters.html#a94bd8a46a188d88039685eb4576c3e8b", null ], + [ "fruit_color", "struct_tomato_parameters.html#a279c4b778fee52501f8daedd4133f469", null ], + [ "fruit_radius", "struct_tomato_parameters.html#ae1c9e01c2ec65614c5302c8287ecd80a", null ], + [ "fruit_subdivisions", "struct_tomato_parameters.html#a42340b46c2de4ed21b1520cbfe7897db", null ], + [ "leaf_length", "struct_tomato_parameters.html#a0fc2acabb718f35337f71046fb540f83", null ], + [ "leaf_subdivisions", "struct_tomato_parameters.html#a2a3d8f1b74a1800db22926eaf2ec9ea8", null ], + [ "leaf_texture_file", "struct_tomato_parameters.html#ab800737ab2431324662b39f46d6e8b06", null ], + [ "plant_count", "struct_tomato_parameters.html#a3e32aed174650e40d708fb75fc7d6a41", null ], + [ "plant_height", "struct_tomato_parameters.html#adf398ca857bb113ffa65f3ded195ab23", null ], + [ "plant_spacing", "struct_tomato_parameters.html#a979927066ea306b2f5d3897ba0d5b09c", null ], + [ "row_spacing", "struct_tomato_parameters.html#a5b019fdf3087dbe150ef61cb68afd6f6", null ], + [ "shoot_color", "struct_tomato_parameters.html#a55cd91024165c3139c172ec3add2333c", null ], + [ "shoot_subdivisions", "struct_tomato_parameters.html#a056a0790faac4d769f749f75979c37af", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_triad.html b/doc/html/struct_triad.html index 8b2a70630..01c91c1b2 100644 --- a/doc/html/struct_triad.html +++ b/doc/html/struct_triad.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_triangulation.html b/doc/html/struct_triangulation.html index f8db1d90e..f2984cd18 100644 --- a/doc/html/struct_triangulation.html +++ b/doc/html/struct_triangulation.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_unilateral_grapevine_parameters.html b/doc/html/struct_unilateral_grapevine_parameters.html index 8b994ff5c..7fef2c3d8 100644 --- a/doc/html/struct_unilateral_grapevine_parameters.html +++ b/doc/html/struct_unilateral_grapevine_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_unilateral_grapevine_parameters.js b/doc/html/struct_unilateral_grapevine_parameters.js new file mode 100644 index 000000000..feeaad84d --- /dev/null +++ b/doc/html/struct_unilateral_grapevine_parameters.js @@ -0,0 +1,8 @@ +var struct_unilateral_grapevine_parameters = +[ + [ "UnilateralGrapevineParameters", "struct_unilateral_grapevine_parameters.html#a1f4063470113acb28186cf92b3030283", null ], + [ "UnilateralGrapevineParameters", "struct_unilateral_grapevine_parameters.html#ab85a40a1bc4bd1880f74814278ff7fd2", null ], + [ "buildCanopy", "struct_unilateral_grapevine_parameters.html#a84f41cb676c8614d336ed930457eaee1", null ], + [ "buildPlant", "struct_unilateral_grapevine_parameters.html#a4141eeadb3aa3269b739a08965ffa676", null ], + [ "readParametersFromXML", "struct_unilateral_grapevine_parameters.html#a78630bdc04ab711e118de436e4e03b20", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_v_s_p_grapevine_parameters.html b/doc/html/struct_v_s_p_grapevine_parameters.html index 144be6f2c..981e2848c 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
- + + diff --git a/doc/html/struct_v_s_p_grapevine_parameters.js b/doc/html/struct_v_s_p_grapevine_parameters.js new file mode 100644 index 000000000..6d8e09a93 --- /dev/null +++ b/doc/html/struct_v_s_p_grapevine_parameters.js @@ -0,0 +1,8 @@ +var struct_v_s_p_grapevine_parameters = +[ + [ "VSPGrapevineParameters", "struct_v_s_p_grapevine_parameters.html#af61690f86b14f0f6852e2c43b5549217", null ], + [ "VSPGrapevineParameters", "struct_v_s_p_grapevine_parameters.html#a07cb2adfeec316d0cf5ce9ffb2266dc2", null ], + [ "buildCanopy", "struct_v_s_p_grapevine_parameters.html#ae045693dbcb6e4935b292b226b6d98d6", null ], + [ "buildPlant", "struct_v_s_p_grapevine_parameters.html#a8c7d85f23ca257d820f7c28f6d6d4deb", null ], + [ "readParametersFromXML", "struct_v_s_p_grapevine_parameters.html#a07f45311c1199758112af1c5ecd93b66", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_vegetative_bud.html b/doc/html/struct_vegetative_bud.html index f7495a8db..14402acd0 100644 --- a/doc/html/struct_vegetative_bud.html +++ b/doc/html/struct_vegetative_bud.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
@@ -168,10 +178,13 @@

PlantArchitecture.h

- -
+ + diff --git a/doc/html/struct_walnut_canopy_parameters.html b/doc/html/struct_walnut_canopy_parameters.html index 643faf11d..8ad1fa24a 100644 --- a/doc/html/struct_walnut_canopy_parameters.html +++ b/doc/html/struct_walnut_canopy_parameters.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_walnut_canopy_parameters.js b/doc/html/struct_walnut_canopy_parameters.js new file mode 100644 index 000000000..f00c45497 --- /dev/null +++ b/doc/html/struct_walnut_canopy_parameters.js @@ -0,0 +1,22 @@ +var struct_walnut_canopy_parameters = +[ + [ "WalnutCanopyParameters", "struct_walnut_canopy_parameters.html#a3e9529efe557947137c49fefa450bb85", null ], + [ "WalnutCanopyParameters", "struct_walnut_canopy_parameters.html#ac233d993d5d15fd3fff46245a0365b93", null ], + [ "buildCanopy", "struct_walnut_canopy_parameters.html#ad0cb95df36b8fea5edd3f5c3b801999a", null ], + [ "buildPlant", "struct_walnut_canopy_parameters.html#a3f356a99983d3540171519f42e270808", null ], + [ "readParametersFromXML", "struct_walnut_canopy_parameters.html#a888acadc0f54524dc3aabe152a7a1679", null ], + [ "branch_length", "struct_walnut_canopy_parameters.html#aabf3f873a3ed1d5850b7697b297ae295", null ], + [ "fruit_radius", "struct_walnut_canopy_parameters.html#a620fceb81c9e7cdc0d350f51183f9b8e", null ], + [ "fruit_subdivisions", "struct_walnut_canopy_parameters.html#a4c3ac117f2b32ee15b22ff2e0ec4c325", null ], + [ "fruit_texture_file", "struct_walnut_canopy_parameters.html#a43de7836434a46b15520a96a80036d89", null ], + [ "leaf_length", "struct_walnut_canopy_parameters.html#a7b59b3a39200e3cd904806700ebcef03", null ], + [ "leaf_subdivisions", "struct_walnut_canopy_parameters.html#a4709a2450a721bd0cd148917c866663f", null ], + [ "leaf_texture_file", "struct_walnut_canopy_parameters.html#a7927fbdc60d70addb5762ef2caf4eccf", null ], + [ "plant_count", "struct_walnut_canopy_parameters.html#a0a8fd703c9e0f1beedf990d85038d173", null ], + [ "plant_spacing", "struct_walnut_canopy_parameters.html#a250d9f9ed73cd73c39f9dd6033771fe3", null ], + [ "row_spacing", "struct_walnut_canopy_parameters.html#af95c46150f1f3ed22dcea4d23e5821d8", null ], + [ "trunk_height", "struct_walnut_canopy_parameters.html#aeaa0ebb5a837d6a57254f8a1f023aef9", null ], + [ "trunk_radius", "struct_walnut_canopy_parameters.html#a4d86caeb5dffe23b091a9c808005f307", null ], + [ "wood_subdivisions", "struct_walnut_canopy_parameters.html#a1c61b154388db34cd6cff475de3e2dd7", null ], + [ "wood_texture_file", "struct_walnut_canopy_parameters.html#aaa467205c3f449a3b11bd4fe19c4716e", null ] +]; \ No newline at end of file diff --git a/doc/html/struct_weber_penn_tree_parameters.html b/doc/html/struct_weber_penn_tree_parameters.html index cde2a3612..33749512d 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
@@ -852,10 +862,13 @@

WeberPennTree.h

- -
+ + diff --git a/doc/html/struct_white_spruce_canopy_parameters.html b/doc/html/struct_white_spruce_canopy_parameters.html index c7e410165..84f208ffe 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
+ + diff --git a/doc/html/struct_white_spruce_canopy_parameters.js b/doc/html/struct_white_spruce_canopy_parameters.js new file mode 100644 index 000000000..1595fc5ff --- /dev/null +++ b/doc/html/struct_white_spruce_canopy_parameters.js @@ -0,0 +1,25 @@ +var struct_white_spruce_canopy_parameters = +[ + [ "WhiteSpruceCanopyParameters", "struct_white_spruce_canopy_parameters.html#abab47c6661e734271286dbe4808f484b", null ], + [ "WhiteSpruceCanopyParameters", "struct_white_spruce_canopy_parameters.html#a5b11a0899997319c0371c0bc89330f05", null ], + [ "buildCanopy", "struct_white_spruce_canopy_parameters.html#a2ee193c4c845ce721cb30d9fc473beb2", null ], + [ "buildPlant", "struct_white_spruce_canopy_parameters.html#ab5cbed92a2f2de16b9c5ff1b559a2f55", null ], + [ "readParametersFromXML", "struct_white_spruce_canopy_parameters.html#a2dbc61de09c55a8dfdd9a490d2ef3be3", null ], + [ "base_height", "struct_white_spruce_canopy_parameters.html#a6f6626318bb82788ba433efecde7830c", null ], + [ "branches_per_level", "struct_white_spruce_canopy_parameters.html#afa54ff0b14e18e615a40ed80386491dc", null ], + [ "canopy_configuration", "struct_white_spruce_canopy_parameters.html#aff224456a6befb2203c9f225ad6e4fe7", null ], + [ "crown_radius", "struct_white_spruce_canopy_parameters.html#a97c71fefdb2f53e1e058f0be363ee592", null ], + [ "level_spacing", "struct_white_spruce_canopy_parameters.html#a4b00e11bfdda7982ce18779b40eadd6d", null ], + [ "needle_color", "struct_white_spruce_canopy_parameters.html#ab3687772981118c2b4aaeb4ff544289a", null ], + [ "needle_length", "struct_white_spruce_canopy_parameters.html#a41a653b953bd7a5f9c6cecfb07f1bfb4", null ], + [ "needle_subdivisions", "struct_white_spruce_canopy_parameters.html#a28eb26d944a0e67a41b1b06343090fc0", null ], + [ "needle_width", "struct_white_spruce_canopy_parameters.html#a11cc85d4a6176b908aff31b408d70cf3", null ], + [ "plant_count", "struct_white_spruce_canopy_parameters.html#a6df2f849f402259e099b1dafdabc0a2c", null ], + [ "plant_spacing", "struct_white_spruce_canopy_parameters.html#a3a46d591c89d1436a2892b76c4703e34", null ], + [ "shoot_angle", "struct_white_spruce_canopy_parameters.html#a6d61ce74788b23c5539f4bc1a65caf1e", null ], + [ "shoot_radius", "struct_white_spruce_canopy_parameters.html#a515f8b93fb025d4413e06ed4afef82d3", null ], + [ "trunk_height", "struct_white_spruce_canopy_parameters.html#a46f1f25dba30c6af07228680d80837a6", null ], + [ "trunk_radius", "struct_white_spruce_canopy_parameters.html#ab5771594720bf44fc57c40cedd629ff5", null ], + [ "wood_subdivisions", "struct_white_spruce_canopy_parameters.html#a57cc0a77f816bddab4701f2777c13317", null ], + [ "wood_texture_file", "struct_white_spruce_canopy_parameters.html#a3062fb397f90b7f5d29faf21794a04aa", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1_date.html b/doc/html/structhelios_1_1_date.html index 871b3748c..577807575 100644 --- a/doc/html/structhelios_1_1_date.html +++ b/doc/html/structhelios_1_1_date.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1_date.js b/doc/html/structhelios_1_1_date.js new file mode 100644 index 000000000..1dd8fa84b --- /dev/null +++ b/doc/html/structhelios_1_1_date.js @@ -0,0 +1,14 @@ +var structhelios_1_1_date = +[ + [ "Date", "structhelios_1_1_date.html#a0cf0a25b63afde0c55203451e827b56a", null ], + [ "Date", "structhelios_1_1_date.html#ab6a3fd0b6aa30e71a995f71c24c68d1b", null ], + [ "incrementDay", "structhelios_1_1_date.html#a82d115420d5c45d28e35d6226c3c8636", null ], + [ "isLeapYear", "structhelios_1_1_date.html#ae54ee66704fedfe50c8efc16695f3e9e", null ], + [ "JulianDay", "structhelios_1_1_date.html#abf3a401379adb23851174683a9191efc", null ], + [ "operator!=", "structhelios_1_1_date.html#aa22bf3af71b348a4d5ffda2ec0f711d1", null ], + [ "operator==", "structhelios_1_1_date.html#a097ff893e7fc52d101fdcb4ced84354b", null ], + [ "operator<<", "structhelios_1_1_date.html#a189b8537a2e0696e2f38da34e0f13eec", null ], + [ "day", "structhelios_1_1_date.html#a876b0513daf0bcf0ab305029be3377d8", null ], + [ "month", "structhelios_1_1_date.html#a5d75f8c8616d778e470a59e0b3e890a3", null ], + [ "year", "structhelios_1_1_date.html#aee4be32c2bd722143658b4771fe96253", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1_global_data.html b/doc/html/structhelios_1_1_global_data.html index c98e9623f..036c82751 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
@@ -376,10 +382,13 @@

Context.h

- -
+ + diff --git a/doc/html/structhelios_1_1_location.html b/doc/html/structhelios_1_1_location.html index 51e3ee6b2..565b98f76 100644 --- a/doc/html/structhelios_1_1_location.html +++ b/doc/html/structhelios_1_1_location.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1_location.js b/doc/html/structhelios_1_1_location.js new file mode 100644 index 000000000..9d0e3d2a5 --- /dev/null +++ b/doc/html/structhelios_1_1_location.js @@ -0,0 +1,11 @@ +var structhelios_1_1_location = +[ + [ "Location", "structhelios_1_1_location.html#a15dfbb1d375999d28e857fca72e12b74", null ], + [ "Location", "structhelios_1_1_location.html#aa91915971c5c6f75a99540b5517bea2b", null ], + [ "operator!=", "structhelios_1_1_location.html#af4aa7f58f7b88f7cff711d77f018bccd", null ], + [ "operator==", "structhelios_1_1_location.html#a2d451323ab20191a7f123849da04e269", null ], + [ "operator<<", "structhelios_1_1_location.html#a60375cac034fe50880b47569df6e8f69", null ], + [ "latitude_deg", "structhelios_1_1_location.html#a3924339ab5a0e35c47519792c335ff22", null ], + [ "longitude_deg", "structhelios_1_1_location.html#a29c4f6f1b7453821766f833673eeaff3", null ], + [ "UTC_offset", "structhelios_1_1_location.html#afd6a8f1100ee868e966f191719733058", null ] +]; \ No newline at end of file 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 905c558c9..de1eac3f0 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1_r_g_b_acolor.js b/doc/html/structhelios_1_1_r_g_b_acolor.js new file mode 100644 index 000000000..f618a8aca --- /dev/null +++ b/doc/html/structhelios_1_1_r_g_b_acolor.js @@ -0,0 +1,15 @@ +var structhelios_1_1_r_g_b_acolor = +[ + [ "RGBAcolor", "structhelios_1_1_r_g_b_acolor.html#a37d62b0c0e7d5a2d19a8ea0159984bea", null ], + [ "RGBAcolor", "structhelios_1_1_r_g_b_acolor.html#a45e32082a71599a971bf927981959b55", null ], + [ "RGBAcolor", "structhelios_1_1_r_g_b_acolor.html#aa479f8992b4b3201bf45b5e7140c3920", null ], + [ "RGBAcolor", "structhelios_1_1_r_g_b_acolor.html#ae03b805667e5f6f2914e0ec53375588f", null ], + [ "operator!=", "structhelios_1_1_r_g_b_acolor.html#a8adb7872a82b7d73660cca8d8e597f98", null ], + [ "operator==", "structhelios_1_1_r_g_b_acolor.html#abed23df133a671e295dcbf559c8a3ff5", null ], + [ "scale", "structhelios_1_1_r_g_b_acolor.html#a4d6937733ccdd97cee440a56bd556ff3", null ], + [ "operator<<", "structhelios_1_1_r_g_b_acolor.html#aaa76985ee048b321703f78175e2b87b7", null ], + [ "a", "structhelios_1_1_r_g_b_acolor.html#a1941a63762f40fe1aabc5bb863a7aa1e", null ], + [ "b", "structhelios_1_1_r_g_b_acolor.html#aaa86bd3e17f03ffdc182c5c9b67587e3", null ], + [ "g", "structhelios_1_1_r_g_b_acolor.html#ac018f8ed01b4d4128a68ebe42e1e6a00", null ], + [ "r", "structhelios_1_1_r_g_b_acolor.html#a15af7f1c4d0e5e23a7ec2488fe0964df", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1_r_g_bcolor.html b/doc/html/structhelios_1_1_r_g_bcolor.html index 26738cdc5..e25cdae56 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1_r_g_bcolor.js b/doc/html/structhelios_1_1_r_g_bcolor.js new file mode 100644 index 000000000..c9451a2bb --- /dev/null +++ b/doc/html/structhelios_1_1_r_g_bcolor.js @@ -0,0 +1,15 @@ +var structhelios_1_1_r_g_bcolor = +[ + [ "RGBcolor", "structhelios_1_1_r_g_bcolor.html#a030dae08fe8c38ad9bb7c735254ac53e", null ], + [ "RGBcolor", "structhelios_1_1_r_g_bcolor.html#a3e99268f14b8cdff29d50230585fad36", null ], + [ "RGBcolor", "structhelios_1_1_r_g_bcolor.html#adbf756a81c862233091e6b823d35e904", null ], + [ "RGBcolor", "structhelios_1_1_r_g_bcolor.html#a80d4a3e0c267ee3d93b832b0e575be4a", null ], + [ "RGBcolor", "structhelios_1_1_r_g_bcolor.html#ae9ae503986d99822085d79d27a8e8362", null ], + [ "operator!=", "structhelios_1_1_r_g_bcolor.html#ac0fa9361ccd323b9f6be61c51523a3ce", null ], + [ "operator==", "structhelios_1_1_r_g_bcolor.html#a3cfc4c0f132c841f3a18ff9bdae21e22", null ], + [ "scale", "structhelios_1_1_r_g_bcolor.html#a5b7b7b5734588bcf49444997b091f8b6", null ], + [ "operator<<", "structhelios_1_1_r_g_bcolor.html#a47b1d94ed5f6fa0c8ae897e02a06435c", null ], + [ "b", "structhelios_1_1_r_g_bcolor.html#a1b3ba3f5b77ef3082088eff853d4c335", null ], + [ "g", "structhelios_1_1_r_g_bcolor.html#ae002d220d8695538760eee2a6c4e9023", null ], + [ "r", "structhelios_1_1_r_g_bcolor.html#a3e16659a90c69e6043c33c113b2fffe8", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1_spherical_coord.html b/doc/html/structhelios_1_1_spherical_coord.html index 00a92ed5f..e05e06100 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.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1_spherical_coord.js b/doc/html/structhelios_1_1_spherical_coord.js new file mode 100644 index 000000000..4806ec8d2 --- /dev/null +++ b/doc/html/structhelios_1_1_spherical_coord.js @@ -0,0 +1,14 @@ +var structhelios_1_1_spherical_coord = +[ + [ "SphericalCoord", "structhelios_1_1_spherical_coord.html#a93171497b8c90975366e1945e6993dcd", null ], + [ "SphericalCoord", "structhelios_1_1_spherical_coord.html#adb761c897335d495e5f2b42064ccb5b1", null ], + [ "SphericalCoord", "structhelios_1_1_spherical_coord.html#aada6ce13523a731118c7a603a8d7c4d2", null ], + [ "operator!=", "structhelios_1_1_spherical_coord.html#a145cb6d467be654bc647c15e4fd9646a", null ], + [ "operator=", "structhelios_1_1_spherical_coord.html#afe4ef2437aad9bca5863eeb387b1eee5", null ], + [ "operator==", "structhelios_1_1_spherical_coord.html#afa6791361ed489019d0689a52cac5621", null ], + [ "operator<<", "structhelios_1_1_spherical_coord.html#ad9381fdcb8448d8834b4ce43465b5335", null ], + [ "azimuth", "structhelios_1_1_spherical_coord.html#af63b7ee76a5d57bf5881079eff52aa59", null ], + [ "elevation", "structhelios_1_1_spherical_coord.html#abaa336d9a00b67f486ab1ff040420a73", null ], + [ "radius", "structhelios_1_1_spherical_coord.html#a017f345f74aeaa332cdd36b66b22c906", null ], + [ "zenith", "structhelios_1_1_spherical_coord.html#a1cf17b1a139ed955ab0dd765e49b0643", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1_time.html b/doc/html/structhelios_1_1_time.html index 9f009a14c..6ca80e8f2 100644 --- a/doc/html/structhelios_1_1_time.html +++ b/doc/html/structhelios_1_1_time.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1_time.js b/doc/html/structhelios_1_1_time.js new file mode 100644 index 000000000..d71d5dfe7 --- /dev/null +++ b/doc/html/structhelios_1_1_time.js @@ -0,0 +1,12 @@ +var structhelios_1_1_time = +[ + [ "Time", "structhelios_1_1_time.html#a6265f89a66bfff369fecf125bebfa3e2", null ], + [ "Time", "structhelios_1_1_time.html#a2b47ac09cf37b9183c1236beebd2bd10", null ], + [ "Time", "structhelios_1_1_time.html#a98d45a9c451c5ff2013b78f7d1ee7f57", null ], + [ "operator!=", "structhelios_1_1_time.html#a9e2b7c5426528477fb14973543bd55be", null ], + [ "operator==", "structhelios_1_1_time.html#a8a0bab271dcb31616ba52c4fd5f754cd", null ], + [ "operator<<", "structhelios_1_1_time.html#a5d53ebf9a42b3aa2d959a3cd5023c71a", null ], + [ "hour", "structhelios_1_1_time.html#a6ec639cf61cf283c5e999d152d27839f", null ], + [ "minute", "structhelios_1_1_time.html#a744b90da076192b90a3ee4ce2ff3743a", null ], + [ "second", "structhelios_1_1_time.html#a627acedd68e0228600727b867db537dd", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1_timer.html b/doc/html/structhelios_1_1_timer.html index 6c63dcc57..1610431de 100644 --- a/doc/html/structhelios_1_1_timer.html +++ b/doc/html/structhelios_1_1_timer.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
@@ -127,7 +133,7 @@

Detailed Description

MATLAB-style timer. Call tic() to start timer, call toc() to stop timer and print duration.

-

Definition at line 619 of file global.h.

+

Definition at line 623 of file global.h.

Constructor & Destructor Documentation

◆ Timer()

@@ -147,12 +153,12 @@

-inline +inline

-

Definition at line 622 of file global.h.

+

Definition at line 626 of file global.h.

@@ -175,14 +181,14 @@

-inline +inline

Start timer.

-

Definition at line 627 of file global.h.

+

Definition at line 631 of file global.h.

@@ -204,14 +210,14 @@

-inline +inline @@ -233,7 +239,7 @@

-inline +inline @@ -249,10 +255,13 @@

global.h - - + + diff --git a/doc/html/structhelios_1_1_timer.js b/doc/html/structhelios_1_1_timer.js new file mode 100644 index 000000000..8e1dea299 --- /dev/null +++ b/doc/html/structhelios_1_1_timer.js @@ -0,0 +1,6 @@ +var structhelios_1_1_timer = +[ + [ "tic", "structhelios_1_1_timer.html#a47d04d3a8054ad2b6bbb9623c000090c", null ], + [ "toc", "structhelios_1_1_timer.html#a9d3f79551cc1089cb6dd81d3bb68f537", null ], + [ "toc", "structhelios_1_1_timer.html#a0449918d3129616aa908b5580069c7b6", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1int2.html b/doc/html/structhelios_1_1int2.html index bd91e0019..aa8dbfee2 100644 --- a/doc/html/structhelios_1_1int2.html +++ b/doc/html/structhelios_1_1int2.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1int2.js b/doc/html/structhelios_1_1int2.js new file mode 100644 index 000000000..a01b09513 --- /dev/null +++ b/doc/html/structhelios_1_1int2.js @@ -0,0 +1,17 @@ +var structhelios_1_1int2 = +[ + [ "int2", "structhelios_1_1int2.html#ae80f1c6c40c21e97047d6db1c2496a45", null ], + [ "int2", "structhelios_1_1int2.html#a8e3f84e45ffe63afd76374fdaa8cfb86", null ], + [ "int2", "structhelios_1_1int2.html#af32c6b747588deb32596333589573774", null ], + [ "int2", "structhelios_1_1int2.html#aa5d8b588ac6ea94d0a30b0bce4e8f198", null ], + [ "operator!=", "structhelios_1_1int2.html#aa56785402e6db8119c1ed30a49948218", null ], + [ "operator+", "structhelios_1_1int2.html#a14302add4995370f272dd321216a64ec", null ], + [ "operator+=", "structhelios_1_1int2.html#aa09f5fff701bf0847ba3d90ae9ea8583", null ], + [ "operator-", "structhelios_1_1int2.html#a39dfd15acdd548f1c93be6e7b8a1a475", null ], + [ "operator-", "structhelios_1_1int2.html#acfb7317221012445f653b395c28f774f", null ], + [ "operator-=", "structhelios_1_1int2.html#a5838914611d1837e927638c83f4a1bf9", null ], + [ "operator==", "structhelios_1_1int2.html#a6f1ec1cd4223e5f0bbfaa16e636af533", null ], + [ "operator<<", "structhelios_1_1int2.html#aa70779f707686be8b004587a4220a153", null ], + [ "x", "structhelios_1_1int2.html#ae14968ab74816df03efc977bb5d7b9c7", null ], + [ "y", "structhelios_1_1int2.html#a369861259a6061aa4287f954238e1e21", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1int3.html b/doc/html/structhelios_1_1int3.html index 16185faf2..f9d71d2ba 100644 --- a/doc/html/structhelios_1_1int3.html +++ b/doc/html/structhelios_1_1int3.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1int3.js b/doc/html/structhelios_1_1int3.js new file mode 100644 index 000000000..ed3b37eeb --- /dev/null +++ b/doc/html/structhelios_1_1int3.js @@ -0,0 +1,18 @@ +var structhelios_1_1int3 = +[ + [ "int3", "structhelios_1_1int3.html#a083ddc83d97c9eb4963c61a008a8ed98", null ], + [ "int3", "structhelios_1_1int3.html#a7d8c299d611aaff2092ef6c6811a1435", null ], + [ "int3", "structhelios_1_1int3.html#a4be47afa5e91a293126a39b9928d7d21", null ], + [ "int3", "structhelios_1_1int3.html#a3522bf2be027f0897d62a56fe412096c", null ], + [ "operator!=", "structhelios_1_1int3.html#a71f26f049c1fb4f1cdd066c13ce77f62", null ], + [ "operator+", "structhelios_1_1int3.html#ac05dad4f6ff3f71fcd5dd3549d00fc3d", null ], + [ "operator+=", "structhelios_1_1int3.html#a5569b625b5206c5c6074d2498dbc2295", null ], + [ "operator-", "structhelios_1_1int3.html#ade3be6bb42b51bd8875e485ca9e6274b", null ], + [ "operator-", "structhelios_1_1int3.html#adbe1fd230ee2591e64fdc15d71204848", null ], + [ "operator-=", "structhelios_1_1int3.html#a383f2cb4438661dd93bef01cfb52d646", null ], + [ "operator==", "structhelios_1_1int3.html#aced326938393fe95e1725e55b9bd4dd8", null ], + [ "operator<<", "structhelios_1_1int3.html#a6f576c885af0d781aadda850a2ca77af", null ], + [ "x", "structhelios_1_1int3.html#a1ce8c8391637ea6e33bb30b1d0adfc50", null ], + [ "y", "structhelios_1_1int3.html#aeba3aa4380ec4d9c216f98be95083d5c", null ], + [ "z", "structhelios_1_1int3.html#adb4b47bc05bdb62677200e025e4bf641", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1int4.html b/doc/html/structhelios_1_1int4.html index 26e2763da..2fe18d2c0 100644 --- a/doc/html/structhelios_1_1int4.html +++ b/doc/html/structhelios_1_1int4.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1int4.js b/doc/html/structhelios_1_1int4.js new file mode 100644 index 000000000..ee7077856 --- /dev/null +++ b/doc/html/structhelios_1_1int4.js @@ -0,0 +1,19 @@ +var structhelios_1_1int4 = +[ + [ "int4", "structhelios_1_1int4.html#a495ca613c03f0b6748dc484e1d5bc6a6", null ], + [ "int4", "structhelios_1_1int4.html#a0c96514a7e15c6638d34ddfe50b7c7fc", null ], + [ "int4", "structhelios_1_1int4.html#ad4011b8fcdb338dd35b97eab6a90e978", null ], + [ "int4", "structhelios_1_1int4.html#a56c4775603496c334254104c76608e1f", null ], + [ "operator!=", "structhelios_1_1int4.html#affc0813de0395a8aad56f4be7d0b04ca", null ], + [ "operator+", "structhelios_1_1int4.html#a6b3eb9a070e397d5a0e7c60e0b4696b1", null ], + [ "operator+=", "structhelios_1_1int4.html#ab7ec3cec60a44e6ac8fc4dc6d422fde1", null ], + [ "operator-", "structhelios_1_1int4.html#a4d7a1b7d29e0d436fe35f927d645b7c7", null ], + [ "operator-", "structhelios_1_1int4.html#a67b8bf23d9a9377fb295d4dad92ead6a", null ], + [ "operator-=", "structhelios_1_1int4.html#a3726af5576f9ed3ed3cf5d7c97a8159d", null ], + [ "operator==", "structhelios_1_1int4.html#a779368fbba5e30ad5bba83072c9fdf83", null ], + [ "operator<<", "structhelios_1_1int4.html#ac6b32d39d92de0b8585c64048040f0f9", null ], + [ "w", "structhelios_1_1int4.html#a997159b161576d521fdad7e2d5e3786f", null ], + [ "x", "structhelios_1_1int4.html#a1ac3b0b91901dc1d1497267bd3f3b4c3", null ], + [ "y", "structhelios_1_1int4.html#ae979ffc27c702a6b67258d07ddcdf3b3", null ], + [ "z", "structhelios_1_1int4.html#a5c5969a3b94d165c3a24a5235ea50a99", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1vec2.html b/doc/html/structhelios_1_1vec2.html index 6029ffebc..7175b6a4c 100644 --- a/doc/html/structhelios_1_1vec2.html +++ b/doc/html/structhelios_1_1vec2.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1vec2.js b/doc/html/structhelios_1_1vec2.js new file mode 100644 index 000000000..b3b991f98 --- /dev/null +++ b/doc/html/structhelios_1_1vec2.js @@ -0,0 +1,24 @@ +var structhelios_1_1vec2 = +[ + [ "vec2", "structhelios_1_1vec2.html#a951e897069d3cc32a062667a54422882", null ], + [ "vec2", "structhelios_1_1vec2.html#a4b3c6f1a3d5f981fd5c0b858088462aa", null ], + [ "vec2", "structhelios_1_1vec2.html#a61b92b2d15fa008486ca55b7baf3d8ce", null ], + [ "vec2", "structhelios_1_1vec2.html#af23055ca8145b094c275e9790c1ef8c2", null ], + [ "magnitude", "structhelios_1_1vec2.html#a1931ec5c78112202c14634634f429073", null ], + [ "normalize", "structhelios_1_1vec2.html#a04c00c49095d3bbc0a19d5da3d61493f", null ], + [ "operator!=", "structhelios_1_1vec2.html#a17f3c1246cb0d3ac6c3f7e88d925fc8c", null ], + [ "operator*", "structhelios_1_1vec2.html#aff56c21393bd165f0f7a716535caa9e0", null ], + [ "operator*", "structhelios_1_1vec2.html#ad8557c2528c67f4736853e0eb2da84ad", null ], + [ "operator+", "structhelios_1_1vec2.html#ab10677029f53c641eb7a16f2b05a5b77", null ], + [ "operator+", "structhelios_1_1vec2.html#a6e0dfda32de091ffaead085c42e9da6c", null ], + [ "operator+=", "structhelios_1_1vec2.html#a04b63f7eea6d70bb1d05a1d3f5cae24c", null ], + [ "operator-", "structhelios_1_1vec2.html#ad37fb5771915e31225d39d3df8c669ed", null ], + [ "operator-", "structhelios_1_1vec2.html#a91e810accf20886a20afc9ed0c3d5f07", null ], + [ "operator-", "structhelios_1_1vec2.html#a919b93ba0bf660ae2b7e65500982e3d7", null ], + [ "operator-=", "structhelios_1_1vec2.html#a575d6107bcec4582c106b711142a17c2", null ], + [ "operator/", "structhelios_1_1vec2.html#a910c611bcf9c2ea1cd3ff38f0bd375e8", null ], + [ "operator==", "structhelios_1_1vec2.html#ab0c78672d242efe3aede0a4bd03eaeea", null ], + [ "operator<<", "structhelios_1_1vec2.html#a5e585083b0cf16b2e73958747390e152", null ], + [ "x", "structhelios_1_1vec2.html#a8dda241c2560b203a3b0a479d1c9e12e", null ], + [ "y", "structhelios_1_1vec2.html#ab4afff51f764cbf9bab0949ae067977e", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1vec3.html b/doc/html/structhelios_1_1vec3.html index 53ffff7f1..b6f2e40fd 100644 --- a/doc/html/structhelios_1_1vec3.html +++ b/doc/html/structhelios_1_1vec3.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1vec3.js b/doc/html/structhelios_1_1vec3.js new file mode 100644 index 000000000..bd24d39ff --- /dev/null +++ b/doc/html/structhelios_1_1vec3.js @@ -0,0 +1,25 @@ +var structhelios_1_1vec3 = +[ + [ "vec3", "structhelios_1_1vec3.html#a872ffa408ca0c7a9ae8f48bdcb1ff59f", null ], + [ "vec3", "structhelios_1_1vec3.html#ad72bf7ebc0bf7a337c33fd804b047f17", null ], + [ "vec3", "structhelios_1_1vec3.html#a674873bc59af57ba7149ad5339e45266", null ], + [ "vec3", "structhelios_1_1vec3.html#a98f0ea866d759cc41f85af848bd47392", null ], + [ "magnitude", "structhelios_1_1vec3.html#adb96b24e6544d106a19e029c2594fee4", null ], + [ "normalize", "structhelios_1_1vec3.html#a7a6826239394edc32ce6ae58b4622524", null ], + [ "operator!=", "structhelios_1_1vec3.html#ada103df1691b54465c2b1b529e0c5832", null ], + [ "operator*", "structhelios_1_1vec3.html#af73b1a2553239424ec86cdb0c8c40396", null ], + [ "operator*", "structhelios_1_1vec3.html#add5a63009e9808b16ba05b6f13a247c9", null ], + [ "operator+", "structhelios_1_1vec3.html#a3c9cee7dfe117cf1e89c79308562df2c", null ], + [ "operator+", "structhelios_1_1vec3.html#a4d847b9be59bfb23ea7ea5a5a8f21cb7", null ], + [ "operator+=", "structhelios_1_1vec3.html#abd94e98635de454f86ad00ce77e6e2ad", null ], + [ "operator-", "structhelios_1_1vec3.html#a5a0176fe2d334f8a30ab00a975c2bdb1", null ], + [ "operator-", "structhelios_1_1vec3.html#ab6d099de4a986d24b7414114700bb66a", null ], + [ "operator-", "structhelios_1_1vec3.html#ad5557e6f3320abb0cab521a0aa87532f", null ], + [ "operator-=", "structhelios_1_1vec3.html#a47a2080f5ba1e3690956ad8dd9160780", null ], + [ "operator/", "structhelios_1_1vec3.html#a09c648b26b7333d2726b7fbceab85be7", null ], + [ "operator==", "structhelios_1_1vec3.html#a00f6165fb3f01c65d7046111b6143fd4", null ], + [ "operator<<", "structhelios_1_1vec3.html#a87277dd90e0869e2e8e7ce376dfc7033", null ], + [ "x", "structhelios_1_1vec3.html#a80003da235393c031b8561e678a184a1", null ], + [ "y", "structhelios_1_1vec3.html#ac0be54042f7a639c99ea4dce377f9a65", null ], + [ "z", "structhelios_1_1vec3.html#a870c14ca45729f58e8628a050ce38b6f", null ] +]; \ No newline at end of file diff --git a/doc/html/structhelios_1_1vec4.html b/doc/html/structhelios_1_1vec4.html index 7e2301ddf..9e60d2716 100644 --- a/doc/html/structhelios_1_1vec4.html +++ b/doc/html/structhelios_1_1vec4.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
+ + diff --git a/doc/html/structhelios_1_1vec4.js b/doc/html/structhelios_1_1vec4.js new file mode 100644 index 000000000..669db65c0 --- /dev/null +++ b/doc/html/structhelios_1_1vec4.js @@ -0,0 +1,26 @@ +var structhelios_1_1vec4 = +[ + [ "vec4", "structhelios_1_1vec4.html#a94756adab8fcf1382e2bde79c00014f0", null ], + [ "vec4", "structhelios_1_1vec4.html#a2fbcf26c016cdceafd9f3354b430363d", null ], + [ "vec4", "structhelios_1_1vec4.html#ab92cc5f8e93238b01c9639f011347281", null ], + [ "vec4", "structhelios_1_1vec4.html#ade4e8c762963b0ce0a195805f1ebccbd", null ], + [ "magnitude", "structhelios_1_1vec4.html#a416f39c133309add363f43fd5f1e340c", null ], + [ "normalize", "structhelios_1_1vec4.html#a6bb8bb78aaea6e5703fd1d40dbd39865", null ], + [ "operator!=", "structhelios_1_1vec4.html#a628c2b9a02267a04a7a0cea2f81751ea", null ], + [ "operator*", "structhelios_1_1vec4.html#ac2e0c4e83c5996aaae993fc465793c46", null ], + [ "operator*", "structhelios_1_1vec4.html#af4405b9a3827567189c0386ce937ed1b", null ], + [ "operator+", "structhelios_1_1vec4.html#a12ed9a7a675ba5a734326d90d82d4ffc", null ], + [ "operator+", "structhelios_1_1vec4.html#a766b22dfe3aa73999248fa60fd753960", null ], + [ "operator+=", "structhelios_1_1vec4.html#a795da5aba8f107010589dffda7f11d4d", null ], + [ "operator-", "structhelios_1_1vec4.html#a64f1627b4f2c6487231f315527afbf15", null ], + [ "operator-", "structhelios_1_1vec4.html#a98039082899cd4872d383e039cc0b812", null ], + [ "operator-", "structhelios_1_1vec4.html#afd6f6b82dd6d3512cc8e1560e218bab2", null ], + [ "operator-=", "structhelios_1_1vec4.html#a5cff99d238392c388015d1a0ac4456ae", null ], + [ "operator/", "structhelios_1_1vec4.html#aa86d6caee3381dd0a14a74ea5e743604", null ], + [ "operator==", "structhelios_1_1vec4.html#aa8f6ace5ba502b2b958b64b1d032d1c3", null ], + [ "operator<<", "structhelios_1_1vec4.html#a32f014dbb41084ece2ad85f19c540874", null ], + [ "w", "structhelios_1_1vec4.html#a5d4e8add341c4076176aac3574fe0937", null ], + [ "x", "structhelios_1_1vec4.html#a96036e1d3ac15f03190a7bbf74ce0d73", null ], + [ "y", "structhelios_1_1vec4.html#a3dd547e787593c51f07a6ea131bcab8d", null ], + [ "z", "structhelios_1_1vec4.html#a660ee0cf07d74bac3c989ce39e035d3b", null ] +]; \ No newline at end of file diff --git a/doc/html/structjpg__error__mgr.html b/doc/html/structjpg__error__mgr.html index eda44a86c..0c444e16e 100644 --- a/doc/html/structjpg__error__mgr.html +++ b/doc/html/structjpg__error__mgr.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
-
-
@@ -150,10 +160,13 @@

global.cpp

- -
+ + diff --git a/doc/html/structmy__error__mgr.html b/doc/html/structmy__error__mgr.html index 565f50583..d2f993808 100644 --- a/doc/html/structmy__error__mgr.html +++ b/doc/html/structmy__error__mgr.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
-
-
@@ -150,10 +160,13 @@

Visualizer.cpp

- -
+ + diff --git a/doc/html/tomato_8cpp_source.html b/doc/html/tomato_8cpp_source.html index f11efd07e..a37b3794b 100644 --- a/doc/html/tomato_8cpp_source.html +++ b/doc/html/tomato_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
tomato.cpp
@@ -277,7 +283,7 @@
170
171 }
172
-
173 branch_UUIDs = context->addTube( params.shoot_subdivisions, nodes, radius, color );
+
173 branch_UUIDs = context->addTube( params.shoot_subdivisions, nodes, radius, color );
174
175 std::vector<float> shoot_heights;
176 shoot_heights.push_back( 0.4 );
@@ -298,7 +304,7 @@
191
192 vec3 position = interpolateTube( nodes, shoot_heights.at(i) );
193
-
194 vec3 base_direction = sphere2cart( make_SphericalCoord( 0.2*PI_F+0.2*PI_F*float(i)/float(Nshoots-1), 2*PI_F*context->randu()) );
+
194 vec3 base_direction = sphere2cart( make_SphericalCoord( 0.2*PI_F+0.2*PI_F*float(i)/float(Nshoots-1), 2*PI_F*context->randu()) );
195
196 float tip_angle = 0.5*PI_F+0.2*PI_F*float(i)/float(Nshoots-1);
197
@@ -319,13 +325,13 @@
helios::vec3 interpolateTube(const std::vector< helios::vec3 > &P, float frac)
Interpolate the position of a point along a tube.
uint tomato(const TomatoParameters &params, const helios::vec3 &origin)
Function to add an individual tomato plant.
Definition tomato.cpp:139
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
float randu()
Draw a random number from a uniform distribution between 0 and 1.
Definition Context.cpp:1178
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5646
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
+
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5673
+
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5957
+
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5836
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
vec3 sphere2cart(const SphericalCoord &Spherical)
Convert Spherical coordinates to Cartesian coordinates.
Definition global.cpp:617
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
@@ -344,13 +350,16 @@
Vector of spherical coordinates (elevation,azimuth)
const float & elevation
Elevation angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
- - + + diff --git a/doc/html/usergroup0.html b/doc/html/usergroup0.html index b77bdceb2..2a23d1343 100644 --- a/doc/html/usergroup0.html +++ b/doc/html/usergroup0.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + -
+
+ +
+
+
+
- -
+ + diff --git a/doc/html/visualizer_basics.html b/doc/html/visualizer_basics.html index e75deb631..cb0aac0d3 100644 --- a/doc/html/visualizer_basics.html +++ b/doc/html/visualizer_basics.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + +
+
+ +
+
+
+
- -
-
Tutorial 7: Visualizer Basics
@@ -182,10 +188,13 @@

}

- - + + diff --git a/doc/html/visualizer_pdata.html b/doc/html/visualizer_pdata.html index b6e9ae0fb..6f736f53b 100644 --- a/doc/html/visualizer_pdata.html +++ b/doc/html/visualizer_pdata.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+
- -
-
Tutorial 8: Visualizing primitive data values
@@ -153,10 +159,13 @@

- - + + diff --git a/doc/html/walnut_8cpp_source.html b/doc/html/walnut_8cpp_source.html index acddc98dc..c0a8b452e 100644 --- a/doc/html/walnut_8cpp_source.html +++ b/doc/html/walnut_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
walnut.cpp
@@ -455,16 +461,16 @@
348
349 uint ID_trunk = addBranch( origin, make_vec3(0,0,1), params.trunk_radius, origin + make_vec3( unif_distribution(generator)*3*params.trunk_radius, unif_distribution(generator)*3*params.trunk_radius, params.trunk_height ), make_vec3(0,0,0.5*params.trunk_height), 0.5*params.trunk_radius, 8, params, generator, context );
350
-
351 UUID_trunk.push_back(context->getObjectPointer(ID_trunk)->getPrimitiveUUIDs());
+
351 UUID_trunk.push_back(context->getObjectPointer(ID_trunk)->getPrimitiveUUIDs());
352
-
353 std::vector<vec3> pos_trunk = context->getTubeObjectPointer(ID_trunk)->getNodes();
-
354 std::vector<float> rad_trunk = context->getTubeObjectPointer(ID_trunk)->getNodeRadii();
+
353 std::vector<vec3> pos_trunk = context->getTubeObjectPointer(ID_trunk)->getNodes();
+
354 std::vector<float> rad_trunk = context->getTubeObjectPointer(ID_trunk)->getNodeRadii();
355
356 branchRecursion( pos_trunk, rad_trunk, 1, 3, leaf_prototype, nut_prototype, UUID_branch_plant, UUID_leaf_plant, UUID_fruit_plant.front(), params, generator, context );
357
358
-
359 context->deletePrimitive( leaf_prototype );
-
360 context->deletePrimitive( nut_prototype );
+
359 context->deletePrimitive( leaf_prototype );
+
360 context->deletePrimitive( nut_prototype );
361
362 UUID_branch.push_back(UUID_branch_plant);
363 UUID_leaf.push_back(UUID_leaf_plant);
@@ -479,9 +485,8 @@
float getVariation(float V, std::minstd_rand0 &generator, bool positive=false)
Draw a random number (float) from a uniform distribution between -V and V.
uint walnut(const WalnutCanopyParameters &params, const helios::vec3 &origin)
Function to add an individual walnut tree.
Definition walnut.cpp:333
std::vector< uint > getPrimitiveUUIDs() const
Get the UUIDs for all primitives contained in the object.
Definition Context.cpp:2256
-
Stores the state associated with simulation.
Definition Context.h:1882
+
Stores the state associated with simulation.
Definition Context.h:1888
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
void deletePrimitive(uint UUID)
Delete a single primitive from the context.
Definition Context.cpp:1536
CompoundObject * getObjectPointer(uint ObjID) const
Get a pointer to a Compound Object.
Definition Context.cpp:2574
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
uint copyPrimitive(uint UUID)
Make a copy of a primitive from the context.
Definition Context.cpp:1578
@@ -490,8 +495,8 @@
std::vector< float > getNodeRadii() const
Get the radius at each of the tube object nodes.
Definition Context.cpp:3508
std::vector< helios::vec3 > getNodes() const
Get the Cartesian coordinates of each of the tube object nodes.
Definition Context.cpp:3493
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
-
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:4728
-
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5646
+
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:4755
+
std::vector< uint > addSphere(uint Ndivs, const vec3 &center, float radius)
Add a spherical compound object to the Context.
Definition Context.cpp:5673
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
helios::vec3 spline_interp3(float u, const vec3 &x_start, const vec3 &tan_start, const vec3 &x_end, const vec3 &tan_end)
Function to perform cubic Hermite spline interpolation.
Definition global.cpp:2768
uint addTriangle(const helios::vec3 &vertex0, const helios::vec3 &vertex1, const helios::vec3 &vertex2)
Add new Triangle geometric primitive.
Definition Context.cpp:1328
@@ -513,17 +518,20 @@
float azimuth
Azimuthal angle (radians)
int y
Second element in vector.
int x
First element in vector.
-
Vector of two elements of type 'float'.
-
Vector of three elements of type 'float'.
+
Vector of two elements of type 'float'.
+
Vector of three elements of type 'float'.
vec3 normalize()
Normalize vector components such that the magnitude is unity.
float x
First element in vector.
float z
Third element in vector.
float y
Second element in vector.
- - + + diff --git a/doc/html/whitespruce_8cpp_source.html b/doc/html/whitespruce_8cpp_source.html index 5b3813983..2d1834469 100644 --- a/doc/html/whitespruce_8cpp_source.html +++ b/doc/html/whitespruce_8cpp_source.html @@ -38,7 +38,7 @@ Logo -
 v1.3.26 +
 v1.3.27
@@ -46,7 +46,7 @@
- + + +
+ +
+
+
+ -
whitespruce.cpp
@@ -133,7 +139,7 @@
26 pos_main.at(i) = pos_main.at(i) + origin;
27 }
28
-
29 UUID_trunk_plant = context->addTube(params.wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
+
29 UUID_trunk_plant = context->addTube(params.wood_subdivisions,pos_main,rad_main, params.wood_texture_file.c_str() );
30
31 //---- first order branches -----//
32
@@ -179,7 +185,7 @@
72
73 //printf("rad_branch = %f\n",rad_branch.back());
74
-
75 U = context->addTube(params.wood_subdivisions,pos_branch,rad_branch, params.wood_texture_file.c_str() );
+
75 U = context->addTube(params.wood_subdivisions,pos_branch,rad_branch, params.wood_texture_file.c_str() );
76 UUID_branch_plant.insert(UUID_branch_plant.end(), U.begin(), U.end());
77
78 for( int k=0; k<2*Nbranches; k++ ){
@@ -229,14 +235,14 @@
122
123 SphericalCoord rotation = cart2sphere(norm);
124
-
125 UUID_leaf_plant.push_back( context->addTile( make_vec3(0,0,0), make_vec2(0.1*params.needle_length,params.needle_length), make_SphericalCoord(0,0), params.needle_subdivisions, params.needle_color ) );
+
125 UUID_leaf_plant.push_back( context->addTile( make_vec3(0,0,0), make_vec2(0.1*params.needle_length,params.needle_length), make_SphericalCoord(0,0), params.needle_subdivisions, params.needle_color ) );
126
127 float downangle = 0.2*PI_F;
-
128 context->rotatePrimitive( UUID_leaf_plant.back(), downangle-rotation.elevation, "x" );
-
129 context->translatePrimitive( UUID_leaf_plant.back(), make_vec3(0,-0.55*params.needle_length,0) );
-
130 context->rotatePrimitive( UUID_leaf_plant.back(), 0.5*PI_F-rotation.azimuth, "z" );
-
131 context->rotatePrimitive( UUID_leaf_plant.back(), getVariation(PI_F,generator), norm );
-
132 context->translatePrimitive( UUID_leaf_plant.back(), nbase );
+
128 context->rotatePrimitive( UUID_leaf_plant.back(), downangle-rotation.elevation, "x" );
+
129 context->translatePrimitive( UUID_leaf_plant.back(), make_vec3(0,-0.55*params.needle_length,0) );
+
130 context->rotatePrimitive( UUID_leaf_plant.back(), 0.5*PI_F-rotation.azimuth, "z" );
+
131 context->rotatePrimitive( UUID_leaf_plant.back(), getVariation(PI_F,generator), norm );
+
132 context->translatePrimitive( UUID_leaf_plant.back(), nbase );
133
134 }
135
@@ -261,10 +267,6 @@
helios::vec3 interpolateTube(const std::vector< helios::vec3 > &P, float frac)
Interpolate the position of a point along a tube.
float getVariation(float V, std::minstd_rand0 &generator, bool positive=false)
Draw a random number (float) from a uniform distribution between -V and V.
uint whitespruce(const WhiteSpruceCanopyParameters &params, const helios::vec3 &origin)
Function to add an individual white spruce tree.
-
void translatePrimitive(uint UUID, const vec3 &shift)
Translate a primitive using its UUID.
Definition Context.cpp:1406
-
void rotatePrimitive(uint UUID, float rot, const char *axis)
Rotate a primitive about the x, y, or z axis using its UUID.
Definition Context.cpp:1420
-
std::vector< uint > addTube(uint Ndivs, const std::vector< vec3 > &nodes, const std::vector< float > &radius)
Add a 3D tube compound object to the Context.
Definition Context.cpp:5930
-
std::vector< uint > addTile(const vec3 &center, const vec2 &size, const SphericalCoord &rotation, const int2 &subdiv)
Add a patch that is subdivided into a regular grid of sub-patches (tiled)
Definition Context.cpp:5809
SphericalCoord cart2sphere(const vec3 &Cartesian)
Convert Cartesian coordinates to spherical coordinates.
Definition global.cpp:610
vec2 make_vec2(float x, float y)
Make a vec2 from two floats.
vec3 make_vec3(float x, float y, float z)
Make a vec3 from three floats.
@@ -285,12 +287,15 @@
Vector of spherical coordinates (elevation,azimuth)
const float & elevation
Elevation angle (radians)
float azimuth
Azimuthal angle (radians)
-
Vector of three elements of type 'float'.
+
Vector of three elements of type 'float'.
- - + + diff --git a/doc/images/Helios_logo_small.png b/doc/images/Helios_logo_small.png index 65732fadffbde053928fd08dac15285a500d7862..92ab7db459e035fc96c7372a076316b143a6d005 100644 GIT binary patch delta 28389 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%0Ajq9Rmgb_v(KyE|Y&N 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 diff --git a/doc/images/PSL_logo_compact.png b/doc/images/PSL_logo_compact.png index a693f784c8e84b03761d68bb5350464e2edd1f76..22ecf064a8013f33c63db44bca22c3babdd40815 100644 GIT binary patch literal 21823 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 literal 22219 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 cell_area(inclinations.size(),0); float db = 0.5f*M_PI/float(Nbins); //bin width @@ -644,6 +645,8 @@ void LiDARcloud::exportTriangleInclinationDistribution( const char* filename, ui inclinations.at(cell).at(bin) += area; + cell_area.at(cell) += area; + } ofstream file; @@ -656,7 +659,76 @@ void LiDARcloud::exportTriangleInclinationDistribution( const char* filename, ui for( int cell=0; cell> azimuths( getGridCellCount() ); + for( int i=0; i cell_area(azimuths.size(),0); + + float db = 2*M_PI/float(Nbins); //bin width + + for( std::size_t t=0; tM_PI*2){ + azimuth=azimuth-M_PI*2; + } + } + + + float area = tri.area; + + uint bin = floor(azimuth/db); + if( bin>=Nbins ){ + bin = Nbins-1; + } + + azimuths.at(cell).at(bin) += area; + cell_area.at(cell) += area; + + } + + ofstream file; + + file.open(filename); + + if( !file.is_open() ){ + throw( std::runtime_error("ERROR (LiDARcloud::exportTriangleAzimuthDistribution): Could not open file '" + std::string(filename) + "' for writing.") ); + } + + for( int cell=0; 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 A#SxgV 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�A0X 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%0A=?nZq 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

P8k*+N_dvc?15b#UA;ll-$@ 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 Y4)>qPingMLBfv#bPF41Y3^3^b1LxihG5`Po literal 0 HcmV?d00001 diff --git a/plugins/plantarchitecture/doc/PlantArchitecture.dox b/plugins/plantarchitecture/doc/PlantArchitecture.dox index 9155a8f48..51f66b84a 100755 --- a/plugins/plantarchitecture/doc/PlantArchitecture.dox +++ b/plugins/plantarchitecture/doc/PlantArchitecture.dox @@ -476,8 +476,8 @@ Parameters defining the geometry and growth of the shoot are given in the \ref S | 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 | degrees/(meters)^0.5 | Factor determining the amount of random "wiggle" in internode growth along the shoot. | | --- **Growth Parameters** --- ||||| -| phyllochron_min | RandomParameter_float | 1.0 | days/leaf | Time between the emergence of successive phytomers along the shoot (minimum time or maximum growth rate). | -| elongation_rate | RandomParameter_float | 0.2 | meter/meter/day | Relative rate of elongation of the internode of the shoot. Units are meters of elongation per meter of maximum internode length per day. | +| phyllochron_min | RandomParameter_float | 1.0 | days/leaf | Minimum time between the emergence of successive phytomers along the shoot (minimum time or maximum growth rate). The actual phyllochron can be increased dynamically if the carbohydrate model is enabled. | +| elongation_rate_max | RandomParameter_float | 0.2 | meter/meter/day | Maximum relative rate of elongation of the internode of the shoot. Units are meters of elongation per meter of maximum internode length per day. The actual elongation rate can be reduced dynamically if the carbohydrate model is enabled. | | girth_area_factor | RandomParameter_float | 0 | cm^2 branch area / m^2 downstream leaf area | Cross-sectional area of internode (girth), determined by the amount of downstream leaf area. The girth will only increase and does not decrease if leaves are lost. Set this factor to 0 to prevent girth scaling. | | vegetative_bud_break_time | RandomParameter_float | 5 | days | Amount of time after the bud is created or after dormancy is broken for the vegetative bud to break. | | vegetative_bud_break_probability_decay_rate | RandomParameter_float | 0 | 1/nodes | Rate at which the probability a bud produces a shoot changes along the shoot. If >0, probability is 1 at the shoot base and decreases to a value of \htmlonlyvegetative_bud_break_probability_min\endhtmlonly. If <0, the probability is 1 at the shoot tip and decreases backward. | diff --git a/plugins/plantarchitecture/include/PlantArchitecture.h b/plugins/plantarchitecture/include/PlantArchitecture.h index cabadd5db..774050a5b 100644 --- a/plugins/plantarchitecture/include/PlantArchitecture.h +++ b/plugins/plantarchitecture/include/PlantArchitecture.h @@ -697,7 +697,7 @@ struct ShootParameters{ RandomParameter_float phyllochron_min; //days/phytomer - RandomParameter_float elongation_rate; //length/day + RandomParameter_float elongation_rate_max; //length/day // Minimum probability that bud with this shoot type will break and form a new shoot RandomParameter_float vegetative_bud_break_probability_min; @@ -736,8 +736,6 @@ struct ShootParameters{ this->max_nodes_per_season.resample(); this->phyllochron_min = a.phyllochron_min; this->phyllochron_min.resample(); - this->elongation_rate = a.elongation_rate; - this->elongation_rate.resample(); this->girth_area_factor = a.girth_area_factor; this->girth_area_factor.resample(); this->vegetative_bud_break_probability_min = a.vegetative_bud_break_probability_min; @@ -890,6 +888,8 @@ struct Phytomer { void removeLeaf(); + void deletePhytomer(); + // ---- phytomer data ---- // //! Coordinates of internode tube segments. Index is tube segment within internode @@ -1012,6 +1012,8 @@ struct Shoot { float sumShootLeafArea( uint start_node_index = 0 ) const; + float sumChildVolume( uint start_node_index = 0) const; + void propagateDownstreamLeafArea(Shoot* shoot, uint node_index, float leaf_area); uint current_node_number = 0; @@ -1028,8 +1030,14 @@ struct Shoot { const uint rank; const uint parent_petiole_index; - float carbohydrate_pool_molC = 0.01; // mol C - float old_shoot_volume = 0; + float carbohydrate_pool_molC = 0; // mol C + float old_shoot_volume; + + float phyllochron_increase = 2; + float phyllochron_recovery = phyllochron_increase * 1.5; + + float elongation_decay = 0.5; + float elongation_recovery = elongation_decay /1.5 ; uint days_with_negative_carbon_balance = 0; @@ -1042,6 +1050,8 @@ struct Shoot { bool meristem_is_alive = true; float phyllochron_counter = 0; + float phyllochron_min = 6; + float elongation_max = .25; float curvature_perturbation = 0; float yaw_perturbation = 0; @@ -1064,6 +1074,9 @@ struct Shoot { std::string shoot_type_label; + float phyllochron_instantaneous; + float elongation_rate_instantaneous; + std::vector > phytomers; PlantArchitecture* plantarchitecture_ptr; @@ -1074,12 +1087,13 @@ struct Shoot { struct PlantInstance{ - PlantInstance(const helios::vec3 &a_base_position, float a_current_age, helios::Context *a_context_ptr) : base_position(a_base_position), current_age(a_current_age), context_ptr(a_context_ptr) {} + PlantInstance(const helios::vec3 &a_base_position, float a_current_age, const std::string &a_plant_name, helios::Context *a_context_ptr) : base_position(a_base_position), current_age(a_current_age), plant_name(a_plant_name), context_ptr(a_context_ptr) {} std::vector > shoot_tree; helios::vec3 base_position; float current_age; float time_since_dormancy = 0; helios::Context *context_ptr; + std::string plant_name; std::pair epicormic_shoot_probability_perlength_per_day; //.first is the epicormic shoot label string, .second is the probability //Phenological thresholds @@ -1234,21 +1248,23 @@ class PlantArchitecture{ /** * \param[in] time_step_days Time interval in days. */ - void advanceTime( float time_step_days ); + void advanceTime(float time_step_days); + + void accumulateHourlyLeafPhotosynthesis(); //! Advance plant growth by a specified time interval for all plants /** * \param[in] time_step_years Number of years to advance. * \param[in] time_step_days Number of days to advance (added to number of years). */ - void advanceTime( int time_step_years, float time_step_days ); + void advanceTime(int time_step_years, float time_step_days); //! Advance plant growth by a specified time interval for a single plant /** * \param[in] plantID ID of the plant instance. * \param[in] time_step_days Time interval in days. */ - void advanceTime( uint plantID, float time_step_days ); + void advanceTime(uint plantID, float time_step_days); // -- plant building methods -- // @@ -1368,6 +1384,8 @@ class PlantArchitecture{ // -- methods for modifying the current plant state -- // + void initializeCarbohydratePool(float carbohydrate_concentration_molC_m3); + void initializePlantCarbohydratePool(uint plantID, float carbohydrate_concentration_molC_m3 ); void initializeShootCarbohydratePool(uint plantID, uint shootID, float carbohydrate_concentration_molC_m3 ); @@ -1392,8 +1410,12 @@ class PlantArchitecture{ void breakPlantDormancy( uint plantID ); + void pruneBranch(uint plantID, uint shootID, uint node_index); + // -- methods for querying information about the plant -- // + std::string getPlantName(uint plantID) const; + float getPlantAge(uint plantID) const; uint getShootNodeCount( uint plantID, uint shootID ) const; @@ -1427,10 +1449,9 @@ class PlantArchitecture{ /** * \param[in] plantID ID of the plant instance. * \param[in] Nbins Number of bins for the histogram. - * \param[in] normalize [OPTIONAL] Normalize the histogram to integrate to 1. * \return Histogram of leaf inclination angles. Bins are evenly spaced between 0 and 90 degrees. */ - std::vector getPlantLeafInclinationAngleDistribution(uint plantID, uint Nbins, bool normalize=false) const; + std::vector getPlantLeafInclinationAngleDistribution(uint plantID, uint Nbins) const; //! Get the total number of leaves on the plant /** @@ -1446,6 +1467,12 @@ class PlantArchitecture{ */ void writePlantMeshVertices(uint plantID, const std::string &filename) const; + //! Get IDs for all plant instances + /** + * \return Vector of plant IDs for all plant instances + */ + std::vector getAllPlantIDs() const; + //! Get object IDs for all organs objects for a given plant /** * \param[in] plantID ID of the plant instance. @@ -1550,6 +1577,12 @@ class PlantArchitecture{ */ std::vector getAllObjectIDs() const; + // -- carbohydrate model -- // + + void enableCarbohydrateModel(); + + void disableCarbohydrateModel(); + // -- manual plant generation from input string -- // std::string getPlantString(uint plantID) const; @@ -1625,12 +1658,14 @@ class PlantArchitecture{ void accumulateShootPhotosynthesis(); - void accumulateHourlyLeafPhotosynthesis(); - void subtractShootMaintenanceCarbon(float dt ); void subtractShootGrowthCarbon(); - void checkCarbonPool_abortbuds(); + void checkCarbonPool_abortBuds(); + void checkCarbonPool_adjustPhyllochron(); + void checkCarbonPool_transferCarbon(); + + bool carbon_model_enabled = false; // --- Plant Library --- // @@ -1666,6 +1701,10 @@ class PlantArchitecture{ uint buildGrapevineVSP( const helios::vec3 &base_position ); + void initializeGroundCherryWeedShoots(); + + uint buildGroundCherryWeedPlant( const helios::vec3 &base_position ); + void initializeMaizeShoots(); uint buildMaizePlant( const helios::vec3 &base_position ); diff --git a/plugins/plantarchitecture/src/CarbohydrateModel.cpp b/plugins/plantarchitecture/src/CarbohydrateModel.cpp index b8a7df443..e40861b51 100644 --- a/plugins/plantarchitecture/src/CarbohydrateModel.cpp +++ b/plugins/plantarchitecture/src/CarbohydrateModel.cpp @@ -1,6 +1,6 @@ /** \file "CarbohydrateModel.cpp" Definitions related to carbohydrate model calculations in the plant architecture plug-in. - Copyright (C) 2016-2025 Brian Bailey + Copyright (C) 2016-2024 Brian Bailey This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,15 +22,17 @@ using namespace helios; float C_molecular_wt = 12.01; //g C mol^-1 -float rho_w = 675000; //Almond wood density (g m^-3) -float wood_carbon_percentage = .5; //portion of the dry weight of the wood made up by carbon +float rho_w = 650000; //Almond wood density (g m^-3) +float wood_carbon_percentage = .475; //portion of the dry weight of the wood made up by carbon + +float shoot_root_ratio = 10; float SLA = 1.75e-2; //ratio of leaf area to leaf dry mass m^2 / g DW float leaf_carbon_percentage = .4444; //portion of the dry weight of the leaf made up by carbon -float total_flower_cost = 8.33e-3; //mol C flower^-1 (Bustan & Goldschmidt 2002) +float total_flower_cost = 8.33e-4; //mol C flower^-1 (Bustan & Goldschmidt 2002) float flower_production_cost = total_flower_cost*.69; //mol C flower^-1 (Bustan & Goldschmidt 2002) float flower_growth_respiration = total_flower_cost*.31; //mol C flower^-1 (Bustan & Goldschmidt 2002) @@ -67,18 +69,8 @@ float Phytomer::calculatePhytomerConstructionCosts(){ leaf_area += context_ptr->getObjectArea(leaf_objID); } } - leaf_area /= current_leaf_scale_factor; //convert to fully-expanded area phytomer_carbon_cost += leaf_construction_cost_base*leaf_area; - //internode (cost per volume basis) - float internode_volume = 0; - uint start_ind = shoot_index.x*phytomer_parameters.internode.length_segments; - for( int segment = start_ind; segmentgetTubeObjectSegmentVolume( parent_shoot_ptr->internode_tube_objID, segment ); - } - internode_volume /= current_internode_scale_factor; //convert to fully-elongated volume - phytomer_carbon_cost += internode_construction_cost_base*internode_volume; - return phytomer_carbon_cost; } @@ -97,6 +89,22 @@ float Phytomer::calculateFlowerConstructionCosts(const FloralBud &fbud) { return flower_carbon_cost; } +void PlantArchitecture::initializeCarbohydratePool(float carbohydrate_concentration_molC_m3){ + + for( auto &plant: plant_instances ) { + + auto shoot_tree = &plant.second.shoot_tree; + + for (auto &shoot: *shoot_tree) { + //calculate shoot volume + float shoot_volume = shoot->calculateShootInternodeVolume(); + //set carbon pool + shoot->carbohydrate_pool_molC = shoot_volume * carbohydrate_concentration_molC_m3; + + } + } +} + void PlantArchitecture::initializePlantCarbohydratePool(uint plantID, float carbohydrate_concentration_molC_m3 ){ if( plant_instances.find(plantID) == plant_instances.end() ){ @@ -138,25 +146,36 @@ void PlantArchitecture::accumulateHourlyLeafPhotosynthesis() { for( auto &shoot: *shoot_tree ){ - for( auto &phytomer: shoot->phytomers ){ + if(shoot->isdormant) { + for( auto &phytomer: shoot->phytomers ){ + for( auto &leaf_objID: flatten(phytomer->leaf_objIDs) ) { + for (uint UUID: context_ptr->getObjectPrimitiveUUIDs(leaf_objID)) { + context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", 0); + } + } + } + }else{ + for( auto &phytomer: shoot->phytomers ){ - for( auto &leaf_objID: flatten(phytomer->leaf_objIDs) ){ - for( uint UUID : context_ptr->getObjectPrimitiveUUIDs(leaf_objID) ){ - float lUUID_area = context_ptr->getPrimitiveArea(UUID); - float leaf_A; - context_ptr->getPrimitiveData(UUID,"net_photosynthesis", leaf_A); - //std::cout<< "leaf photosynthesis mol C: "<< leaf_A<leaf_objIDs) ){ + for( uint UUID : context_ptr->getObjectPrimitiveUUIDs(leaf_objID) ){ + float lUUID_area = context_ptr->getPrimitiveArea(UUID); + float leaf_A; + context_ptr->getPrimitiveData(UUID,"net_photosynthesis", leaf_A); + //std::cout<< "leaf photosynthesis mol C: "<< leaf_A<getPrimitiveData(UUID,"cumulative_net_photosynthesis", current_net_photo); - current_net_photo += new_hourly_photo; - context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", current_net_photo); - //std::cout<< "net photo mol C: "<< current_net_photo<getPrimitiveData(UUID,"cumulative_net_photosynthesis", current_net_photo); + current_net_photo += new_hourly_photo; + context_ptr->setPrimitiveData(UUID, "cumulative_net_photosynthesis", current_net_photo); + //std::cout<< "net photo mol C: "<< current_net_photo<carbohydrate_pool_molC += net_photosynthesis; + //std::cout<< "Net photosynthesis"<< net_photosynthesis<doesObjectExist(shoot->internode_tube_objID) ) { - shoot->carbohydrate_pool_molC -= context_ptr->getTubeObjectVolume(shoot->internode_tube_objID) * rho_cw * stem_maintainance_respiration_rate * dt; //remove shoot maintenance respiration - shoot->carbohydrate_pool_molC -= context_ptr->getTubeObjectVolume(shoot->internode_tube_objID) * rho_cw * .2 / .76 * root_maintainance_respiration_rate * dt; //remove root maintenance respiration portion + if(shoot->isdormant) { + shoot->carbohydrate_pool_molC -= + shoot->old_shoot_volume * rho_cw * + stem_maintainance_respiration_rate * .2 * dt; //remove shoot maintenance respiration + }else{ + shoot->carbohydrate_pool_molC -= + shoot->old_shoot_volume * rho_cw * + stem_maintainance_respiration_rate * dt; //remove shoot maintenance respiration + //std::cout << "shoot stem maintenance: " << context_ptr->getTubeObjectVolume(shoot->internode_tube_objID) * rho_cw * stem_maintainance_respiration_rate * dt << std::endl; + shoot->carbohydrate_pool_molC -= + shoot->old_shoot_volume * rho_cw * .2 / .76 * root_maintainance_respiration_rate * dt; //remove root maintenance respiration portion + //std::cout << "shoot root maintenance: " << context_ptr->getTubeObjectVolume(shoot->internode_tube_objID) * rho_cw * .2 / .76 * root_maintainance_respiration_rate * dt << std::endl; + } } } @@ -237,7 +268,7 @@ void PlantArchitecture::subtractShootMaintenanceCarbon(float dt ) { void PlantArchitecture::subtractShootGrowthCarbon(){ //\todo move to externally settable parameter - float rho_cw = rho_w * 0.5 / 12.01; //Density of carbon in almond wood (mol C m^-3) + float rho_cw = rho_w * wood_carbon_percentage / C_molecular_wt; //Density of carbon in almond wood (mol C m^-3) float growth_respiration_fraction = 0.28; //Accounting for the growth carbon lost to respiration (assumed 28%) @@ -249,12 +280,19 @@ void PlantArchitecture::subtractShootGrowthCarbon(){ for( auto &shoot: *shoot_tree ){ float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shoot->ID)->calculateShootInternodeVolume(); - float shoot_growth_carbon_demand = rho_cw*( shoot_volume - shoot->old_shoot_volume) / (1-growth_respiration_fraction); //Structural carbon + growth respiration required to construct new shoot volume + float shoot_growth_carbon_demand = rho_cw*( shoot_volume - shoot->old_shoot_volume) * 0.5 * (1+growth_respiration_fraction); //Structural carbon + growth respiration required to construct new shoot volume shoot->carbohydrate_pool_molC -= shoot_growth_carbon_demand; //Subtract construction carbon + growth respiration from the carbon pool + //std::cout<old_shoot_volume<<" old shoot volume"<old_shoot_volume = shoot_volume; //Set old volume to the current volume for the next timestep + std::cout<<"shoot growth demand: " << shoot_growth_carbon_demand<< std::endl; + std::cout<<"shoot carbohydrate pool mol C: " << shoot->carbohydrate_pool_molC<< std::endl; + context_ptr->setObjectData( shoot->internode_tube_objID, "carbohydrate_concentration", shoot->carbohydrate_pool_molC / shoot_volume ); + std::cout<<"Shoot Carbohydate Concentration (mg/g dry weight): "<<(shoot->carbohydrate_pool_molC*12.01*1000) / (shoot_volume*rho_w)<ID<carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume){ if(parentID <1000000){ - shoot_tree_ptr->at(parentID)->carbohydrate_pool_molC += (shoot->carbohydrate_pool_molC - carbohydrate_threshold*shoot_volume)*storage_conductance; - shoot->carbohydrate_pool_molC -= (shoot->carbohydrate_pool_molC - carbohydrate_threshold*shoot_volume)*storage_conductance; - shoot->days_with_negative_carbon_balance = 0; - goto shoot_balanced; - }else{ shoot->days_with_negative_carbon_balance = 0; goto shoot_balanced; } - }else if(shoot->days_with_negative_carbon_balance < day_threshold){ shoot->days_with_negative_carbon_balance += 1; }else if(shoot->days_with_negative_carbon_balance >= day_threshold) { @@ -377,4 +408,124 @@ void PlantArchitecture::checkCarbonPool_abortbuds(){ } +} + + +void PlantArchitecture::checkCarbonPool_adjustPhyllochron(){ + float carbohydrate_threshold = 150*rho_w/(1000*C_molecular_wt); //mol C/m3 + float carbohydrate_threshold_low = 50*rho_w/(1000*C_molecular_wt); //mol C/m3 + + for( auto &plant: plant_instances ){ + + uint plantID = plant.first; + auto shoot_tree = &plant.second.shoot_tree; + auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree; + + for( auto &shoot: *shoot_tree ){ + + uint shootID = shoot->ID; + + float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume(); + float working_carb_pool = shoot->carbohydrate_pool_molC; + uint parentID = shoot->parent_shoot_ID; + + if(shoot->carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume){ + if(shoot->phyllochron_instantaneous > shoot->shoot_parameters.phyllochron_min.val() * shoot->phyllochron_recovery){ + shoot->phyllochron_instantaneous = shoot->phyllochron_instantaneous / shoot->phyllochron_recovery; + }else{ + shoot->phyllochron_instantaneous = shoot->shoot_parameters.phyllochron_min.val(); + } + + if(shoot->elongation_rate_instantaneous < shoot->shoot_parameters.elongation_rate_max.val() * shoot->elongation_recovery){ + shoot->elongation_rate_instantaneous = shoot->elongation_rate_instantaneous / shoot->elongation_recovery; + }else{ + shoot->elongation_rate_instantaneous = shoot->shoot_parameters.elongation_rate_max.val(); + } + + }else if (shoot->carbohydrate_pool_molC < carbohydrate_threshold_low*shoot_volume) { + shoot->elongation_rate_instantaneous = shoot->shoot_parameters.phyllochron_min.val() * 20; + shoot->phyllochron_instantaneous = 100; + + }else{ + if(shoot->phyllochron_instantaneous <= shoot->shoot_parameters.phyllochron_min.val() * 20){ + shoot->phyllochron_instantaneous = shoot->phyllochron_instantaneous * shoot->phyllochron_increase; + } + if(shoot->elongation_rate_instantaneous >= shoot->shoot_parameters.elongation_rate_max.val()*0.005){ + shoot->elongation_rate_instantaneous = shoot->elongation_rate_instantaneous * shoot->elongation_decay; + } + } + + } + + } + +} + +void PlantArchitecture::checkCarbonPool_transferCarbon(){ + float carbohydrate_threshold = 50*rho_w/(1000*C_molecular_wt); //mol C/m3 + float storage_conductance = 0.25; + float return_conductance = 0.25; + + for( auto &plant: plant_instances ){ + + uint plantID = plant.first; + auto shoot_tree = &plant.second.shoot_tree; + auto shoot_tree_ptr = &plant_instances.at(plantID).shoot_tree; + + for( auto &shoot: *shoot_tree ){ + + uint shootID = shoot->ID; + + float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume(); + uint parentID = shoot->parent_shoot_ID; + + if(shoot->carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume){ + if(parentID <1000000 ){ + float transfer_mol_C = (shoot->carbohydrate_pool_molC - carbohydrate_threshold * shoot_volume) * storage_conductance; + shoot_tree_ptr->at(parentID)->carbohydrate_pool_molC += + transfer_mol_C; + shoot->carbohydrate_pool_molC -= + transfer_mol_C; + + } + + } + + } + + for( auto &shoot: *shoot_tree ){ + uint shootID = shoot->ID; + float shoot_volume = plant_instances.at(plantID).shoot_tree.at(shootID)->calculateShootInternodeVolume(); + if(shoot->carbohydrate_pool_molC > carbohydrate_threshold*shoot_volume) { + + float totalChildVolume = shoot->sumChildVolume(0); + //std::cout<<"child volume: "<phytomers.size(); p++) { + //call recursively for child shoots + if (shoot->childIDs.find(p) != shoot->childIDs.end()) { + for (int child_shoot_ID: shoot->childIDs.at(p)) { + float child_volume = plant_instances.at(plantID).shoot_tree.at( + child_shoot_ID)->sumChildVolume(0)+plant_instances.at(plantID).shoot_tree.at( + child_shoot_ID)->calculateShootInternodeVolume(); + float child_ratio = child_volume / totalChildVolume; + //std::cout<<"child ratio: "<carbohydrate_pool_molC - carbohydrate_threshold * shoot_volume)*return_conductance*child_ratio; + + shoot_tree_ptr->at(child_shoot_ID)->carbohydrate_pool_molC += + transfer_mol_C; + shoot->carbohydrate_pool_molC -= + transfer_mol_C; + //std::cout<<"Carb to child: "<<(shoot->carbohydrate_pool_molC - carbohydrate_threshold*shoot_volume)*return_conductance*child_ratio<plant_instances.at(this->plantID).shoot_tree.at(this->parent_shoot_ID)->carbohydrate_pool_molC -= flower_cost; - }else if( state == BUD_FRUITING ){ //adding a fruit - float fruit_cost = calculateFruitConstructionCosts(fbud); - plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(this->parent_shoot_ID)->carbohydrate_pool_molC -= fruit_cost; + if( plantarchitecture_ptr->carbon_model_enabled ){ + if( state == BUD_FLOWER_CLOSED || (fbud.state == BUD_ACTIVE && state == BUD_FLOWER_OPEN ) ){ //state went from active to closed flower or open flower + float flower_cost = calculateFlowerConstructionCosts(fbud); + plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(this->parent_shoot_ID)->carbohydrate_pool_molC -= flower_cost; + }else if( state == BUD_FRUITING ){ //adding a fruit + float fruit_cost = calculateFruitConstructionCosts(fbud); + plantarchitecture_ptr->plant_instances.at(this->plantID).shoot_tree.at(this->parent_shoot_ID)->carbohydrate_pool_molC -= fruit_cost; + } } // Delete geometry from previous reproductive state (if present) @@ -544,7 +546,9 @@ int Shoot::appendPhytomer(float internode_radius, float internode_length_max, fl } //calculate fully expanded/elongated carbon costs - this->carbohydrate_pool_molC -= phytomer->calculatePhytomerConstructionCosts(); + if( plantarchitecture_ptr->carbon_model_enabled ){ + this->carbohydrate_pool_molC -= phytomer->calculatePhytomerConstructionCosts(); + } return (int) phytomers.size() - 1; } @@ -773,6 +777,29 @@ float Shoot::sumShootLeafArea(uint start_node_index) const { return area; } + +float Shoot::sumChildVolume( uint start_node_index ) const{ + + if( start_node_index>=phytomers.size() ){ + helios_runtime_error("ERROR (Shoot::sumChildVolume): Start node index out of range."); + } + + float volume = 0; + + for( uint p=start_node_index; pplant_instances.at(plantID).shoot_tree.at(child_shoot_ID)->calculateShootInternodeVolume(); + } + } + + } + + return volume; + +} + Phytomer::Phytomer(const PhytomerParameters ¶ms, Shoot *parent_shoot, uint phytomer_index, const helios::vec3 &parent_internode_axis, const helios::vec3 &parent_petiole_axis, helios::vec3 internode_base_origin, const AxisRotation &shoot_base_rotation, float internode_radius, float internode_length_max, float internode_length_scale_factor_fraction, float leaf_scale_factor_fraction, uint rank, PlantArchitecture *plantarchitecture_ptr, helios::Context *context_ptr) @@ -1749,6 +1776,54 @@ void Phytomer::removeLeaf() { } } +void Phytomer::deletePhytomer(){ + + // internode + if( context_ptr->doesObjectExist(parent_shoot_ptr->internode_tube_objID) ) { + context_ptr->pruneTubeNodes(parent_shoot_ptr->internode_tube_objID, this->shoot_index.x); + parent_shoot_ptr->terminateApicalBud(); + } + + // leaves + this->removeLeaf(); + + //inflorescence + for (auto &petiole: this->floral_buds) { + for (auto &fbud: petiole) { + for (int p = fbud.inflorescence_objIDs.size() - 1; p >= 0; p--) { + uint objID = fbud.inflorescence_objIDs.at(p); + context_ptr->deleteObject(objID); + fbud.inflorescence_objIDs.erase(fbud.inflorescence_objIDs.begin() + p); + fbud.inflorescence_bases.erase(fbud.inflorescence_bases.begin() + p); + } + for (int p = fbud.peduncle_objIDs.size() - 1; p >= 0; p--) { + uint objID = fbud.peduncle_objIDs.at(p); + context_ptr->deleteObject(fbud.peduncle_objIDs); + context_ptr->deleteObject(fbud.inflorescence_objIDs); + fbud.peduncle_objIDs.clear(); + fbud.inflorescence_objIDs.clear(); + fbud.inflorescence_bases.clear(); + break; + } + } + } + + // delete next phytomer on shoot + if (shoot_index.x < parent_shoot_ptr->phytomers.size() - 1) { + auto next_phytomer = parent_shoot_ptr->phytomers.at(shoot_index.x + 1); + next_phytomer->deletePhytomer(); + } + + // delete any child shoots + if( parent_shoot_ptr->childIDs.find(shoot_index.x) != parent_shoot_ptr->childIDs.end() ){ + for( auto childID: parent_shoot_ptr->childIDs.at(shoot_index.x) ){ + auto child_shoot = plantarchitecture_ptr->plant_instances.at(plantID).shoot_tree.at(childID); + child_shoot->phytomers.front()->deletePhytomer(); + } + } + +} + bool Phytomer::hasLeaf() const { return (!leaf_bases.empty() && !leaf_bases.front().empty()); } @@ -1765,6 +1840,8 @@ Shoot::Shoot(uint plant_ID, int shoot_ID, int parent_shoot_ID, uint parent_node, isdormant = true; gravitropic_curvature = shoot_params.gravitropic_curvature.val(); context_ptr = plant_architecture_ptr->context_ptr; + phyllochron_instantaneous = shoot_parameters.phyllochron_min.val(); + elongation_rate_instantaneous = shoot_parameters.elongation_rate_max.val(); if( parent_shoot_ID>=0 ) { plant_architecture_ptr->plant_instances.at(plantID).shoot_tree.at(parent_shoot_ID)->childIDs[(int) parent_node_index].push_back(shoot_ID); @@ -2302,7 +2379,7 @@ float PlantArchitecture::getPlantHeight(uint plantID) const{ } -std::vector PlantArchitecture::getPlantLeafInclinationAngleDistribution(uint plantID, uint Nbins, bool normalize) const { +std::vector PlantArchitecture::getPlantLeafInclinationAngleDistribution(uint plantID, uint Nbins) const { if( plant_instances.find(plantID) == plant_instances.end() ){ helios_runtime_error("ERROR (PlantArchitecture::getPlantLeafInclinationAngleDistribution): Plant with ID of " + std::to_string(plantID) + " does not exist."); @@ -2316,15 +2393,17 @@ std::vector PlantArchitecture::getPlantLeafInclinationAngleDistribution(u for( uint UUID : leaf_UUIDs ){ vec3 normal = context_ptr->getPrimitiveNormal(UUID); float theta = acos_safe(fabs(normal.z)); + float area = context_ptr->getPrimitiveArea(UUID); uint bin = uint( std::floor(theta / dtheta) ); - leaf_inclination_angles.at(bin)++; + if (bin >= Nbins) { + bin = Nbins - 1; // Ensure bin index is within range + } + leaf_inclination_angles.at(bin)+=area; } - if( normalize ){ - float sum = helios::sum(leaf_inclination_angles); - for( float &angle : leaf_inclination_angles ){ - angle /= sum; - } + float sum = helios::sum(leaf_inclination_angles); + for( float &angle : leaf_inclination_angles ){ + angle /= sum; } return leaf_inclination_angles; @@ -2373,6 +2452,13 @@ void PlantArchitecture::setPlantAge(uint plantID, float a_current_age) { // this->current_age = current_age; } +std::string PlantArchitecture::getPlantName(uint plantID) const{ + if( plant_instances.find(plantID) == plant_instances.end() ){ + helios_runtime_error("ERROR (PlantArchitecture::getPlantName): Plant with ID of " + std::to_string(plantID) + " does not exist."); + } + return plant_instances.at(plantID).plant_name; +} + float PlantArchitecture::getPlantAge(uint plantID) const{ if( plant_instances.find(plantID) == plant_instances.end() ){ helios_runtime_error("ERROR (PlantArchitecture::setPlantAge): Plant with ID of " + std::to_string(plantID) + " does not exist."); @@ -2451,6 +2537,21 @@ void PlantArchitecture::breakPlantDormancy( uint plantID ){ } } +void PlantArchitecture::pruneBranch(uint plantID, uint shootID, uint node_index){ + + if( plant_instances.find(plantID) == plant_instances.end() ){ + helios_runtime_error("ERROR (PlantArchitecture::pruneBranch): Plant with ID of " + std::to_string(plantID) + " does not exist."); + }else if( shootID>=plant_instances.at(plantID).shoot_tree.size() ){ + helios_runtime_error("ERROR (PlantArchitecture::pruneBranch): Shoot with ID of " + std::to_string(shootID) + " does not exist on plant " + std::to_string(plantID) + "."); + }else if( node_index>=plant_instances.at(plantID).shoot_tree.at(shootID)->current_node_number ){ + helios_runtime_error("ERROR (PlantArchitecture::pruneBranch): Node index " + std::to_string(node_index) + " is out of range for shoot " + std::to_string(shootID) + "."); + } + + auto &shoot = plant_instances.at(plantID).shoot_tree.at(shootID); + + shoot->phytomers.at(node_index)->deletePhytomer(); + +} uint PlantArchitecture::getShootNodeCount( uint plantID, uint shootID ) const{ if( plant_instances.find(plantID) == plant_instances.end() ){ @@ -2482,6 +2583,18 @@ float PlantArchitecture::getShootTaper( uint plantID, uint shootID ) const{ return taper; } +std::vector PlantArchitecture::getAllPlantIDs() const{ + + std::vector objIDs; + objIDs.reserve(plant_instances.size()); + + for( const auto &plant : plant_instances ){ + objIDs.push_back(plant.first); + } + + return objIDs; +} + std::vector PlantArchitecture::getAllPlantObjectIDs(uint plantID) const{ if( plant_instances.find(plantID) == plant_instances.end() ){ @@ -2727,13 +2840,21 @@ std::vector PlantArchitecture::getAllObjectIDs() const { return objIDs_all; } +void PlantArchitecture::enableCarbohydrateModel() { + carbon_model_enabled = true; +} + +void PlantArchitecture::disableCarbohydrateModel() { + carbon_model_enabled = false; +} + uint PlantArchitecture::addPlantInstance(const helios::vec3 &base_position, float current_age) { if( current_age<0 ){ helios_runtime_error("ERROR (PlantArchitecture::addPlantInstance): Current age must be greater than or equal to zero."); } - PlantInstance instance(base_position, current_age, context_ptr); + PlantInstance instance(base_position, current_age, "custom", context_ptr); plant_instances.emplace(plant_count, instance); @@ -2843,7 +2964,7 @@ void PlantArchitecture::advanceTime(float time_step_days) { } } -void PlantArchitecture::advanceTime( int time_step_years, float time_step_days ) { +void PlantArchitecture::advanceTime(int time_step_years, float time_step_days) { for (auto &plant: plant_instances) { uint plantID = plant.first; @@ -2851,7 +2972,7 @@ void PlantArchitecture::advanceTime( int time_step_years, float time_step_days ) } } -void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) { +void PlantArchitecture::advanceTime(uint plantID, float time_step_days) { if( plant_instances.find(plantID) == plant_instances.end() ){ helios_runtime_error("ERROR (PlantArchitecture::advanceTime): Plant with ID of " + std::to_string(plantID) + " does not exist."); @@ -2885,6 +3006,11 @@ void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) { dt_max = remainder_time; } + // **** accumulate photosynthate **** // + if( carbon_model_enabled ){ + accumulateShootPhotosynthesis(); + } + if (plant_instance.current_age <= plant_instance.max_age && plant_instance.current_age + dt_max > plant_instance.max_age) { std::cout << "PlantArchitecture::advanceTime: Plant has reached its maximum supported age. No further growth will occur." << std::endl; } else if (plant_instance.current_age >= plant_instance.max_age) { @@ -2901,7 +3027,6 @@ void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) { plant_instance.time_since_dormancy = 0; for (const auto &shoot: *shoot_tree) { shoot->makeDormant(); - shoot->carbohydrate_pool_molC = 100; } harvestPlant(plantID); continue; @@ -2924,7 +3049,6 @@ void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) { // breaking dormancy if (shoot->isdormant && plant_instance.time_since_dormancy >= plant_instance.dd_to_dormancy_break) { shoot->breakDormancy(); - shoot->carbohydrate_pool_molC = 1e6; } if (shoot->isdormant) { @@ -3019,7 +3143,7 @@ void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) { for (auto &phytomer: shoot->phytomers) { //scale internode length if (phytomer->current_internode_scale_factor < 1) { - float dL_internode = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->internode_length_max; + float dL_internode = dt_max * shoot->elongation_rate_instantaneous * phytomer->internode_length_max; float length_scale = fmin(1.f, (phytomer->getInternodeLength() + dL_internode) / phytomer->internode_length_max); phytomer->setInternodeLengthScaleFraction(length_scale, false); } @@ -3039,7 +3163,7 @@ void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) { if (phytomer->hasLeaf() && phytomer->current_leaf_scale_factor <= 1) { float tip_ind = ceil(float(phytomer->leaf_size_max.front().size()-1)/2.f); float leaf_length = phytomer->current_leaf_scale_factor * phytomer->leaf_size_max.front().at(tip_ind); - float dL_leaf = dt_max * shoot->shoot_parameters.elongation_rate.val() * phytomer->leaf_size_max.front().at(tip_ind); + float dL_leaf = dt_max * shoot->elongation_rate_instantaneous * phytomer->leaf_size_max.front().at(tip_ind); float scale = fmin(1.f, (leaf_length + dL_leaf) / phytomer->phytomer_parameters.leaf.prototype_scale.val() ); phytomer->phytomer_parameters.leaf.prototype_scale.resample(); phytomer->setLeafScaleFraction(scale); @@ -3111,11 +3235,7 @@ void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) { // leaves for (uint petiole = 0; petiole < phytomer->leaf_objIDs.size(); petiole++) { if (detectGroundCollision(phytomer->leaf_objIDs.at(petiole))) { - context_ptr->deleteObject(phytomer->leaf_objIDs.at(petiole)); - phytomer->leaf_objIDs.at(petiole).clear(); - phytomer->leaf_bases.at(petiole).clear(); - context_ptr->deleteObject(phytomer->petiole_objIDs.at(petiole)); - phytomer->petiole_objIDs.at(petiole).clear(); + phytomer->removeLeaf(); } } @@ -3196,15 +3316,22 @@ void PlantArchitecture::advanceTime( uint plantID, float time_step_days ) { addEpicormicShoot(plantID, shoot->ID, epicormic_fraction.at(s), 1, 0, internode_radius, internode_length_max, 0.01, 0.01, 0, epicormic_shoot_label); } } - - // **** subtract maintenance carbon costs **** // - // subtractShootMaintenanceCarbon(dt_max); - - if (output_object_data.find("carbohydrate_concentration") != output_object_data.end() && context_ptr->doesObjectExist(shoot->internode_tube_objID)) { - float shoot_volume = shoot->calculateShootInternodeVolume(); - context_ptr->setObjectData(shoot->internode_tube_objID, "carbohydrate_concentration",shoot->carbohydrate_pool_molC / shoot_volume); + if( carbon_model_enabled ){ + if (output_object_data.find("carbohydrate_concentration") != output_object_data.end() && context_ptr->doesObjectExist(shoot->internode_tube_objID)) { + float shoot_volume = shoot->calculateShootInternodeVolume(); + context_ptr->setObjectData(shoot->internode_tube_objID, "carbohydrate_concentration",shoot->carbohydrate_pool_molC / shoot_volume); + } } } + + // **** subtract maintenance carbon costs **** // + if( carbon_model_enabled ){ + subtractShootMaintenanceCarbon(time_step_days); + subtractShootGrowthCarbon(); + checkCarbonPool_adjustPhyllochron(); + checkCarbonPool_abortBuds(); + checkCarbonPool_transferCarbon(); + } } //update Context geometry diff --git a/plugins/plantarchitecture/src/PlantLibrary.cpp b/plugins/plantarchitecture/src/PlantLibrary.cpp index 6cee95443..7dc3edef6 100644 --- a/plugins/plantarchitecture/src/PlantLibrary.cpp +++ b/plugins/plantarchitecture/src/PlantLibrary.cpp @@ -47,6 +47,8 @@ uint PlantArchitecture::buildPlantInstanceFromLibrary( const helios::vec3 &base_ plantID = buildCowpeaPlant(base_position); }else if( current_plant_model == "grapevine_VSP" ) { plantID = buildGrapevineVSP(base_position); + }else if( current_plant_model == "groundcherryweed" ) { + plantID = buildGroundCherryWeedPlant(base_position); }else if( current_plant_model == "maize" ) { plantID = buildMaizePlant(base_position); }else if( current_plant_model == "olive" ) { @@ -79,6 +81,8 @@ uint PlantArchitecture::buildPlantInstanceFromLibrary( const helios::vec3 &base_ assert(true); //shouldn't be here } + plant_instances.at(plantID).plant_name = current_plant_model; + if( age>0 ){ advanceTime( plantID, age); } @@ -140,6 +144,8 @@ void PlantArchitecture::initializeDefaultShoots( const std::string &plant_label initializeCowpeaShoots(); }else if( plant_label == "grapevine_VSP" ) { initializeGrapevineVSPShoots(); + }else if( plant_label == "groundcherryweed" ) { + initializeGroundCherryWeedShoots(); }else if( plant_label == "maize" ) { initializeMaizeShoots(); }else if( plant_label == "olive" ) { @@ -241,7 +247,7 @@ void PlantArchitecture::initializeAlmondTreeShoots(){ shoot_parameters_trunk.girth_area_factor = 8.f; shoot_parameters_trunk.vegetative_bud_break_probability_min = 0; shoot_parameters_trunk.vegetative_bud_break_time = 0; - shoot_parameters_trunk.tortuosity = 1.5; + 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}); @@ -256,7 +262,7 @@ void PlantArchitecture::initializeAlmondTreeShoots(){ shoot_parameters_proleptic.max_nodes = 50; shoot_parameters_proleptic.max_nodes_per_season = 25; shoot_parameters_proleptic.phyllochron_min = 2; - shoot_parameters_proleptic.elongation_rate = 0.15; + shoot_parameters_proleptic.elongation_rate_max = 0.15; shoot_parameters_proleptic.girth_area_factor = 8.f; shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.15; shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.4; @@ -299,7 +305,7 @@ void PlantArchitecture::initializeAlmondTreeShoots(){ shoot_parameters_scaffold.max_nodes = 40; shoot_parameters_scaffold.gravitropic_curvature = 150; shoot_parameters_scaffold.internode_length_max = 0.04; - shoot_parameters_scaffold.tortuosity = 1.5; + shoot_parameters_scaffold.tortuosity = 1.; shoot_parameters_scaffold.defineChildShootTypes({"proleptic"},{1.0}); defineShootType("trunk", shoot_parameters_trunk); @@ -427,7 +433,7 @@ void PlantArchitecture::initializeAppleTreeShoots(){ shoot_parameters_proleptic.max_nodes = 40; shoot_parameters_proleptic.max_nodes_per_season = 20; shoot_parameters_proleptic.phyllochron_min = 2.0; - shoot_parameters_proleptic.elongation_rate = 0.15; + shoot_parameters_proleptic.elongation_rate_max = 0.2; shoot_parameters_proleptic.girth_area_factor = 5.f; shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.1; shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.4; @@ -557,7 +563,7 @@ void PlantArchitecture::initializeAsparagusShoots() { shoot_parameters.gravitropic_curvature = -200; shoot_parameters.phyllochron_min = 1; - shoot_parameters.elongation_rate = 0.15; + shoot_parameters.elongation_rate_max = 0.15; // shoot_parameters.girth_growth_rate = 0.00005; shoot_parameters.girth_area_factor = 30; shoot_parameters.vegetative_bud_break_time = 5; @@ -642,7 +648,7 @@ void PlantArchitecture::initializeBindweedShoots() { shoot_parameters_primary.vegetative_bud_break_time = 3; shoot_parameters_primary.base_roll = 90; shoot_parameters_primary.phyllochron_min = 1; - shoot_parameters_primary.elongation_rate = 0.25; + shoot_parameters_primary.elongation_rate_max = 0.3; shoot_parameters_primary.girth_area_factor = 0; shoot_parameters_primary.internode_length_max = 0.03; shoot_parameters_primary.internode_length_decay_rate = 0; @@ -664,7 +670,7 @@ void PlantArchitecture::initializeBindweedShoots() { shoot_parameters_base.vegetative_bud_break_probability_min = 1.0; shoot_parameters_base.vegetative_bud_break_time = 2; shoot_parameters_base.phyllochron_min = 2; - shoot_parameters_base.elongation_rate = 0.15; + shoot_parameters_base.elongation_rate_max = 0.15; shoot_parameters_base.girth_area_factor = 0.f; shoot_parameters_base.gravitropic_curvature = 0; shoot_parameters_base.internode_length_max = 0.01; @@ -808,7 +814,7 @@ void PlantArchitecture::initializeBeanShoots() { shoot_parameters_trifoliate.gravitropic_curvature = 200; shoot_parameters_trifoliate.phyllochron_min = 2; - shoot_parameters_trifoliate.elongation_rate = 0.1; + shoot_parameters_trifoliate.elongation_rate_max = 0.1; shoot_parameters_trifoliate.girth_area_factor = 1.5f; shoot_parameters_trifoliate.vegetative_bud_break_time = 15; shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.1; @@ -905,7 +911,7 @@ void PlantArchitecture::initializeCheeseweedShoots() { shoot_parameters_base.vegetative_bud_break_probability_min = 0.2; shoot_parameters_base.vegetative_bud_break_time = 6; shoot_parameters_base.phyllochron_min = 2; - shoot_parameters_base.elongation_rate = 0.1; + shoot_parameters_base.elongation_rate_max = 0.1; shoot_parameters_base.girth_area_factor = 10.f; shoot_parameters_base.gravitropic_curvature = 0; shoot_parameters_base.internode_length_max = 0.0015; @@ -948,9 +954,9 @@ void PlantArchitecture::initializeCowpeaShoots() { leaf_prototype_trifoliate.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_tip_centered.png"; leaf_prototype_trifoliate.leaf_texture_file[-1] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_left_centered.png"; leaf_prototype_trifoliate.leaf_texture_file[1] = "plugins/plantarchitecture/assets/textures/CowpeaLeaf_right_centered.png"; - leaf_prototype_trifoliate.leaf_aspect_ratio = 0.8f; + leaf_prototype_trifoliate.leaf_aspect_ratio = 0.7f; leaf_prototype_trifoliate.midrib_fold_fraction = 0.2; - leaf_prototype_trifoliate.longitudinal_curvature.uniformDistribution(-0.4f, -0.1f); + leaf_prototype_trifoliate.longitudinal_curvature.uniformDistribution(-0.3f, -0.1f); leaf_prototype_trifoliate.lateral_curvature = -0.4f; leaf_prototype_trifoliate.subdivisions = 6; leaf_prototype_trifoliate.unique_prototypes = 5; @@ -975,7 +981,7 @@ void PlantArchitecture::initializeCowpeaShoots() { phytomer_parameters_trifoliate.petiole.petioles_per_internode = 1; phytomer_parameters_trifoliate.petiole.pitch.uniformDistribution(45,60); phytomer_parameters_trifoliate.petiole.radius = 0.0018; - phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.08,0.1); + phytomer_parameters_trifoliate.petiole.length.uniformDistribution(0.06,0.08); phytomer_parameters_trifoliate.petiole.taper = 0.25; phytomer_parameters_trifoliate.petiole.curvature.uniformDistribution(-200,-50); phytomer_parameters_trifoliate.petiole.color = make_RGBcolor(0.17,0.25,0.07); @@ -983,7 +989,8 @@ void PlantArchitecture::initializeCowpeaShoots() { phytomer_parameters_trifoliate.petiole.radial_subdivisions = 6; phytomer_parameters_trifoliate.leaf.leaves_per_petiole = 3; - phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10); +// phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(0, 10); + phytomer_parameters_trifoliate.leaf.pitch.normalDistribution(45, 20); phytomer_parameters_trifoliate.leaf.yaw = 10; phytomer_parameters_trifoliate.leaf.roll = -15; phytomer_parameters_trifoliate.leaf.leaflet_offset = 0.4; @@ -1001,7 +1008,7 @@ void PlantArchitecture::initializeCowpeaShoots() { phytomer_parameters_trifoliate.peduncle.radial_subdivisions = 6; phytomer_parameters_trifoliate.inflorescence.flowers_per_peduncle = 4;//.uniformDistribution(1, 3); - phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.05; + phytomer_parameters_trifoliate.inflorescence.flower_offset = 0.025; phytomer_parameters_trifoliate.inflorescence.pitch.uniformDistribution(50,70); phytomer_parameters_trifoliate.inflorescence.roll.uniformDistribution(-20,20); phytomer_parameters_trifoliate.inflorescence.flower_prototype_scale = 0.03; @@ -1040,10 +1047,10 @@ void PlantArchitecture::initializeCowpeaShoots() { shoot_parameters_trifoliate.gravitropic_curvature = 200; shoot_parameters_trifoliate.phyllochron_min = 2; - shoot_parameters_trifoliate.elongation_rate = 0.1; + shoot_parameters_trifoliate.elongation_rate_max = 0.1; shoot_parameters_trifoliate.girth_area_factor = 1.5f; - shoot_parameters_trifoliate.vegetative_bud_break_time = 15; - shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.1; + shoot_parameters_trifoliate.vegetative_bud_break_time = 10; + shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.2; shoot_parameters_trifoliate.vegetative_bud_break_probability_decay_rate = -0.4; // shoot_parameters_trifoliate.max_terminal_floral_buds = 0; (default) shoot_parameters_trifoliate.flower_bud_break_probability.uniformDistribution(0.1,0.15); @@ -1162,7 +1169,7 @@ void PlantArchitecture::initializeGrapevineVSPShoots() { shoot_parameters_main.vegetative_bud_break_probability_decay_rate = 1.; shoot_parameters_main.vegetative_bud_break_time = 30; shoot_parameters_main.phyllochron_min.uniformDistribution(1.75,2.25); - shoot_parameters_main.elongation_rate = 0.15; + shoot_parameters_main.elongation_rate_max = 0.15; shoot_parameters_main.girth_area_factor = 1.f; shoot_parameters_main.gravitropic_curvature = 400; shoot_parameters_main.tortuosity = 15; @@ -1244,6 +1251,122 @@ uint PlantArchitecture::buildGrapevineVSP(const helios::vec3 &base_position) { } +void PlantArchitecture::initializeGroundCherryWeedShoots() { + + // ---- Leaf Prototype ---- // + + LeafPrototype leaf_prototype(context_ptr->getRandomGenerator()); + leaf_prototype.leaf_texture_file[0] = "plugins/plantarchitecture/assets/textures/GroundCherryLeaf.png"; + leaf_prototype.leaf_aspect_ratio.uniformDistribution(0.3,0.5); + leaf_prototype.midrib_fold_fraction = 0.2f; + leaf_prototype.longitudinal_curvature = 0.1f;; + leaf_prototype.lateral_curvature = -0.3f; + leaf_prototype.wave_period = 0.35f; + leaf_prototype.wave_amplitude = 0.08f; + leaf_prototype.subdivisions = 6; + leaf_prototype.unique_prototypes = 5; + + // ---- Phytomer Parameters ---- // + + PhytomerParameters phytomer_parameters(context_ptr->getRandomGenerator()); + + phytomer_parameters.internode.pitch = 5; + phytomer_parameters.internode.phyllotactic_angle = 137.5; + phytomer_parameters.internode.radius_initial = 0.0005; + phytomer_parameters.internode.color = make_RGBcolor(0.213, 0.270, 0.056); + phytomer_parameters.internode.length_segments = 1; + + phytomer_parameters.petiole.petioles_per_internode = 1; + phytomer_parameters.petiole.pitch.uniformDistribution(45,60); + phytomer_parameters.petiole.radius = 0.0005; + phytomer_parameters.petiole.length = 0.025; + phytomer_parameters.petiole.taper = 0.15; + phytomer_parameters.petiole.curvature.uniformDistribution(-150,-50); + phytomer_parameters.petiole.color = phytomer_parameters.internode.color; + phytomer_parameters.petiole.length_segments = 2; + + phytomer_parameters.leaf.leaves_per_petiole = 1; + phytomer_parameters.leaf.pitch.uniformDistribution(-30, 5); + phytomer_parameters.leaf.yaw = 10; + phytomer_parameters.leaf.roll = 0; + phytomer_parameters.leaf.prototype_scale.uniformDistribution(0.06,0.08); + phytomer_parameters.leaf.prototype = leaf_prototype; + + phytomer_parameters.peduncle.length = 0.01; + phytomer_parameters.peduncle.radius = 0.001; + phytomer_parameters.peduncle.pitch = 20; + phytomer_parameters.peduncle.roll = 0; + phytomer_parameters.peduncle.curvature = -700; + phytomer_parameters.peduncle.color = phytomer_parameters.internode.color; + phytomer_parameters.peduncle.length_segments = 2; + phytomer_parameters.peduncle.radial_subdivisions = 6; + + phytomer_parameters.inflorescence.flowers_per_peduncle = 1; + phytomer_parameters.inflorescence.pitch = 0; + phytomer_parameters.inflorescence.roll.uniformDistribution(-30,30); + phytomer_parameters.inflorescence.flower_prototype_scale = 0.01; + phytomer_parameters.inflorescence.flower_prototype_function = BindweedFlowerPrototype; + phytomer_parameters.inflorescence.fruit_prototype_scale = 0.06; + // phytomer_parameters.inflorescence.fruit_prototype_function = GroundCherryFruitPrototype; + phytomer_parameters.inflorescence.fruit_gravity_factor_fraction = 0.75; + + // ---- Shoot Parameters ---- // + + ShootParameters shoot_parameters(context_ptr->getRandomGenerator()); + shoot_parameters.phytomer_parameters = phytomer_parameters; + // shoot_parameters.phytomer_parameters.phytomer_creation_function = TomatoPhytomerCreationFunction; + + shoot_parameters.max_nodes = 26; + shoot_parameters.insertion_angle_tip = 50; + shoot_parameters.insertion_angle_decay_rate = 0; + shoot_parameters.internode_length_max = 0.015; + shoot_parameters.internode_length_min = 0.0; + shoot_parameters.internode_length_decay_rate = 0; + shoot_parameters.base_roll = 90; + shoot_parameters.base_yaw.uniformDistribution(-20,20); + shoot_parameters.gravitropic_curvature = 700; + shoot_parameters.tortuosity = 3; + + shoot_parameters.phyllochron_min = 1; + shoot_parameters.elongation_rate_max = 0.1; + shoot_parameters.girth_area_factor = 3.f; + shoot_parameters.vegetative_bud_break_time = 7; + shoot_parameters.vegetative_bud_break_probability_min = 0.2; + shoot_parameters.vegetative_bud_break_probability_decay_rate = -0.5; + shoot_parameters.flower_bud_break_probability = 0.25; + shoot_parameters.fruit_set_probability = 0.5; + shoot_parameters.flowers_require_dormancy = false; + shoot_parameters.growth_requires_dormancy = false; + shoot_parameters.determinate_shoot_growth = false; + + shoot_parameters.defineChildShootTypes({"mainstem"},{1.0}); + + defineShootType("mainstem",shoot_parameters); + +} + +uint PlantArchitecture::buildGroundCherryWeedPlant(const helios::vec3 &base_position) { + + if (shoot_types.empty()) { + //automatically initialize ground cherry plant shoots + initializeGroundCherryWeedShoots(); + } + + uint plantID = addPlantInstance(base_position, 0); + + AxisRotation base_rotation = make_AxisRotation(0, context_ptr->randu(0.f, 2.f * M_PI), context_ptr->randu(0.f, 2.f * M_PI)); + uint uID_stem = addBaseStemShoot(plantID, 1, base_rotation, 0.0025, 0.018, 0.01, 0.01, 0, "mainstem"); + + breakPlantDormancy(plantID); + + setPlantPhenologicalThresholds(plantID, 0, 20, -1, 20, 30, 1000, false); + + plant_instances.at(plantID).max_age = 50; + + return plantID; + +} + void PlantArchitecture::initializeMaizeShoots() { // ---- Leaf Prototype ---- // @@ -1313,7 +1436,7 @@ void PlantArchitecture::initializeMaizeShoots() { shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0.5; shoot_parameters_mainstem.flower_bud_break_probability = 1; shoot_parameters_mainstem.phyllochron_min = 2; - shoot_parameters_mainstem.elongation_rate = 0.1; + shoot_parameters_mainstem.elongation_rate_max = 0.1; shoot_parameters_mainstem.girth_area_factor = 8.f; shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-500,0); shoot_parameters_mainstem.internode_length_max = 0.22; @@ -1427,7 +1550,7 @@ void PlantArchitecture::initializeOliveTreeShoots(){ shoot_parameters_proleptic.max_nodes.uniformDistribution(16,24); shoot_parameters_proleptic.max_nodes_per_season.uniformDistribution(8,12); shoot_parameters_proleptic.phyllochron_min = 2.0; - shoot_parameters_proleptic.elongation_rate = 0.25; + shoot_parameters_proleptic.elongation_rate_max = 0.25; shoot_parameters_proleptic.girth_area_factor = 5.f; shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.025; shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 1.0; @@ -1587,7 +1710,7 @@ void PlantArchitecture::initializePistachioTreeShoots(){ shoot_parameters_proleptic.max_nodes.uniformDistribution(16,24); shoot_parameters_proleptic.max_nodes_per_season.uniformDistribution(8,12); shoot_parameters_proleptic.phyllochron_min = 2.0; - shoot_parameters_proleptic.elongation_rate = 0.25; + shoot_parameters_proleptic.elongation_rate_max = 0.25; shoot_parameters_proleptic.girth_area_factor = 8.f; shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.025; shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.7; @@ -1707,7 +1830,7 @@ void PlantArchitecture::initializePuncturevineShoots() { shoot_parameters_primary.vegetative_bud_break_time = 3; shoot_parameters_primary.base_roll = 90; shoot_parameters_primary.phyllochron_min = 1; - shoot_parameters_primary.elongation_rate = 0.2; + shoot_parameters_primary.elongation_rate_max = 0.2; shoot_parameters_primary.girth_area_factor = 0.f; shoot_parameters_primary.internode_length_max = 0.02; shoot_parameters_primary.internode_length_decay_rate = 0; @@ -1729,7 +1852,7 @@ void PlantArchitecture::initializePuncturevineShoots() { shoot_parameters_base.vegetative_bud_break_probability_min = 1; shoot_parameters_base.vegetative_bud_break_time = 2; shoot_parameters_base.phyllochron_min = 2; - shoot_parameters_base.elongation_rate = 0.15; + shoot_parameters_base.elongation_rate_max = 0.15; shoot_parameters_base.gravitropic_curvature = 0; shoot_parameters_base.internode_length_max = 0.01; shoot_parameters_base.internode_length_decay_rate = 0; @@ -1837,7 +1960,7 @@ void PlantArchitecture::initializeEasternRedbudShoots() { shoot_parameters_main.vegetative_bud_break_probability_min = 1.0; shoot_parameters_main.vegetative_bud_break_time = 2; shoot_parameters_main.phyllochron_min = 2; - shoot_parameters_main.elongation_rate = 0.1; + shoot_parameters_main.elongation_rate_max = 0.1; shoot_parameters_main.girth_area_factor = 4.f; shoot_parameters_main.gravitropic_curvature = 300; shoot_parameters_main.tortuosity = 5; @@ -1971,7 +2094,7 @@ void PlantArchitecture::initializeRiceShoots() { shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0; shoot_parameters_mainstem.flower_bud_break_probability = 1; shoot_parameters_mainstem.phyllochron_min = 2; - shoot_parameters_mainstem.elongation_rate = 0.1; + shoot_parameters_mainstem.elongation_rate_max = 0.1; shoot_parameters_mainstem.girth_area_factor = 5.f; shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-1000,-400); shoot_parameters_mainstem.internode_length_max = 0.0075; @@ -2056,7 +2179,7 @@ void PlantArchitecture::initializeButterLettuceShoots() { shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters; shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0; shoot_parameters_mainstem.phyllochron_min = 2; - shoot_parameters_mainstem.elongation_rate = 0.15; + shoot_parameters_mainstem.elongation_rate_max = 0.15; shoot_parameters_mainstem.girth_area_factor = 0.f; shoot_parameters_mainstem.gravitropic_curvature = 10; shoot_parameters_mainstem.internode_length_max = 0.001; @@ -2158,7 +2281,7 @@ void PlantArchitecture::initializeSorghumShoots() { shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0; shoot_parameters_mainstem.flower_bud_break_probability = 1; shoot_parameters_mainstem.phyllochron_min = 2; - shoot_parameters_mainstem.elongation_rate = 0.1; + shoot_parameters_mainstem.elongation_rate_max = 0.1; shoot_parameters_mainstem.girth_area_factor = 5.f; shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-1000,-400); shoot_parameters_mainstem.internode_length_max = 0.26; @@ -2289,7 +2412,7 @@ void PlantArchitecture::initializeSoybeanShoots() { shoot_parameters_trifoliate.gravitropic_curvature = 400; shoot_parameters_trifoliate.phyllochron_min = 2; - shoot_parameters_trifoliate.elongation_rate = 0.1; + shoot_parameters_trifoliate.elongation_rate_max = 0.1; shoot_parameters_trifoliate.girth_area_factor = 2.f; shoot_parameters_trifoliate.vegetative_bud_break_time = 15; shoot_parameters_trifoliate.vegetative_bud_break_probability_min = 0.05; @@ -2421,7 +2544,7 @@ void PlantArchitecture::initializeStrawberryShoots() { shoot_parameters.tortuosity = 0; shoot_parameters.phyllochron_min = 2; - shoot_parameters.elongation_rate = 0.1; + shoot_parameters.elongation_rate_max = 0.1; shoot_parameters.girth_area_factor = 2.f; shoot_parameters.vegetative_bud_break_time = 15; shoot_parameters.vegetative_bud_break_probability_min = 0.1; @@ -2510,7 +2633,7 @@ void PlantArchitecture::initializeSugarbeetShoots() { shoot_parameters_mainstem.phytomer_parameters = phytomer_parameters_sugarbeet; shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0; shoot_parameters_mainstem.phyllochron_min = 2; - shoot_parameters_mainstem.elongation_rate = 0.1; + shoot_parameters_mainstem.elongation_rate_max = 0.1; shoot_parameters_mainstem.girth_area_factor = 20.f; shoot_parameters_mainstem.gravitropic_curvature = 10; shoot_parameters_mainstem.internode_length_max = 0.001; @@ -2626,7 +2749,7 @@ void PlantArchitecture::initializeTomatoShoots() { shoot_parameters.tortuosity = 3; shoot_parameters.phyllochron_min = 2; - shoot_parameters.elongation_rate = 0.1; + shoot_parameters.elongation_rate_max = 0.1; shoot_parameters.girth_area_factor = 3.f; shoot_parameters.vegetative_bud_break_time = 10; shoot_parameters.vegetative_bud_break_probability_min = 0.15; @@ -2748,7 +2871,7 @@ void PlantArchitecture::initializeWalnutTreeShoots(){ shoot_parameters_proleptic.max_nodes = 30; shoot_parameters_proleptic.max_nodes_per_season = 15; shoot_parameters_proleptic.phyllochron_min = 2.; - shoot_parameters_proleptic.elongation_rate = 0.15; + shoot_parameters_proleptic.elongation_rate_max = 0.15; shoot_parameters_proleptic.girth_area_factor = 10.f; shoot_parameters_proleptic.vegetative_bud_break_probability_min = 0.05; shoot_parameters_proleptic.vegetative_bud_break_probability_decay_rate = 0.6; @@ -2890,7 +3013,7 @@ void PlantArchitecture::initializeWheatShoots() { shoot_parameters_mainstem.vegetative_bud_break_probability_min = 0; shoot_parameters_mainstem.flower_bud_break_probability = 1; shoot_parameters_mainstem.phyllochron_min = 2; - shoot_parameters_mainstem.elongation_rate = 0.1; + shoot_parameters_mainstem.elongation_rate_max = 0.1; shoot_parameters_mainstem.girth_area_factor = 6.f; shoot_parameters_mainstem.gravitropic_curvature.uniformDistribution(-500,-200); shoot_parameters_mainstem.flowers_require_dormancy = false; diff --git a/plugins/radiation/CMakeLists.txt b/plugins/radiation/CMakeLists.txt index 798986170..34276fffa 100755 --- a/plugins/radiation/CMakeLists.txt +++ b/plugins/radiation/CMakeLists.txt @@ -77,7 +77,12 @@ else() set( OPTIX_COMPILE_OPTIMIZATION_LEVEL_3 ON ) endif() -set( CUDA_SOURCES "src/primitiveIntersection.cu;src/rayGeneration.cu;src/rayHit.cu;" ) +set( CUDA_SOURCES + src/primitiveIntersection.cu + src/rayGeneration.cu + src/rayHit.cu +) + cuda_compile_ptx( cuda_ptx_files ${CUDA_SOURCES} ) add_custom_target(ptx ALL DEPENDS ${cuda_ptx_files} ${CUDA_SOURCES} ${OPTIX_LIBRARIES} SOURCES ${CUDA_SOURCES} ) add_dependencies( radiation ptx ) @@ -89,6 +94,29 @@ add_custom_command( TARGET ptx POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMA add_custom_command( TARGET ptx POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/plugins/radiation/cuda_compile_ptx_1_generated_rayHit.cu.ptx ${CMAKE_BINARY_DIR}/plugins/radiation/cuda_compile_ptx_generated_rayHit.cu.ptx DEPENDS ${CMAKE_BINARY_DIR}/plugins/radiation/cuda_compile_ptx_1_generated_rayHit.cu.ptx ) endif() +# Define a CUDA object library (makes CLion aware of CUDA files) +#add_library(CudaPTX OBJECT ${CUDA_SOURCES}) +#set_target_properties(CudaPTX PROPERTIES CUDA_SEPARABLE_COMPILATION ON) + +# Custom target to generate PTX files +#set(PTX_FILES) +#foreach(CU_FILE ${CUDA_SOURCES}) +# get_filename_component(CU_NAME ${CU_FILE} NAME_WE) +# set(PTX_FILE ${CMAKE_BINARY_DIR}/plugins/radiation/${CU_NAME}.ptx) +# add_custom_command( +# OUTPUT ${PTX_FILE} +# COMMAND ${CUDA_NVCC_EXECUTABLE} --ptx ${CMAKE_CURRENT_SOURCE_DIR}/${CU_FILE} -o ${PTX_FILE} +# -I${OPTIX_PATH}include -I${CMAKE_CURRENT_SOURCE_DIR}/include +# DEPENDS ${CU_FILE} +# ) +# list(APPEND PTX_FILES ${PTX_FILE}) +#endforeach() + +#add_custom_target(ptx ALL DEPENDS ${PTX_FILES}) + +# Ensure main project depends on PTX target +#add_dependencies(radiation ptx) + file( COPY include/disk.png DESTINATION ${CMAKE_BINARY_DIR}/plugins/radiation/) file( COPY spectral_data DESTINATION ${CMAKE_BINARY_DIR}/plugins/radiation/ ) file( COPY camera_light_models DESTINATION ${CMAKE_BINARY_DIR}/plugins/radiation/ ) \ No newline at end of file diff --git a/plugins/radiation/include/RadiationModel.h b/plugins/radiation/include/RadiationModel.h index c023ddeea..241ae8017 100755 --- a/plugins/radiation/include/RadiationModel.h +++ b/plugins/radiation/include/RadiationModel.h @@ -124,7 +124,6 @@ struct RadiationBand{ diffuseDistNorm = 1.f; emissionFlag = true; wavebandBounds = helios::make_vec2(0,0); - radiativepropertiesinitialized = false; } //! Label for band @@ -163,9 +162,6 @@ struct RadiationBand{ //! Waveband range of band helios::vec2 wavebandBounds; - //! Flag to indicate whether radiative bands have been initialized for this band - bool radiativepropertiesinitialized; - private: @@ -1050,7 +1046,7 @@ class RadiationModel{ std::map radiation_bands; - std::vector scattering_iterations_needed; + std::map scattering_iterations_needed; // --- radiation source variables --- // @@ -1172,7 +1168,7 @@ class RadiationModel{ /** This function should be called anytime primitive radiative properties are modified. If radiative properties were not set in the Context, default radiative properties will be applied (black body). \note \ref updateRadiativeProperties() must be called before simulation can be run */ - void updateRadiativeProperties( const std::vector &labels ); + void updateRadiativeProperties(); //! Load Context global data corresponding to spectral data /** @@ -1389,8 +1385,11 @@ class RadiationModel{ RTvariable max_scatters_RTvariable; RTbuffer max_scatters_RTbuffer; - //! Number of radiative bands - RTvariable Nbands_RTvariable; + //! Number of radiative bands in the radiation model + RTvariable Nbands_global_RTvariable; + + //! Number of radiative bands in the current launch + RTvariable Nbands_launch_RTvariable; //! Flag to disable launches for certain bands RTvariable band_launch_flag_RTvariable; @@ -1643,6 +1642,8 @@ class RadiationModel{ */ bool isgeometryinitialized; + bool radiativepropertiesneedupdate = true; + std::vector isbandpropertyinitialized; bool islightvisualizationenabled = false; diff --git a/plugins/radiation/spectral_data/leaf_surface_spectral_library.xml b/plugins/radiation/spectral_data/leaf_surface_spectral_library.xml index b071b7cf4..fe96dd886 100644 --- a/plugins/radiation/spectral_data/leaf_surface_spectral_library.xml +++ b/plugins/radiation/spectral_data/leaf_surface_spectral_library.xml @@ -68838,10 +68838,4314 @@ 2500 0.0997066666666667 + + + 350 0.323 + 351 0.312 + 352 0.307 + 353 0.306 + 354 0.306 + 355 0.296 + 356 0.289 + 357 0.288 + 358 0.290 + 359 0.291 + 360 0.283 + 361 0.278 + 362 0.275 + 363 0.273 + 364 0.272 + 365 0.270 + 366 0.258 + 367 0.247 + 368 0.242 + 369 0.239 + 370 0.233 + 371 0.221 + 372 0.216 + 373 0.218 + 374 0.218 + 375 0.215 + 376 0.211 + 377 0.211 + 378 0.213 + 379 0.214 + 380 0.213 + 381 0.209 + 382 0.199 + 383 0.190 + 384 0.181 + 385 0.171 + 386 0.165 + 387 0.163 + 388 0.163 + 389 0.165 + 390 0.167 + 391 0.168 + 392 0.167 + 393 0.161 + 394 0.157 + 395 0.153 + 396 0.147 + 397 0.140 + 398 0.133 + 399 0.129 + 400 0.128 + 401 0.127 + 402 0.122 + 403 0.116 + 404 0.112 + 405 0.109 + 406 0.108 + 407 0.106 + 408 0.103 + 409 0.101 + 410 0.101 + 411 0.100 + 412 0.099 + 413 0.097 + 414 0.095 + 415 0.094 + 416 0.096 + 417 0.099 + 418 0.099 + 419 0.100 + 420 0.101 + 421 0.098 + 422 0.094 + 423 0.091 + 424 0.091 + 425 0.090 + 426 0.090 + 427 0.090 + 428 0.090 + 429 0.088 + 430 0.087 + 431 0.087 + 432 0.089 + 433 0.089 + 434 0.088 + 435 0.087 + 436 0.085 + 437 0.084 + 438 0.084 + 439 0.084 + 440 0.084 + 441 0.086 + 442 0.088 + 443 0.090 + 444 0.093 + 445 0.093 + 446 0.090 + 447 0.090 + 448 0.090 + 449 0.090 + 450 0.090 + 451 0.090 + 452 0.091 + 453 0.094 + 454 0.094 + 455 0.090 + 456 0.090 + 457 0.091 + 458 0.094 + 459 0.094 + 460 0.093 + 461 0.091 + 462 0.093 + 463 0.094 + 464 0.091 + 465 0.092 + 466 0.094 + 467 0.096 + 468 0.096 + 469 0.095 + 470 0.097 + 471 0.099 + 472 0.099 + 473 0.097 + 474 0.096 + 475 0.095 + 476 0.095 + 477 0.096 + 478 0.096 + 479 0.096 + 480 0.095 + 481 0.095 + 482 0.094 + 483 0.094 + 484 0.095 + 485 0.094 + 486 0.094 + 487 0.095 + 488 0.094 + 489 0.094 + 490 0.094 + 491 0.095 + 492 0.094 + 493 0.094 + 494 0.095 + 495 0.096 + 496 0.096 + 497 0.097 + 498 0.096 + 499 0.096 + 500 0.097 + 501 0.098 + 502 0.098 + 503 0.098 + 504 0.099 + 505 0.099 + 506 0.100 + 507 0.100 + 508 0.100 + 509 0.101 + 510 0.102 + 511 0.104 + 512 0.105 + 513 0.106 + 514 0.106 + 515 0.107 + 516 0.109 + 517 0.111 + 518 0.113 + 519 0.114 + 520 0.116 + 521 0.118 + 522 0.120 + 523 0.122 + 524 0.124 + 525 0.126 + 526 0.128 + 527 0.130 + 528 0.133 + 529 0.135 + 530 0.136 + 531 0.137 + 532 0.138 + 533 0.141 + 534 0.142 + 535 0.144 + 536 0.145 + 537 0.145 + 538 0.146 + 539 0.146 + 540 0.147 + 541 0.149 + 542 0.149 + 543 0.149 + 544 0.150 + 545 0.151 + 546 0.151 + 547 0.152 + 548 0.153 + 549 0.153 + 550 0.153 + 551 0.154 + 552 0.154 + 553 0.154 + 554 0.154 + 555 0.154 + 556 0.153 + 557 0.152 + 558 0.152 + 559 0.152 + 560 0.150 + 561 0.150 + 562 0.149 + 563 0.148 + 564 0.147 + 565 0.146 + 566 0.145 + 567 0.143 + 568 0.142 + 569 0.140 + 570 0.139 + 571 0.138 + 572 0.137 + 573 0.135 + 574 0.134 + 575 0.133 + 576 0.131 + 577 0.130 + 578 0.129 + 579 0.129 + 580 0.128 + 581 0.127 + 582 0.126 + 583 0.125 + 584 0.125 + 585 0.125 + 586 0.124 + 587 0.124 + 588 0.123 + 589 0.123 + 590 0.123 + 591 0.123 + 592 0.123 + 593 0.123 + 594 0.122 + 595 0.122 + 596 0.122 + 597 0.122 + 598 0.122 + 599 0.122 + 600 0.121 + 601 0.121 + 602 0.121 + 603 0.120 + 604 0.120 + 605 0.119 + 606 0.119 + 607 0.118 + 608 0.117 + 609 0.117 + 610 0.116 + 611 0.116 + 612 0.116 + 613 0.115 + 614 0.114 + 615 0.114 + 616 0.113 + 617 0.113 + 618 0.112 + 619 0.112 + 620 0.112 + 621 0.112 + 622 0.111 + 623 0.111 + 624 0.111 + 625 0.111 + 626 0.111 + 627 0.111 + 628 0.111 + 629 0.111 + 630 0.111 + 631 0.111 + 632 0.111 + 633 0.111 + 634 0.111 + 635 0.111 + 636 0.111 + 637 0.111 + 638 0.111 + 639 0.110 + 640 0.110 + 641 0.110 + 642 0.110 + 643 0.109 + 644 0.109 + 645 0.109 + 646 0.109 + 647 0.108 + 648 0.108 + 649 0.107 + 650 0.107 + 651 0.107 + 652 0.106 + 653 0.106 + 654 0.105 + 655 0.105 + 656 0.105 + 657 0.104 + 658 0.104 + 659 0.104 + 660 0.103 + 661 0.103 + 662 0.102 + 663 0.102 + 664 0.102 + 665 0.102 + 666 0.102 + 667 0.102 + 668 0.102 + 669 0.101 + 670 0.101 + 671 0.101 + 672 0.101 + 673 0.101 + 674 0.102 + 675 0.101 + 676 0.102 + 677 0.102 + 678 0.102 + 679 0.103 + 680 0.103 + 681 0.103 + 682 0.104 + 683 0.104 + 684 0.104 + 685 0.105 + 686 0.106 + 687 0.107 + 688 0.107 + 689 0.108 + 690 0.110 + 691 0.111 + 692 0.113 + 693 0.116 + 694 0.119 + 695 0.123 + 696 0.128 + 697 0.133 + 698 0.138 + 699 0.144 + 700 0.151 + 701 0.159 + 702 0.167 + 703 0.175 + 704 0.184 + 705 0.193 + 706 0.202 + 707 0.212 + 708 0.221 + 709 0.230 + 710 0.240 + 711 0.250 + 712 0.259 + 713 0.270 + 714 0.280 + 715 0.290 + 716 0.300 + 717 0.311 + 718 0.320 + 719 0.330 + 720 0.340 + 721 0.350 + 722 0.359 + 723 0.369 + 724 0.378 + 725 0.387 + 726 0.396 + 727 0.404 + 728 0.412 + 729 0.420 + 730 0.428 + 731 0.435 + 732 0.442 + 733 0.449 + 734 0.455 + 735 0.461 + 736 0.466 + 737 0.471 + 738 0.476 + 739 0.481 + 740 0.485 + 741 0.490 + 742 0.494 + 743 0.497 + 744 0.501 + 745 0.505 + 746 0.508 + 747 0.511 + 748 0.513 + 749 0.516 + 750 0.518 + 751 0.520 + 752 0.522 + 753 0.524 + 754 0.526 + 755 0.527 + 756 0.528 + 757 0.529 + 758 0.530 + 759 0.531 + 760 0.532 + 761 0.532 + 762 0.533 + 763 0.534 + 764 0.535 + 765 0.536 + 766 0.537 + 767 0.537 + 768 0.538 + 769 0.538 + 770 0.539 + 771 0.539 + 772 0.539 + 773 0.540 + 774 0.540 + 775 0.540 + 776 0.541 + 777 0.541 + 778 0.541 + 779 0.541 + 780 0.541 + 781 0.542 + 782 0.542 + 783 0.542 + 784 0.543 + 785 0.543 + 786 0.543 + 787 0.543 + 788 0.543 + 789 0.544 + 790 0.544 + 791 0.544 + 792 0.544 + 793 0.544 + 794 0.544 + 795 0.544 + 796 0.545 + 797 0.545 + 798 0.545 + 799 0.545 + 800 0.545 + 801 0.545 + 802 0.546 + 803 0.546 + 804 0.546 + 805 0.546 + 806 0.546 + 807 0.546 + 808 0.546 + 809 0.546 + 810 0.546 + 811 0.546 + 812 0.546 + 813 0.546 + 814 0.546 + 815 0.546 + 816 0.546 + 817 0.546 + 818 0.546 + 819 0.547 + 820 0.547 + 821 0.547 + 822 0.547 + 823 0.548 + 824 0.548 + 825 0.548 + 826 0.549 + 827 0.549 + 828 0.548 + 829 0.548 + 830 0.547 + 831 0.548 + 832 0.548 + 833 0.548 + 834 0.548 + 835 0.548 + 836 0.549 + 837 0.550 + 838 0.550 + 839 0.550 + 840 0.550 + 841 0.550 + 842 0.551 + 843 0.550 + 844 0.550 + 845 0.550 + 846 0.550 + 847 0.550 + 848 0.551 + 849 0.551 + 850 0.550 + 851 0.550 + 852 0.551 + 853 0.551 + 854 0.551 + 855 0.552 + 856 0.551 + 857 0.552 + 858 0.552 + 859 0.552 + 860 0.552 + 861 0.551 + 862 0.551 + 863 0.551 + 864 0.551 + 865 0.551 + 866 0.551 + 867 0.552 + 868 0.552 + 869 0.551 + 870 0.551 + 871 0.551 + 872 0.552 + 873 0.552 + 874 0.551 + 875 0.551 + 876 0.552 + 877 0.551 + 878 0.552 + 879 0.551 + 880 0.551 + 881 0.551 + 882 0.551 + 883 0.550 + 884 0.552 + 885 0.551 + 886 0.550 + 887 0.551 + 888 0.552 + 889 0.551 + 890 0.551 + 891 0.552 + 892 0.551 + 893 0.552 + 894 0.551 + 895 0.551 + 896 0.551 + 897 0.551 + 898 0.551 + 899 0.550 + 900 0.550 + 901 0.551 + 902 0.551 + 903 0.550 + 904 0.550 + 905 0.550 + 906 0.551 + 907 0.550 + 908 0.550 + 909 0.550 + 910 0.549 + 911 0.550 + 912 0.551 + 913 0.549 + 914 0.550 + 915 0.551 + 916 0.550 + 917 0.550 + 918 0.551 + 919 0.551 + 920 0.551 + 921 0.550 + 922 0.550 + 923 0.551 + 924 0.551 + 925 0.549 + 926 0.550 + 927 0.550 + 928 0.548 + 929 0.547 + 930 0.549 + 931 0.547 + 932 0.547 + 933 0.548 + 934 0.548 + 935 0.547 + 936 0.548 + 937 0.548 + 938 0.546 + 939 0.548 + 940 0.545 + 941 0.544 + 942 0.544 + 943 0.545 + 944 0.545 + 945 0.546 + 946 0.546 + 947 0.546 + 948 0.545 + 949 0.544 + 950 0.543 + 951 0.542 + 952 0.542 + 953 0.540 + 954 0.539 + 955 0.539 + 956 0.536 + 957 0.537 + 958 0.538 + 959 0.536 + 960 0.535 + 961 0.535 + 962 0.536 + 963 0.534 + 964 0.534 + 965 0.536 + 966 0.536 + 967 0.534 + 968 0.536 + 969 0.538 + 970 0.537 + 971 0.537 + 972 0.537 + 973 0.537 + 974 0.537 + 975 0.537 + 976 0.538 + 977 0.538 + 978 0.538 + 979 0.538 + 980 0.538 + 981 0.539 + 982 0.539 + 983 0.539 + 984 0.540 + 985 0.540 + 986 0.540 + 987 0.541 + 988 0.541 + 989 0.541 + 990 0.541 + 991 0.542 + 992 0.542 + 993 0.542 + 994 0.542 + 995 0.542 + 996 0.542 + 997 0.542 + 998 0.542 + 999 0.542 + 1000 0.542 + 1001 0.543 + 1002 0.543 + 1003 0.543 + 1004 0.543 + 1005 0.543 + 1006 0.543 + 1007 0.543 + 1008 0.542 + 1009 0.542 + 1010 0.542 + 1011 0.543 + 1012 0.543 + 1013 0.543 + 1014 0.543 + 1015 0.544 + 1016 0.544 + 1017 0.545 + 1018 0.545 + 1019 0.546 + 1020 0.547 + 1021 0.547 + 1022 0.547 + 1023 0.547 + 1024 0.547 + 1025 0.547 + 1026 0.547 + 1027 0.547 + 1028 0.547 + 1029 0.548 + 1030 0.547 + 1031 0.547 + 1032 0.547 + 1033 0.548 + 1034 0.548 + 1035 0.549 + 1036 0.549 + 1037 0.550 + 1038 0.550 + 1039 0.551 + 1040 0.551 + 1041 0.551 + 1042 0.551 + 1043 0.551 + 1044 0.550 + 1045 0.551 + 1046 0.551 + 1047 0.551 + 1048 0.551 + 1049 0.551 + 1050 0.551 + 1051 0.551 + 1052 0.551 + 1053 0.551 + 1054 0.552 + 1055 0.552 + 1056 0.552 + 1057 0.552 + 1058 0.552 + 1059 0.553 + 1060 0.553 + 1061 0.552 + 1062 0.552 + 1063 0.551 + 1064 0.551 + 1065 0.550 + 1066 0.550 + 1067 0.550 + 1068 0.550 + 1069 0.551 + 1070 0.551 + 1071 0.552 + 1072 0.552 + 1073 0.552 + 1074 0.553 + 1075 0.553 + 1076 0.553 + 1077 0.553 + 1078 0.552 + 1079 0.552 + 1080 0.552 + 1081 0.552 + 1082 0.552 + 1083 0.552 + 1084 0.552 + 1085 0.552 + 1086 0.552 + 1087 0.552 + 1088 0.552 + 1089 0.552 + 1090 0.552 + 1091 0.552 + 1092 0.552 + 1093 0.552 + 1094 0.551 + 1095 0.551 + 1096 0.551 + 1097 0.551 + 1098 0.551 + 1099 0.550 + 1100 0.550 + 1101 0.550 + 1102 0.550 + 1103 0.550 + 1104 0.550 + 1105 0.550 + 1106 0.550 + 1107 0.550 + 1108 0.549 + 1109 0.549 + 1110 0.548 + 1111 0.548 + 1112 0.548 + 1113 0.548 + 1114 0.548 + 1115 0.548 + 1116 0.548 + 1117 0.548 + 1118 0.548 + 1119 0.548 + 1120 0.548 + 1121 0.547 + 1122 0.547 + 1123 0.546 + 1124 0.546 + 1125 0.545 + 1126 0.544 + 1127 0.544 + 1128 0.543 + 1129 0.543 + 1130 0.543 + 1131 0.542 + 1132 0.541 + 1133 0.540 + 1134 0.539 + 1135 0.538 + 1136 0.537 + 1137 0.536 + 1138 0.535 + 1139 0.534 + 1140 0.533 + 1141 0.532 + 1142 0.530 + 1143 0.529 + 1144 0.527 + 1145 0.525 + 1146 0.523 + 1147 0.521 + 1148 0.520 + 1149 0.519 + 1150 0.517 + 1151 0.516 + 1152 0.515 + 1153 0.514 + 1154 0.514 + 1155 0.513 + 1156 0.512 + 1157 0.512 + 1158 0.511 + 1159 0.511 + 1160 0.510 + 1161 0.510 + 1162 0.510 + 1163 0.509 + 1164 0.509 + 1165 0.508 + 1166 0.508 + 1167 0.508 + 1168 0.508 + 1169 0.508 + 1170 0.508 + 1171 0.509 + 1172 0.509 + 1173 0.509 + 1174 0.509 + 1175 0.510 + 1176 0.510 + 1177 0.510 + 1178 0.510 + 1179 0.509 + 1180 0.509 + 1181 0.509 + 1182 0.509 + 1183 0.509 + 1184 0.509 + 1185 0.509 + 1186 0.509 + 1187 0.509 + 1188 0.509 + 1189 0.509 + 1190 0.509 + 1191 0.509 + 1192 0.508 + 1193 0.508 + 1194 0.508 + 1195 0.507 + 1196 0.507 + 1197 0.507 + 1198 0.508 + 1199 0.508 + 1200 0.509 + 1201 0.509 + 1202 0.509 + 1203 0.509 + 1204 0.510 + 1205 0.510 + 1206 0.510 + 1207 0.510 + 1208 0.511 + 1209 0.511 + 1210 0.511 + 1211 0.512 + 1212 0.512 + 1213 0.513 + 1214 0.513 + 1215 0.513 + 1216 0.514 + 1217 0.514 + 1218 0.514 + 1219 0.514 + 1220 0.515 + 1221 0.515 + 1222 0.515 + 1223 0.516 + 1224 0.516 + 1225 0.516 + 1226 0.517 + 1227 0.517 + 1228 0.517 + 1229 0.517 + 1230 0.517 + 1231 0.517 + 1232 0.517 + 1233 0.517 + 1234 0.517 + 1235 0.517 + 1236 0.517 + 1237 0.517 + 1238 0.517 + 1239 0.517 + 1240 0.517 + 1241 0.517 + 1242 0.517 + 1243 0.518 + 1244 0.518 + 1245 0.518 + 1246 0.519 + 1247 0.519 + 1248 0.519 + 1249 0.519 + 1250 0.520 + 1251 0.520 + 1252 0.520 + 1253 0.520 + 1254 0.520 + 1255 0.520 + 1256 0.520 + 1257 0.520 + 1258 0.520 + 1259 0.520 + 1260 0.520 + 1261 0.520 + 1262 0.519 + 1263 0.519 + 1264 0.519 + 1265 0.519 + 1266 0.519 + 1267 0.519 + 1268 0.519 + 1269 0.519 + 1270 0.519 + 1271 0.519 + 1272 0.518 + 1273 0.518 + 1274 0.518 + 1275 0.518 + 1276 0.518 + 1277 0.518 + 1278 0.518 + 1279 0.518 + 1280 0.518 + 1281 0.518 + 1282 0.518 + 1283 0.517 + 1284 0.517 + 1285 0.516 + 1286 0.516 + 1287 0.515 + 1288 0.515 + 1289 0.515 + 1290 0.514 + 1291 0.514 + 1292 0.514 + 1293 0.513 + 1294 0.513 + 1295 0.513 + 1296 0.512 + 1297 0.512 + 1298 0.511 + 1299 0.511 + 1300 0.510 + 1301 0.510 + 1302 0.509 + 1303 0.508 + 1304 0.507 + 1305 0.506 + 1306 0.505 + 1307 0.505 + 1308 0.504 + 1309 0.503 + 1310 0.501 + 1311 0.500 + 1312 0.499 + 1313 0.498 + 1314 0.497 + 1315 0.497 + 1316 0.496 + 1317 0.495 + 1318 0.494 + 1319 0.493 + 1320 0.492 + 1321 0.491 + 1322 0.490 + 1323 0.489 + 1324 0.487 + 1325 0.486 + 1326 0.484 + 1327 0.483 + 1328 0.481 + 1329 0.479 + 1330 0.478 + 1331 0.476 + 1332 0.475 + 1333 0.474 + 1334 0.472 + 1335 0.471 + 1336 0.469 + 1337 0.467 + 1338 0.466 + 1339 0.464 + 1340 0.462 + 1341 0.460 + 1342 0.458 + 1343 0.456 + 1344 0.455 + 1345 0.453 + 1346 0.452 + 1347 0.451 + 1348 0.450 + 1349 0.448 + 1350 0.447 + 1351 0.445 + 1352 0.443 + 1353 0.441 + 1354 0.440 + 1355 0.438 + 1356 0.437 + 1357 0.435 + 1358 0.433 + 1359 0.432 + 1360 0.430 + 1361 0.429 + 1362 0.427 + 1363 0.425 + 1364 0.423 + 1365 0.421 + 1366 0.419 + 1367 0.417 + 1368 0.414 + 1369 0.412 + 1370 0.410 + 1371 0.407 + 1372 0.405 + 1373 0.402 + 1374 0.398 + 1375 0.395 + 1376 0.391 + 1377 0.388 + 1378 0.384 + 1379 0.380 + 1380 0.375 + 1381 0.370 + 1382 0.364 + 1383 0.359 + 1384 0.353 + 1385 0.346 + 1386 0.340 + 1387 0.334 + 1388 0.327 + 1389 0.321 + 1390 0.315 + 1391 0.308 + 1392 0.302 + 1393 0.295 + 1394 0.288 + 1395 0.282 + 1396 0.276 + 1397 0.270 + 1398 0.265 + 1399 0.259 + 1400 0.254 + 1401 0.249 + 1402 0.244 + 1403 0.239 + 1404 0.235 + 1405 0.230 + 1406 0.226 + 1407 0.222 + 1408 0.219 + 1409 0.215 + 1410 0.212 + 1411 0.210 + 1412 0.208 + 1413 0.206 + 1414 0.204 + 1415 0.203 + 1416 0.201 + 1417 0.200 + 1418 0.198 + 1419 0.196 + 1420 0.194 + 1421 0.193 + 1422 0.192 + 1423 0.191 + 1424 0.191 + 1425 0.190 + 1426 0.190 + 1427 0.190 + 1428 0.189 + 1429 0.189 + 1430 0.188 + 1431 0.187 + 1432 0.186 + 1433 0.186 + 1434 0.186 + 1435 0.187 + 1436 0.187 + 1437 0.187 + 1438 0.187 + 1439 0.188 + 1440 0.188 + 1441 0.188 + 1442 0.188 + 1443 0.189 + 1444 0.189 + 1445 0.189 + 1446 0.189 + 1447 0.189 + 1448 0.190 + 1449 0.190 + 1450 0.191 + 1451 0.191 + 1452 0.192 + 1453 0.192 + 1454 0.192 + 1455 0.192 + 1456 0.192 + 1457 0.191 + 1458 0.191 + 1459 0.191 + 1460 0.192 + 1461 0.193 + 1462 0.194 + 1463 0.195 + 1464 0.195 + 1465 0.196 + 1466 0.197 + 1467 0.198 + 1468 0.198 + 1469 0.199 + 1470 0.200 + 1471 0.201 + 1472 0.203 + 1473 0.204 + 1474 0.205 + 1475 0.207 + 1476 0.209 + 1477 0.210 + 1478 0.212 + 1479 0.214 + 1480 0.215 + 1481 0.216 + 1482 0.217 + 1483 0.218 + 1484 0.219 + 1485 0.220 + 1486 0.221 + 1487 0.222 + 1488 0.223 + 1489 0.225 + 1490 0.226 + 1491 0.227 + 1492 0.228 + 1493 0.230 + 1494 0.232 + 1495 0.233 + 1496 0.235 + 1497 0.236 + 1498 0.238 + 1499 0.239 + 1500 0.240 + 1501 0.242 + 1502 0.243 + 1503 0.244 + 1504 0.246 + 1505 0.247 + 1506 0.249 + 1507 0.250 + 1508 0.251 + 1509 0.252 + 1510 0.253 + 1511 0.254 + 1512 0.256 + 1513 0.258 + 1514 0.259 + 1515 0.261 + 1516 0.264 + 1517 0.265 + 1518 0.267 + 1519 0.268 + 1520 0.269 + 1521 0.270 + 1522 0.271 + 1523 0.272 + 1524 0.273 + 1525 0.275 + 1526 0.276 + 1527 0.278 + 1528 0.280 + 1529 0.281 + 1530 0.283 + 1531 0.285 + 1532 0.286 + 1533 0.287 + 1534 0.289 + 1535 0.290 + 1536 0.291 + 1537 0.293 + 1538 0.294 + 1539 0.295 + 1540 0.297 + 1541 0.298 + 1542 0.299 + 1543 0.301 + 1544 0.302 + 1545 0.303 + 1546 0.304 + 1547 0.305 + 1548 0.306 + 1549 0.308 + 1550 0.309 + 1551 0.310 + 1552 0.312 + 1553 0.313 + 1554 0.314 + 1555 0.315 + 1556 0.316 + 1557 0.317 + 1558 0.318 + 1559 0.319 + 1560 0.320 + 1561 0.322 + 1562 0.323 + 1563 0.324 + 1564 0.325 + 1565 0.326 + 1566 0.327 + 1567 0.328 + 1568 0.329 + 1569 0.329 + 1570 0.330 + 1571 0.332 + 1572 0.333 + 1573 0.333 + 1574 0.334 + 1575 0.335 + 1576 0.336 + 1577 0.337 + 1578 0.338 + 1579 0.339 + 1580 0.340 + 1581 0.341 + 1582 0.342 + 1583 0.342 + 1584 0.343 + 1585 0.344 + 1586 0.344 + 1587 0.345 + 1588 0.346 + 1589 0.347 + 1590 0.349 + 1591 0.350 + 1592 0.350 + 1593 0.351 + 1594 0.352 + 1595 0.352 + 1596 0.353 + 1597 0.353 + 1598 0.354 + 1599 0.354 + 1600 0.355 + 1601 0.356 + 1602 0.357 + 1603 0.357 + 1604 0.358 + 1605 0.359 + 1606 0.359 + 1607 0.360 + 1608 0.360 + 1609 0.360 + 1610 0.361 + 1611 0.361 + 1612 0.361 + 1613 0.362 + 1614 0.364 + 1615 0.365 + 1616 0.366 + 1617 0.367 + 1618 0.368 + 1619 0.368 + 1620 0.369 + 1621 0.369 + 1622 0.368 + 1623 0.368 + 1624 0.369 + 1625 0.369 + 1626 0.370 + 1627 0.370 + 1628 0.371 + 1629 0.371 + 1630 0.372 + 1631 0.372 + 1632 0.373 + 1633 0.373 + 1634 0.374 + 1635 0.375 + 1636 0.376 + 1637 0.377 + 1638 0.378 + 1639 0.378 + 1640 0.379 + 1641 0.379 + 1642 0.379 + 1643 0.379 + 1644 0.379 + 1645 0.379 + 1646 0.379 + 1647 0.379 + 1648 0.379 + 1649 0.380 + 1650 0.380 + 1651 0.380 + 1652 0.380 + 1653 0.380 + 1654 0.380 + 1655 0.380 + 1656 0.380 + 1657 0.380 + 1658 0.381 + 1659 0.381 + 1660 0.381 + 1661 0.381 + 1662 0.381 + 1663 0.381 + 1664 0.381 + 1665 0.381 + 1666 0.381 + 1667 0.381 + 1668 0.381 + 1669 0.381 + 1670 0.381 + 1671 0.381 + 1672 0.380 + 1673 0.380 + 1674 0.380 + 1675 0.379 + 1676 0.379 + 1677 0.379 + 1678 0.378 + 1679 0.378 + 1680 0.377 + 1681 0.377 + 1682 0.377 + 1683 0.376 + 1684 0.376 + 1685 0.376 + 1686 0.376 + 1687 0.376 + 1688 0.376 + 1689 0.375 + 1690 0.374 + 1691 0.373 + 1692 0.372 + 1693 0.371 + 1694 0.369 + 1695 0.368 + 1696 0.367 + 1697 0.366 + 1698 0.366 + 1699 0.366 + 1700 0.366 + 1701 0.366 + 1702 0.366 + 1703 0.365 + 1704 0.365 + 1705 0.364 + 1706 0.364 + 1707 0.364 + 1708 0.364 + 1709 0.364 + 1710 0.363 + 1711 0.362 + 1712 0.362 + 1713 0.362 + 1714 0.362 + 1715 0.361 + 1716 0.361 + 1717 0.361 + 1718 0.361 + 1719 0.361 + 1720 0.361 + 1721 0.361 + 1722 0.360 + 1723 0.360 + 1724 0.359 + 1725 0.357 + 1726 0.356 + 1727 0.355 + 1728 0.354 + 1729 0.353 + 1730 0.352 + 1731 0.352 + 1732 0.352 + 1733 0.352 + 1734 0.351 + 1735 0.351 + 1736 0.350 + 1737 0.350 + 1738 0.349 + 1739 0.348 + 1740 0.348 + 1741 0.347 + 1742 0.346 + 1743 0.345 + 1744 0.344 + 1745 0.344 + 1746 0.343 + 1747 0.343 + 1748 0.342 + 1749 0.341 + 1750 0.340 + 1751 0.340 + 1752 0.339 + 1753 0.338 + 1754 0.337 + 1755 0.336 + 1756 0.335 + 1757 0.333 + 1758 0.332 + 1759 0.331 + 1760 0.330 + 1761 0.329 + 1762 0.329 + 1763 0.329 + 1764 0.329 + 1765 0.329 + 1766 0.329 + 1767 0.328 + 1768 0.327 + 1769 0.326 + 1770 0.326 + 1771 0.326 + 1772 0.326 + 1773 0.325 + 1774 0.325 + 1775 0.324 + 1776 0.323 + 1777 0.323 + 1778 0.322 + 1779 0.321 + 1780 0.321 + 1781 0.321 + 1782 0.320 + 1783 0.319 + 1784 0.318 + 1785 0.316 + 1786 0.315 + 1787 0.314 + 1788 0.314 + 1789 0.314 + 1790 0.314 + 1791 0.315 + 1792 0.317 + 1793 0.318 + 1794 0.318 + 1795 0.317 + 1796 0.317 + 1797 0.316 + 1798 0.316 + 1799 0.315 + 1800 0.315 + 1801 0.315 + 1802 0.315 + 1803 0.315 + 1804 0.315 + 1805 0.315 + 1806 0.315 + 1807 0.316 + 1808 0.317 + 1809 0.318 + 1810 0.318 + 1811 0.319 + 1812 0.319 + 1813 0.319 + 1814 0.318 + 1815 0.318 + 1816 0.317 + 1817 0.316 + 1818 0.316 + 1819 0.316 + 1820 0.316 + 1821 0.316 + 1822 0.316 + 1823 0.316 + 1824 0.316 + 1825 0.315 + 1826 0.313 + 1827 0.311 + 1828 0.310 + 1829 0.310 + 1830 0.309 + 1831 0.309 + 1832 0.308 + 1833 0.308 + 1834 0.307 + 1835 0.306 + 1836 0.305 + 1837 0.305 + 1838 0.304 + 1839 0.303 + 1840 0.302 + 1841 0.301 + 1842 0.300 + 1843 0.299 + 1844 0.298 + 1845 0.297 + 1846 0.296 + 1847 0.295 + 1848 0.294 + 1849 0.292 + 1850 0.289 + 1851 0.286 + 1852 0.283 + 1853 0.281 + 1854 0.278 + 1855 0.276 + 1856 0.273 + 1857 0.271 + 1858 0.268 + 1859 0.265 + 1860 0.263 + 1861 0.260 + 1862 0.256 + 1863 0.253 + 1864 0.248 + 1865 0.244 + 1866 0.239 + 1867 0.233 + 1868 0.227 + 1869 0.222 + 1870 0.216 + 1871 0.211 + 1872 0.206 + 1873 0.201 + 1874 0.196 + 1875 0.191 + 1876 0.188 + 1877 0.185 + 1878 0.183 + 1879 0.180 + 1880 0.177 + 1881 0.168 + 1882 0.159 + 1883 0.149 + 1884 0.138 + 1885 0.125 + 1886 0.111 + 1887 0.090 + 1888 0.065 + 1889 0.048 + 1890 0.047 + 1891 0.046 + 1892 0.047 + 1893 0.055 + 1894 0.063 + 1895 0.066 + 1896 0.063 + 1897 0.061 + 1898 0.059 + 1899 0.057 + 1900 0.059 + 1901 0.074 + 1902 0.094 + 1903 0.103 + 1904 0.093 + 1905 0.075 + 1906 0.060 + 1907 0.045 + 1908 0.034 + 1909 0.034 + 1910 0.041 + 1911 0.052 + 1912 0.062 + 1913 0.073 + 1914 0.080 + 1915 0.077 + 1916 0.067 + 1917 0.059 + 1918 0.057 + 1919 0.058 + 1920 0.060 + 1921 0.063 + 1922 0.067 + 1923 0.068 + 1924 0.068 + 1925 0.066 + 1926 0.065 + 1927 0.064 + 1928 0.064 + 1929 0.065 + 1930 0.067 + 1931 0.069 + 1932 0.071 + 1933 0.071 + 1934 0.072 + 1935 0.073 + 1936 0.074 + 1937 0.077 + 1938 0.084 + 1939 0.092 + 1940 0.094 + 1941 0.090 + 1942 0.083 + 1943 0.074 + 1944 0.060 + 1945 0.049 + 1946 0.049 + 1947 0.058 + 1948 0.069 + 1949 0.081 + 1950 0.094 + 1951 0.101 + 1952 0.098 + 1953 0.090 + 1954 0.082 + 1955 0.072 + 1956 0.064 + 1957 0.062 + 1958 0.067 + 1959 0.073 + 1960 0.077 + 1961 0.079 + 1962 0.082 + 1963 0.084 + 1964 0.086 + 1965 0.087 + 1966 0.087 + 1967 0.087 + 1968 0.083 + 1969 0.074 + 1970 0.065 + 1971 0.062 + 1972 0.065 + 1973 0.070 + 1974 0.078 + 1975 0.088 + 1976 0.094 + 1977 0.095 + 1978 0.092 + 1979 0.089 + 1980 0.086 + 1981 0.083 + 1982 0.081 + 1983 0.081 + 1984 0.081 + 1985 0.083 + 1986 0.086 + 1987 0.091 + 1988 0.099 + 1989 0.110 + 1990 0.117 + 1991 0.119 + 1992 0.117 + 1993 0.114 + 1994 0.108 + 1995 0.102 + 1996 0.100 + 1997 0.102 + 1998 0.105 + 1999 0.105 + 2000 0.104 + 2001 0.103 + 2002 0.098 + 2003 0.093 + 2004 0.093 + 2005 0.097 + 2006 0.104 + 2007 0.110 + 2008 0.117 + 2009 0.121 + 2010 0.119 + 2011 0.114 + 2012 0.110 + 2013 0.109 + 2014 0.109 + 2015 0.110 + 2016 0.112 + 2017 0.114 + 2018 0.114 + 2019 0.110 + 2020 0.109 + 2021 0.112 + 2022 0.118 + 2023 0.122 + 2024 0.120 + 2025 0.116 + 2026 0.115 + 2027 0.115 + 2028 0.117 + 2029 0.122 + 2030 0.130 + 2031 0.135 + 2032 0.131 + 2033 0.122 + 2034 0.118 + 2035 0.121 + 2036 0.126 + 2037 0.130 + 2038 0.134 + 2039 0.136 + 2040 0.134 + 2041 0.130 + 2042 0.130 + 2043 0.139 + 2044 0.151 + 2045 0.154 + 2046 0.146 + 2047 0.135 + 2048 0.128 + 2049 0.123 + 2050 0.121 + 2051 0.125 + 2052 0.132 + 2053 0.137 + 2054 0.141 + 2055 0.143 + 2056 0.146 + 2057 0.148 + 2058 0.150 + 2059 0.148 + 2060 0.145 + 2061 0.143 + 2062 0.143 + 2063 0.144 + 2064 0.144 + 2065 0.144 + 2066 0.144 + 2067 0.143 + 2068 0.141 + 2069 0.139 + 2070 0.137 + 2071 0.136 + 2072 0.138 + 2073 0.148 + 2074 0.158 + 2075 0.162 + 2076 0.163 + 2077 0.160 + 2078 0.153 + 2079 0.142 + 2080 0.136 + 2081 0.136 + 2082 0.139 + 2083 0.144 + 2084 0.151 + 2085 0.157 + 2086 0.161 + 2087 0.164 + 2088 0.166 + 2089 0.169 + 2090 0.170 + 2091 0.167 + 2092 0.158 + 2093 0.152 + 2094 0.152 + 2095 0.156 + 2096 0.159 + 2097 0.163 + 2098 0.166 + 2099 0.165 + 2100 0.159 + 2101 0.154 + 2102 0.155 + 2103 0.160 + 2104 0.165 + 2105 0.171 + 2106 0.177 + 2107 0.181 + 2108 0.183 + 2109 0.183 + 2110 0.181 + 2111 0.177 + 2112 0.176 + 2113 0.182 + 2114 0.189 + 2115 0.188 + 2116 0.180 + 2117 0.173 + 2118 0.167 + 2119 0.163 + 2120 0.165 + 2121 0.180 + 2122 0.193 + 2123 0.194 + 2124 0.186 + 2125 0.178 + 2126 0.174 + 2127 0.171 + 2128 0.174 + 2129 0.184 + 2130 0.193 + 2131 0.192 + 2132 0.184 + 2133 0.178 + 2134 0.177 + 2135 0.180 + 2136 0.185 + 2137 0.194 + 2138 0.200 + 2139 0.193 + 2140 0.180 + 2141 0.174 + 2142 0.178 + 2143 0.186 + 2144 0.189 + 2145 0.190 + 2146 0.188 + 2147 0.182 + 2148 0.173 + 2149 0.173 + 2150 0.180 + 2151 0.189 + 2152 0.196 + 2153 0.203 + 2154 0.207 + 2155 0.207 + 2156 0.204 + 2157 0.201 + 2158 0.197 + 2159 0.194 + 2160 0.191 + 2161 0.189 + 2162 0.188 + 2163 0.188 + 2164 0.190 + 2165 0.193 + 2166 0.198 + 2167 0.202 + 2168 0.204 + 2169 0.203 + 2170 0.201 + 2171 0.196 + 2172 0.190 + 2173 0.182 + 2174 0.175 + 2175 0.173 + 2176 0.176 + 2177 0.181 + 2178 0.187 + 2179 0.195 + 2180 0.199 + 2181 0.200 + 2182 0.197 + 2183 0.193 + 2184 0.186 + 2185 0.180 + 2186 0.175 + 2187 0.172 + 2188 0.172 + 2189 0.176 + 2190 0.181 + 2191 0.186 + 2192 0.190 + 2193 0.194 + 2194 0.198 + 2195 0.202 + 2196 0.205 + 2197 0.207 + 2198 0.207 + 2199 0.203 + 2200 0.197 + 2201 0.190 + 2202 0.181 + 2203 0.175 + 2204 0.172 + 2205 0.173 + 2206 0.178 + 2207 0.188 + 2208 0.197 + 2209 0.199 + 2210 0.198 + 2211 0.194 + 2212 0.186 + 2213 0.179 + 2214 0.181 + 2215 0.187 + 2216 0.192 + 2217 0.197 + 2218 0.199 + 2219 0.195 + 2220 0.186 + 2221 0.178 + 2222 0.170 + 2223 0.164 + 2224 0.164 + 2225 0.169 + 2226 0.174 + 2227 0.178 + 2228 0.180 + 2229 0.179 + 2230 0.176 + 2231 0.175 + 2232 0.178 + 2233 0.183 + 2234 0.188 + 2235 0.194 + 2236 0.198 + 2237 0.199 + 2238 0.197 + 2239 0.193 + 2240 0.184 + 2241 0.177 + 2242 0.174 + 2243 0.172 + 2244 0.172 + 2245 0.175 + 2246 0.177 + 2247 0.174 + 2248 0.171 + 2249 0.172 + 2250 0.177 + 2251 0.181 + 2252 0.181 + 2253 0.180 + 2254 0.179 + 2255 0.179 + 2256 0.179 + 2257 0.179 + 2258 0.179 + 2259 0.177 + 2260 0.174 + 2261 0.171 + 2262 0.171 + 2263 0.172 + 2264 0.173 + 2265 0.174 + 2266 0.174 + 2267 0.172 + 2268 0.168 + 2269 0.165 + 2270 0.162 + 2271 0.160 + 2272 0.160 + 2273 0.162 + 2274 0.162 + 2275 0.161 + 2276 0.160 + 2277 0.159 + 2278 0.158 + 2279 0.159 + 2280 0.162 + 2281 0.162 + 2282 0.159 + 2283 0.154 + 2284 0.148 + 2285 0.141 + 2286 0.137 + 2287 0.137 + 2288 0.139 + 2289 0.135 + 2290 0.127 + 2291 0.121 + 2292 0.114 + 2293 0.109 + 2294 0.111 + 2295 0.117 + 2296 0.120 + 2297 0.119 + 2298 0.116 + 2299 0.113 + 2300 0.110 + 2301 0.110 + 2302 0.112 + 2303 0.113 + 2304 0.110 + 2305 0.105 + 2306 0.103 + 2307 0.102 + 2308 0.104 + 2309 0.111 + 2310 0.119 + 2311 0.123 + 2312 0.124 + 2313 0.123 + 2314 0.120 + 2315 0.116 + 2316 0.112 + 2317 0.107 + 2318 0.103 + 2319 0.100 + 2320 0.099 + 2321 0.100 + 2322 0.103 + 2323 0.106 + 2324 0.110 + 2325 0.113 + 2326 0.116 + 2327 0.119 + 2328 0.121 + 2329 0.121 + 2330 0.121 + 2331 0.119 + 2332 0.117 + 2333 0.115 + 2334 0.113 + 2335 0.112 + 2336 0.113 + 2337 0.114 + 2338 0.116 + 2339 0.117 + 2340 0.114 + 2341 0.105 + 2342 0.097 + 2343 0.093 + 2344 0.091 + 2345 0.093 + 2346 0.098 + 2347 0.103 + 2348 0.108 + 2349 0.111 + 2350 0.110 + 2351 0.105 + 2352 0.101 + 2353 0.096 + 2354 0.094 + 2355 0.101 + 2356 0.107 + 2357 0.105 + 2358 0.095 + 2359 0.085 + 2360 0.074 + 2361 0.066 + 2362 0.070 + 2363 0.079 + 2364 0.088 + 2365 0.098 + 2366 0.106 + 2367 0.111 + 2368 0.112 + 2369 0.106 + 2370 0.095 + 2371 0.087 + 2372 0.080 + 2373 0.080 + 2374 0.092 + 2375 0.106 + 2376 0.109 + 2377 0.103 + 2378 0.096 + 2379 0.085 + 2380 0.077 + 2381 0.075 + 2382 0.077 + 2383 0.077 + 2384 0.077 + 2385 0.075 + 2386 0.069 + 2387 0.063 + 2388 0.056 + 2389 0.049 + 2390 0.047 + 2391 0.050 + 2392 0.055 + 2393 0.065 + 2394 0.073 + 2395 0.070 + 2396 0.063 + 2397 0.061 + 2398 0.064 + 2399 0.067 + 2400 0.070 + 2401 0.073 + 2402 0.079 + 2403 0.085 + 2404 0.089 + 2405 0.093 + 2406 0.094 + 2407 0.095 + 2408 0.093 + 2409 0.086 + 2410 0.076 + 2411 0.069 + 2412 0.063 + 2413 0.056 + 2414 0.047 + 2415 0.039 + 2416 0.034 + 2417 0.032 + 2418 0.031 + 2419 0.033 + 2420 0.036 + 2421 0.041 + 2422 0.044 + 2423 0.035 + 2424 0.025 + 2425 0.030 + 2426 0.052 + 2427 0.066 + 2428 0.068 + 2429 0.069 + 2430 0.073 + 2431 0.077 + 2432 0.083 + 2433 0.090 + 2434 0.093 + 2435 0.092 + 2436 0.089 + 2437 0.083 + 2438 0.078 + 2439 0.075 + 2440 0.075 + 2441 0.074 + 2442 0.073 + 2443 0.069 + 2444 0.061 + 2445 0.053 + 2446 0.048 + 2447 0.050 + 2448 0.053 + 2449 0.067 + 2450 0.076 + 2451 0.078 + 2452 0.080 + 2453 0.085 + 2454 0.089 + 2455 0.086 + 2456 0.079 + 2457 0.072 + 2458 0.065 + 2459 0.055 + 2460 0.047 + 2461 0.047 + 2462 0.049 + 2463 0.049 + 2464 0.041 + 2465 0.035 + 2466 0.052 + 2467 0.074 + 2468 0.091 + 2469 0.103 + 2470 0.117 + 2471 0.131 + 2472 0.152 + 2473 0.160 + 2474 0.161 + 2475 0.159 + 2476 0.156 + 2477 0.149 + 2478 0.142 + 2479 0.118 + 2480 0.057 + 2481 0.024 + 2482 0.022 + 2483 0.035 + 2484 0.059 + 2485 0.078 + 2486 0.093 + 2487 0.110 + 2488 0.134 + 2489 0.169 + 2490 0.205 + 2491 0.228 + 2492 0.242 + 2493 0.248 + 2494 0.246 + 2495 0.254 + 2496 0.254 + 2497 0.250 + 2498 0.242 + 2499 0.227 + 2500 0.205 + - - - - + + + 350 0.183 + 351 0.175 + 352 0.168 + 353 0.162 + 354 0.156 + 355 0.150 + 356 0.145 + 357 0.141 + 358 0.137 + 359 0.135 + 360 0.135 + 361 0.137 + 362 0.138 + 363 0.139 + 364 0.138 + 365 0.134 + 366 0.128 + 367 0.121 + 368 0.115 + 369 0.110 + 370 0.106 + 371 0.103 + 372 0.099 + 373 0.095 + 374 0.092 + 375 0.090 + 376 0.089 + 377 0.090 + 378 0.090 + 379 0.085 + 380 0.082 + 381 0.079 + 382 0.076 + 383 0.074 + 384 0.073 + 385 0.071 + 386 0.069 + 387 0.068 + 388 0.067 + 389 0.067 + 390 0.068 + 391 0.067 + 392 0.067 + 393 0.067 + 394 0.065 + 395 0.059 + 396 0.056 + 397 0.051 + 398 0.045 + 399 0.042 + 400 0.040 + 401 0.036 + 402 0.037 + 403 0.038 + 404 0.039 + 405 0.038 + 406 0.037 + 407 0.038 + 408 0.037 + 409 0.034 + 410 0.032 + 411 0.032 + 412 0.031 + 413 0.030 + 414 0.030 + 415 0.031 + 416 0.031 + 417 0.029 + 418 0.026 + 419 0.025 + 420 0.025 + 421 0.024 + 422 0.024 + 423 0.024 + 424 0.023 + 425 0.022 + 426 0.020 + 427 0.019 + 428 0.018 + 429 0.018 + 430 0.019 + 431 0.020 + 432 0.018 + 433 0.016 + 434 0.014 + 435 0.012 + 436 0.012 + 437 0.013 + 438 0.013 + 439 0.013 + 440 0.012 + 441 0.013 + 442 0.014 + 443 0.014 + 444 0.014 + 445 0.014 + 446 0.013 + 447 0.013 + 448 0.012 + 449 0.011 + 450 0.011 + 451 0.011 + 452 0.010 + 453 0.010 + 454 0.010 + 455 0.008 + 456 0.008 + 457 0.009 + 458 0.010 + 459 0.009 + 460 0.007 + 461 0.007 + 462 0.008 + 463 0.009 + 464 0.008 + 465 0.009 + 466 0.010 + 467 0.009 + 468 0.010 + 469 0.011 + 470 0.012 + 471 0.011 + 472 0.010 + 473 0.010 + 474 0.010 + 475 0.010 + 476 0.009 + 477 0.008 + 478 0.008 + 479 0.008 + 480 0.008 + 481 0.007 + 482 0.007 + 483 0.007 + 484 0.007 + 485 0.006 + 486 0.006 + 487 0.007 + 488 0.006 + 489 0.006 + 490 0.007 + 491 0.006 + 492 0.006 + 493 0.006 + 494 0.007 + 495 0.007 + 496 0.008 + 497 0.008 + 498 0.007 + 499 0.007 + 500 0.008 + 501 0.008 + 502 0.008 + 503 0.007 + 504 0.008 + 505 0.009 + 506 0.009 + 507 0.010 + 508 0.010 + 509 0.011 + 510 0.011 + 511 0.011 + 512 0.012 + 513 0.013 + 514 0.014 + 515 0.015 + 516 0.016 + 517 0.017 + 518 0.018 + 519 0.020 + 520 0.021 + 521 0.022 + 522 0.024 + 523 0.026 + 524 0.027 + 525 0.029 + 526 0.031 + 527 0.032 + 528 0.033 + 529 0.035 + 530 0.036 + 531 0.038 + 532 0.039 + 533 0.040 + 534 0.041 + 535 0.042 + 536 0.043 + 537 0.044 + 538 0.044 + 539 0.044 + 540 0.045 + 541 0.045 + 542 0.046 + 543 0.046 + 544 0.046 + 545 0.047 + 546 0.047 + 547 0.048 + 548 0.048 + 549 0.048 + 550 0.048 + 551 0.048 + 552 0.049 + 553 0.049 + 554 0.049 + 555 0.049 + 556 0.048 + 557 0.048 + 558 0.048 + 559 0.047 + 560 0.047 + 561 0.046 + 562 0.045 + 563 0.044 + 564 0.043 + 565 0.042 + 566 0.042 + 567 0.041 + 568 0.040 + 569 0.039 + 570 0.038 + 571 0.036 + 572 0.035 + 573 0.034 + 574 0.033 + 575 0.032 + 576 0.031 + 577 0.030 + 578 0.029 + 579 0.028 + 580 0.028 + 581 0.028 + 582 0.027 + 583 0.027 + 584 0.026 + 585 0.025 + 586 0.025 + 587 0.024 + 588 0.024 + 589 0.024 + 590 0.023 + 591 0.023 + 592 0.023 + 593 0.023 + 594 0.023 + 595 0.023 + 596 0.022 + 597 0.022 + 598 0.022 + 599 0.022 + 600 0.022 + 601 0.022 + 602 0.021 + 603 0.021 + 604 0.021 + 605 0.021 + 606 0.020 + 607 0.019 + 608 0.019 + 609 0.019 + 610 0.018 + 611 0.018 + 612 0.017 + 613 0.017 + 614 0.017 + 615 0.016 + 616 0.015 + 617 0.015 + 618 0.015 + 619 0.015 + 620 0.014 + 621 0.014 + 622 0.014 + 623 0.014 + 624 0.014 + 625 0.014 + 626 0.014 + 627 0.013 + 628 0.013 + 629 0.013 + 630 0.014 + 631 0.014 + 632 0.014 + 633 0.013 + 634 0.013 + 635 0.013 + 636 0.013 + 637 0.013 + 638 0.013 + 639 0.012 + 640 0.012 + 641 0.012 + 642 0.011 + 643 0.011 + 644 0.010 + 645 0.010 + 646 0.010 + 647 0.009 + 648 0.009 + 649 0.009 + 650 0.009 + 651 0.008 + 652 0.008 + 653 0.008 + 654 0.008 + 655 0.007 + 656 0.007 + 657 0.007 + 658 0.007 + 659 0.006 + 660 0.006 + 661 0.006 + 662 0.006 + 663 0.005 + 664 0.006 + 665 0.005 + 666 0.005 + 667 0.005 + 668 0.005 + 669 0.005 + 670 0.005 + 671 0.005 + 672 0.004 + 673 0.004 + 674 0.004 + 675 0.005 + 676 0.005 + 677 0.005 + 678 0.005 + 679 0.005 + 680 0.005 + 681 0.005 + 682 0.005 + 683 0.005 + 684 0.005 + 685 0.006 + 686 0.006 + 687 0.006 + 688 0.007 + 689 0.008 + 690 0.009 + 691 0.011 + 692 0.013 + 693 0.015 + 694 0.018 + 695 0.022 + 696 0.026 + 697 0.030 + 698 0.035 + 699 0.040 + 700 0.046 + 701 0.052 + 702 0.059 + 703 0.065 + 704 0.073 + 705 0.079 + 706 0.087 + 707 0.094 + 708 0.102 + 709 0.109 + 710 0.117 + 711 0.125 + 712 0.133 + 713 0.141 + 714 0.149 + 715 0.157 + 716 0.165 + 717 0.174 + 718 0.182 + 719 0.190 + 720 0.198 + 721 0.205 + 722 0.213 + 723 0.222 + 724 0.230 + 725 0.237 + 726 0.244 + 727 0.251 + 728 0.258 + 729 0.265 + 730 0.271 + 731 0.277 + 732 0.283 + 733 0.289 + 734 0.294 + 735 0.299 + 736 0.304 + 737 0.308 + 738 0.312 + 739 0.316 + 740 0.320 + 741 0.323 + 742 0.327 + 743 0.331 + 744 0.334 + 745 0.336 + 746 0.339 + 747 0.341 + 748 0.344 + 749 0.346 + 750 0.348 + 751 0.350 + 752 0.352 + 753 0.354 + 754 0.355 + 755 0.357 + 756 0.358 + 757 0.358 + 758 0.359 + 759 0.360 + 760 0.361 + 761 0.362 + 762 0.363 + 763 0.363 + 764 0.364 + 765 0.365 + 766 0.366 + 767 0.366 + 768 0.367 + 769 0.367 + 770 0.368 + 771 0.368 + 772 0.369 + 773 0.369 + 774 0.369 + 775 0.370 + 776 0.370 + 777 0.370 + 778 0.371 + 779 0.371 + 780 0.371 + 781 0.371 + 782 0.372 + 783 0.372 + 784 0.372 + 785 0.373 + 786 0.373 + 787 0.373 + 788 0.373 + 789 0.373 + 790 0.374 + 791 0.374 + 792 0.374 + 793 0.374 + 794 0.375 + 795 0.375 + 796 0.375 + 797 0.375 + 798 0.375 + 799 0.376 + 800 0.376 + 801 0.376 + 802 0.376 + 803 0.377 + 804 0.377 + 805 0.377 + 806 0.377 + 807 0.377 + 808 0.377 + 809 0.377 + 810 0.377 + 811 0.377 + 812 0.378 + 813 0.378 + 814 0.378 + 815 0.378 + 816 0.378 + 817 0.379 + 818 0.379 + 819 0.378 + 820 0.378 + 821 0.379 + 822 0.380 + 823 0.380 + 824 0.380 + 825 0.380 + 826 0.380 + 827 0.380 + 828 0.380 + 829 0.380 + 830 0.380 + 831 0.380 + 832 0.380 + 833 0.380 + 834 0.380 + 835 0.381 + 836 0.382 + 837 0.382 + 838 0.382 + 839 0.382 + 840 0.382 + 841 0.382 + 842 0.382 + 843 0.382 + 844 0.382 + 845 0.382 + 846 0.382 + 847 0.383 + 848 0.383 + 849 0.384 + 850 0.383 + 851 0.383 + 852 0.383 + 853 0.384 + 854 0.384 + 855 0.384 + 856 0.384 + 857 0.384 + 858 0.385 + 859 0.385 + 860 0.385 + 861 0.384 + 862 0.385 + 863 0.385 + 864 0.386 + 865 0.386 + 866 0.385 + 867 0.385 + 868 0.386 + 869 0.385 + 870 0.385 + 871 0.386 + 872 0.386 + 873 0.386 + 874 0.387 + 875 0.387 + 876 0.387 + 877 0.387 + 878 0.387 + 879 0.387 + 880 0.387 + 881 0.387 + 882 0.387 + 883 0.388 + 884 0.388 + 885 0.387 + 886 0.387 + 887 0.388 + 888 0.388 + 889 0.388 + 890 0.388 + 891 0.388 + 892 0.388 + 893 0.388 + 894 0.388 + 895 0.388 + 896 0.389 + 897 0.389 + 898 0.388 + 899 0.388 + 900 0.388 + 901 0.389 + 902 0.388 + 903 0.389 + 904 0.388 + 905 0.388 + 906 0.389 + 907 0.389 + 908 0.389 + 909 0.388 + 910 0.388 + 911 0.388 + 912 0.388 + 913 0.388 + 914 0.388 + 915 0.389 + 916 0.390 + 917 0.389 + 918 0.389 + 919 0.389 + 920 0.390 + 921 0.390 + 922 0.390 + 923 0.390 + 924 0.390 + 925 0.390 + 926 0.390 + 927 0.389 + 928 0.389 + 929 0.389 + 930 0.389 + 931 0.389 + 932 0.388 + 933 0.388 + 934 0.388 + 935 0.387 + 936 0.388 + 937 0.388 + 938 0.388 + 939 0.390 + 940 0.388 + 941 0.388 + 942 0.389 + 943 0.388 + 944 0.387 + 945 0.387 + 946 0.386 + 947 0.387 + 948 0.387 + 949 0.386 + 950 0.386 + 951 0.386 + 952 0.385 + 953 0.385 + 954 0.383 + 955 0.382 + 956 0.382 + 957 0.381 + 958 0.381 + 959 0.380 + 960 0.381 + 961 0.382 + 962 0.381 + 963 0.381 + 964 0.380 + 965 0.381 + 966 0.382 + 967 0.380 + 968 0.379 + 969 0.381 + 970 0.381 + 971 0.380 + 972 0.380 + 973 0.380 + 974 0.380 + 975 0.380 + 976 0.380 + 977 0.379 + 978 0.379 + 979 0.379 + 980 0.379 + 981 0.379 + 982 0.379 + 983 0.379 + 984 0.380 + 985 0.380 + 986 0.380 + 987 0.381 + 988 0.381 + 989 0.382 + 990 0.382 + 991 0.383 + 992 0.384 + 993 0.384 + 994 0.385 + 995 0.386 + 996 0.386 + 997 0.386 + 998 0.387 + 999 0.387 + 1000 0.387 + 1001 0.387 + 1002 0.387 + 1003 0.387 + 1004 0.387 + 1005 0.388 + 1006 0.388 + 1007 0.388 + 1008 0.388 + 1009 0.389 + 1010 0.389 + 1011 0.389 + 1012 0.389 + 1013 0.390 + 1014 0.390 + 1015 0.389 + 1016 0.389 + 1017 0.390 + 1018 0.390 + 1019 0.390 + 1020 0.391 + 1021 0.391 + 1022 0.392 + 1023 0.392 + 1024 0.392 + 1025 0.393 + 1026 0.393 + 1027 0.393 + 1028 0.393 + 1029 0.393 + 1030 0.394 + 1031 0.394 + 1032 0.395 + 1033 0.395 + 1034 0.395 + 1035 0.395 + 1036 0.395 + 1037 0.395 + 1038 0.395 + 1039 0.395 + 1040 0.395 + 1041 0.395 + 1042 0.395 + 1043 0.396 + 1044 0.396 + 1045 0.396 + 1046 0.396 + 1047 0.396 + 1048 0.397 + 1049 0.397 + 1050 0.397 + 1051 0.397 + 1052 0.398 + 1053 0.398 + 1054 0.398 + 1055 0.398 + 1056 0.398 + 1057 0.399 + 1058 0.399 + 1059 0.399 + 1060 0.399 + 1061 0.399 + 1062 0.399 + 1063 0.399 + 1064 0.399 + 1065 0.399 + 1066 0.399 + 1067 0.399 + 1068 0.399 + 1069 0.399 + 1070 0.399 + 1071 0.400 + 1072 0.400 + 1073 0.400 + 1074 0.400 + 1075 0.400 + 1076 0.400 + 1077 0.399 + 1078 0.399 + 1079 0.399 + 1080 0.399 + 1081 0.399 + 1082 0.399 + 1083 0.399 + 1084 0.399 + 1085 0.400 + 1086 0.400 + 1087 0.400 + 1088 0.400 + 1089 0.400 + 1090 0.400 + 1091 0.400 + 1092 0.399 + 1093 0.399 + 1094 0.399 + 1095 0.399 + 1096 0.399 + 1097 0.399 + 1098 0.398 + 1099 0.398 + 1100 0.398 + 1101 0.399 + 1102 0.399 + 1103 0.399 + 1104 0.399 + 1105 0.400 + 1106 0.400 + 1107 0.400 + 1108 0.399 + 1109 0.399 + 1110 0.398 + 1111 0.398 + 1112 0.398 + 1113 0.398 + 1114 0.398 + 1115 0.398 + 1116 0.398 + 1117 0.398 + 1118 0.398 + 1119 0.398 + 1120 0.397 + 1121 0.397 + 1122 0.396 + 1123 0.396 + 1124 0.396 + 1125 0.395 + 1126 0.395 + 1127 0.395 + 1128 0.394 + 1129 0.394 + 1130 0.393 + 1131 0.393 + 1132 0.392 + 1133 0.391 + 1134 0.390 + 1135 0.389 + 1136 0.388 + 1137 0.387 + 1138 0.386 + 1139 0.385 + 1140 0.384 + 1141 0.383 + 1142 0.382 + 1143 0.381 + 1144 0.379 + 1145 0.378 + 1146 0.376 + 1147 0.375 + 1148 0.374 + 1149 0.373 + 1150 0.372 + 1151 0.371 + 1152 0.371 + 1153 0.370 + 1154 0.370 + 1155 0.369 + 1156 0.369 + 1157 0.368 + 1158 0.368 + 1159 0.367 + 1160 0.367 + 1161 0.367 + 1162 0.366 + 1163 0.366 + 1164 0.366 + 1165 0.365 + 1166 0.365 + 1167 0.365 + 1168 0.365 + 1169 0.365 + 1170 0.365 + 1171 0.365 + 1172 0.365 + 1173 0.365 + 1174 0.365 + 1175 0.365 + 1176 0.365 + 1177 0.365 + 1178 0.365 + 1179 0.365 + 1180 0.365 + 1181 0.365 + 1182 0.365 + 1183 0.365 + 1184 0.364 + 1185 0.364 + 1186 0.364 + 1187 0.364 + 1188 0.364 + 1189 0.364 + 1190 0.364 + 1191 0.364 + 1192 0.364 + 1193 0.364 + 1194 0.364 + 1195 0.364 + 1196 0.364 + 1197 0.364 + 1198 0.364 + 1199 0.364 + 1200 0.364 + 1201 0.365 + 1202 0.365 + 1203 0.366 + 1204 0.366 + 1205 0.366 + 1206 0.366 + 1207 0.366 + 1208 0.366 + 1209 0.366 + 1210 0.366 + 1211 0.366 + 1212 0.366 + 1213 0.366 + 1214 0.367 + 1215 0.367 + 1216 0.367 + 1217 0.368 + 1218 0.369 + 1219 0.369 + 1220 0.370 + 1221 0.370 + 1222 0.371 + 1223 0.371 + 1224 0.371 + 1225 0.371 + 1226 0.371 + 1227 0.371 + 1228 0.371 + 1229 0.372 + 1230 0.372 + 1231 0.372 + 1232 0.372 + 1233 0.372 + 1234 0.372 + 1235 0.373 + 1236 0.373 + 1237 0.373 + 1238 0.373 + 1239 0.373 + 1240 0.373 + 1241 0.373 + 1242 0.373 + 1243 0.374 + 1244 0.374 + 1245 0.375 + 1246 0.375 + 1247 0.375 + 1248 0.376 + 1249 0.376 + 1250 0.376 + 1251 0.376 + 1252 0.376 + 1253 0.375 + 1254 0.375 + 1255 0.376 + 1256 0.376 + 1257 0.376 + 1258 0.376 + 1259 0.376 + 1260 0.376 + 1261 0.376 + 1262 0.376 + 1263 0.376 + 1264 0.376 + 1265 0.375 + 1266 0.375 + 1267 0.376 + 1268 0.376 + 1269 0.376 + 1270 0.376 + 1271 0.377 + 1272 0.377 + 1273 0.377 + 1274 0.377 + 1275 0.377 + 1276 0.376 + 1277 0.376 + 1278 0.376 + 1279 0.376 + 1280 0.376 + 1281 0.376 + 1282 0.375 + 1283 0.375 + 1284 0.375 + 1285 0.375 + 1286 0.375 + 1287 0.374 + 1288 0.374 + 1289 0.374 + 1290 0.374 + 1291 0.374 + 1292 0.373 + 1293 0.373 + 1294 0.373 + 1295 0.372 + 1296 0.372 + 1297 0.371 + 1298 0.371 + 1299 0.371 + 1300 0.370 + 1301 0.370 + 1302 0.369 + 1303 0.369 + 1304 0.368 + 1305 0.367 + 1306 0.367 + 1307 0.366 + 1308 0.365 + 1309 0.365 + 1310 0.364 + 1311 0.363 + 1312 0.362 + 1313 0.361 + 1314 0.361 + 1315 0.360 + 1316 0.359 + 1317 0.358 + 1318 0.357 + 1319 0.357 + 1320 0.356 + 1321 0.355 + 1322 0.354 + 1323 0.353 + 1324 0.352 + 1325 0.350 + 1326 0.349 + 1327 0.348 + 1328 0.346 + 1329 0.345 + 1330 0.344 + 1331 0.343 + 1332 0.341 + 1333 0.340 + 1334 0.339 + 1335 0.338 + 1336 0.337 + 1337 0.335 + 1338 0.334 + 1339 0.333 + 1340 0.331 + 1341 0.330 + 1342 0.329 + 1343 0.328 + 1344 0.326 + 1345 0.325 + 1346 0.324 + 1347 0.323 + 1348 0.322 + 1349 0.321 + 1350 0.320 + 1351 0.319 + 1352 0.318 + 1353 0.316 + 1354 0.315 + 1355 0.314 + 1356 0.313 + 1357 0.312 + 1358 0.310 + 1359 0.309 + 1360 0.308 + 1361 0.306 + 1362 0.305 + 1363 0.303 + 1364 0.302 + 1365 0.300 + 1366 0.299 + 1367 0.297 + 1368 0.295 + 1369 0.294 + 1370 0.292 + 1371 0.290 + 1372 0.288 + 1373 0.286 + 1374 0.283 + 1375 0.280 + 1376 0.277 + 1377 0.273 + 1378 0.270 + 1379 0.266 + 1380 0.262 + 1381 0.258 + 1382 0.254 + 1383 0.250 + 1384 0.246 + 1385 0.241 + 1386 0.236 + 1387 0.231 + 1388 0.226 + 1389 0.220 + 1390 0.215 + 1391 0.210 + 1392 0.205 + 1393 0.200 + 1394 0.194 + 1395 0.189 + 1396 0.184 + 1397 0.180 + 1398 0.175 + 1399 0.170 + 1400 0.165 + 1401 0.161 + 1402 0.157 + 1403 0.153 + 1404 0.150 + 1405 0.147 + 1406 0.144 + 1407 0.140 + 1408 0.137 + 1409 0.135 + 1410 0.132 + 1411 0.129 + 1412 0.127 + 1413 0.125 + 1414 0.123 + 1415 0.122 + 1416 0.121 + 1417 0.120 + 1418 0.118 + 1419 0.117 + 1420 0.116 + 1421 0.115 + 1422 0.114 + 1423 0.113 + 1424 0.113 + 1425 0.112 + 1426 0.111 + 1427 0.111 + 1428 0.110 + 1429 0.110 + 1430 0.110 + 1431 0.109 + 1432 0.109 + 1433 0.109 + 1434 0.109 + 1435 0.109 + 1436 0.109 + 1437 0.109 + 1438 0.109 + 1439 0.109 + 1440 0.109 + 1441 0.109 + 1442 0.109 + 1443 0.109 + 1444 0.109 + 1445 0.109 + 1446 0.109 + 1447 0.109 + 1448 0.109 + 1449 0.109 + 1450 0.110 + 1451 0.110 + 1452 0.110 + 1453 0.110 + 1454 0.111 + 1455 0.111 + 1456 0.111 + 1457 0.111 + 1458 0.111 + 1459 0.111 + 1460 0.112 + 1461 0.112 + 1462 0.112 + 1463 0.113 + 1464 0.113 + 1465 0.114 + 1466 0.115 + 1467 0.116 + 1468 0.117 + 1469 0.118 + 1470 0.119 + 1471 0.120 + 1472 0.121 + 1473 0.123 + 1474 0.124 + 1475 0.125 + 1476 0.126 + 1477 0.127 + 1478 0.129 + 1479 0.130 + 1480 0.131 + 1481 0.132 + 1482 0.133 + 1483 0.134 + 1484 0.135 + 1485 0.136 + 1486 0.137 + 1487 0.138 + 1488 0.140 + 1489 0.141 + 1490 0.142 + 1491 0.142 + 1492 0.143 + 1493 0.144 + 1494 0.145 + 1495 0.146 + 1496 0.148 + 1497 0.149 + 1498 0.151 + 1499 0.152 + 1500 0.153 + 1501 0.155 + 1502 0.156 + 1503 0.157 + 1504 0.158 + 1505 0.158 + 1506 0.159 + 1507 0.160 + 1508 0.161 + 1509 0.163 + 1510 0.164 + 1511 0.165 + 1512 0.166 + 1513 0.168 + 1514 0.169 + 1515 0.170 + 1516 0.171 + 1517 0.172 + 1518 0.174 + 1519 0.175 + 1520 0.176 + 1521 0.177 + 1522 0.179 + 1523 0.180 + 1524 0.181 + 1525 0.182 + 1526 0.183 + 1527 0.185 + 1528 0.187 + 1529 0.188 + 1530 0.189 + 1531 0.190 + 1532 0.191 + 1533 0.192 + 1534 0.193 + 1535 0.193 + 1536 0.194 + 1537 0.195 + 1538 0.196 + 1539 0.197 + 1540 0.199 + 1541 0.200 + 1542 0.202 + 1543 0.203 + 1544 0.204 + 1545 0.206 + 1546 0.207 + 1547 0.208 + 1548 0.208 + 1549 0.209 + 1550 0.210 + 1551 0.211 + 1552 0.212 + 1553 0.213 + 1554 0.214 + 1555 0.214 + 1556 0.215 + 1557 0.216 + 1558 0.217 + 1559 0.218 + 1560 0.219 + 1561 0.220 + 1562 0.221 + 1563 0.222 + 1564 0.223 + 1565 0.224 + 1566 0.225 + 1567 0.226 + 1568 0.227 + 1569 0.227 + 1570 0.229 + 1571 0.230 + 1572 0.231 + 1573 0.232 + 1574 0.233 + 1575 0.234 + 1576 0.234 + 1577 0.235 + 1578 0.235 + 1579 0.235 + 1580 0.236 + 1581 0.236 + 1582 0.237 + 1583 0.238 + 1584 0.238 + 1585 0.239 + 1586 0.240 + 1587 0.241 + 1588 0.242 + 1589 0.243 + 1590 0.244 + 1591 0.245 + 1592 0.245 + 1593 0.246 + 1594 0.247 + 1595 0.247 + 1596 0.248 + 1597 0.248 + 1598 0.249 + 1599 0.249 + 1600 0.250 + 1601 0.250 + 1602 0.251 + 1603 0.252 + 1604 0.252 + 1605 0.253 + 1606 0.253 + 1607 0.254 + 1608 0.254 + 1609 0.255 + 1610 0.255 + 1611 0.256 + 1612 0.256 + 1613 0.256 + 1614 0.257 + 1615 0.257 + 1616 0.258 + 1617 0.258 + 1618 0.259 + 1619 0.260 + 1620 0.261 + 1621 0.261 + 1622 0.262 + 1623 0.263 + 1624 0.263 + 1625 0.264 + 1626 0.264 + 1627 0.264 + 1628 0.263 + 1629 0.263 + 1630 0.263 + 1631 0.264 + 1632 0.264 + 1633 0.265 + 1634 0.266 + 1635 0.266 + 1636 0.267 + 1637 0.267 + 1638 0.267 + 1639 0.268 + 1640 0.268 + 1641 0.268 + 1642 0.268 + 1643 0.269 + 1644 0.269 + 1645 0.269 + 1646 0.269 + 1647 0.270 + 1648 0.270 + 1649 0.270 + 1650 0.271 + 1651 0.271 + 1652 0.271 + 1653 0.271 + 1654 0.271 + 1655 0.271 + 1656 0.271 + 1657 0.271 + 1658 0.271 + 1659 0.271 + 1660 0.271 + 1661 0.272 + 1662 0.272 + 1663 0.272 + 1664 0.271 + 1665 0.270 + 1666 0.269 + 1667 0.269 + 1668 0.269 + 1669 0.269 + 1670 0.269 + 1671 0.270 + 1672 0.271 + 1673 0.272 + 1674 0.272 + 1675 0.271 + 1676 0.271 + 1677 0.270 + 1678 0.270 + 1679 0.269 + 1680 0.268 + 1681 0.268 + 1682 0.268 + 1683 0.268 + 1684 0.268 + 1685 0.267 + 1686 0.267 + 1687 0.266 + 1688 0.266 + 1689 0.266 + 1690 0.266 + 1691 0.266 + 1692 0.266 + 1693 0.265 + 1694 0.265 + 1695 0.265 + 1696 0.264 + 1697 0.263 + 1698 0.263 + 1699 0.262 + 1700 0.262 + 1701 0.262 + 1702 0.262 + 1703 0.261 + 1704 0.261 + 1705 0.261 + 1706 0.260 + 1707 0.260 + 1708 0.259 + 1709 0.259 + 1710 0.259 + 1711 0.259 + 1712 0.258 + 1713 0.258 + 1714 0.258 + 1715 0.257 + 1716 0.257 + 1717 0.256 + 1718 0.256 + 1719 0.256 + 1720 0.255 + 1721 0.255 + 1722 0.255 + 1723 0.254 + 1724 0.254 + 1725 0.253 + 1726 0.252 + 1727 0.251 + 1728 0.251 + 1729 0.250 + 1730 0.249 + 1731 0.249 + 1732 0.248 + 1733 0.248 + 1734 0.248 + 1735 0.247 + 1736 0.247 + 1737 0.247 + 1738 0.247 + 1739 0.246 + 1740 0.246 + 1741 0.246 + 1742 0.246 + 1743 0.246 + 1744 0.246 + 1745 0.245 + 1746 0.243 + 1747 0.241 + 1748 0.240 + 1749 0.239 + 1750 0.238 + 1751 0.237 + 1752 0.237 + 1753 0.238 + 1754 0.238 + 1755 0.238 + 1756 0.238 + 1757 0.238 + 1758 0.237 + 1759 0.237 + 1760 0.236 + 1761 0.235 + 1762 0.235 + 1763 0.234 + 1764 0.234 + 1765 0.234 + 1766 0.233 + 1767 0.233 + 1768 0.232 + 1769 0.232 + 1770 0.231 + 1771 0.230 + 1772 0.230 + 1773 0.230 + 1774 0.230 + 1775 0.230 + 1776 0.229 + 1777 0.228 + 1778 0.226 + 1779 0.225 + 1780 0.224 + 1781 0.224 + 1782 0.224 + 1783 0.225 + 1784 0.225 + 1785 0.226 + 1786 0.227 + 1787 0.226 + 1788 0.225 + 1789 0.224 + 1790 0.224 + 1791 0.225 + 1792 0.225 + 1793 0.226 + 1794 0.226 + 1795 0.226 + 1796 0.226 + 1797 0.226 + 1798 0.225 + 1799 0.223 + 1800 0.223 + 1801 0.223 + 1802 0.223 + 1803 0.223 + 1804 0.224 + 1805 0.224 + 1806 0.225 + 1807 0.225 + 1808 0.226 + 1809 0.226 + 1810 0.226 + 1811 0.225 + 1812 0.225 + 1813 0.224 + 1814 0.223 + 1815 0.223 + 1816 0.223 + 1817 0.222 + 1818 0.223 + 1819 0.223 + 1820 0.223 + 1821 0.224 + 1822 0.223 + 1823 0.223 + 1824 0.223 + 1825 0.224 + 1826 0.224 + 1827 0.225 + 1828 0.225 + 1829 0.225 + 1830 0.225 + 1831 0.224 + 1832 0.223 + 1833 0.222 + 1834 0.221 + 1835 0.221 + 1836 0.221 + 1837 0.221 + 1838 0.220 + 1839 0.219 + 1840 0.218 + 1841 0.216 + 1842 0.215 + 1843 0.215 + 1844 0.214 + 1845 0.213 + 1846 0.211 + 1847 0.209 + 1848 0.207 + 1849 0.204 + 1850 0.202 + 1851 0.200 + 1852 0.198 + 1853 0.197 + 1854 0.195 + 1855 0.194 + 1856 0.191 + 1857 0.188 + 1858 0.185 + 1859 0.182 + 1860 0.180 + 1861 0.177 + 1862 0.175 + 1863 0.172 + 1864 0.170 + 1865 0.168 + 1866 0.165 + 1867 0.162 + 1868 0.159 + 1869 0.155 + 1870 0.151 + 1871 0.146 + 1872 0.141 + 1873 0.135 + 1874 0.129 + 1875 0.123 + 1876 0.119 + 1877 0.115 + 1878 0.112 + 1879 0.109 + 1880 0.104 + 1881 0.097 + 1882 0.083 + 1883 0.065 + 1884 0.052 + 1885 0.045 + 1886 0.039 + 1887 0.035 + 1888 0.033 + 1889 0.028 + 1890 0.021 + 1891 0.013 + 1892 0.009 + 1893 0.008 + 1894 0.009 + 1895 0.008 + 1896 0.007 + 1897 0.006 + 1898 0.013 + 1899 0.026 + 1900 0.032 + 1901 0.026 + 1902 0.013 + 1903 0.003 + 1904 0.001 + 1905 0.000 + 1906 0.002 + 1907 0.011 + 1908 0.022 + 1909 0.025 + 1910 0.020 + 1911 0.012 + 1912 0.009 + 1913 0.006 + 1914 0.002 + 1915 0.003 + 1916 0.008 + 1917 0.011 + 1918 0.011 + 1919 0.009 + 1920 0.007 + 1921 0.006 + 1922 0.003 + 1923 0.001 + 1924 0.002 + 1925 0.003 + 1926 0.004 + 1927 0.006 + 1928 0.007 + 1929 0.007 + 1930 0.006 + 1931 0.005 + 1932 0.007 + 1933 0.010 + 1934 0.013 + 1935 0.014 + 1936 0.014 + 1937 0.014 + 1938 0.012 + 1939 0.009 + 1940 0.008 + 1941 0.009 + 1942 0.009 + 1943 0.009 + 1944 0.008 + 1945 0.008 + 1946 0.008 + 1947 0.009 + 1948 0.009 + 1949 0.009 + 1950 0.009 + 1951 0.009 + 1952 0.014 + 1953 0.019 + 1954 0.020 + 1955 0.018 + 1956 0.014 + 1957 0.012 + 1958 0.010 + 1959 0.008 + 1960 0.008 + 1961 0.008 + 1962 0.009 + 1963 0.010 + 1964 0.011 + 1965 0.012 + 1966 0.016 + 1967 0.019 + 1968 0.022 + 1969 0.022 + 1970 0.021 + 1971 0.024 + 1972 0.030 + 1973 0.034 + 1974 0.035 + 1975 0.033 + 1976 0.030 + 1977 0.027 + 1978 0.023 + 1979 0.021 + 1980 0.021 + 1981 0.022 + 1982 0.022 + 1983 0.021 + 1984 0.020 + 1985 0.017 + 1986 0.013 + 1987 0.012 + 1988 0.016 + 1989 0.023 + 1990 0.028 + 1991 0.029 + 1992 0.028 + 1993 0.028 + 1994 0.027 + 1995 0.027 + 1996 0.031 + 1997 0.039 + 1998 0.046 + 1999 0.045 + 2000 0.040 + 2001 0.036 + 2002 0.034 + 2003 0.033 + 2004 0.034 + 2005 0.038 + 2006 0.042 + 2007 0.046 + 2008 0.048 + 2009 0.049 + 2010 0.050 + 2011 0.051 + 2012 0.050 + 2013 0.047 + 2014 0.042 + 2015 0.039 + 2016 0.038 + 2017 0.039 + 2018 0.040 + 2019 0.043 + 2020 0.046 + 2021 0.047 + 2022 0.048 + 2023 0.049 + 2024 0.049 + 2025 0.048 + 2026 0.047 + 2027 0.046 + 2028 0.046 + 2029 0.049 + 2030 0.056 + 2031 0.061 + 2032 0.063 + 2033 0.063 + 2034 0.064 + 2035 0.065 + 2036 0.067 + 2037 0.069 + 2038 0.073 + 2039 0.076 + 2040 0.077 + 2041 0.075 + 2042 0.073 + 2043 0.071 + 2044 0.069 + 2045 0.068 + 2046 0.069 + 2047 0.070 + 2048 0.073 + 2049 0.078 + 2050 0.080 + 2051 0.075 + 2052 0.066 + 2053 0.062 + 2054 0.064 + 2055 0.069 + 2056 0.074 + 2057 0.079 + 2058 0.082 + 2059 0.080 + 2060 0.075 + 2061 0.072 + 2062 0.074 + 2063 0.078 + 2064 0.081 + 2065 0.083 + 2066 0.084 + 2067 0.082 + 2068 0.078 + 2069 0.075 + 2070 0.075 + 2071 0.077 + 2072 0.079 + 2073 0.085 + 2074 0.089 + 2075 0.089 + 2076 0.084 + 2077 0.080 + 2078 0.079 + 2079 0.079 + 2080 0.081 + 2081 0.085 + 2082 0.090 + 2083 0.094 + 2084 0.097 + 2085 0.099 + 2086 0.102 + 2087 0.105 + 2088 0.106 + 2089 0.105 + 2090 0.103 + 2091 0.099 + 2092 0.093 + 2093 0.089 + 2094 0.089 + 2095 0.091 + 2096 0.093 + 2097 0.095 + 2098 0.097 + 2099 0.096 + 2100 0.091 + 2101 0.088 + 2102 0.092 + 2103 0.100 + 2104 0.105 + 2105 0.106 + 2106 0.106 + 2107 0.106 + 2108 0.106 + 2109 0.107 + 2110 0.113 + 2111 0.122 + 2112 0.125 + 2113 0.121 + 2114 0.114 + 2115 0.110 + 2116 0.109 + 2117 0.108 + 2118 0.105 + 2119 0.103 + 2120 0.102 + 2121 0.102 + 2122 0.104 + 2123 0.106 + 2124 0.108 + 2125 0.110 + 2126 0.109 + 2127 0.107 + 2128 0.107 + 2129 0.112 + 2130 0.116 + 2131 0.116 + 2132 0.114 + 2133 0.114 + 2134 0.117 + 2135 0.121 + 2136 0.124 + 2137 0.126 + 2138 0.127 + 2139 0.124 + 2140 0.119 + 2141 0.115 + 2142 0.113 + 2143 0.112 + 2144 0.112 + 2145 0.114 + 2146 0.116 + 2147 0.117 + 2148 0.117 + 2149 0.117 + 2150 0.118 + 2151 0.120 + 2152 0.121 + 2153 0.123 + 2154 0.124 + 2155 0.126 + 2156 0.128 + 2157 0.127 + 2158 0.125 + 2159 0.122 + 2160 0.119 + 2161 0.115 + 2162 0.114 + 2163 0.117 + 2164 0.120 + 2165 0.124 + 2166 0.128 + 2167 0.129 + 2168 0.126 + 2169 0.123 + 2170 0.120 + 2171 0.117 + 2172 0.115 + 2173 0.116 + 2174 0.118 + 2175 0.120 + 2176 0.123 + 2177 0.125 + 2178 0.126 + 2179 0.126 + 2180 0.125 + 2181 0.124 + 2182 0.122 + 2183 0.119 + 2184 0.117 + 2185 0.116 + 2186 0.118 + 2187 0.122 + 2188 0.125 + 2189 0.127 + 2190 0.129 + 2191 0.128 + 2192 0.126 + 2193 0.123 + 2194 0.118 + 2195 0.113 + 2196 0.113 + 2197 0.115 + 2198 0.119 + 2199 0.125 + 2200 0.131 + 2201 0.137 + 2202 0.142 + 2203 0.145 + 2204 0.143 + 2205 0.139 + 2206 0.136 + 2207 0.134 + 2208 0.134 + 2209 0.137 + 2210 0.141 + 2211 0.142 + 2212 0.139 + 2213 0.135 + 2214 0.134 + 2215 0.133 + 2216 0.132 + 2217 0.130 + 2218 0.129 + 2219 0.129 + 2220 0.130 + 2221 0.130 + 2222 0.128 + 2223 0.127 + 2224 0.129 + 2225 0.132 + 2226 0.136 + 2227 0.139 + 2228 0.142 + 2229 0.143 + 2230 0.141 + 2231 0.140 + 2232 0.139 + 2233 0.140 + 2234 0.139 + 2235 0.139 + 2236 0.138 + 2237 0.139 + 2238 0.140 + 2239 0.138 + 2240 0.135 + 2241 0.130 + 2242 0.123 + 2243 0.115 + 2244 0.109 + 2245 0.105 + 2246 0.103 + 2247 0.107 + 2248 0.114 + 2249 0.118 + 2250 0.119 + 2251 0.119 + 2252 0.121 + 2253 0.123 + 2254 0.124 + 2255 0.125 + 2256 0.124 + 2257 0.121 + 2258 0.117 + 2259 0.113 + 2260 0.110 + 2261 0.107 + 2262 0.105 + 2263 0.104 + 2264 0.103 + 2265 0.101 + 2266 0.100 + 2267 0.101 + 2268 0.102 + 2269 0.105 + 2270 0.109 + 2271 0.113 + 2272 0.114 + 2273 0.114 + 2274 0.113 + 2275 0.112 + 2276 0.111 + 2277 0.110 + 2278 0.109 + 2279 0.108 + 2280 0.105 + 2281 0.103 + 2282 0.101 + 2283 0.100 + 2284 0.099 + 2285 0.098 + 2286 0.097 + 2287 0.095 + 2288 0.094 + 2289 0.093 + 2290 0.092 + 2291 0.091 + 2292 0.091 + 2293 0.090 + 2294 0.090 + 2295 0.089 + 2296 0.087 + 2297 0.083 + 2298 0.078 + 2299 0.072 + 2300 0.064 + 2301 0.059 + 2302 0.057 + 2303 0.056 + 2304 0.053 + 2305 0.052 + 2306 0.054 + 2307 0.059 + 2308 0.065 + 2309 0.071 + 2310 0.076 + 2311 0.075 + 2312 0.070 + 2313 0.067 + 2314 0.065 + 2315 0.064 + 2316 0.064 + 2317 0.064 + 2318 0.062 + 2319 0.059 + 2320 0.058 + 2321 0.063 + 2322 0.072 + 2323 0.078 + 2324 0.082 + 2325 0.084 + 2326 0.081 + 2327 0.077 + 2328 0.073 + 2329 0.069 + 2330 0.065 + 2331 0.061 + 2332 0.057 + 2333 0.054 + 2334 0.052 + 2335 0.053 + 2336 0.056 + 2337 0.060 + 2338 0.063 + 2339 0.065 + 2340 0.066 + 2341 0.068 + 2342 0.069 + 2343 0.070 + 2344 0.070 + 2345 0.069 + 2346 0.068 + 2347 0.066 + 2348 0.062 + 2349 0.058 + 2350 0.056 + 2351 0.055 + 2352 0.054 + 2353 0.051 + 2354 0.050 + 2355 0.050 + 2356 0.052 + 2357 0.055 + 2358 0.060 + 2359 0.064 + 2360 0.066 + 2361 0.067 + 2362 0.067 + 2363 0.065 + 2364 0.063 + 2365 0.060 + 2366 0.057 + 2367 0.052 + 2368 0.047 + 2369 0.042 + 2370 0.038 + 2371 0.033 + 2372 0.029 + 2373 0.023 + 2374 0.018 + 2375 0.014 + 2376 0.012 + 2377 0.012 + 2378 0.015 + 2379 0.018 + 2380 0.022 + 2381 0.025 + 2382 0.028 + 2383 0.034 + 2384 0.040 + 2385 0.045 + 2386 0.045 + 2387 0.045 + 2388 0.045 + 2389 0.044 + 2390 0.039 + 2391 0.035 + 2392 0.029 + 2393 0.019 + 2394 0.013 + 2395 0.015 + 2396 0.020 + 2397 0.022 + 2398 0.020 + 2399 0.019 + 2400 0.018 + 2401 0.019 + 2402 0.019 + 2403 0.021 + 2404 0.020 + 2405 0.017 + 2406 0.016 + 2407 0.016 + 2408 0.017 + 2409 0.016 + 2410 0.015 + 2411 0.015 + 2412 0.014 + 2413 0.016 + 2414 0.017 + 2415 0.017 + 2416 0.016 + 2417 0.014 + 2418 0.012 + 2419 0.010 + 2420 0.009 + 2421 0.008 + 2422 0.008 + 2423 0.009 + 2424 0.010 + 2425 0.012 + 2426 0.013 + 2427 0.013 + 2428 0.014 + 2429 0.017 + 2430 0.020 + 2431 0.022 + 2432 0.024 + 2433 0.025 + 2434 0.026 + 2435 0.028 + 2436 0.029 + 2437 0.028 + 2438 0.026 + 2439 0.023 + 2440 0.019 + 2441 0.017 + 2442 0.015 + 2443 0.015 + 2444 0.015 + 2445 0.016 + 2446 0.016 + 2447 0.015 + 2448 0.011 + 2449 0.008 + 2450 0.009 + 2451 0.011 + 2452 0.016 + 2453 0.017 + 2454 0.021 + 2455 0.024 + 2456 0.032 + 2457 0.036 + 2458 0.037 + 2459 0.038 + 2460 0.040 + 2461 0.042 + 2462 0.045 + 2463 0.047 + 2464 0.049 + 2465 0.050 + 2466 0.044 + 2467 0.041 + 2468 0.036 + 2469 0.030 + 2470 0.037 + 2471 0.051 + 2472 0.068 + 2473 0.083 + 2474 0.096 + 2475 0.101 + 2476 0.100 + 2477 0.104 + 2478 0.115 + 2479 0.124 + 2480 0.123 + 2481 0.119 + 2482 0.116 + 2483 0.111 + 2484 0.105 + 2485 0.098 + 2486 0.080 + 2487 0.049 + 2488 0.036 + 2489 0.025 + 2490 0.016 + 2491 0.021 + 2492 0.042 + 2493 0.017 + 2494 0.001 + 2495 0.000 + 2496 0.020 + 2497 0.062 + 2498 0.140 + 2499 0.221 + 2500 0.304 + \ No newline at end of file diff --git a/plugins/radiation/src/RadiationModel.cpp b/plugins/radiation/src/RadiationModel.cpp index 414b0a644..941e58ec9 100755 --- a/plugins/radiation/src/RadiationModel.cpp +++ b/plugins/radiation/src/RadiationModel.cpp @@ -207,6 +207,8 @@ void RadiationModel::addRadiationBand(const std::string &label ){ source.source_fluxes[label] = -1.f; } + radiativepropertiesneedupdate = true; + } void RadiationModel::addRadiationBand( const std::string &label, float wavelength1, float wavelength2 ){ @@ -232,9 +234,7 @@ void RadiationModel::addRadiationBand( const std::string &label, float wavelengt source.source_fluxes[label] = -1.f; } - - - + radiativepropertiesneedupdate = true; } @@ -1198,6 +1198,8 @@ void RadiationModel::addRadiationCamera(const std::string &camera_label, const s buildCameraModelGeometry(camera_label); } + radiativepropertiesneedupdate = true; + } void RadiationModel::addRadiationCamera(const std::string &camera_label, const std::vector &band_label, const helios::vec3 &position, const helios::SphericalCoord &viewing_direction, const CameraProperties &camera_properties, uint antialiasing_samples) { @@ -1637,8 +1639,10 @@ void RadiationModel::initializeOptiX() { addBuffer( "source_fluxes", source_fluxes_RTbuffer, source_fluxes_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_FLOAT, 1 ); //number of radiation bands - RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nbands", &Nbands_RTvariable ) ); - RT_CHECK_ERROR( rtVariableSet1ui( Nbands_RTvariable,0 ) ); + RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nbands_global", &Nbands_global_RTvariable ) ); + RT_CHECK_ERROR( rtVariableSet1ui( Nbands_global_RTvariable,0 ) ); + RT_CHECK_ERROR( rtContextDeclareVariable( OptiX_Context, "Nbands_launch", &Nbands_launch_RTvariable ) ); + RT_CHECK_ERROR( rtVariableSet1ui( Nbands_launch_RTvariable,0 ) ); //flag to disable launches for certain bands addBuffer( "band_launch_flag", band_launch_flag_RTbuffer, band_launch_flag_RTvariable, RT_BUFFER_INPUT, RT_FORMAT_BYTE, 1 ); @@ -1992,12 +1996,9 @@ void RadiationModel::updateGeometry( const std::vector& UUIDs ){ std::cout << "Updating geometry in radiation transport model..." << std::flush; } - for ( auto &band : radiation_bands ) { - band.second.radiativepropertiesinitialized = false; - } - context_UUIDs = UUIDs; + //remove any primitive UUIDs that don't exist or have zero area for( int u=context_UUIDs.size()-1; u>=0; u-- ){ float area = context->getPrimitiveArea(context_UUIDs.at(u)); if( !context->doesPrimitiveExist( context_UUIDs.at(u) ) ){ @@ -2481,13 +2482,15 @@ void RadiationModel::updateGeometry( const std::vector& UUIDs ){ // printf("available device memory at end of acceleration build: %6.3f GB\n",device_memory*1e-3); // } + radiativepropertiesneedupdate = true; + if( message_flag ){ std::cout << "done." << std::endl; } } -void RadiationModel::updateRadiativeProperties( const std::vector &labels ) { +void RadiationModel::updateRadiativeProperties() { // Possible scenarios for specifying a primitive's radiative properties // 1. If primitive data of form reflectivity_band/transmissivity_band is given, this value is used and overrides any other option. @@ -2499,15 +2502,15 @@ void RadiationModel::updateRadiativeProperties( const std::vector & std::cout << "Updating radiative properties..." << std::flush; } - uint Nbands = labels.size();//number of radiative bands + uint Nbands = radiation_bands.size();//number of radiative bands uint Nsources = radiation_sources.size(); uint Ncameras = cameras.size(); size_t Nobjects = primitiveID.size(); size_t Nprimitives = context_UUIDs.size(); - scattering_iterations_needed.resize(Nbands); - for( int b=0; b > > rho, tau; //first index is the source, second index is the primitive, third index is the band @@ -2515,12 +2518,9 @@ void RadiationModel::updateRadiativeProperties( const std::vector & float eps; std::string prop; - - for( auto &label : radiation_bands){ - label.second.radiativepropertiesinitialized = false; - } - for ( const auto &label: labels) { - radiation_bands.at(label).radiativepropertiesinitialized = true; + std::vector band_labels; + for ( auto &band : radiation_bands ) { + band_labels.push_back(band.first); } rho.resize(Nsources); @@ -2561,11 +2561,11 @@ void RadiationModel::updateRadiativeProperties( const std::vector & for (uint b = 0; b < Nbands; b++) { - if( camera.second.band_spectral_response.find(labels.at(b)) == camera.second.band_spectral_response.end() ){ + if( camera.second.band_spectral_response.find(band_labels.at(b)) == camera.second.band_spectral_response.end() ){ continue; } - std::string camera_response = camera.second.band_spectral_response.at(labels.at(b)); + std::string camera_response = camera.second.band_spectral_response.at(band_labels.at(b)); if (!camera_response.empty()) { @@ -2689,7 +2689,7 @@ void RadiationModel::updateRadiativeProperties( const std::vector & } for (uint b = 0; b < Nbands; b++) { - std::string band = labels.at(b); + std::string band = band_labels.at(b); for (uint s = 0; s < Nsources; s++) { @@ -2747,7 +2747,7 @@ void RadiationModel::updateRadiativeProperties( const std::vector & } for( uint b=0; b & } uint b = 0; - for (const auto &band: labels) { + for (const auto &band : band_labels) { //check for primitive data of form "reflectivity_bandname" prop = "reflectivity_" + band; @@ -2916,7 +2916,7 @@ void RadiationModel::updateRadiativeProperties( const std::vector & } } if( rho.at(s).at(u).at(b)!=0 ){ - scattering_iterations_needed.at(b) = true; + scattering_iterations_needed.at(band) = true; } for( auto &odata : output_prim_data ) { if ( odata == "reflectivity" ){ @@ -2939,7 +2939,7 @@ void RadiationModel::updateRadiativeProperties( const std::vector & } b = 0; - for ( const auto &band: labels ) { + for ( const auto &band : band_labels ) { //check for primitive data of form "transmissivity_bandname" prop = "transmissivity_" + band; @@ -2981,7 +2981,7 @@ void RadiationModel::updateRadiativeProperties( const std::vector & } } if( tau.at(s).at(u).at(b)!=0 ){ - scattering_iterations_needed.at(b) = true; + scattering_iterations_needed.at(band) = true; } for( auto &odata : output_prim_data ) { if (odata == "transmissivity" ){ @@ -2995,7 +2995,7 @@ void RadiationModel::updateRadiativeProperties( const std::vector & // Emissivity (only for error checking) b = 0; - for (const auto &band: labels) { + for (const auto &band : band_labels) { prop = "emissivity_" + band; @@ -3017,7 +3017,7 @@ void RadiationModel::updateRadiativeProperties( const std::vector & } } if( eps!=1 ){ - scattering_iterations_needed.at(b) = true; + scattering_iterations_needed.at(band) = true; } assert(doesBandExist(band)); @@ -3058,6 +3058,8 @@ void RadiationModel::updateRadiativeProperties( const std::vector & initializeBuffer1Df(rho_cam_RTbuffer, flatten(rho_cam)); initializeBuffer1Df(tau_cam_RTbuffer, flatten(tau_cam)); + radiativepropertiesneedupdate = false; + if( message_flag ) { std::cout << "done\n"; } @@ -3123,6 +3125,15 @@ void RadiationModel::runBand( const std::vector &label ) { //----- VERIFICATIONS -----// + //We need the band label strings to appear in the same order as in radiation_bands map. + //this is because that was the order in which radiative properties were laid out when updateRadiativeProperties() was called + std::vector band_labels; + for( auto &band : radiation_bands ){ + if( std::find( label.begin(), label.end(), band.first ) != label.end() ) { + band_labels.push_back(band.first); + } + } + //Check to make sure some geometry was added to the context if( context->getPrimitiveCount()==0 ){ std::cerr << "WARNING (RadiationModel::runBand): No geometry was added to the context. There is nothing to simulate...exiting." << std::endl; @@ -3134,7 +3145,8 @@ void RadiationModel::runBand( const std::vector &label ) { updateGeometry(); } - for( const std::string &band : label ){ + //Check that all the bands passed to the runBand() method exist + for( const std::string &band : band_labels ){ if( !doesBandExist(band) ){ helios_runtime_error("ERROR (RadiationModel::runBand): Cannot run band " + band + " because it is not a valid band. Use addRadiationBand() function to add the band."); } @@ -3145,22 +3157,26 @@ void RadiationModel::runBand( const std::vector &label ) { addCollimatedRadiationSource(); } - for( const auto &band : label ) { - if (!radiation_bands.at(band).radiativepropertiesinitialized) { - updateRadiativeProperties(label); - break; - } + if( radiativepropertiesneedupdate ){ + updateRadiativeProperties(); } - //Set the number of radiative bands - size_t Nbands = label.size(); + //Number of radiation bands in this launch + size_t Nbands_launch = band_labels.size(); + RT_CHECK_ERROR( rtVariableSet1ui( Nbands_launch_RTvariable, Nbands_launch ) ); - RT_CHECK_ERROR( rtVariableSet1ui( Nbands_RTvariable, Nbands ) ); + //Number of total bands in the radiation model + size_t Nbands_global = radiation_bands.size(); + RT_CHECK_ERROR( rtVariableSet1ui( Nbands_global_RTvariable, Nbands_global ) ); //Run all bands by default - std::vector band_launch_flag(Nbands); - for( uint b=0; b band_launch_flag(Nbands_global); + uint bb=0; + for( auto &band : radiation_bands ){ + if( std::find( band_labels.begin(), band_labels.end(), band.first ) != band_labels.end() ) { + band_launch_flag.at(bb) = 1; + } + bb++; } initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag ); @@ -3184,10 +3200,10 @@ void RadiationModel::runBand( const std::vector &label ) { RT_CHECK_ERROR( rtVariableSet1ui( Ncameras_RTvariable, Ncameras ) ); //Set scattering depth for each band - std::vector scattering_depth(Nbands); + std::vector scattering_depth(Nbands_launch); bool scatteringenabled = false; - for( auto b=0; b0 ){ scatteringenabled=true; } @@ -3195,17 +3211,17 @@ void RadiationModel::runBand( const std::vector &label ) { initializeBuffer1Dui( max_scatters_RTbuffer, scattering_depth ); //Issue warning if rho>0, tau>0, or eps<1 - for( int b=0; b diffuse_flux(Nbands); + std::vector diffuse_flux(Nbands_launch); bool diffuseenabled = false; - for( auto b=0; b0.f ){ diffuseenabled=true; } @@ -3213,28 +3229,28 @@ void RadiationModel::runBand( const std::vector &label ) { initializeBuffer1Df( diffuse_flux_RTbuffer, diffuse_flux ); //Set diffuse extinction coefficient for each band - std::vector diffuse_extinction(Nbands,0); + std::vector diffuse_extinction(Nbands_launch, 0); if( diffuseenabled ) { - for (auto b = 0; b < Nbands; b++) { - diffuse_extinction.at(b) = radiation_bands.at(label.at(b)).diffuseExtinction; + for (auto b = 0; b < Nbands_launch; b++) { + diffuse_extinction.at(b) = radiation_bands.at(band_labels.at(b)).diffuseExtinction; } } initializeBuffer1Df(diffuse_extinction_RTbuffer, diffuse_extinction); //Set diffuse distribution normalization factor for each band - std::vector diffuse_dist_norm(Nbands,0); + std::vector diffuse_dist_norm(Nbands_launch, 0); if( diffuseenabled ) { - for (auto b = 0; b < Nbands; b++) { - diffuse_dist_norm.at(b) = radiation_bands.at(label.at(b)).diffuseDistNorm; + for (auto b = 0; b < Nbands_launch; b++) { + diffuse_dist_norm.at(b) = radiation_bands.at(band_labels.at(b)).diffuseDistNorm; } initializeBuffer1Df(diffuse_dist_norm_RTbuffer, diffuse_dist_norm); } //Set diffuse distribution peak direction for each band - std::vector diffuse_peak_dir(Nbands); + std::vector diffuse_peak_dir(Nbands_launch); if( diffuseenabled ) { - for (auto b = 0; b < Nbands; b++) { - helios::vec3 peak_dir = radiation_bands.at(label.at(b)).diffusePeakDir; + for (auto b = 0; b < Nbands_launch; b++) { + helios::vec3 peak_dir = radiation_bands.at(band_labels.at(b)).diffusePeakDir; diffuse_peak_dir.at(b) = optix::make_float3(peak_dir.x,peak_dir.y,peak_dir.z); } initializeBuffer1Dfloat3(diffuse_peak_dir_RTbuffer, diffuse_peak_dir); @@ -3242,8 +3258,8 @@ void RadiationModel::runBand( const std::vector &label ) { //Determine whether emission is enabled for any band bool emissionenabled = false; - for( auto b=0; b &label ) { } // Zero buffers - zeroBuffer1D( radiation_in_RTbuffer, Nbands*Nprimitives ); - zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives ); - zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives ); - zeroBuffer1D( Rsky_RTbuffer, Nbands*Nprimitives ); + zeroBuffer1D(radiation_in_RTbuffer, Nbands_launch * Nprimitives ); + zeroBuffer1D(scatter_buff_top_RTbuffer, Nbands_launch * Nprimitives ); + zeroBuffer1D(scatter_buff_bottom_RTbuffer, Nbands_launch * Nprimitives ); + zeroBuffer1D(Rsky_RTbuffer, Nbands_launch * Nprimitives ); if( Ncameras>0 ){ - zeroBuffer1D( scatter_buff_top_cam_RTbuffer, Nbands*Nprimitives ); - zeroBuffer1D( scatter_buff_bottom_cam_RTbuffer, Nbands*Nprimitives ); + zeroBuffer1D(scatter_buff_top_cam_RTbuffer, Nbands_launch * Nprimitives ); + zeroBuffer1D(scatter_buff_bottom_cam_RTbuffer, Nbands_launch * Nprimitives ); } std::vector TBS_top, TBS_bottom; - TBS_top.resize(Nbands*Nprimitives, 0); + TBS_top.resize(Nbands_launch * Nprimitives, 0); TBS_bottom = TBS_top; std::map > > radiation_in_camera; @@ -3297,8 +3313,8 @@ void RadiationModel::runBand( const std::vector &label ) { bool rundirect = false; for( uint s=0; s0.f){ + for(uint b=0; b < Nbands_launch; b++ ){ + if( getSourceFlux( s, band_labels.at(b))>0.f){ rundirect = true; break; } @@ -3319,10 +3335,10 @@ void RadiationModel::runBand( const std::vector &label ) { size_t s=0; for( const auto &source : radiation_sources ) { - fluxes.at(s).resize(Nbands); + fluxes.at(s).resize(Nbands_launch); for( auto b=0; b &label ) { if( emissionenabled || diffuseenabled ){ std::vector flux_top, flux_bottom; - flux_top.resize(Nbands*Nprimitives,0); + flux_top.resize(Nbands_launch * Nprimitives, 0); flux_bottom = flux_top; //If we are doing a diffuse/emission ray trace anyway and we have direct scattered energy, we get a "free" scattering trace here if( scatteringenabled && rundirect ){ flux_top=getOptiXbufferData( scatter_buff_top_RTbuffer ); flux_bottom=getOptiXbufferData( scatter_buff_bottom_RTbuffer ); - zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives ); - zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives ); + zeroBuffer1D(scatter_buff_top_RTbuffer, Nbands_launch * Nprimitives ); + zeroBuffer1D(scatter_buff_bottom_RTbuffer, Nbands_launch * Nprimitives ); } //add any emitted energy to the outgoing energy buffer @@ -3419,11 +3435,11 @@ void RadiationModel::runBand( const std::vector &label ) { scatter_buff_bottom_cam_data = (float*)ptr; } - for (auto b = 0; b < Nbands; b++) { - if (radiation_bands.at(label.at(b)).emissionFlag) { - std::string prop = "emissivity_" + label.at(b); + for (auto b = 0; b < Nbands_launch; b++) { + if (radiation_bands.at(band_labels.at(b)).emissionFlag) { + std::string prop = "emissivity_" + band_labels.at(b); for (size_t u = 0; u < Nprimitives; u++) { - size_t ind = u * Nbands + b; + size_t ind = u * Nbands_launch + b; uint p = context_UUIDs.at(u); if (context->doesPrimitiveDataExist(p, prop.c_str())) { context->getPrimitiveData(p, prop.c_str(), eps); @@ -3521,7 +3537,7 @@ void RadiationModel::runBand( const std::vector &label ) { if( scatteringenabled ){ - for( auto b=0; b &label ) { std::cout << "Performing scattering ray trace (iteration " << s+1 << " of " << scatteringDepth << ")..." << std::flush; } - for( uint b=0; bdepth ) { if( message_flag ) { - std::cout << "Skipping band " << label.at(b) << " for scattering launch " << s + 1 << std::flush; + std::cout << "Skipping band " << band_labels.at(b) << " for scattering launch " << s + 1 << std::flush; } - band_launch_flag.at(b) = 0; - }else{ - band_launch_flag.at(b) = 1; + band_launch_flag.at(b_global) = 0; } } initializeBuffer1Dchar( band_launch_flag_RTbuffer, band_launch_flag ); @@ -3563,9 +3584,9 @@ void RadiationModel::runBand( const std::vector &label ) { // } copyBuffer1D( scatter_buff_top_RTbuffer, radiation_out_top_RTbuffer ); - zeroBuffer1D( scatter_buff_top_RTbuffer, Nbands*Nprimitives ); + zeroBuffer1D(scatter_buff_top_RTbuffer, Nbands_launch * Nprimitives ); copyBuffer1D( scatter_buff_bottom_RTbuffer, radiation_out_bottom_RTbuffer ); - zeroBuffer1D( scatter_buff_bottom_RTbuffer, Nbands*Nprimitives ); + zeroBuffer1D(scatter_buff_bottom_RTbuffer, Nbands_launch * Nprimitives ); for( uint launch=0; launch &label ) { //re-set diffuse radiation fluxes if( diffuseenabled ){ - for( auto b=0; b &label ) { RT_CHECK_ERROR( rtVariableSet1f( camera_viewplane_length_RTvariable, 0.5f/tanf(0.5f*camera.second.HFOV_degrees*M_PI/180.f) ) ); RT_CHECK_ERROR( rtVariableSet1ui( camera_ID_RTvariable, cam )); - zeroBuffer1D( radiation_in_camera_RTbuffer, camera.second.resolution.x*camera.second.resolution.y*Nbands ); + zeroBuffer1D( radiation_in_camera_RTbuffer, camera.second.resolution.x * camera.second.resolution.y * Nbands_launch ); optix::int3 launch_dim_camera = optix::make_int3( camera.second.antialiasing_samples, camera.second.resolution.x, camera.second.resolution.y ); @@ -3641,17 +3662,17 @@ void RadiationModel::runBand( const std::vector &label ) { std::string camera_label = camera.second.label; - for( auto b=0; bsetGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_data.at(label.at(b))[0]); + context->setGlobalData(data_label.c_str(), HELIOS_TYPE_FLOAT,camera.second.resolution.x*camera.second.resolution.y,&camera.second.pixel_data.at(band_labels.at(b))[0]); } @@ -3701,11 +3722,11 @@ void RadiationModel::runBand( const std::vector &label ) { std::vector UUIDs_context_all = context->getAllUUIDs(); - for( auto b=0; bsetPrimitiveData(context_UUIDs.at(u), prop.c_str(), R); if (radiation_flux_data.at(ind) != radiation_flux_data.at(ind)) { @@ -5229,31 +5250,35 @@ void RadiationModel::writeObjectDataLabelMap(const std::string &cameralabel, con for (uint j = 0; j < camera_resolution.y; j++) { for (uint i = 0; i < camera_resolution.x; i++) { uint ii = camera_resolution.x - i -1; - uint UUID =pixel_UUIDs.at(j * camera_resolution.x + ii)-1; + uint UUID = pixel_UUIDs.at(j * camera_resolution.x + ii)-1; + if( !context->doesPrimitiveExist(UUID) ){ + pixel_data << padvalue << " "; + continue; + } uint objID = context->getPrimitiveParentObjectID(UUID); if (context->doesObjectExist(objID) && context->doesObjectDataExist(objID,object_data_label.c_str())){ HeliosDataType datatype = context->getObjectDataType(objID,object_data_label.c_str()); if( datatype == HELIOS_TYPE_FLOAT ){ float labeldata; - context->getObjectData(UUID,object_data_label.c_str(),labeldata); + context->getObjectData(objID,object_data_label.c_str(),labeldata); pixel_data << labeldata << " "; empty_flag = false; } else if (datatype == HELIOS_TYPE_UINT){ uint labeldata; - context->getObjectData(UUID,object_data_label.c_str(),labeldata); + context->getObjectData(objID,object_data_label.c_str(),labeldata); pixel_data << labeldata << " "; empty_flag = false; } else if (datatype == HELIOS_TYPE_INT){ int labeldata; - context->getObjectData(UUID,object_data_label.c_str(),labeldata); + context->getObjectData(objID,object_data_label.c_str(),labeldata); pixel_data << labeldata << " "; empty_flag = false; } else if (datatype == HELIOS_TYPE_DOUBLE){ double labeldata; - context->getObjectData(UUID,object_data_label.c_str(),labeldata); + context->getObjectData(objID,object_data_label.c_str(),labeldata); pixel_data << labeldata << " "; empty_flag = false; }else{ diff --git a/plugins/radiation/src/rayHit.cu b/plugins/radiation/src/rayHit.cu index feed7806c..23c400421 100755 --- a/plugins/radiation/src/rayHit.cu +++ b/plugins/radiation/src/rayHit.cu @@ -29,7 +29,8 @@ rtDeclareVariable(rtObject, top_object, , ); rtDeclareVariable( unsigned int, UUID, attribute UUID, ); -rtDeclareVariable( unsigned int, Nbands,, ); +rtDeclareVariable( unsigned int, Nbands_launch,, ); +rtDeclareVariable( unsigned int, Nbands_global,, ); rtBuffer band_launch_flag; rtDeclareVariable( unsigned int, Nprimitives,, ); @@ -203,14 +204,16 @@ RT_PROGRAM void closest_hit_diffuse() { bool face = dot(normal, ray.direction) < 0; - for (size_t b = 0; b < Nbands; b++) { + int b = -1; + for (int b_global = 0; b_global < Nbands_global; b_global++) { - if( band_launch_flag[b]==0 ){ + if( band_launch_flag[b_global]==0 ){ continue; } + b++; - size_t ind_origin = Nbands * origin_UUID + b; - size_t ind_hit = Nbands * UUID + b; + size_t ind_origin = Nbands_launch * origin_UUID + b; + size_t ind_hit = Nbands_launch * UUID + b; double strength; if (face || primitive_type[objID] == 4) { @@ -223,8 +226,9 @@ RT_PROGRAM void closest_hit_diffuse() { continue; } - float t_rho = rho[ Nprimitives*Nbands*prd.source_ID + Nbands*origin_UUID + b ]; - float t_tau = tau[ Nprimitives*Nbands*prd.source_ID + Nbands*origin_UUID + b ]; + size_t radprop_ind_global = Nprimitives*Nbands_global*prd.source_ID + Nbands_global*origin_UUID + b_global; + float t_rho = rho[ radprop_ind_global ]; + float t_tau = tau[ radprop_ind_global ]; if (primitive_type[objectID[origin_UUID]] == 4) { //ray was launched from voxel @@ -253,7 +257,7 @@ RT_PROGRAM void closest_hit_diffuse() { } } if( Ncameras>0 ) { - size_t indc = prd.source_ID*Nprimitives*Nbands*Ncameras + origin_UUID*Nbands*Ncameras + b*Ncameras + camera_ID; + size_t indc = prd.source_ID*Nprimitives*Nbands_global*Ncameras + origin_UUID*Nbands_global*Ncameras + b_global*Ncameras + camera_ID; float t_rho_cam = rho_cam[ indc ]; float t_tau_cam = tau_cam[ indc ]; if ((t_rho_cam > 0 || t_tau_cam > 0) && strength > 0) { @@ -369,12 +373,12 @@ RT_PROGRAM void closest_hit_camera() { float3 camera_normal = d_rotatePoint( make_float3(0,0,1), -0.5*M_PI+camera_direction.x, 0.5f*M_PI-camera_direction.y ); double strength; - for( size_t b=0; b0 ) { - size_t indc = prd.source_ID*Nprimitives*Nbands*Ncameras + prd.origin_UUID*Nbands*Ncameras + b*Ncameras + camera_ID; + size_t indc = prd.source_ID*Nprimitives*Nbands_global*Ncameras + prd.origin_UUID*Nbands_global*Ncameras + b_global*Ncameras + camera_ID; float t_rho_cam = rho_cam[ indc ]; float t_tau_cam = tau_cam[ indc ]; if ( (t_rho_cam > 0 || t_tau_cam > 0) && strength>0 ) { @@ -535,18 +542,21 @@ RT_PROGRAM void miss_diffuse() { // // atomicFloatAdd(&Rsky[prd.origin_UUID], strength); - for( size_t b=0; b 0.f) { - size_t ind_origin = Nbands * prd.origin_UUID + b; + size_t ind_origin = Nbands_launch * prd.origin_UUID + b; - float t_rho = rho[Nprimitives*Nbands*prd.source_ID+Nbands*prd.origin_UUID+b]; - float t_tau = tau[Nprimitives*Nbands*prd.source_ID+Nbands*prd.origin_UUID+b]; + size_t radprop_ind_global = Nprimitives*Nbands_global*prd.source_ID + Nbands_global*prd.origin_UUID + b_global; + float t_rho = rho[ radprop_ind_global ]; + float t_tau = tau[ radprop_ind_global ]; if (primitive_type[objectID[prd.origin_UUID]] == 4) { //ray was launched from voxel @@ -574,7 +584,7 @@ RT_PROGRAM void miss_diffuse() { float strength = fd * diffuse_flux[b] * prd.strength; - // absorption + // absorption atomicAdd(&radiation_in[ind_origin], strength * (1.f - t_rho - t_tau) ); if (t_rho > 0 || t_tau > 0) { @@ -587,7 +597,7 @@ RT_PROGRAM void miss_diffuse() { } } if( Ncameras>0 ) { - size_t indc = prd.source_ID*Nprimitives*Nbands*Ncameras + prd.origin_UUID*Nbands*Ncameras + b*Ncameras + camera_ID; + size_t indc = prd.source_ID*Nprimitives*Nbands_global*Ncameras + prd.origin_UUID*Nbands_global*Ncameras + b_global*Ncameras + camera_ID; float t_rho_cam = rho_cam[ indc ]; float t_tau_cam = tau_cam[ indc ]; if ( (t_rho_cam > 0 || t_tau_cam > 0) && prd.strength>0 ) { @@ -611,7 +621,7 @@ RT_PROGRAM void miss_diffuse() { RT_PROGRAM void miss_camera() { - for( size_t b=0; b 0.f) { @@ -626,7 +636,7 @@ RT_PROGRAM void miss_camera() { } //absorption - atomicAdd(&radiation_in_camera[Nbands*prd.origin_UUID+b], fd * diffuse_flux[b] * prd.strength); + atomicAdd(&radiation_in_camera[Nbands_launch*prd.origin_UUID+b], fd * diffuse_flux[b] * prd.strength); } diff --git a/plugins/radiation/src/selfTest.cpp b/plugins/radiation/src/selfTest.cpp index b1619a90a..75a2bf98a 100644 --- a/plugins/radiation/src/selfTest.cpp +++ b/plugins/radiation/src/selfTest.cpp @@ -48,7 +48,7 @@ int RadiationModel::selfTest(){ shortwave_exact_0 = 0.7f*Qs; shortwave_exact_1 = 0.3f*0.2f*Qs; - longwave_exact_0 = 0.f;//sigma*powf(300.f,4)*0.2f; + longwave_exact_0 = 0.f; longwave_exact_1 = sigma*powf(300.f,4)*0.2f; Context context_1; @@ -464,7 +464,7 @@ int RadiationModel::selfTest(){ std::cout << "Test #6: Parallel disks (Texture Masked Patches)..." << std::flush; - uint Ndirect_6 = 100; + uint Ndirect_6 = 1000; uint Ndiffuse_6 = 500000; shortwave_rho = 0.3; diff --git a/plugins/visualizer/src/Visualizer.cpp b/plugins/visualizer/src/Visualizer.cpp index e8a84fa14..4b6068b8b 100755 --- a/plugins/visualizer/src/Visualizer.cpp +++ b/plugins/visualizer/src/Visualizer.cpp @@ -2421,6 +2421,7 @@ void Visualizer::addTextboxByCenter( const char* textstring, const vec3 ¢er, } + FT_Done_Face(face); FT_Done_FreeType(ft); } @@ -4371,7 +4372,7 @@ void cursorCallback( GLFWwindow* window, double xpos, double ypos ){ void scrollCallback( GLFWwindow* window, double xoffset, double yoffset ){ dscroll = (float) yoffset; scrollY = yoffset; - if (yoffset > 0.0 or yoffset < 0.0){ + if (yoffset > 0.0 || yoffset < 0.0){ scroll = true; } else {scroll = false;} } diff --git a/samples/context_selftest/main.cpp b/samples/context_selftest/main.cpp index 5756fd438..2cc75f728 100755 --- a/samples/context_selftest/main.cpp +++ b/samples/context_selftest/main.cpp @@ -4,6 +4,17 @@ using namespace helios; int main(){ +#ifdef USE_OPENMP + std::cout << "OpenMP is enabled. Running with " << omp_get_max_threads() << " threads.\n"; + #pragma omp parallel + { + int id = omp_get_thread_num(); + std::cout << "Hello from thread " << id << std::endl; + } +#else + std::cout << "OpenMP is not enabled. Running single-threaded.\n"; +#endif + //Run the self-test return Context::selfTest(); diff --git a/samples/plantarchitecture_selftest/main.cpp b/samples/plantarchitecture_selftest/main.cpp index 58d3851fe..ad6621586 100755 --- a/samples/plantarchitecture_selftest/main.cpp +++ b/samples/plantarchitecture_selftest/main.cpp @@ -3,7 +3,6 @@ using namespace helios; int main(){ - //Run the self-test return PlantArchitecture::selfTest(); diff --git a/samples/tutorial11/main.cpp b/samples/tutorial11/main.cpp index f422febaa..525785093 100644 --- a/samples/tutorial11/main.cpp +++ b/samples/tutorial11/main.cpp @@ -39,7 +39,7 @@ int main(){ // *** 2. Slicing and cropping primitives on the boundaries *** // - // slice and primitives that lie on the canopy boundaries (imagine taking a knife and perfectly cutting along the edges of the canopy) + // slice any primitives that lie on the canopy boundaries (imagine taking a knife and perfectly cutting along the edges of the canopy) VoxelIntersection vslice(&context); // define variables that give the center (x,y,z) coordinate of the canopy and the overall canopy dimensions