5#define WIN32_LEAN_AND_MEAN
9#elif defined(__APPLE__)
10#ifdef ENABLE_HELIOS_VISUALIZER
13#elif defined(__linux__)
14#ifdef ENABLE_HELIOS_VISUALIZER
22#ifdef ENABLE_HELIOS_VISUALIZER
26#define GLFW_INCLUDE_NONE
27#include "GLFW/glfw3.h"
28#include "backends/imgui_impl_glfw.h"
29#include "backends/imgui_impl_opengl3.h"
31#include "imgui_internal.h"
32#include "misc/cpp/imgui_stdlib.h"
38#ifdef ENABLE_BOUNDARYLAYERCONDUCTANCEMODEL
39const bool enable_blconductance =
true;
41const bool enable_blconductance =
false;
44#ifdef ENABLE_ENERGYBALANCEMODEL
45const bool enable_energybalance =
true;
47const bool enable_energybalance =
false;
50#ifdef ENABLE_PLANT_ARCHITECTURE
51const bool enable_plantarchitecture =
true;
53const bool enable_plantarchitecture =
false;
56#ifdef ENABLE_RADIATION_MODEL
57const bool enable_radiation =
true;
59const bool enable_radiation =
false;
62#ifdef ENABLE_SOLARPOSITION
63const bool enable_solarposition =
true;
65const bool enable_solarposition =
false;
68#ifdef ENABLE_HELIOS_VISUALIZER
69const bool enable_visualizer =
true;
71const bool enable_visualizer =
false;
75using namespace helios;
79 std::ostringstream oss;
80 oss << v.
x <<
" " << v.
y;
85 std::ostringstream oss;
86 oss << v.
x <<
" " << v.
y;
91 std::ostringstream oss;
92 oss << v.
x <<
" " << v.
y <<
" " << v.
z;
96std::vector<vec3>
interpolate(
const std::vector<int> &keypoints,
const std::vector<helios::vec3> &positions,
int num_points) {
97 std::vector<vec3> pos = positions;
98 std::vector<vec3> result(num_points);
99 std::vector<int> keypoints_sorted = keypoints;
100 std::sort(keypoints_sorted.begin(), keypoints_sorted.end());
101 std::map<int, int> keypoints_loc;
102 for (
int i = 0; i < keypoints.size(); i++) {
103 keypoints_loc.insert({keypoints[i], i});
105 if (keypoints.size() == 1) {
106 std::fill(result.begin(), result.end(), pos[0]);
109 if (keypoints_sorted[keypoints_sorted.size() - 1] != num_points - 1) {
110 keypoints_sorted.push_back(num_points - 1);
111 keypoints_loc.insert({num_points - 1,
static_cast<int>(keypoints.size())});
112 pos.push_back(pos[pos.size() - 1]);
114 for (
int i = 0; i < keypoints_sorted.size() - 1; i++) {
115 int keypoint = keypoints_sorted[i];
116 int keypoint_idx = keypoints_loc[keypoints_sorted[i]];
117 int next_keypoint = keypoints_sorted[i + 1];
118 int next_keypoint_idx = keypoints_loc[keypoints_sorted[i + 1]];
119 std::vector<vec3> curr_positions =
linspace(pos[keypoint_idx], pos[next_keypoint_idx], next_keypoint - keypoint + 1);
120 for (
int j = 0; j < next_keypoint - keypoint + 1; j++) {
121 int idx = j + keypoint;
122 result[idx] = curr_positions[j];
129#ifdef ENABLE_HELIOS_VISUALIZER
130 ImVec2 p = ImGui::GetCursorScreenPos();
131 ImDrawList *draw_list = ImGui::GetWindowDrawList();
133 float height = ImGui::GetFrameHeight();
134 float width = height * 1.55f;
135 float radius = height * 0.50f;
137 ImGui::InvisibleButton(str_id, ImVec2(width, height));
138 if (ImGui::IsItemClicked())
141 float t = *v ? 1.0f : 0.0f;
143 ImGuiContext &g = *GImGui;
144 const float ANIM_SPEED = 0.08f;
145 if (g.LastActiveId == g.CurrentWindow->GetID(str_id))
147 float t_anim = ImSaturate(g.LastActiveIdTimer / ANIM_SPEED);
148 t = *v ? (t_anim) : (1.0f - t_anim);
152 if (ImGui::IsItemHovered())
153 col_bg = ImGui::GetColorU32(ImLerp(ImVec4(0.78f, 0.78f, 0.78f, 1.0f), ImVec4(0.64f, 0.83f, 0.34f, 1.0f), t));
155 col_bg = ImGui::GetColorU32(ImLerp(ImVec4(0.85f, 0.85f, 0.85f, 1.0f), ImVec4(0.56f, 0.83f, 0.26f, 1.0f), t));
157 draw_list->AddRectFilled(p, ImVec2(p.x + width, p.y + height), col_bg, height * 0.5f);
158 draw_list->AddCircleFilled(ImVec2(p.x + radius + t * (width - radius * 2.0f), p.y + radius), radius - 1.5f, IM_COL32(255, 255, 255, 255));
163static bool nfd_corrupted_imgui =
false;
166 std::string file_name;
167#ifdef ENABLE_HELIOS_VISUALIZER
171 GetCurrentDirectory(MAX_PATH, CWD);
174 char szFile[260] = {0};
176 ZeroMemory(&ofn,
sizeof(ofn));
177 ofn.lStructSize =
sizeof(ofn);
178 ofn.hwndOwner =
nullptr;
179 ofn.lpstrFile = szFile;
180 ofn.nMaxFile =
sizeof(szFile);
181 ofn.lpstrFilter =
"All Files\0*.*\0Text Files\0*.txt\0";
182 ofn.nFilterIndex = 1;
183 ofn.lpstrFileTitle =
nullptr;
184 ofn.nMaxFileTitle = 0;
185 ofn.lpstrInitialDir =
nullptr;
186 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
188 if (GetOpenFileName(&ofn)) {
189 std::cout <<
"Selected file: " << ofn.lpstrFile << std::endl;
191 std::cout <<
"No file selected." << std::endl;
196 SetCurrentDirectory(CWD);
198 file_name = (std::string) ofn.lpstrFile;
199#elif defined(__APPLE__)
200 nfdchar_t *outPath =
nullptr;
201 nfdresult_t result = NFD_OpenDialog(
nullptr,
nullptr, &outPath);
203 if (result == NFD_OKAY) {
206 file_name = std::string(outPath);
208 }
else if (result == NFD_CANCEL) {
209 puts(
"User pressed cancel.");
212 std::cout <<
"Error: " << NFD_GetError() << std::endl;
214#elif defined(__linux__)
215 nfdchar_t *outPath =
nullptr;
216 nfdresult_t result = NFD_OpenDialog(
nullptr,
nullptr, &outPath);
218 if (result == NFD_OKAY) {
221 file_name = std::string(outPath);
223 }
else if (result == NFD_CANCEL) {
224 puts(
"User pressed cancel.");
227 std::cout <<
"Error: " << NFD_GetError() << std::endl;
238 std::string file_name;
239#ifdef ENABLE_HELIOS_VISUALIZER
243 GetCurrentDirectory(MAX_PATH, CWD);
246 char szFile[260] = {0};
248 ZeroMemory(&ofn,
sizeof(ofn));
249 ofn.lStructSize =
sizeof(ofn);
250 ofn.hwndOwner =
nullptr;
251 ofn.lpstrFile = szFile;
252 ofn.nMaxFile =
sizeof(szFile);
253 std::string filterList =
"";
254 for (std::string extension: extensions) {
255 std::string ext_lower = extension;
256 std::string ext_upper = extension;
257 std::transform(ext_lower.begin(), ext_lower.end(), ext_lower.begin(), ::tolower);
258 std::transform(ext_upper.begin(), ext_upper.end(), ext_upper.begin(), ::toupper);
259 filterList += ext_upper +
" Files (*." + ext_lower +
")";
261 filterList +=
"*." + ext_lower;
265 ofn.lpstrFilter = filterList.c_str();
266 ofn.nFilterIndex = 1;
267 ofn.lpstrFileTitle =
nullptr;
268 ofn.nMaxFileTitle = 0;
269 ofn.lpstrInitialDir =
nullptr;
270 ofn.Flags = OFN_PATHMUSTEXIST;
272 if (GetSaveFileName(&ofn)) {
273 std::cout <<
"Selected file: " << ofn.lpstrFile << std::endl;
275 std::cout <<
"No file selected." << std::endl;
279 std::string ext_ = extensions[ofn.nFilterIndex - 1];
280 std::transform(ext_.begin(), ext_.end(), ext_.begin(), ::tolower);
281 std::string ext =
"." + ext_;
284 SetCurrentDirectory(CWD);
286 file_name = (std::string) ofn.lpstrFile;
288 std::filesystem::path file_path(file_name);
289 if (file_path.extension().empty()) {
290 file_path.replace_extension(ext);
291 file_name = file_path.string();
293#elif defined(__APPLE__)
294 nfdchar_t *outPath =
nullptr;
295 std::string filterList_ =
"";
296 for (std::string extension: extensions) {
297 std::string ext_lower = extension;
298 std::transform(ext_lower.begin(), ext_lower.end(), ext_lower.begin(), ::tolower);
299 filterList_ += ext_lower +
",";
301 if (!filterList_.empty() && filterList_.back() ==
',')
302 filterList_.pop_back();
303 const nfdchar_t *filterList = filterList_.c_str();
304 nfdresult_t result = NFD_SaveDialog(filterList,
nullptr, &outPath);
306 if (result == NFD_OKAY) {
309 file_name = std::string(outPath);
312 std::string ext_ = extensions[0];
313 std::transform(ext_.begin(), ext_.end(), ext_.begin(), ::tolower);
314 std::string ext =
"." + ext_;
315 if (file_name.find(
'.') == std::string::npos)
317 }
else if (result == NFD_CANCEL) {
318 puts(
"User pressed cancel.");
321 std::cout <<
"Error: " << NFD_GetError() << std::endl;
323#elif defined(__linux__)
324 nfdchar_t *outPath =
nullptr;
325 std::string filterList_ =
"";
326 for (std::string extension: extensions) {
327 std::string ext_lower = extension;
328 std::transform(ext_lower.begin(), ext_lower.end(), ext_lower.begin(), ::tolower);
329 filterList_ += ext_lower +
",";
331 if (!filterList_.empty() && filterList_.back() ==
',')
332 filterList_.pop_back();
333 const nfdchar_t *filterList = filterList_.c_str();
334 nfdresult_t result = NFD_SaveDialog(filterList,
nullptr, &outPath);
336 if (result == NFD_OKAY) {
339 file_name = std::string(outPath);
342 std::string ext_ = extensions[0];
343 std::transform(ext_.begin(), ext_.end(), ext_.begin(), ::tolower);
344 std::string ext =
"." + ext_;
345 if (file_name.find(
'.') == std::string::npos)
347 }
else if (result == NFD_CANCEL) {
348 puts(
"User pressed cancel.");
351 std::cout <<
"Error: " << NFD_GetError() << std::endl;
360std::vector<std::string>
get_xml_node_values(
const std::string &xml_input,
const std::string &name,
const std::string &parent) {
362 pugi::xml_document xml_library_doc;
363 std::vector<std::string> labels_vec{};
364 std::string xml_library_error =
"Failed to load XML Library file";
365 if (!
open_xml_file(xml_input, xml_library_doc, xml_library_error)) {
368 pugi::xml_node helios = xml_library_doc.child(
"helios");
369 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
370 std::string default_value =
"";
371 if (!p.attribute(name.c_str()).empty()) {
372 const char *node_str = p.attribute(name.c_str()).value();
373 default_value = (std::string) node_str;
375 labels_vec.push_back(default_value);
382void ProjectBuilder::deleteArrows() {
383 for (
auto &arrow_vec: arrow_dict) {
384 for (std::vector<uint> arrow: arrow_vec.second) {
392void ProjectBuilder::updateArrows() {
393#ifdef ENABLE_RADIATION_MODEL
394 for (
auto rig_label_: rig_labels_set) {
396 std::string current_rig = rig_label_;
397 arrow_dict[current_rig] = std::vector<std::vector<uint>>{};
398 for (
int i = 1; i < camera_position_vec[rig_dict[current_rig]].size(); i++) {
399 vec3 arrow_pos = camera_position_vec[rig_dict[current_rig]][i - 1];
400 vec3 arrow_direction_vec = arrow_pos - camera_position_vec[rig_dict[current_rig]][i];
402 vec3 arrow_scale(0.35, 0.35, 0.35);
403 arrow_dict[current_rig].push_back(
context->
loadOBJ(
"plugins/radiation/camera_light_models/Arrow.obj", nullorigin, arrow_scale, nullrotation, RGB::blue,
"YUP",
true));
411 RGBcolor rig_color = rig_colors[rig_dict[current_rig]];
412 col[0] = rig_color.
r;
413 col[1] = rig_color.
g;
414 col[2] = rig_color.
b;
421void ProjectBuilder::deleteCameraModels() {
422 for (
auto &camera_model: camera_models_dict) {
425 camera_models_dict.clear();
429void ProjectBuilder::updateCameraModels() {
430#ifdef ENABLE_RADIATION_MODEL
431 for (
auto rig_label_: rig_labels_set) {
432 int camera_idx = rig_dict[rig_label_];
433 camera_models_dict[rig_label_] = std::vector<uint>{};
434 vec3 camera_pos = camera_position_vec[camera_idx][0];
435 vec3 camera_direction_vec = camera_lookat_vec[camera_idx][0] - camera_pos;
437 vec3 camera_scale(1.0, 1.0, 1.0);
438 camera_models_dict[rig_label_] =
context->
loadOBJ(
"plugins/radiation/camera_light_models/Camera.obj", nullorigin, camera_scale, nullrotation, RGB::blue,
"ZUP",
true);
444 RGBcolor rig_color = rig_colors[camera_idx];
445 col[0] = rig_color.
r;
446 col[1] = rig_color.
g;
447 col[2] = rig_color.
b;
454void ProjectBuilder::updatePrimitiveTypes() {
457 primitive_names.clear();
458 primitive_names_set.clear();
459 primitive_UUIDs.clear();
464 primitive_names.push_back(
"All");
465 primitive_names_set.insert(
"All");
468 for (
auto &primitive_UUID: allUUIDs) {
469 std::string default_value;
472 if (primitive_names_set.find(default_value) == primitive_names_set.end()) {
473 primitive_names.push_back(default_value);
474 primitive_names_set.insert(default_value);
476 if (primitive_UUIDs.find(default_value) == primitive_UUIDs.end()) {
477 std::vector<uint> new_UUIDs;
479 primitive_UUIDs.insert({default_value, new_UUIDs});
481 primitive_UUIDs[default_value].push_back(primitive_UUID);
482 if (primitive_continuous.find(default_value) == primitive_continuous.end()) {
483 primitive_continuous.insert({default_value, {
false,
false,
false}});
484 for (std::string band: bandlabels) {
485 primitive_values[band].insert({default_value, {reflectivity, transmissivity, emissivity}});
487 primitive_spectra.insert({default_value, {reflectivity_spectrum, transmissivity_spectrum, emissivity_spectrum}});
490 current_primitive =
"All";
512void ProjectBuilder::updateDataGroups() {
515 data_groups_set.clear();
516 data_groups_set.insert(
"All");
517 for (
auto &group: data_groups) {
518 data_groups_set.insert(group);
524 for (std::pair<std::string, std::vector<uint>> primitive_pair: primitive_UUIDs) {
525 if (primitive_continuous[primitive_pair.first].empty())
527 if (!primitive_continuous[primitive_pair.first][0]) {
528 for (std::string band: bandlabels) {
529 float reflectivity = primitive_values[band][primitive_pair.first][0];
530 std::string reflectivity_band =
"reflectivity_" + band;
534 std::string reflectivity_spectrum = primitive_spectra[primitive_pair.first][0];
535 if (!reflectivity_spectrum.empty()) {
536 context->
setPrimitiveData(primitive_UUIDs[primitive_pair.first],
"reflectivity_spectrum", reflectivity_spectrum);
538 std::cout <<
"WARNING: No value given for '" << primitive_pair.first <<
"_reflectivity_spectrum'. Assuming " << primitive_pair.first <<
" primitives are black across all shortwave bands." << std::endl;
541 if (!primitive_continuous[primitive_pair.first][1]) {
542 for (std::string band: bandlabels) {
543 float transmissivity = primitive_values[band][primitive_pair.first][1];
544 std::string transmissivity_band =
"transmissivity_" + band;
548 std::string transmissivity_spectrum = primitive_spectra[primitive_pair.first][1];
549 if (!transmissivity_spectrum.empty()) {
550 context->
setPrimitiveData(primitive_UUIDs[primitive_pair.first],
"transmissivity_spectrum", transmissivity_spectrum);
552 std::cout <<
"WARNING: No value given for '" << primitive_pair.first <<
"_transmissivity_spectrum'. Assuming " << primitive_pair.first <<
" primitives are black across all shortwave bands." << std::endl;
555 if (!primitive_continuous[primitive_pair.first][2]) {
556 for (std::string band: bandlabels) {
557 if (bandlabels_set_emissivity.find(band) != bandlabels_set_emissivity.end())
559 float emissivity = primitive_values[band][primitive_pair.first][2];
560 std::string emissivity_band =
"emissivity_" + band;
564 std::string emissivity_spectrum = primitive_spectra[primitive_pair.first][2];
565 if (!emissivity_spectrum.empty()) {
568 std::cout <<
"WARNING: No value given for '" << primitive_pair.first <<
"_emissivity_spectrum'. Assuming " << primitive_pair.first <<
" primitives are black across all shortwave bands." << std::endl;
573 for (
uint UUID: all_UUIDs) {
578 std::string curr_data_group;
581 std::string curr_prim_type;
585 curr_prim_type =
"All";
587 if (primitive_continuous_dict[curr_data_group][curr_prim_type].empty())
589 if (!primitive_continuous_dict[curr_data_group][curr_prim_type][0]) {
590 for (std::string band: bandlabels) {
591 float reflectivity = primitive_values_dict[curr_data_group][band][curr_prim_type][0];
592 std::string reflectivity_band =
"reflectivity_" + band;
596 std::string reflectivity_spectrum = primitive_spectra_dict[curr_data_group][curr_prim_type][0];
597 if (!reflectivity_spectrum.empty()) {
600 std::cout <<
"WARNING: No value given for '" << curr_prim_type <<
"_reflectivity_spectrum'. Assuming " << curr_prim_type <<
" primitives are black across all shortwave bands." << std::endl;
603 if (!primitive_continuous_dict[curr_data_group][curr_prim_type][1]) {
604 for (std::string band: bandlabels) {
605 float transmissivity = primitive_values_dict[curr_data_group][band][curr_prim_type][1];
606 std::string transmissivity_band =
"transmissivity_" + band;
610 std::string transmissivity_spectrum = primitive_spectra_dict[curr_data_group][curr_prim_type][1];
611 if (!transmissivity_spectrum.empty()) {
614 std::cout <<
"WARNING: No value given for '" << curr_prim_type <<
"_transmissivity_spectrum'. Assuming " << curr_prim_type <<
" primitives are black across all shortwave bands." << std::endl;
617 if (!primitive_continuous_dict[curr_data_group][curr_prim_type][2]) {
618 for (std::string band: bandlabels) {
619 if (bandlabels_set_emissivity.find(band) != bandlabels_set_emissivity.end())
621 float emissivity = primitive_values_dict[curr_data_group][band][curr_prim_type][2];
622 std::string emissivity_band =
"emissivity_" + band;
626 std::string emissivity_spectrum = primitive_spectra_dict[curr_data_group][curr_prim_type][2];
627 if (!emissivity_spectrum.empty()) {
630 std::cout <<
"WARNING: No value given for '" << curr_prim_type <<
"_emissivity_spectrum'. Assuming " << curr_prim_type <<
" primitives are black across all shortwave bands." << std::endl;
634#ifdef ENABLE_RADIATION_MODEL
640#ifdef ENABLE_RADIATION_MODEL
641 for (std::string rig_label: rig_labels_set) {
642 int rig_index = rig_dict[rig_label];
643 for (std::string rig_camera_label: rig_camera_labels[rig_index]) {
644 int camera_index = camera_dict[rig_camera_label];
656 std::string camera_label_ = rig_label +
"_" + rig_camera_label;
657 vec3 camera_position_ = camera_positions[rig_index];
658 vec3 camera_lookat_ = camera_lookats[rig_index];
660 for (
auto &band: bandlabels) {
666 for (std::string band_group_name: band_group_names) {
667 bandGroup curr_band_group = band_group_lookup[band_group_name];
668 if (!curr_band_group.grayscale) {
678#ifdef ENABLE_RADIATION_MODEL
680 deleteCameraModels();
683 for (
int _ = 0; _ < num_recordings; _++) {
685 std::string image_dir =
"./saved/";
686 std::string image_dir_base =
"./saved_";
687 int image_dir_idx = 0;
688 while (std::filesystem::exists(image_dir)) {
689 image_dir = image_dir_base + std::to_string(image_dir_idx) +
"/";
692 std::filesystem::create_directory(image_dir);
693 std::cout <<
"Saving images to " << image_dir << std::endl;
695 std::ofstream classes_names_file(image_dir +
"classes.names");
696 if (classes_names_file.is_open()) {
697 std::vector<std::string> classes(bounding_boxes_map.size());
698 for (
auto &bbox_pair: bounding_boxes_map) {
699 classes[bbox_pair.second] = bbox_pair.first;
701 for (std::string cls: classes) {
702 classes_names_file << cls << std::endl;
706 std::vector<uint> temp_lights{};
707 for (std::string rig_label: rig_labels_set) {
708 int rig_index = rig_dict[rig_label];
709 std::vector<vec3> interpolated_camera_positions =
interpolate(keypoint_frames[rig_index], camera_position_vec[rig_index], num_images_vec[rig_index]);
710 std::vector<vec3> interpolated_camera_lookats =
interpolate(keypoint_frames[rig_index], camera_lookat_vec[rig_index], num_images_vec[rig_index]);
712 for (std::string light: rig_light_labels[rig_dict[rig_label]]) {
713 int light_idx = light_dict[light];
715 if (light_types[light_idx] ==
"sphere") {
717 temp_lights.push_back(new_light_UUID);
718 }
else if (light_types[light_dict[light]] ==
"rectangle") {
720 temp_lights.push_back(new_light_UUID);
721 }
else if (light_types[light_dict[light]] ==
"disk") {
723 temp_lights.push_back(new_light_UUID);
725 for (
auto &band: bandlabels) {
732 for (
int i = 0; i < interpolated_camera_positions.size(); i++) {
734 for (
uint light_ID: temp_lights) {
739 for (std::string rig_camera_label: rig_camera_labels[rig_index]) {
740 int camera_index = camera_dict[rig_camera_label];
741 std::string cameralabel = rig_label +
"_" + rig_camera_label;
746 for (std::string band_group_name: band_group_names) {
747 bandGroup curr_band_group = band_group_lookup[band_group_name];
748 if (!curr_band_group.grayscale) {
754 for (std::string rig_camera_label: rig_camera_labels[rig_index]) {
755 std::string cameralabel = rig_label +
"_" + rig_camera_label;
757 for (std::string band_group_name: band_group_names) {
758 bandGroup curr_band_group = band_group_lookup[band_group_name];
759 if (std::find(curr_band_group.bands.begin(), curr_band_group.bands.end(),
"red") != curr_band_group.bands.end() &&
760 std::find(curr_band_group.bands.begin(), curr_band_group.bands.end(),
"green") != curr_band_group.bands.end() &&
761 std::find(curr_band_group.bands.begin(), curr_band_group.bands.end(),
"blue") != curr_band_group.bands.end()) {
764 std::vector<std::string> band_group_vec;
765 if (!curr_band_group.grayscale) {
766 band_group_vec = curr_band_group.bands;
768 band_group_vec = std::vector<std::string>{curr_band_group.bands[0]};
770 radiation->
writeCameraImage(cameralabel, band_group_vec, band_group_name + std::to_string(i), image_dir + rig_label +
'/');
771 if (band_group_lookup[band_group_name].norm) {
775 if (write_depth[rig_dict[current_rig]])
777 if (write_norm_depth[rig_dict[current_rig]])
781 for (std::string band_group_: band_group_names) {
782 for (std::string primitive_name: primitive_names) {
783 if (!primitive_name.empty()) {
784 primitive_name[0] = std::tolower(
static_cast<unsigned char>(primitive_name[0]));
787 for (
auto &box_pair: bounding_boxes_map) {
788 if (bounding_boxes_object.find(box_pair.first) != bounding_boxes_object.end()) {
790 if (write_segmentation_mask[rig_dict[current_rig]]) {
793 }
else if (bounding_boxes_primitive.find(box_pair.first) == bounding_boxes_object.end()) {
794 radiation->
writeImageBoundingBoxes(cameralabel, box_pair.first, box_pair.second, band_group_ + std::to_string(i) +
"_bbox",
"classes.txt", image_dir + rig_label +
'/');
795 if (write_segmentation_mask[rig_dict[current_rig]]) {
805 for (
uint temp_light: temp_lights) {
814 updateCameraModels();
815#ifdef ENABLE_HELIOS_VISUALIZER
824#ifdef ENABLE_HELIOS_VISUALIZER
825 const char *font_name =
"LCD";
832#ifdef ENABLE_BOUNDARYLAYERCONDUCTANCEMODEL
836#ifdef ENABLE_ENERGYBALANCEMODEL
840#ifdef ENABLE_SOLARPOSITION
844#ifdef ENABLE_RADIATION_MODEL
850#ifdef ENABLE_CANOPY_GENERATOR
854#ifdef ENABLE_PLANT_ARCHITECTURE
867#ifdef ENABLE_HELIOS_VISUALIZER
868#ifdef ENABLE_PLANT_ARCHITECTURE
884#ifdef ENABLE_PLANT_ARCHITECTURE
886#ifdef ENABLE_RADIATION_MODEL
889 std::cout <<
"Loaded PlantArchitecture plugin." << std::endl;
892 std::cout <<
"Excluding PlantArchitecture plugin." << std::endl;
896 InitializeSimulation(xml_input_file,
context);
899#ifdef ENABLE_PLANT_ARCHITECTURE
906#ifdef ENABLE_RADIATION_MODEL
908 std::cout <<
"Loaded Radiation plugin." << std::endl;
911 std::cout <<
"Excluding Radiation plugin." << std::endl;
916#ifdef ENABLE_SOLARPOSITION
918 std::cout <<
"Loaded SolarPosition plugin." << std::endl;
921 std::cout <<
"Excluding SolarPosition plugin." << std::endl;
926#ifdef ENABLE_RADIATION_MODEL
932#ifdef ENABLE_ENERGYBALANCEMODEL
934 std::cout <<
"Loaded EnergyBalance plugin." << std::endl;
937 std::cout <<
"Excluding EnergyBalance plugin." << std::endl;
942#ifdef ENABLE_BOUNDARYLAYERCONDUCTANCEMODEL
944 std::cout <<
"Loaded BoundaryLayerConductance plugin." << std::endl;
947 std::cout <<
"Excluding BoundaryLayerConductance plugin." << std::endl;
952#if defined(ENABLE_ENERGYBALANCEMODEL) && defined(ENABLE_BOUNDARYLAYERCONDUCTANCEMODEL)
957#ifdef ENABLE_CANOPY_GENERATOR
959 std::cout <<
"Loaded CanopyGenerator plugin." << std::endl;
962 std::cout <<
"Excluding CanopyGenerator plugin." << std::endl;
967 if (enable_radiation) {
972 if (enable_radiation) {
977 if (enable_radiation) {
984 if (enable_plantarchitecture) {
988 primitive_UUIDs[
"ground"] = ground_UUIDs;
989 primitive_UUIDs[
"leaf"] = leaf_UUIDs;
997 if (!
open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
1002 updatePrimitiveTypes();
1009 if (timeseries_variables.empty()) {
1010 std::cout <<
"No timeseries data was loaded. Skipping time loop." << std::endl;
1014 for (
uint timestep = 0; timestep < num_time_points; timestep++) {
1027 if (air_humidity > 1) {
1029 air_humidity /= 100.f;
1030 if (air_humidity > 1) {
1031 std::cout <<
"WARNING: air_humidity must be between 0 and 1. Setting to default value of 0.5." << std::endl;
1032 air_humidity = 0.5f;
1034 std::cout <<
"WARNING: air_humidity read from timeseries was greater than 1.0. It was assumed that the given value was in percent and was automatically divided by 100." << std::endl;
1040#ifdef ENABLE_RADIATION_MODEL
1045 if (diffuse_extinction_coeff > 0) {
1064 std::vector<std::string> new_band_group_vector = {
"PAR",
"NIR",
"LW"};
1065 bandGroup new_band_group{new_band_group_vector,
false,
false,
false};
1066 band_group_lookup.insert({
"default", new_band_group});
1067 band_group_names.insert(
"default");
1070 PAR_absorbed /= ground_area;
1073 NIR_absorbed /= ground_area;
1076 LW_absorbed /= ground_area;
1078 std::cout <<
"Absorbed PAR: " << PAR_absorbed <<
" W/m^2" << std::endl;
1079 std::cout <<
"Absorbed NIR: " << NIR_absorbed <<
" W/m^2" << std::endl;
1080 std::cout <<
"Absorbed LW: " << LW_absorbed <<
" W/m^2" << std::endl;
1085 for (
auto &xml_file: camera_xml_library_files) {
1086 if (xml_file.empty() || !std::filesystem::exists(xml_file)) {
1087 std::cout <<
"WARNING: Could not find camera XML library file: " + xml_file <<
". Skipping..." << std::endl;
1093 for (
auto &xml_file: light_xml_library_files) {
1094 if (xml_file.empty() || !std::filesystem::exists(xml_file)) {
1095 std::cout <<
"WARNING: Could not find light XML library file: " + xml_file <<
". Skipping..." << std::endl;
1102#ifdef ENABLE_RADIATION_MODEL
1122 updateCameraModels();
1124 helios = xmldoc.child(
"helios");
1126 refreshVisualizationTypes();
1133 xml_input_file = xml_path;
1140 std::map<std::string, int> labels_dict = {};
1141 helios = xmldoc.child(
"helios");
1142 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1143 std::string default_value =
"canopy_0";
1144 if (!p.attribute(name.c_str()).empty()) {
1145 const char *node_str = p.attribute(name.c_str()).value();
1146 default_value = (std::string) node_str;
1148 labels_vec.push_back(default_value);
1149 labels_dict.insert({default_value, counter});
1157 helios = xmldoc.child(
"helios");
1158 const char *rig_ =
"rig";
1159 for (pugi::xml_node
rig = helios.child(rig_);
rig;
rig =
rig.next_sibling(rig_)) {
1161 std::vector<int> curr_keypoints;
1162 for (pugi::xml_node p =
rig.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1163 std::string default_value = std::to_string(count);
1164 if (!p.attribute(name.c_str()).empty()) {
1165 const char *node_str = p.attribute(name.c_str()).value();
1166 default_value = (std::string) node_str;
1168 std::stringstream keypoint_value;
1169 keypoint_value << default_value.c_str();
1171 keypoint_value >> keypoint_;
1172 curr_keypoints.push_back(keypoint_);
1175 keypoints.push_back(curr_keypoints);
1180 helios = xmldoc.child(
"helios");
1181 const char *rig_ =
"rig";
1183 for (pugi::xml_node
rig = helios.child(rig_);
rig;
rig =
rig.next_sibling(rig_)) {
1185 for (pugi::xml_node p =
rig.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1186 std::string default_value = std::to_string(count);
1187 p.append_attribute(name.c_str());
1188 p.attribute(name.c_str()).set_value(keypoints[rig_count][count]);
1196 helios = xmldoc.child(
"helios");
1197 pugi::xml_node p = helios;
1198 if (parent !=
"helios") {
1199 p = helios.child(parent.c_str());
1201 pugi::xml_node node;
1202 node = p.child(name.c_str());
1204 std::cout <<
"WARNING: No value given for '" << name <<
"'. Using default value of " << default_value << std::endl;
1206 const char *node_str = node.child_value();
1207 if (!
parse_int(node_str, default_value)) {
1209 }
else if (default_value < 0) {
1210 helios_runtime_error(
"ERROR: Value given for '" + name +
"' must be greater than or equal to 0.");
1216 helios = xmldoc.child(
"helios");
1217 pugi::xml_node p = helios;
1218 if (parent !=
"helios") {
1219 p = helios.child(parent.c_str());
1221 pugi::xml_node node;
1222 node = p.child(name.c_str());
1224 std::cout <<
"WARNING: No value given for '" << name <<
"'. Using default value of " << default_value << std::endl;
1226 const char *node_str = node.child_value();
1237 helios = xmldoc.child(
"helios");
1238 pugi::xml_node p = helios;
1239 if (parent !=
"helios") {
1240 p = helios.child(parent.c_str());
1242 pugi::xml_node node;
1243 node = p.child(name.c_str());
1245 std::cout <<
"WARNING: No value given for '" << name <<
"'. Using default value of " << default_value << std::endl;
1247 const char *node_str = node.child_value();
1248 default_value = node_str;
1253 helios = xmldoc.child(
"helios");
1254 pugi::xml_node p = helios;
1255 if (parent !=
"helios") {
1256 p = helios.child(parent.c_str());
1258 pugi::xml_node node;
1259 node = p.child(name.c_str());
1261 std::cout <<
"WARNING: No value given for '" << name <<
"'. Using default value of " << default_value << std::endl;
1263 const char *node_str = node.child_value();
1266 }
else if (default_value.
x <= 0 || default_value.
y <= 0) {
1273 helios = xmldoc.child(
"helios");
1274 pugi::xml_node p = helios;
1275 if (parent !=
"helios") {
1276 p = helios.child(parent.c_str());
1278 pugi::xml_node node;
1279 node = p.child(name.c_str());
1281 std::cout <<
"WARNING: No value given for '" << name <<
"'. Using default value of " << default_value << std::endl;
1283 const char *node_str = node.child_value();
1292 helios = xmldoc.child(
"helios");
1293 pugi::xml_node p = helios;
1294 if (parent !=
"helios") {
1295 p = helios.child(parent.c_str());
1297 pugi::xml_node node;
1298 node = p.child(name.c_str());
1300 std::cout <<
"WARNING: No value given for '" << name <<
"'. Using default value of " << default_value << std::endl;
1302 const char *node_str = node.child_value();
1305 }
else if (default_value.
x <= 0 || default_value.
y <= 0) {
1313 helios = xmldoc.child(
"helios");
1314 pugi::xml_node p = helios;
1315 if (parent !=
"helios") {
1316 p = helios.child(parent.c_str());
1318 pugi::xml_node node;
1319 node = p.child(name.c_str());
1321 std::cout <<
"WARNING: No distribution given for '" << name <<
"'. Using default distribution of N/A." << std::endl;
1324 const char *node_str = node.child_value();
1333 helios = xmldoc.child(
"helios");
1334 pugi::xml_node p = helios;
1335 if (parent !=
"helios") {
1336 p = helios.child(parent.c_str());
1338 pugi::xml_node node;
1339 node = p.child(name.c_str());
1341 node = p.append_child(name.c_str());
1343 std::string dist_type;
1344 std::string param_1;
1345 std::string param_2;
1348 dist_type =
"normal";
1349 param_1 = std::to_string(
distribution.dist.normal->mean());
1350 param_2 = std::to_string(
distribution.dist.normal->stddev());
1353 dist_type =
"uniform";
1354 param_1 = std::to_string(
distribution.dist.uniform->a());
1355 param_2 = std::to_string(
distribution.dist.uniform->b());
1358 dist_type =
"weibull";
1359 param_1 = std::to_string(
distribution.dist.weibull->a());
1360 param_2 = std::to_string(
distribution.dist.weibull->b());
1368 node.text().set((dist_type +
" " + param_1 +
" " + param_2 +
" " + repeat).c_str());
1372bool parse_distribution(
const std::string &input_string,
distribution &converted_distribution) {
1373 std::istringstream vecstream(input_string);
1374 std::vector<std::string> tmp_s(4);
1375 vecstream >> tmp_s[0];
1376 vecstream >> tmp_s[1];
1377 vecstream >> tmp_s[2];
1378 vecstream >> tmp_s[3];
1379 std::string dist_type;
1380 std::vector<float> dist_params = {0.0, 0.0};
1386 if (dist_type ==
"normal") {
1387 dist.normal =
new std::normal_distribution<float>;
1388 *dist.normal = std::normal_distribution<float>(dist_params[0], dist_params[1]);
1389 converted_distribution.dist = dist;
1390 converted_distribution.flag = 0;
1391 converted_distribution.repeat = (bool) repeat;
1392 }
else if (dist_type ==
"uniform") {
1393 dist.uniform =
new std::uniform_real_distribution<float>;
1394 *dist.uniform = std::uniform_real_distribution<float>(dist_params[0], dist_params[1]);
1395 converted_distribution.dist = dist;
1396 converted_distribution.flag = 1;
1397 converted_distribution.repeat = (bool) repeat;
1398 }
else if (dist_type ==
"weibull") {
1399 dist.weibull =
new std::weibull_distribution<float>;
1400 *dist.weibull = std::weibull_distribution<float>(dist_params[0], dist_params[1]);
1401 converted_distribution.dist = dist;
1402 converted_distribution.flag = 2;
1403 converted_distribution.repeat = (bool) repeat;
1405 converted_distribution.flag = -1;
1412 helios = xmldoc.child(
"helios");
1413 pugi::xml_node node;
1414 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1415 node = p.child(name.c_str());
1417 std::cout <<
"WARNING: No value given for '" << name <<
"'.";
1419 const char *node_str = node.child_value();
1428 default_vec.push_back(default_value);
1436 helios = xmldoc.child(
"helios");
1437 pugi::xml_node node;
1438 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1439 node = p.child(name.c_str());
1441 std::cout <<
"WARNING: No value given for '" << name <<
"'.";
1443 const char *node_str = node.child_value();
1448 default_vec.push_back(default_value);
1456 helios = xmldoc.child(
"helios");
1457 pugi::xml_node node;
1458 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1459 node = p.child(name.c_str());
1461 std::cout <<
"WARNING: No value given for '" << name <<
"'.";
1463 const char *node_str = node.child_value();
1465 default_vec.push_back(default_value);
1472 helios = xmldoc.child(
"helios");
1473 pugi::xml_node node;
1474 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1475 node = p.child(name.c_str());
1477 std::cout <<
"WARNING: No value given for '" << name <<
"'.";
1479 const char *node_str = node.child_value();
1480 float default_value;
1483 }
else if (default_value < 0) {
1484 helios_runtime_error(
"ERROR: Value given for '" + name +
"' must be greater than or equal to 0.");
1486 default_vec.push_back(default_value);
1494 helios = xmldoc.child(
"helios");
1495 pugi::xml_node node;
1496 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1497 node = p.child(name.c_str());
1499 std::cout <<
"WARNING: No value given for '" << name <<
"'.";
1501 const char *node_str = node.child_value();
1503 if (!
parse_int(node_str, default_value)) {
1505 }
else if (default_value < 0) {
1506 helios_runtime_error(
"ERROR: Value given for '" + name +
"' must be greater than or equal to 0.");
1508 default_vec.push_back(default_value);
1516 helios = xmldoc.child(
"helios");
1517 pugi::xml_node node;
1518 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1519 node = p.child(name.c_str());
1521 std::cout <<
"WARNING: No value given for '" << name <<
"'.";
1523 const char *node_str = node.child_value();
1527 }
else if (default_value.
x <= 0 || default_value.
y <= 0) {
1528 helios_runtime_error(
"ERROR: Value given for '" + name +
"' must be greater than or equal to 0.");
1530 default_vec.push_back(default_value);
1538 helios = xmldoc.child(
"helios");
1539 pugi::xml_node node;
1540 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1541 node = p.child(name.c_str());
1543 std::cout <<
"WARNING: No value given for '" << name <<
"'.";
1545 const char *node_str = node.child_value();
1550 default_vec.push_back(default_value);
1558 helios = xmldoc.child(
"helios");
1560 if (parent !=
"helios") {
1561 p_ = helios.child(parent.c_str());
1565 for (pugi::xml_node p = p_; p; p = p.next_sibling(parent.c_str())) {
1566 std::vector<vec3> curr_vec = {};
1567 for (pugi::xml_node node = p.child(name.c_str()); node; node = node.next_sibling(name.c_str())) {
1568 const char *node_str = node.child_value();
1573 curr_vec.push_back(default_value);
1576 default_vec.push_back(curr_vec);
1582 helios = xmldoc.child(
"helios");
1584 if (parent !=
"helios") {
1585 p_ = helios.child(parent.c_str());
1589 for (pugi::xml_node p = p_; p; p = p.next_sibling(parent.c_str())) {
1590 std::set<std::string> curr_vec = {};
1591 for (pugi::xml_node node = p.child(name.c_str()); node; node = node.next_sibling(name.c_str())) {
1592 const char *node_str = node.child_value();
1593 std::string default_value;
1597 default_value = node_str;
1598 curr_vec.insert(default_value);
1601 default_vec.push_back(curr_vec);
1607 helios = xmldoc.child(
"helios");
1609 if (parent !=
"helios") {
1610 p_ = helios.child(parent.c_str());
1614 for (pugi::xml_node p = p_; p; p = p.next_sibling(parent.c_str())) {
1615 for (pugi::xml_node node = p.child(name.c_str()); node; node = node.next_sibling(name.c_str())) {
1616 const char *node_str = node.child_value();
1617 std::string default_value;
1621 default_value = node_str;
1622 default_set.insert(default_value);
1631 helios = xmldoc.child(
"helios");
1633 std::set<pugi::xml_node> curr_nodes_set;
1634 for (pugi::xml_node node = helios.child(parent.c_str()); node; node = node.next_sibling(parent.c_str())) {
1635 curr_nodes_set.insert(node);
1637 for (
auto node: curr_nodes_set) {
1638 node.parent().remove_child(node);
1641 std::map<std::string, int> labels_dict = {};
1642 for (
auto new_node_label: labels_vec) {
1643 pugi::xml_node new_node = helios.append_child(parent.c_str());
1644 pugi::xml_attribute node_label = new_node.attribute(name.c_str());
1645 node_label.set_value(new_node_label.c_str());
1646 new_node.append_attribute(name.c_str()).set_value(new_node_label.c_str());
1654 helios = xmldoc.child(
"helios");
1655 pugi::xml_node p = helios;
1656 if (parent !=
"helios") {
1657 p = helios.child(parent.c_str());
1659 pugi::xml_node node;
1660 node = p.child(name.c_str());
1662 node = p.append_child(name.c_str());
1664 node.text().set(std::to_string(default_value).c_str());
1668 helios = xmldoc.child(
"helios");
1669 pugi::xml_node p = helios;
1670 if (parent !=
"helios") {
1671 p = helios.child(parent.c_str());
1673 pugi::xml_node node;
1674 node = p.child(name.c_str());
1676 node = p.append_child(name.c_str());
1678 node.text().set(std::to_string(default_value).c_str());
1682 helios = xmldoc.child(
"helios");
1683 pugi::xml_node p = helios;
1684 if (parent !=
"helios") {
1685 p = helios.child(parent.c_str());
1687 pugi::xml_node node;
1688 node = p.child(name.c_str());
1690 node = p.append_child(name.c_str());
1692 node.text().set(default_value.c_str());
1696 helios = xmldoc.child(
"helios");
1697 pugi::xml_node p = helios;
1698 if (parent !=
"helios") {
1699 p = helios.child(parent.c_str());
1701 pugi::xml_node node;
1702 node = p.child(name.c_str());
1704 p.remove_child(name.c_str());
1709 helios = xmldoc.child(
"helios");
1710 pugi::xml_node p = helios;
1711 if (parent !=
"helios") {
1712 p = helios.child(parent.c_str());
1714 pugi::xml_node node;
1715 node = p.child(name.c_str());
1717 node = p.append_child(name.c_str());
1723 helios = xmldoc.child(
"helios");
1724 pugi::xml_node p = helios;
1725 if (parent !=
"helios") {
1726 p = helios.child(parent.c_str());
1728 pugi::xml_node node;
1729 node = p.child(name.c_str());
1731 node = p.append_child(name.c_str());
1737 helios = xmldoc.child(
"helios");
1738 pugi::xml_node p = helios;
1739 if (parent !=
"helios") {
1740 p = helios.child(parent.c_str());
1742 pugi::xml_node node;
1743 node = p.child(name.c_str());
1745 node = p.append_child(name.c_str());
1751void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<vec2> &values_vec, std::map<std::string, int> &node_map) {
1752 helios = xmldoc.child(
"helios");
1754 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1755 pugi::xml_node node = p.child(field_name.c_str());
1757 node = p.append_child(field_name.c_str());
1759 pugi::xml_attribute label = p.attribute(
"label");
1760 int idx = node_map[label.as_string()];
1766void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<vec3> &values_vec, std::map<std::string, int> &node_map) {
1767 helios = xmldoc.child(
"helios");
1769 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1770 pugi::xml_node node = p.child(field_name.c_str());
1772 node = p.append_child(field_name.c_str());
1774 pugi::xml_attribute label = p.attribute(
"label");
1775 int idx = node_map[label.as_string()];
1781void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<helios::RGBcolor> &values_vec, std::map<std::string, int> &node_map) {
1782 helios = xmldoc.child(
"helios");
1784 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1785 pugi::xml_node node = p.child(field_name.c_str());
1787 node = p.append_child(field_name.c_str());
1789 pugi::xml_attribute label = p.attribute(
"label");
1790 int idx = node_map[label.as_string()];
1792 default_values_vec.
x = values_vec[idx].r;
1793 default_values_vec.
y = values_vec[idx].g;
1794 default_values_vec.
z = values_vec[idx].b;
1800void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<int2> &values_vec, std::map<std::string, int> &node_map) {
1801 helios = xmldoc.child(
"helios");
1803 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1804 pugi::xml_node node = p.child(field_name.c_str());
1806 node = p.append_child(field_name.c_str());
1808 pugi::xml_attribute label = p.attribute(
"label");
1809 int idx = node_map[label.as_string()];
1815void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<std::string> &values_vec, std::map<std::string, int> &node_map) {
1816 helios = xmldoc.child(
"helios");
1818 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1819 pugi::xml_node node = p.child(field_name.c_str());
1821 node = p.append_child(field_name.c_str());
1823 pugi::xml_attribute label = p.attribute(
"label");
1824 int idx = node_map[label.as_string()];
1825 node.text().set(values_vec[idx].c_str());
1830void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<int> &values_vec, std::map<std::string, int> &node_map) {
1831 helios = xmldoc.child(
"helios");
1833 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1834 pugi::xml_node node = p.child(field_name.c_str());
1836 node = p.append_child(field_name.c_str());
1838 pugi::xml_attribute label = p.attribute(
"label");
1839 int idx = node_map[label.as_string()];
1840 node.text().set(std::to_string(values_vec[idx]).c_str());
1845void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<float> &values_vec, std::map<std::string, int> &node_map) {
1846 helios = xmldoc.child(
"helios");
1848 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1849 pugi::xml_node node = p.child(field_name.c_str());
1851 node = p.append_child(field_name.c_str());
1853 pugi::xml_attribute label = p.attribute(
"label");
1854 int idx = node_map[label.as_string()];
1855 node.text().set(std::to_string(values_vec[idx]).c_str());
1860void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<std::vector<vec3>> &values_vec, std::map<std::string, int> &node_map) {
1861 helios = xmldoc.child(
"helios");
1863 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1864 std::vector<pugi::xml_node> remove = {};
1865 for (pugi::xml_node node = p.child(field_name.c_str()); node; node = node.next_sibling(field_name.c_str())) {
1866 remove.push_back(node);
1868 for (pugi::xml_node &node: remove) {
1869 p.remove_child(node);
1871 pugi::xml_attribute label = p.attribute(
"label");
1872 int idx = node_map[label.as_string()];
1873 for (
int j = 0; j < values_vec[idx].size(); j++) {
1875 pugi::xml_node new_node = p.append_child(field_name.c_str());
1876 new_node.text().set(
vec_to_string(values_vec[idx][j]).c_str());
1882void ProjectBuilder::xmlSetValues(
const std::string &field_name,
const std::string &node_name, std::vector<std::set<std::string>> &values_vec, std::map<std::string, int> &node_map) {
1883 helios = xmldoc.child(
"helios");
1886 if (node_name !=
"helios") {
1887 p_ = helios.child(node_name.c_str());
1891 for (pugi::xml_node p = p_; p; p = p.next_sibling(node_name.c_str())) {
1892 std::vector<pugi::xml_node> remove{};
1893 for (pugi::xml_node node = p.child(field_name.c_str()); node; node = node.next_sibling(field_name.c_str())) {
1894 remove.push_back(node);
1896 for (pugi::xml_node &node: remove) {
1897 p.remove_child(node);
1899 pugi::xml_attribute label = p.attribute(
"label");
1900 int idx = node_map[label.as_string()];
1901 for (std::string s: values_vec[idx]) {
1903 pugi::xml_node new_node = p.append_child(field_name.c_str());
1904 new_node.text().set(s.c_str());
1911 helios = xmldoc.child(
"helios");
1914 if (parent !=
"helios") {
1915 p_ = helios.child(parent.c_str());
1919 for (pugi::xml_node p = p_; p; p = p.next_sibling(parent.c_str())) {
1920 std::vector<pugi::xml_node> remove{};
1921 for (pugi::xml_node node = p.child(name.c_str()); node; node = node.next_sibling(name.c_str())) {
1922 remove.push_back(node);
1924 for (pugi::xml_node &node: remove) {
1925 p.remove_child(node);
1927 for (std::string s: default_set) {
1929 pugi::xml_node new_node = p.append_child(name.c_str());
1930 new_node.text().set(s.c_str());
1939 std::cout <<
"Project must be built before running visualize." << std::endl;
1943#ifdef ENABLE_HELIOS_VISUALIZER
1955 updatePrimitiveTypes();
1958 IMGUI_CHECKVERSION();
1959 ImGui::CreateContext();
1960 ImGuiIO &io = ImGui::GetIO();
1962 ImFont *arial = io.Fonts->AddFontFromFileTTF(
"plugins/visualizer/fonts/Arial.ttf", 16.0f);
1965 io.FontDefault = arial;
1966 io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
1974 glfwShowWindow(window);
1976 bool show_demo_window =
false;
1977 bool my_tool_active =
true;
1981 ImGui_ImplGlfw_InitForOpenGL(window,
true);
1982 ImGui_ImplOpenGL3_Init();
1985 ImVec2 current_position;
1986 ImVec2 last_position;
1987 bool currently_collapsed;
1988 bool previously_collapsed =
false;
1989 std::string current_tab =
"General";
1990 std::string previous_tab =
"General";
1996 bool switch_visualization =
false;
1998 std::string current_cam_position =
"0";
1999 while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose((GLFWwindow *) window) == 0) {
2001 ImGui_ImplOpenGL3_NewFrame();
2002 ImGui_ImplGlfw_NewFrame();
2022 ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize;
2023 ImGuiWindowFlags window_flags2 = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize;
2027 int windowSize_x = 0;
2028 int windowSize_y = 0;
2030 glfwGetWindowSize((GLFWwindow *) window, &windowSize_x, &windowSize_y);
2031 int2 windowSize(windowSize_x, windowSize_y);
2034 glm::vec4 origin_position;
2035 std::string current_label;
2036 if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
2037 currently_dragging =
"";
2038 disable_dragging =
true;
2040 if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
2041 if (!currently_dragging.empty()) {
2055 ImVec2 mouse_pos = ImGui::GetMousePos();
2057 vec3 camera_pos = camera_lookat_pos[0];
2058 vec3 lookat_pos = camera_lookat_pos[1];
2059 float drag_distance = std::sqrt(std::pow(mouse_pos.x - dragging_start_position.
x, 2) + std::pow(mouse_pos.y - dragging_start_position.
y, 2));
2061 float depth = (camera_pos - lookat_pos).magnitude();
2062 vec3 view_dir = (camera_pos - lookat_pos).normalize();
2066 vec3 right_dir =
cross(world_up, view_dir);
2072 float base_offset = 0.001f;
2073 float offset = base_offset * depth;
2075 if (currently_dragging_type ==
"canopy") {
2076 canopy_dict[currently_dragging].origin += drag_distance * offset * (up_dir + right_dir);
2077 }
else if (currently_dragging_type ==
"rig") {
2078 camera_positions[rig_dict[currently_dragging]] += drag_distance * offset * (up_dir + right_dir);
2081 currently_dragging =
"";
2082 disable_dragging =
false;
2083 dragging_start_position =
int2(0, 0);
2085 int object_window_count = 0;
2086 for (
auto current_label: canopy_labels_set) {
2087 vec3 canopy_origin_ = canopy_dict[current_label].origin;
2088 origin_position = glm::vec4(canopy_origin_.
x, canopy_origin_.
y, canopy_origin_.
z, 1.0);
2089 origin_position = perspectiveTransformationMatrix * origin_position;
2092 ImVec2 next_window_pos = ImVec2(((origin_position.x / origin_position.w) * 0.5f + 0.5f) * windowSize.
x, (1.0f - ((origin_position.y / origin_position.w) * 0.5f + 0.5f)) * windowSize.
y);
2106 ImGui::SetNextWindowCollapsed(
true, ImGuiCond_Once);
2107 ImGui::SetNextWindowPos(next_window_pos);
2109 ImGui::Begin((current_label +
"###" + std::to_string(object_window_count)).c_str(),
nullptr,
2110 ImGui::IsWindowCollapsed() ? 0 : ImGuiWindowFlags_AlwaysAutoResize);
2111 if (ImGui::IsWindowCollapsed()) {
2112 ImGui::SetWindowSize(ImVec2(150, 10));
2114 canopyTab(current_label, object_window_count);
2116 object_window_count++;
2118 for (
auto current_label: rig_labels_set) {
2119 vec3 camera_position_ = camera_position_vec[rig_dict[current_label]][0];
2120 origin_position = glm::vec4(camera_position_.
x, camera_position_.
y, camera_position_.
z, 1.0);
2121 origin_position = perspectiveTransformationMatrix * origin_position;
2124 ImVec2 next_window_pos = ImVec2(((origin_position.x / origin_position.w) * 0.5f + 0.5f) * windowSize.
x, (1.0f - ((origin_position.y / origin_position.w) * 0.5f + 0.5f)) * windowSize.
y);
2138 ImGui::SetNextWindowCollapsed(
true, ImGuiCond_Once);
2139 ImGui::SetNextWindowPos(next_window_pos);
2141 ImGui::Begin((current_label +
"###" + std::to_string(object_window_count)).c_str(),
nullptr,
2142 ImGui::IsWindowCollapsed() ? 0 : ImGuiWindowFlags_AlwaysAutoResize);
2143 if (ImGui::IsWindowCollapsed()) {
2144 ImGui::SetWindowSize(ImVec2(150, 10));
2146 rigTab(current_label, object_window_count);
2148 object_window_count++;
2150 for (std::string obj_name: obj_names_set) {
2151 current_label = obj_name;
2152 vec3 obj_position_ = objects_dict[current_label].position;
2153 origin_position = glm::vec4(obj_position_.
x, obj_position_.
y, obj_position_.
z, 1.0);
2154 origin_position = perspectiveTransformationMatrix * origin_position;
2157 ImVec2 next_window_pos = ImVec2(((origin_position.x / origin_position.w) * 0.5f + 0.5f) * windowSize.
x, (1.0f - ((origin_position.y / origin_position.w) * 0.5f + 0.5f)) * windowSize.
y);
2171 ImGui::SetNextWindowCollapsed(
true, ImGuiCond_Once);
2172 ImGui::SetNextWindowPos(next_window_pos);
2174 ImGui::Begin((current_label +
"###" + std::to_string(object_window_count)).c_str(),
nullptr,
2175 ImGui::IsWindowCollapsed() ? 0 : ImGuiWindowFlags_AlwaysAutoResize);
2176 if (ImGui::IsWindowCollapsed()) {
2177 ImGui::SetWindowSize(ImVec2(150, 10));
2179 objectTab(current_label, object_window_count);
2181 object_window_count++;
2184 ImGui::SetNextWindowCollapsed(
false, ImGuiCond_Once);
2185 ImGui::Begin(
"Editor",
nullptr, window_flags2);
2188 current_position = ImGui::GetWindowPos();
2189 currently_collapsed = ImGui::IsWindowCollapsed();
2191 if (current_tab != previous_tab || current_position.x != last_position.x || current_position.y != last_position.y || currently_collapsed != previously_collapsed) {
2193 previous_tab = current_tab;
2195 if (ImGui::BeginMenuBar()) {
2196 if (ImGui::BeginMenu(
"File")) {
2197 if (ImGui::MenuItem(
"Open..",
"Ctrl+O")) {
2199 if (!file_name.empty()) {
2203 if (ImGui::MenuItem(
"Save XML",
"Ctrl+S")) {
2206 if (ImGui::MenuItem(
"Save As",
"Ctrl+S")) {
2208 if (!new_xml_file.empty()) {
2209 std::string file_extension = new_xml_file;
2210 size_t last_obj_file = file_extension.rfind(
'.');
2211 if (last_obj_file != std::string::npos) {
2212 file_extension = file_extension.substr(last_obj_file + 1);
2214 if (file_extension ==
"xml") {
2215 if (!std::filesystem::exists(new_xml_file)) {
2217 std::filesystem::copy(xml_input_file, new_xml_file, std::filesystem::copy_options::overwrite_existing);
2220 std::string xml_input_file_ = xml_input_file;
2221 pugi::xml_node helios_ = helios;
2222 xml_input_file = new_xml_file;
2223 if (!
open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
2235 std::cout <<
"Not a valid file type. Project must be saved to a XML file." << std::endl;
2239 std::cout <<
"Not a valid file." << std::endl;
2242 if (ImGui::MenuItem(
"Close",
"Ctrl+W")) {
2243 my_tool_active =
false;
2247 if (ImGui::BeginMenu(
"Visualization")) {
2248 refreshVisualizationTypes();
2249 refreshVisualizationTypes();
2250 if (ImGui::MenuItem(
"RGB (Default)") && visualization_type !=
"RGB") {
2251 visualization_type =
"RGB";
2252 switch_visualization =
true;
2254 std::set<std::string> vis_types;
2255 std::set_union(visualization_types_primitive.begin(), visualization_types_primitive.end(), visualization_types_object.begin(), visualization_types_object.end(), std::inserter(vis_types, vis_types.begin()));
2256 for (
auto &type: vis_types) {
2257 if (visualization_types_primitive.find(type) != visualization_types_primitive.end()) {
2258 ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 165, 0, 255));
2260 ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(0, 0, 255, 255));
2262 if (ImGui::MenuItem(type.c_str()) && visualization_type != type) {
2263 visualization_type = type;
2264 switch_visualization =
true;
2266 ImGui::PopStyleColor();
2268 if (switch_visualization) {
2269 if (visualization_type !=
"RGB") {
2270 if (visualization_types_primitive.find(visualization_type) != visualization_types_primitive.end()) {
2279 switch_visualization =
false;
2283 ImGui::EndMenuBar();
2285 std::string image_dir =
"./saved/";
2286 bool dir = std::filesystem::create_directories(image_dir);
2287 if (!dir && !std::filesystem::exists(image_dir)) {
2288 helios_runtime_error(
"Error: image output directory " + image_dir +
" could not be created. Exiting...");
2293#ifdef ENABLE_RADIATION_MODEL
2294 if (ImGui::Button(
"Record")) {
2295 if (band_group_names.empty()) {
2296 std::cout <<
"At least 1 band group (a group of 1 or 3 bands) must be defined to record images." << std::endl;
2299 const char *font_name =
"LCD";
2302 updatePrimitiveTypes();
2307 }
catch (
const std::runtime_error &e) {
2308 std::cerr <<
"Record failed due to exception: " << e.what() << std::endl;
2314 ImGui::OpenPopupOnItemClick(
"repeat_record", ImGuiPopupFlags_MouseButtonRight);
2320 ImGui::Text(
"Console:");
2322 if (ImGui::BeginTabBar(
"Settings#left_tabs_bar")) {
2323 if (ImGui::BeginTabItem(
"General")) {
2324 current_tab =
"General";
2327 ImGui::EndTabItem();
2330 if (ImGui::BeginTabItem(
"Calculation")) {
2331 current_tab =
"Calculation";
2334 ImGui::EndTabItem();
2337 if (ImGui::BeginTabItem(
"Object")) {
2338 current_tab =
"Object";
2340 ImGui::EndTabItem();
2343 if (ImGui::BeginTabItem(
"Canopy")) {
2344 current_tab =
"Canopy";
2347 ImGui::EndTabItem();
2349 if (enable_radiation) {
2350 if (ImGui::BeginTabItem(
"Radiation")) {
2351 current_tab =
"Radiation";
2354 ImGui::EndTabItem();
2357 if (enable_radiation) {
2359 if (ImGui::BeginTabItem(
"Rig")) {
2360 current_tab =
"Rig";
2363 ImGui::EndTabItem();
2366 if (ImGui::BeginTabItem(
"Camera")) {
2367 current_tab =
"Camera";
2370 ImGui::EndTabItem();
2373 if (ImGui::BeginTabItem(
"Light")) {
2374 current_tab =
"Light";
2377 ImGui::EndTabItem();
2382 last_position = current_position;
2383 previously_collapsed = currently_collapsed;
2386 if (is_dirty && !ImGui::IsMouseDragging(ImGuiMouseButton_Left) && !ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
2391 updatePrimitiveTypes();
2403 ImDrawData *draw_data = ImGui::GetDrawData();
2405 ImGui_ImplOpenGL3_RenderDrawData(draw_data);
2406 glfwSwapBuffers(window);
2407 if (!io.WantCaptureMouse && !ImGui::IsAnyItemHovered()) {
2412 std::this_thread::sleep_for(std::chrono::milliseconds(100 / 6));
2415 ImGui_ImplOpenGL3_Shutdown();
2416 ImGui_ImplGlfw_Shutdown();
2417 ImGui::DestroyContext();
2420 std::cout <<
"Visualizer plugin is required for this function." << std::endl;
2442 xmlSetDistribution(
"latitude_dist",
"helios", distributions[distribution_dict[
"latitude"]]);
2445 xmlSetDistribution(
"longitude_dist",
"helios", distributions[distribution_dict[
"longitude"]]);
2448 xmlSetDistribution(
"UTC_offset_dist",
"helios", distributions[distribution_dict[
"UTC_offset"]]);
2450 xmlSetValue(
"csv_weather_file",
"helios", csv_weather_file);
2452 xmlSetValue(
"domain_origin",
"helios", domain_origin);
2453 xmlSetDistribution(
"domain_origin_x_dist",
"helios", distributions[distribution_dict[
"domain_origin_x"]]);
2454 xmlSetDistribution(
"domain_origin_y_dist",
"helios", distributions[distribution_dict[
"domain_origin_y"]]);
2455 xmlSetDistribution(
"domain_origin_z_dist",
"helios", distributions[distribution_dict[
"domain_origin_z"]]);
2457 xmlSetValue(
"domain_extent",
"helios", domain_extent);
2458 xmlSetDistribution(
"domain_extent_x_dist",
"helios", distributions[distribution_dict[
"domain_extent_x"]]);
2459 xmlSetDistribution(
"domain_extent_y_dist",
"helios", distributions[distribution_dict[
"domain_extent_y"]]);
2461 xmlSetValue(
"ground_resolution",
"helios", ground_resolution);
2462 xmlSetDistribution(
"ground_resolution_x_dist",
"helios", distributions[distribution_dict[
"ground_resolution_x"]]);
2463 xmlSetDistribution(
"ground_resolution_y_dist",
"helios", distributions[distribution_dict[
"ground_resolution_y"]]);
2465 xmlSetValue(
"ground_texture_file",
"helios", ground_texture_file);
2467 xmlSetValues(
"camera_xml_library_file",
"helios", camera_xml_library_files);
2469 xmlSetValues(
"light_xml_library_file",
"helios", light_xml_library_files);
2472 helios = xmldoc.child(
"helios");
2473 pugi::xml_node node;
2474 node = helios.child(
"object");
2476 node.parent().remove_child(node);
2481 obj_positions.clear();
2482 obj_orientations.clear();
2485 obj_data_groups.clear();
2486 for (std::string obj_name: obj_names_set) {
2487 object curr_obj = objects_dict[obj_name];
2488 obj_names.push_back(curr_obj.name);
2489 obj_files.push_back(curr_obj.file);
2490 obj_positions.push_back(curr_obj.position);
2491 obj_orientations.push_back(curr_obj.orientation);
2492 obj_scales.push_back(curr_obj.scale);
2493 obj_colors.push_back(curr_obj.color);
2494 obj_data_groups.push_back(curr_obj.data_group);
2498 xmlSetValues(
"file",
"object", obj_files, obj_names_dict);
2499 xmlSetValues(
"position",
"object", obj_positions, obj_names_dict);
2500 xmlSetValues(
"orientation",
"object", obj_orientations, obj_names_dict);
2501 xmlSetValues(
"scale",
"object", obj_scales, obj_names_dict);
2502 xmlSetValues(
"color",
"object", obj_colors, obj_names_dict);
2503 xmlSetValues(
"data_group",
"object", obj_data_groups, obj_names_dict);
2505#ifdef ENABLE_PLANT_ARCHITECTURE
2507 helios = xmldoc.child(
"helios");
2508 node = helios.child(
"canopy");
2510 node.parent().remove_child(node);
2514 ground_clipping_heights.clear();
2515 canopy_labels.clear();
2516 plant_library_names.clear();
2517 plant_library_names_verbose.clear();
2519 individual_plant_locations.clear();
2520 plant_spacings.clear();
2521 plant_counts.clear();
2522 canopy_origins.clear();
2523 canopy_data_groups.clear();
2524 for (std::string canopy_name: canopy_labels_set) {
2525 canopy curr_canopy = canopy_dict[canopy_name];
2526 plant_ages.push_back(curr_canopy.age);
2527 ground_clipping_heights.push_back(curr_canopy.ground_clipping_height);
2528 canopy_labels.push_back(curr_canopy.label);
2529 plant_library_names.push_back(curr_canopy.library_name);
2530 plant_library_names_verbose.push_back(curr_canopy.library_name_verbose);
2531 canopy_IDs.push_back(curr_canopy.IDs);
2532 individual_plant_locations.push_back(curr_canopy.individual_plant_locations);
2533 plant_spacings.push_back(curr_canopy.plant_spacing);
2534 plant_counts.push_back(curr_canopy.plant_count);
2535 canopy_origins.push_back(curr_canopy.origin);
2536 canopy_data_groups.push_back(curr_canopy.data_group);
2540 xmlSetValue(
"canopy_origin",
"canopy_block", canopy_origin);
2541 xmlSetValue(
"plant_count",
"canopy_block", plant_count);
2542 xmlSetValue(
"plant_spacing",
"canopy_block", plant_spacing);
2543 xmlSetValue(
"plant_library_name",
"canopy_block", plant_library_name);
2544 xmlSetValue(
"plant_age",
"canopy_block", plant_age);
2545 xmlSetValue(
"ground_clipping_height",
"canopy_block", ground_clipping_height);
2546 xmlSetValues(
"canopy_origin",
"canopy_block", canopy_origins, canopy_labels_dict);
2547 xmlSetValues(
"plant_count",
"canopy_block", plant_counts, canopy_labels_dict);
2548 xmlSetValues(
"plant_spacing",
"canopy_block", plant_spacings, canopy_labels_dict);
2549 xmlSetValues(
"plant_library_name",
"canopy_block", plant_library_names, canopy_labels_dict);
2550 xmlSetValues(
"plant_age",
"canopy_block", plant_ages, canopy_labels_dict);
2551 xmlSetValues(
"ground_clipping_height",
"canopy_block", ground_clipping_heights, canopy_labels_dict);
2552 xmlSetValues(
"data_group",
"canopy_block", canopy_data_groups, canopy_labels_dict);
2556 helios = xmldoc.child(
"helios");
2557 node = helios.child(
"rig");
2559 node.parent().remove_child(node);
2567 xmlSetValues(
"camera_position",
"rig", camera_position_vec, rig_dict);
2569 xmlSetValues(
"camera_lookat",
"rig", camera_lookat_vec, rig_dict);
2571 xmlSetValues(
"camera_label",
"rig", rig_camera_labels, rig_dict);
2572 setKeypoints(
"keypoint",
"camera_position", keypoint_frames);
2573 xmlSetValues(
"images",
"rig", num_images_vec, rig_dict);
2574 std::vector<int> write_depth_{};
2575 std::vector<int> write_norm_depth_{};
2576 for (
int i = 0; i < write_depth.size(); i++) {
2577 if (write_depth[i]) {
2578 write_depth_.push_back(1);
2580 write_depth_.push_back(0);
2582 if (write_norm_depth[i]) {
2583 write_norm_depth_.push_back(1);
2585 write_norm_depth_.push_back(0);
2589 xmlSetValues(
"normdepth",
"rig", write_norm_depth_, rig_dict);
2592 xmlSetValue(
"camera_resolution",
"camera", camera_resolution);
2593 xmlSetValue(
"focal_plane_distance",
"camera", focal_plane_distance);
2594 xmlSetValue(
"lens_diameter",
"camera", lens_diameter);
2595 xmlSetValue(
"FOV_aspect_ratio",
"camera", FOV_aspect_ratio);
2597 xmlSetValues(
"camera_resolution",
"camera", camera_resolutions, camera_dict);
2598 for (std::string &band: bandlabels) {
2599 for (std::string &camera: camera_names) {
2600 xmlSetValue(
"camera_calibration_" + band,
"camera", camera_calibrations[camera_dict[camera]][band]);
2603 xmlSetValues(
"focal_plane_distance",
"camera", focal_plane_distances, camera_dict);
2604 xmlSetValues(
"lens_diameter",
"camera", lens_diameters, camera_dict);
2605 xmlSetValues(
"FOV_aspect_ratio",
"camera", FOV_aspect_ratios, camera_dict);
2609 xmlSetValues(
"light_type",
"light", light_types, light_dict);
2610 xmlSetValues(
"light_spectra",
"light", light_spectra, light_dict);
2611 xmlSetValues(
"light_direction",
"light", light_direction_vec, light_dict);
2612 xmlSetValues(
"light_rotation",
"light", light_rotation_vec, light_dict);
2613 xmlSetValues(
"light_size",
"light", light_size_vec, light_dict);
2614 xmlSetValues(
"light_source_flux",
"light", light_flux_vec, light_dict);
2615 xmlSetValues(
"light_radius",
"light", light_radius_vec, light_dict);
2616 xmlSetValues(
"light_label",
"rig", rig_light_labels, light_dict);
2618 xmlSetValue(
"direct_ray_count",
"radiation", direct_ray_count);
2619 xmlSetValue(
"diffuse_ray_count",
"radiation", diffuse_ray_count);
2620 xmlSetValue(
"diffuse_extinction_coeff",
"radiation", diffuse_extinction_coeff);
2621 xmlSetValue(
"scattering_depth",
"radiation", scattering_depth);
2622 xmlSetValue(
"air_turbidity",
"radiation", air_turbidity);
2623 xmlSetValues(
"load_xml_library_file",
"radiation", xml_library_files);
2624 xmlSetValue(
"solar_direct_spectrum",
"radiation", solar_direct_spectrum);
2625 xmlSetValue(
"leaf_reflectivity_spectrum",
"radiation", leaf_reflectivity_spectrum);
2626 xmlSetValue(
"leaf_transmissivity_spectrum",
"radiation", leaf_transmissivity_spectrum);
2627 xmlSetValue(
"leaf_emissivity",
"radiation", leaf_emissivity);
2628 xmlSetValue(
"ground_reflectivity_spectrum",
"radiation", ground_reflectivity_spectrum);
2629 for (std::string prim: primitive_names) {
2633 if (primitive_continuous[prim][0]) {
2634 xmlSetValue(prim +
"_reflectivity_spectrum",
"radiation", primitive_spectra[prim][0]);
2639 if (primitive_continuous[prim][1]) {
2640 xmlSetValue(prim +
"_transmissivity_spectrum",
"radiation", primitive_spectra[prim][1]);
2644 for (std::string band: bandlabels) {
2647 xmlSetValue(prim +
"_reflectivity",
"radiation", primitive_values[band][prim][0]);
2648 xmlSetValue(prim +
"_transmissivity",
"radiation", primitive_values[band][prim][1]);
2649 xmlSetValue(prim +
"_emissivity",
"radiation", primitive_values[band][prim][2]);
2652 xmldoc.save_file(xml_input_file.c_str());
2657 xml_input_file = xml_path;
2658 if (!
open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
2684 xmlGetValue(
"csv_weather_file",
"helios", csv_weather_file);
2686 xmlGetValue(
"domain_origin",
"helios", domain_origin);
2697 xmlGetValue(
"domain_extent",
"helios", domain_extent);
2705 xmlGetValue(
"ground_resolution",
"helios", ground_resolution);
2713 xmlGetValue(
"ground_texture_file",
"helios", ground_texture_file);
2715 xmlGetValues(
"camera_xml_library_file",
"helios", camera_xml_library_files);
2716 possible_camera_calibrations.clear();
2717 for (
auto &xml_library_file: camera_xml_library_files) {
2718 if (xml_library_file.empty() || !std::filesystem::exists(xml_library_file)) {
2721 std::vector<std::string> current_camera_file =
get_xml_node_values(xml_library_file,
"label",
"globaldata_vec2");
2722 possible_camera_calibrations.insert(possible_camera_calibrations.end(), current_camera_file.begin(), current_camera_file.end());
2725 xmlGetValues(
"light_xml_library_file",
"helios", light_xml_library_files);
2726 possible_light_spectra.clear();
2727 for (
auto &xml_library_file: light_xml_library_files) {
2728 if (xml_library_file.empty() || !std::filesystem::exists(xml_library_file)) {
2731 std::vector<std::string> current_light_file =
get_xml_node_values(xml_library_file,
"label",
"globaldata_vec2");
2732 possible_light_spectra.insert(possible_light_spectra.end(), current_light_file.begin(), current_light_file.end());
2735 obj_names_dict.clear();
2736 obj_names_dict =
getNodeLabels(
"label",
"object", obj_names);
2737 obj_names_set = std::set<std::string>{obj_names.begin(), obj_names.end()};
2738 if (!obj_names.empty())
2739 current_obj = obj_names[0];
2742 xmlGetValues(
"orientation",
"object", obj_orientations);
2744 prev_obj_positions = obj_positions;
2745 prev_obj_orientations = obj_orientations;
2746 prev_obj_scales = obj_scales;
2747 obj_data_groups.clear();
2752 for (
auto &
obj: objects_dict) {
2753 deleteObject(
obj.second.name);
2755 objects_dict.clear();
2756 for (
int i = 0; i < obj_files.size(); i++) {
2758 std::vector<uint> new_UUIDs;
2759 std::string new_obj_file = obj_files[i];
2760 if (std::filesystem::path(new_obj_file).extension() ==
".obj") {
2762 }
else if (std::filesystem::path(new_obj_file).extension() ==
".ply") {
2765 std::cout <<
"Failed to load object file " << new_obj_file <<
"." << std::endl;
2768 std::filesystem::path mtl_path(new_obj_file);
2769 mtl_path.replace_extension(
"mtl");
2770 if (std::filesystem::exists(mtl_path)) {
2771 new_object.use_texture_file =
true;
2773 new_object.use_texture_file =
false;
2775 std::string obj_material =
"projectbuilder_obj_" + std::to_string(i);
2787 obj_UUIDs.push_back(new_UUIDs);
2788 new_object.index = obj_idx;
2790 new_object.name = obj_names[i];
2791 new_object.file = obj_files[i];
2792 new_object.data_group = obj_data_groups[i];
2793 new_object.UUIDs = new_UUIDs;
2794 new_object.position = obj_positions[i];
2795 new_object.prev_position = obj_positions[i];
2796 new_object.orientation = obj_orientations[i];
2797 new_object.prev_orientation = obj_orientations[i];
2798 new_object.scale = obj_scales[i];
2799 new_object.prev_scale = obj_scales[i];
2800 new_object.color = obj_colors[i];
2801 new_object.prev_color = obj_colors[i];
2802 new_object.is_dirty =
false;
2803 objects_dict[new_object.name] = new_object;
2806#ifdef ENABLE_PLANT_ARCHITECTURE
2807 canopy_labels.clear();
2808 canopy_labels_dict =
getNodeLabels(
"label",
"canopy_block", canopy_labels);
2809 for (
auto canopy_label_: canopy_labels) {
2810 canopy_labels_set.insert(canopy_label_);
2812 if (!canopy_labels.empty())
2813 current_canopy = canopy_labels[0];
2814 xmlGetValue(
"canopy_origin",
"canopy_block", canopy_origin);
2815 xmlGetValue(
"plant_count",
"canopy_block", plant_count);
2816 xmlGetValue(
"plant_spacing",
"canopy_block", plant_spacing);
2817 xmlGetValue(
"plant_library_name",
"canopy_block", plant_library_name);
2818 xmlGetValue(
"plant_age",
"canopy_block", plant_age);
2819 xmlGetValue(
"ground_clipping_height",
"canopy_block", ground_clipping_height);
2820 canopy_origins.clear();
2821 xmlGetValues(
"canopy_origin",
"canopy_block", canopy_origins);
2822 plant_counts.clear();
2823 xmlGetValues(
"plant_count",
"canopy_block", plant_counts);
2824 plant_spacings.clear();
2825 xmlGetValues(
"plant_spacing",
"canopy_block", plant_spacings);
2826 plant_library_names.clear();
2827 xmlGetValues(
"plant_library_name",
"canopy_block", plant_library_names);
2828 for (
int i = 0; i < plant_library_names.size(); i++) {
2829 plant_library_names_verbose.push_back(plant_type_verbose_lookup[plant_library_names[i]]);
2833 ground_clipping_heights.clear();
2834 xmlGetValues(
"ground_clipping_height",
"canopy_block", ground_clipping_heights);
2835 canopy_data_groups.clear();
2836 xmlGetValues(
"data_group",
"canopy_block", canopy_data_groups);
2838 canopy_dict.clear();
2839 for (
int i = 0; i < canopy_labels.size(); i++) {
2841 new_canopy.idx = canopy_idx;
2843 new_canopy.age = plant_ages[i];
2844 new_canopy.ground_clipping_height = ground_clipping_heights[i];
2845 new_canopy.label = canopy_labels[i];
2846 new_canopy.library_name = plant_library_names[i];
2847 new_canopy.library_name_verbose = plant_library_names_verbose[i];
2848 new_canopy.IDs = canopy_IDs[i];
2849 new_canopy.individual_plant_locations = individual_plant_locations[i];
2850 new_canopy.plant_spacing = plant_spacings[i];
2851 new_canopy.plant_count = plant_counts[i];
2852 new_canopy.origin = canopy_origins[i];
2853 new_canopy.data_group = canopy_data_groups[i];
2854 new_canopy.is_dirty =
false;
2855 canopy_dict[new_canopy.label] = new_canopy;
2860#ifdef ENABLE_RADIATION_MODEL
2862 rig_labels_set.clear();
2863 write_depth.clear();
2864 write_norm_depth.clear();
2865 write_segmentation_mask.clear();
2867 for (
auto rig: rig_labels) {
2868 rig_labels_set.insert(
rig);
2871 write_depth.push_back(
false);
2872 write_norm_depth.push_back(
false);
2873 write_segmentation_mask.push_back(
false);
2875 current_rig = rig_labels[0];
2877 xmlGetValue(
"camera_position",
"rig", camera_position);
2878 xmlGetValue(
"camera_lookat",
"rig", camera_lookat);
2880 camera_positions.clear();
2881 xmlGetValues(
"camera_position",
"rig", camera_positions);
2882 camera_position_vec.clear();
2883 xmlGetValues(
"camera_position",
"rig", camera_position_vec);
2884 camera_lookats.clear();
2886 camera_lookat_vec.clear();
2887 xmlGetValues(
"camera_lookat",
"rig", camera_lookat_vec);
2888 camera_labels.clear();
2890 rig_camera_labels.clear();
2891 xmlGetValues(
"camera_label",
"rig", rig_camera_labels);
2892 keypoint_frames.clear();
2893 getKeypoints(
"keypoint",
"camera_position", keypoint_frames);
2894 current_keypoint = std::to_string(keypoint_frames[0][0]);
2895 num_images_vec.clear();
2897 write_depth.clear();
2898 write_norm_depth.clear();
2899 write_segmentation_mask.clear();
2900 std::vector<int> write_depth_{};
2901 std::vector<int> write_norm_depth_{};
2902 std::vector<int> write_segmentation_mask_{};
2905 xmlGetValues(
"segmentation",
"rig", write_segmentation_mask_);
2906 for (
int i = 0; i < write_depth_.size(); i++) {
2907 if (write_depth_[i] == 1) {
2908 write_depth.push_back(
true);
2910 write_depth.push_back(
false);
2912 if (write_norm_depth_[i] == 1) {
2913 write_norm_depth.push_back(
true);
2915 write_norm_depth.push_back(
false);
2917 if (write_segmentation_mask_[i] == 1) {
2918 write_segmentation_mask.push_back(
true);
2920 write_segmentation_mask.push_back(
false);
2924 while (write_depth.size() < rig_labels.size()) {
2925 write_depth.push_back(
false);
2926 write_norm_depth.push_back(
false);
2927 write_segmentation_mask.push_back(
false);
2930 camera_names.clear();
2931 camera_names_set.clear();
2932 camera_dict =
getNodeLabels(
"label",
"camera", camera_names);
2933 current_cam = camera_names[0];
2934 xmlGetValue(
"camera_resolution",
"camera", camera_resolution);
2935 xmlGetValue(
"focal_plane_distance",
"camera", focal_plane_distance);
2936 xmlGetValue(
"lens_diameter",
"camera", lens_diameter);
2937 xmlGetValue(
"FOV_aspect_ratio",
"camera", FOV_aspect_ratio);
2939 camera_resolutions.clear();
2940 xmlGetValues(
"camera_resolution",
"camera", camera_resolutions);
2941 camera_calibrations.clear();
2942 for (std::string &camera: camera_names) {
2943 camera_calibrations.push_back(std::map<std::string, std::string>{});
2944 for (std::string &band: bandlabels) {
2945 xmlGetValue(
"camera_calibration_" + band,
"camera", camera_calibrations[camera_dict[camera]][band]);
2947 camera_names_set.insert(camera);
2949 focal_plane_distances.clear();
2950 xmlGetValues(
"focal_plane_distance",
"camera", focal_plane_distances);
2951 lens_diameters.clear();
2952 xmlGetValues(
"lens_diameter",
"camera", lens_diameters);
2953 FOV_aspect_ratios.clear();
2954 xmlGetValues(
"FOV_aspect_ratio",
"camera", FOV_aspect_ratios);
2958 light_types.clear();
2960 light_direction_vec.clear();
2961 xmlGetValues(
"light_direction",
"light", light_direction_vec);
2962 light_direction_sph_vec.clear();
2963 for (
vec3 vec: light_direction_vec) {
2964 light_direction_sph_vec.push_back(
cart2sphere(vec));
2966 light_rotation_vec.clear();
2967 xmlGetValues(
"light_rotation",
"light", light_rotation_vec);
2968 light_size_vec.clear();
2970 light_flux_vec.clear();
2971 xmlGetValues(
"light_source_flux",
"light", light_flux_vec);
2972 light_radius_vec.clear();
2973 xmlGetValues(
"light_radius",
"light", light_radius_vec);
2974 light_spectra.clear();
2976 light_names.clear();
2977 light_names_set.clear();
2979 for (
auto &light: light_names) {
2980 light_names_set.insert(light);
2982 current_light = light_names[0];
2983 rig_light_labels.clear();
2986 xmlGetValue(
"direct_ray_count",
"radiation", direct_ray_count);
2987 xmlGetValue(
"diffuse_ray_count",
"radiation", diffuse_ray_count);
2988 xmlGetValue(
"diffuse_extinction_coeff",
"radiation", diffuse_extinction_coeff);
2989 xmlGetValue(
"scattering_depth",
"radiation", scattering_depth);
2990 xmlGetValue(
"air_turbidity",
"radiation", air_turbidity);
2991 xmlGetValues(
"load_xml_library_file",
"radiation", xml_library_files);
2992 possible_spectra.clear();
2993 for (
auto &xml_library_file: xml_library_files) {
2994 if (xml_library_file.empty() || !std::filesystem::exists(xml_library_file)) {
2997 std::vector<std::string> current_spectra_file =
get_xml_node_values(xml_library_file,
"label",
"globaldata_vec2");
2998 for (
int i = 0; i < current_spectra_file.size(); i++) {
2999 possible_spectra.insert(current_spectra_file[i]);
3002 xmlGetValue(
"solar_direct_spectrum",
"radiation", solar_direct_spectrum);
3003 xmlGetValue(
"leaf_reflectivity_spectrum",
"radiation", leaf_reflectivity_spectrum);
3004 xmlGetValue(
"leaf_transmissivity_spectrum",
"radiation", leaf_transmissivity_spectrum);
3005 xmlGetValue(
"leaf_emissivity",
"radiation", leaf_emissivity);
3006 xmlGetValue(
"ground_reflectivity_spectrum",
"radiation", ground_reflectivity_spectrum);
3007 primitive_values.clear();
3008 for (std::string band: bandlabels) {
3009 primitive_values[band];
3010 for (std::string prim: primitive_names) {
3011 primitive_values[band][prim] = {ground_reflectivity, ground_transmissivity, ground_emissivity};
3014 primitive_spectra.clear();
3015 primitive_spectra = {{
"All", {reflectivity_spectrum, transmissivity_spectrum, emissivity_spectrum}},
3016 {
"ground", {ground_reflectivity_spectrum, ground_transmissivity_spectrum, ground_emissivity_spectrum}},
3017 {
"leaf", {leaf_reflectivity_spectrum, leaf_transmissivity_spectrum, leaf_emissivity_spectrum}},
3018 {
"petiolule", {petiolule_reflectivity_spectrum, petiolule_transmissivity_spectrum, petiolule_emissivity_spectrum}},
3019 {
"petiole", {petiole_reflectivity_spectrum, petiole_transmissivity_spectrum, petiole_emissivity_spectrum}},
3020 {
"internode", {internode_reflectivity_spectrum, internode_transmissivity_spectrum, internode_emissivity_spectrum}},
3021 {
"peduncle", {peduncle_reflectivity_spectrum, peduncle_transmissivity_spectrum, peduncle_emissivity_spectrum}},
3022 {
"petal", {petal_reflectivity_spectrum, petal_transmissivity_spectrum, petal_emissivity_spectrum}},
3023 {
"pedicel", {pedicel_reflectivity_spectrum, pedicel_transmissivity_spectrum, pedicel_emissivity_spectrum}},
3024 {
"fruit", {fruit_reflectivity_spectrum, fruit_transmissivity_spectrum, fruit_emissivity_spectrum}}};
3025 for (std::string prim: primitive_names) {
3028 std::string default_spectrum =
"";
3030 xmlGetValue(prim +
"_reflectivity_spectrum",
"radiation", default_spectrum);
3031 if (!default_spectrum.empty()) {
3032 primitive_spectra[prim][0] = default_spectrum;
3033 primitive_continuous[prim][0] =
true;
3035 primitive_continuous[prim][0] =
false;
3038 default_spectrum =
"";
3039 xmlGetValue(prim +
"_transmissivity_spectrum",
"radiation", default_spectrum);
3040 if (!default_spectrum.empty()) {
3041 primitive_spectra[prim][1] = default_spectrum;
3042 primitive_continuous[prim][1] =
true;
3044 primitive_continuous[prim][1] =
false;
3046 for (std::string band: bandlabels) {
3049 xmlGetValue(prim +
"_reflectivity",
"radiation", primitive_values[band][prim][0]);
3050 xmlGetValue(prim +
"_transmissivity",
"radiation", primitive_values[band][prim][1]);
3051 xmlGetValue(prim +
"_emissivity",
"radiation", primitive_values[band][prim][2]);
3058 xml_input_file = xml_path;
3059 if (!
open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
3065void ProjectBuilder::calculationTab() {
3066#ifdef ENABLE_HELIOS_VISUALIZER
3068 for (
auto &prim_name: primitive_names_set) {
3069 if (calculation_selection_primitive.find(prim_name) == calculation_selection_primitive.end()) {
3070 calculation_selection_primitive[prim_name] =
false;
3074 calculation_variable_choices.clear();
3075 for (
auto &label: primitive_labels) {
3077 if (heliosNumericTypes.find(dtype) != heliosNumericTypes.end())
3078 calculation_variable_choices.insert(label);
3081 for (
auto &data: global_data) {
3083 if (heliosNumericTypes.find(dtype) != heliosNumericTypes.end())
3084 calculation_variable_choices.insert(data);
3088 for (
auto &data_group: data_groups_set) {
3089 if (calculation_selection_datagroup.find(data_group) == calculation_selection_datagroup.end()) {
3090 calculation_selection_datagroup[data_group] =
false;
3094 if (ImGui::BeginPopup(
"calculation_select_popup_datagroup")) {
3095 for (
auto &calculation_pair: calculation_selection_datagroup) {
3096 ImGui::Selectable(calculation_pair.first.c_str(), &calculation_pair.second, ImGuiSelectableFlags_DontClosePopups);
3100 if (ImGui::Button(
"Select Data Groups")) {
3101 ImGui::OpenPopup(
"calculation_select_popup_datagroup");
3104 ImGui::Text(
"Data Groups:");
3106 if (calculation_selection_datagroup[
"All"]) {
3110 for (
auto &calculation_pair: calculation_selection_datagroup) {
3111 if (calculation_pair.second) {
3112 ImGui::SameLine(), ImGui::Text(
"%i. %s", idx, calculation_pair.first.c_str());
3119 if (ImGui::BeginPopup(
"calculation_select_popup_prim")) {
3120 for (
auto &calculation_pair: calculation_selection_primitive) {
3121 ImGui::Selectable(calculation_pair.first.c_str(), &calculation_pair.second, ImGuiSelectableFlags_DontClosePopups);
3125 if (ImGui::Button(
"Select Primitives")) {
3126 ImGui::OpenPopup(
"calculation_select_popup_prim");
3129 ImGui::Text(
"Primitive Types:");
3131 if (calculation_selection_primitive[
"All"]) {
3135 for (
auto &calculation_pair: calculation_selection_primitive) {
3136 if (calculation_pair.second) {
3137 ImGui::SameLine(), ImGui::Text(
"%i. %s", idx, calculation_pair.first.c_str());
3143 ImGui::SetWindowFontScale(1.25f);
3144 ImGui::Text(
"Global Data:");
3145 ImGui::SetWindowFontScale(1.0f);
3146 for (
int i = 0; i < calculation_variables_global.size(); i++) {
3148 ImGui::SetNextItemWidth(40);
3149 dropDown(
"##operator" + std::to_string(i), calculation_operators_global[i - 1], calculation_operators_choices);
3151 ImGui::Text(
"Scalar:");
3153 ImGui::SetNextItemWidth(50);
3154 std::string scalar_label =
"##Scalar" + std::to_string(i);
3155 ImGui::InputFloat(scalar_label.c_str(), &calculation_scalars_global[i]);
3157 ImGui::Text(
"Variable:");
3159 ImGui::SetNextItemWidth(100);
3160 dropDown(
"##Variable" + std::to_string(i), calculation_variables_global[i], calculation_variable_choices);
3162 ImGui::Text(
"Aggregate:");
3164 ImGui::SetNextItemWidth(100);
3165 dropDown(
"##Operation" + std::to_string(i), calculation_aggregations[i], calculation_aggregation_choices);
3166 if (i == calculation_variables_global.size() - 1) {
3168 if (ImGui::Button(
"Add Operand")) {
3169 calculation_variables_global.push_back(
"");
3170 calculation_scalars_global.push_back(1.0);
3171 calculation_operators_global.push_back(
"+");
3172 calculation_aggregations.push_back(
"Mean");
3176 if (ImGui::Button(
"Remove")) {
3177 calculation_variables_global.pop_back();
3178 calculation_scalars_global.pop_back();
3179 calculation_operators_global.pop_back();
3180 calculation_aggregations.pop_back();
3185 if (ImGui::Button(
"Calculate Result:")) {
3186 globalCalculation();
3189 ImGui::Text(
"%s", std::to_string(calculation_result_global).c_str());
3191 if (ImGui::Button(
"Save to Global Data")) {
3195 ImGui::SetNextItemWidth(100);
3196 ImGui::InputText(
"##global_data_name", &calculation_name_global);
3199 ImGui::SetWindowFontScale(1.25f);
3200 ImGui::Text(
"Primitive Data:");
3201 ImGui::SetWindowFontScale(1.0f);
3202 for (
int i = 0; i < calculation_variables_primitive.size(); i++) {
3204 ImGui::SetNextItemWidth(40);
3205 dropDown(
"##operator_primitive" + std::to_string(i), calculation_operators_primitive[i - 1], calculation_operators_choices);
3207 ImGui::Text(
"Scalar:");
3209 ImGui::SetNextItemWidth(50);
3210 std::string scalar_label =
"##Scalar_primitive-" + std::to_string(i);
3211 ImGui::InputFloat(scalar_label.c_str(), &calculation_scalars_primitive[i]);
3213 ImGui::Text(
"Variable:");
3215 ImGui::SetNextItemWidth(100);
3216 dropDown(
"##Variable_primitive" + std::to_string(i), calculation_variables_primitive[i], calculation_variable_choices);
3217 if (i == calculation_variables_primitive.size() - 1) {
3219 if (ImGui::Button(
"Add Operand##primitive")) {
3220 calculation_variables_primitive.push_back(
"");
3221 calculation_scalars_primitive.push_back(1.0);
3222 calculation_operators_primitive.push_back(
"+");
3226 if (ImGui::Button(
"Remove##primitive")) {
3227 calculation_variables_primitive.pop_back();
3228 calculation_scalars_primitive.pop_back();
3229 calculation_operators_primitive.pop_back();
3234 ImGui::Text(
"Save Primitive Data:");
3236 ImGui::SetNextItemWidth(80);
3237 ImGui::InputText(
"##save_data_name", &calculation_name_primitive);
3239 if (ImGui::Button(
"Save to Primitive Data")) {
3240 savePrimitiveCalculation();
3245void ProjectBuilder::cameraTab() {
3246#if defined(ENABLE_HELIOS_VISUALIZER) && defined(ENABLE_RADIATION_MODEL)
3248 ImGui::SetNextItemWidth(60);
3249 if (ImGui::Button(
"Load XML Library File")) {
3251 if (!new_xml_library_file.empty() && std::filesystem::exists(new_xml_library_file)) {
3252 if (camera_xml_library_files.find(new_xml_library_file) == camera_xml_library_files.end()) {
3253 camera_xml_library_files.insert(new_xml_library_file);
3254 std::vector<std::string> current_camera_file =
get_xml_node_values(new_xml_library_file,
"label",
"globaldata_vec2");
3255 possible_camera_calibrations.insert(possible_camera_calibrations.end(), current_camera_file.begin(), current_camera_file.end());
3262 ImGui::SetWindowFontScale(1.25f);
3263 ImGui::Text(
"Band Groups:");
3264 ImGui::SetWindowFontScale(1.0f);
3265 dropDown(
"##band_group_combo", current_band_group, band_group_names);
3267 if (ImGui::Button(
"Add Band Group")) {
3268 std::string default_band_group_label =
"band_group";
3269 std::string new_band_group_label =
"band_group_0";
3271 while (band_group_lookup.find(new_band_group_label) != band_group_lookup.end()) {
3273 new_band_group_label = default_band_group_label +
"_" + std::to_string(count);
3275 std::vector<std::string> new_band_group_vector;
3276 new_band_group_vector.push_back(
"red");
3277 new_band_group_vector.push_back(
"green");
3278 new_band_group_vector.push_back(
"blue");
3279 bandGroup new_band_group{new_band_group_vector,
false,
false,
false};
3280 band_group_lookup[new_band_group_label] = new_band_group;
3281 band_group_names.insert(new_band_group_label);
3282 current_band_group = new_band_group_label;
3284 if (!current_band_group.empty()) {
3285 ImGui::SetNextItemWidth(100);
3286 std::string prev_group_name = current_band_group;
3287 ImGui::InputText(
"Group Name", ¤t_band_group);
3288 if (current_band_group.empty() || band_group_lookup.find(current_band_group) != band_group_lookup.end()) {
3289 current_band_group = prev_group_name;
3291 if (current_band_group != prev_group_name) {
3292 bandGroup temp = band_group_lookup[prev_group_name];
3293 std::map<std::string, bandGroup>::iterator current_band_group_iter = band_group_lookup.find(prev_group_name);
3294 if (current_band_group_iter != band_group_lookup.end()) {
3295 band_group_lookup.erase(current_band_group_iter);
3297 band_group_lookup[current_band_group] = temp;
3298 band_group_names.erase(prev_group_name);
3299 band_group_names.insert(current_band_group);
3302 if (ImGui::Button(
"Delete Group")) {
3303 band_group_names.erase(current_band_group);
3304 band_group_lookup.erase(current_band_group);
3305 current_band_group =
"";
3307 ImGui::Checkbox(
"Grayscale", &band_group_lookup[current_band_group].grayscale);
3309 ImGui::Checkbox(
"Norm", &band_group_lookup[current_band_group].norm);
3310 if (std::find(band_group_lookup[current_band_group].bands.begin(), band_group_lookup[current_band_group].bands.end(),
"red") != band_group_lookup[current_band_group].bands.end() &&
3311 std::find(band_group_lookup[current_band_group].bands.begin(), band_group_lookup[current_band_group].bands.end(),
"green") != band_group_lookup[current_band_group].bands.end() &&
3312 std::find(band_group_lookup[current_band_group].bands.begin(), band_group_lookup[current_band_group].bands.end(),
"blue") != band_group_lookup[current_band_group].bands.end()) {
3313 band_group_lookup[current_band_group].hdr =
true;
3316 ImGui::SetNextItemWidth(100);
3317 dropDown(
"##band_1_combo", band_group_lookup[current_band_group].bands[0], bandlabels);
3318 if (!band_group_lookup[current_band_group].grayscale) {
3321 ImGui::SetNextItemWidth(100);
3322 dropDown(
"##band_2_combo", band_group_lookup[current_band_group].bands[1], bandlabels);
3325 ImGui::SetNextItemWidth(100);
3326 dropDown(
"##band_3_combo", band_group_lookup[current_band_group].bands[2], bandlabels);
3328 ImGui::Text(
"Select Bands");
3331 ImGui::Text(
"Select Band");
3334 ImGui::SetWindowFontScale(1.25f);
3335 ImGui::Text(
"Edit Camera:");
3336 ImGui::SetWindowFontScale(1.0f);
3337 if (ImGui::BeginCombo(
"##camera_combo", current_cam.c_str())) {
3338 for (
int n = 0; n < camera_names.size(); n++) {
3339 bool is_cam_selected = (current_cam == camera_names[n]);
3340 if (ImGui::Selectable(camera_names[n].c_str(), is_cam_selected))
3341 current_cam = camera_names[n];
3342 if (is_cam_selected)
3343 ImGui::SetItemDefaultFocus();
3348 if (ImGui::Button(
"Add New Camera")) {
3349 std::string default_cam_name =
"camera";
3350 std::string new_cam_name =
"camera_0";
3352 while (camera_dict.find(new_cam_name) != camera_dict.end()) {
3354 new_cam_name = default_cam_name +
"_" + std::to_string(count);
3356 camera_dict.insert({new_cam_name, scast<int>(camera_names.size())});
3357 camera_resolutions.push_back(camera_resolution);
3358 camera_calibrations.push_back(camera_calibrations[camera_dict[current_cam]]);
3359 focal_plane_distances.push_back(focal_plane_distance);
3360 lens_diameters.push_back(lens_diameter);
3361 FOV_aspect_ratios.push_back(FOV_aspect_ratio);
3362 HFOVs.push_back(HFOV);
3363 camera_names.push_back(new_cam_name);
3364 std::string parent =
"camera";
3365 pugi::xml_node camera_block = helios.child(parent.c_str());
3366 pugi::xml_node new_cam_node = helios.append_copy(camera_block);
3367 std::string name =
"label";
3368 pugi::xml_attribute node_label = new_cam_node.attribute(name.c_str());
3369 node_label.set_value(new_cam_name.c_str());
3370 current_cam = new_cam_name;
3372 ImGui::SetNextItemWidth(100);
3373 std::string prev_cam_name = camera_names[camera_dict[current_cam]];
3374 ImGui::InputText(
"##cam_name", &camera_names[camera_dict[current_cam]]);
3375 if (camera_names[camera_dict[current_cam]] != prev_cam_name) {
3376 int temp = camera_dict[current_cam];
3377 current_cam = camera_names[camera_dict[current_cam]];
3378 std::map<std::string, int>::iterator current_cam_iter = camera_dict.find(prev_cam_name);
3379 if (current_cam_iter != camera_dict.end()) {
3380 camera_dict.erase(current_cam_iter);
3382 camera_dict[current_cam] = temp;
3385 ImGui::Text(
"Camera Label");
3387 ImGui::SetNextItemWidth(100);
3388 dropDown(
"##camera_calibration_band", current_calibration_band, bandlabels);
3390 ImGui::Text(
"Band");
3391 ImGui::SetNextItemWidth(250);
3393 dropDown(
"##camera_band_group_combo", camera_calibrations[camera_dict[current_cam]][current_calibration_band], possible_camera_calibrations);
3395 ImGui::Text(
"Calibration");
3411 ImGui::SetNextItemWidth(90);
3412 ImGui::InputInt(
"##camera_resolution_x", &camera_resolutions[camera_dict[current_cam]].x);
3413 randomizePopup(
"camera_resolution_x_" + std::to_string(camera_dict[current_cam]),
createTaggedPtr(&camera_resolutions[camera_dict[current_cam]].x));
3414 randomizerParams(
"camera_resolution_x_" + std::to_string(camera_dict[current_cam]));
3415 ImGui::OpenPopupOnItemClick((
"randomize_camera_resolution_x_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
3417 ImGui::SetNextItemWidth(90);
3418 ImGui::InputInt(
"##camera_resolution_y", &camera_resolutions[camera_dict[current_cam]].y);
3419 randomizePopup(
"camera_resolution_y_" + std::to_string(camera_dict[current_cam]),
createTaggedPtr(&camera_resolutions[camera_dict[current_cam]].y));
3420 randomizerParams(
"camera_resolution_y_" + std::to_string(camera_dict[current_cam]));
3421 ImGui::OpenPopupOnItemClick((
"randomize_camera_resolution_y_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
3423 ImGui::Text(
"Camera Resolution");
3425 ImGui::SetNextItemWidth(50);
3426 ImGui::InputFloat(
"Focal Plane Distance", &focal_plane_distances[camera_dict[current_cam]]);
3427 randomizePopup(
"focal_plane_distance_" + std::to_string(camera_dict[current_cam]),
createTaggedPtr(&focal_plane_distances[camera_dict[current_cam]]));
3428 randomizerParams(
"focal_plane_distance_" + std::to_string(camera_dict[current_cam]));
3429 ImGui::OpenPopupOnItemClick((
"randomize_focal_plane_distance_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
3431 ImGui::SetNextItemWidth(50);
3432 ImGui::InputFloat(
"Lens Diameter", &lens_diameters[camera_dict[current_cam]]);
3433 randomizePopup(
"lens_diameter_" + std::to_string(camera_dict[current_cam]),
createTaggedPtr(&lens_diameters[camera_dict[current_cam]]));
3434 randomizerParams(
"lens_diameter_" + std::to_string(camera_dict[current_cam]));
3435 ImGui::OpenPopupOnItemClick((
"randomize_lens_diameter_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
3437 ImGui::SetNextItemWidth(50);
3438 ImGui::InputFloat(
"FOV Aspect Ratio", &FOV_aspect_ratios[camera_dict[current_cam]]);
3439 randomizePopup(
"FOV_aspect_ratio_" + std::to_string(camera_dict[current_cam]),
createTaggedPtr(&FOV_aspect_ratios[camera_dict[current_cam]]));
3440 randomizerParams(
"FOV_aspect_ratio_" + std::to_string(camera_dict[current_cam]));
3441 ImGui::OpenPopupOnItemClick((
"randomize_FOV_aspect_ratio_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
3443 ImGui::SetNextItemWidth(50);
3444 ImGui::InputFloat(
"HFOV", &HFOVs[camera_dict[current_cam]]);
3445 randomizePopup(
"HFOV_" + std::to_string(camera_dict[current_cam]),
createTaggedPtr(&HFOVs[camera_dict[current_cam]]));
3446 randomizerParams(
"HFOV_" + std::to_string(camera_dict[current_cam]));
3447 ImGui::OpenPopupOnItemClick((
"HFOV_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
3453void ProjectBuilder::canopyTab() {
3454#if defined(ENABLE_HELIOS_VISUALIZER) && defined(ENABLE_PLANT_ARCHITECTURE)
3455 dropDown(
"##canopy_combo", current_canopy, canopy_labels_set);
3457 if (ImGui::Button(
"Add Canopy")) {
3460 if (!current_canopy.empty()) {
3461 if (ImGui::Button(
"Update Canopy")) {
3462 updateCanopy(current_canopy);
3464 canopy_dict[current_canopy].is_dirty =
false;
3467 if (ImGui::Button(
"Delete Canopy")) {
3468 deleteCanopy(current_canopy);
3469 updatePrimitiveTypes();
3473 if (canopy_dict[current_canopy].is_dirty) {
3475 ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
3476 ImGui::Text(
"update required");
3477 ImGui::PopStyleColor();
3479 ImGui::SetNextItemWidth(100);
3480 std::string prev_canopy_name = canopy_dict[current_canopy].label;
3481 ImGui::InputText(
"##canopy_name", &canopy_dict[current_canopy].label);
3482 if (canopy_dict[current_canopy].label != prev_canopy_name && canopy_labels_set.find(canopy_dict[current_canopy].label) == canopy_labels_set.end() && !canopy_dict[current_canopy].label.empty()) {
3483 canopy temp = canopy_dict[current_canopy];
3484 current_canopy = canopy_dict[prev_canopy_name].label;
3485 std::map<std::string, canopy>::iterator current_canopy_iter = canopy_dict.find(prev_canopy_name);
3486 if (current_canopy_iter != canopy_dict.end()) {
3487 canopy_dict.erase(current_canopy_iter);
3489 canopy_dict[current_canopy] = temp;
3491 canopy_labels_set.erase(prev_canopy_name);
3492 canopy_labels_set.insert(current_canopy);
3494 canopy_dict[current_canopy].label = prev_canopy_name;
3497 ImGui::Text(
"Canopy Name");
3499 ImGui::SetNextItemWidth(250);
3501 std::string prev_lib = canopy_dict[current_canopy].library_name_verbose;
3502 dropDown(
"Plant Library###dropdown", canopy_dict[current_canopy].library_name_verbose, plant_types_verbose);
3503 if (canopy_dict[current_canopy].library_name_verbose != prev_lib)
3504 canopy_dict[current_canopy].is_dirty =
true;
3505 canopy_dict[current_canopy].library_name = plant_type_lookup[canopy_dict[current_canopy].library_name_verbose];
3507 ImGui::SetNextItemWidth(100);
3508 std::string prev_canopy_data_group = canopy_dict[current_canopy].data_group;
3509 ImGui::InputText(
"##canopy_data_group", &canopy_dict[current_canopy].data_group);
3510 if (canopy_dict[current_canopy].data_group ==
"All" || canopy_dict[current_canopy].data_group.empty()) {
3511 canopy_dict[current_canopy].data_group = prev_canopy_data_group;
3513 if (!canopy_dict[current_canopy].data_group.empty() && prev_canopy_data_group != canopy_dict[current_canopy].data_group) {
3514 std::string new_data_group = canopy_dict[current_canopy].data_group;
3515 for (
int i = 0; i < canopy_dict[current_canopy].IDs.size(); i++) {
3517 for (
auto &
obj: new_canopy_objIDs) {
3529 ImGui::Text(
"Data Group");
3531 vec3 prev_canopy_origin_ =
vec3(canopy_dict[current_canopy].origin);
3532 ImGui::SetNextItemWidth(60);
3533 ImGui::InputFloat(
"##canopy_origin_x", &canopy_dict[current_canopy].origin.x);
3534 randomizePopup(
"canopy_origin_x_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].origin.x));
3535 randomizerParams(
"canopy_origin_x_" + std::to_string(canopy_dict[current_canopy].idx));
3536 ImGui::OpenPopupOnItemClick((
"randomize_canopy_origin_x_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3538 ImGui::SetNextItemWidth(60);
3539 ImGui::InputFloat(
"##canopy_origin_y", &canopy_dict[current_canopy].origin.y);
3540 randomizePopup(
"canopy_origin_y_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].origin.y));
3541 randomizerParams(
"canopy_origin_y_" + std::to_string(canopy_dict[current_canopy].idx));
3542 ImGui::OpenPopupOnItemClick((
"randomize_canopy_origin_y_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3544 ImGui::SetNextItemWidth(60);
3545 ImGui::InputFloat(
"##canopy_origin_z", &canopy_dict[current_canopy].origin.z);
3546 randomizePopup(
"canopy_origin_z_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].origin.z));
3547 randomizerParams(
"canopy_origin_z_" + std::to_string(canopy_dict[current_canopy].idx));
3548 ImGui::OpenPopupOnItemClick((
"randomize_canopy_origin_z_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3550 ImGui::Text(
"Canopy Origin");
3551 if (prev_canopy_origin_ != canopy_dict[current_canopy].origin) {
3552 canopy_dict[current_canopy].is_dirty =
true;
3555 int2 prev_plant_count_ =
int2(canopy_dict[current_canopy].plant_count);
3556 ImGui::SetNextItemWidth(100);
3557 ImGui::InputInt(
"##plant_count_x", &canopy_dict[current_canopy].plant_count.
x);
3558 canopy_dict[current_canopy].plant_count.x = std::max(canopy_dict[current_canopy].plant_count.
x, 1);
3559 randomizePopup(
"plant_count_x_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].plant_count.
x));
3560 randomizerParams(
"plant_count_x_" + std::to_string(canopy_dict[current_canopy].idx));
3561 ImGui::OpenPopupOnItemClick((
"randomize_plant_count_x_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3563 ImGui::SetNextItemWidth(100);
3564 ImGui::InputInt(
"##plant_count_y", &canopy_dict[current_canopy].plant_count.
y);
3565 canopy_dict[current_canopy].plant_count.y = std::max(canopy_dict[current_canopy].plant_count.
y, 1);
3566 randomizePopup(
"plant_count_y_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].plant_count.
y));
3567 randomizerParams(
"plant_count_y_" + std::to_string(canopy_dict[current_canopy].idx));
3568 ImGui::OpenPopupOnItemClick((
"randomize_plant_count_y_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3570 ImGui::Text(
"Plant Count");
3571 if (prev_plant_count_ != canopy_dict[current_canopy].plant_count) {
3572 canopy_dict[current_canopy].is_dirty =
true;
3575 vec2 prev_plant_spacing_ =
vec2(canopy_dict[current_canopy].plant_spacing);
3576 ImGui::SetNextItemWidth(50);
3577 ImGui::InputFloat(
"##plant_spacing_x", &canopy_dict[current_canopy].plant_spacing.
x);
3578 randomizePopup(
"plant_spacing_x_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].plant_spacing.
x));
3579 randomizerParams(
"plant_spacing_x_" + std::to_string(canopy_dict[current_canopy].idx));
3580 ImGui::OpenPopupOnItemClick((
"randomize_plant_spacing_x_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3582 ImGui::SetNextItemWidth(50);
3583 ImGui::InputFloat(
"##plant_spacing_y", &canopy_dict[current_canopy].plant_spacing.
y);
3584 randomizePopup(
"plant_spacing_y_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].plant_spacing.
y));
3585 randomizerParams(
"plant_spacing_y_" + std::to_string(canopy_dict[current_canopy].idx));
3586 ImGui::OpenPopupOnItemClick((
"randomize_plant_spacing_y_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3588 ImGui::Text(
"Plant Spacing");
3589 if (prev_plant_spacing_ != canopy_dict[current_canopy].plant_spacing) {
3590 canopy_dict[current_canopy].is_dirty =
true;
3593 float prev_age_ = canopy_dict[current_canopy].age;
3594 ImGui::SetNextItemWidth(80);
3595 ImGui::InputFloat(
"Plant Age", &canopy_dict[current_canopy].age);
3596 randomizePopup(
"plant_age_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].age));
3597 randomizerParams(
"plant_age_" + std::to_string(canopy_dict[current_canopy].idx));
3598 ImGui::OpenPopupOnItemClick((
"randomize_plant_age_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3599 if (prev_age_ != canopy_dict[current_canopy].age) {
3600 canopy_dict[current_canopy].is_dirty =
true;
3603 float prev_ground_clipping_height_ = canopy_dict[current_canopy].ground_clipping_height;
3604 ImGui::SetNextItemWidth(80);
3605 ImGui::InputFloat(
"Ground Clipping Height", &canopy_dict[current_canopy].ground_clipping_height);
3606 randomizePopup(
"ground_clipping_height_" + std::to_string(canopy_dict[current_canopy].idx),
createTaggedPtr(&canopy_dict[current_canopy].ground_clipping_height));
3607 randomizerParams(
"ground_clipping_height_" + std::to_string(canopy_dict[current_canopy].idx));
3608 ImGui::OpenPopupOnItemClick((
"randomize_ground_clipping_height_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3609 if (prev_ground_clipping_height_ != canopy_dict[current_canopy].ground_clipping_height) {
3610 canopy_dict[current_canopy].is_dirty =
true;
3612 if (ImGui::Button(
"Save Canopy to OBJ/PLY File")) {
3614 if (!new_obj_file.empty()) {
3615 std::string file_extension = new_obj_file;
3616 size_t last_obj_file = file_extension.rfind(
'.');
3617 if (last_obj_file != std::string::npos) {
3618 file_extension = file_extension.substr(last_obj_file + 1);
3620 if (file_extension ==
"obj" || file_extension ==
"ply") {
3621 if (!std::filesystem::exists(new_obj_file)) {
3623 std::ofstream outFile(new_obj_file);
3625 if (!save_plants_individually) {
3626 saveCanopy(new_obj_file, canopy_dict[current_canopy].IDs, canopy_dict[current_canopy].origin, file_extension);
3628 saveCanopy(new_obj_file, canopy_dict[current_canopy].IDs, canopy_dict[current_canopy].individual_plant_locations, file_extension);
3632 std::cout <<
"Not a valid file type. Object must be saved to .obj or .ply file." << std::endl;
3636 std::cout <<
"Not a valid file." << std::endl;
3640 ImGui::Checkbox(
"Save plants individually", &save_plants_individually);
3646void ProjectBuilder::generalTab() {
3647#ifdef ENABLE_HELIOS_VISUALIZER
3649 ImGui::SetWindowFontScale(1.25f);
3650 ImGui::Text(
"Visualization:");
3651 ImGui::SetWindowFontScale(1.0f);
3653 bool enable_coords_ = enable_coordinate_axes;
3654 toggle_button(
"##coordinate_axes", &enable_coordinate_axes);
3655 if (enable_coords_ != enable_coordinate_axes) {
3656 if (enable_coordinate_axes) {
3665 if (enable_coordinate_axes) {
3666 ImGui::Text(
"Coordinate Axes Enabled");
3668 ImGui::Text(
"Coordinate Axes Disabled");
3671 bool enable_colorbar_ = enable_colorbar;
3673 if (enable_colorbar_ != enable_colorbar) {
3674 if (enable_colorbar) {
3683 if (enable_colorbar) {
3684 ImGui::Text(
"Colorbar Enabled");
3686 ImGui::Text(
"Colorbar Disabled");
3689 std::string prev_lighting_model = lighting_model;
3690 ImGui::SetNextItemWidth(120);
3691 dropDown(
"Lighting Model", lighting_model, lighting_models);
3692 if (prev_lighting_model != lighting_model) {
3693 if (lighting_model ==
"None")
3695 if (lighting_model ==
"Phong")
3697 if (lighting_model ==
"Phong Shadowed")
3700 ImGui::SetNextItemWidth(120);
3702 ImGui::InputFloat(
"Light Intensity Factor", &light_intensity);
3707 if (light_coord_type) {
3709 vec2 light_dir_sphere;
3712 ImGui::Text(
"Elevation:");
3714 ImGui::SetNextItemWidth(80);
3715 ImGui::InputFloat(
"##light_elevation", &light_dir_sphere.
x);
3717 ImGui::Text(
"Azimuth:");
3719 ImGui::SetNextItemWidth(80);
3720 ImGui::InputFloat(
"##light_azimuth", &light_dir_sphere.
y);
3722 ImGui::Text(
"Light Direction (Spherical)");
3723 if (light_dir_sphere.
x != light_dir_sphere_.
elevation || light_dir_sphere.
y != light_dir_sphere_.
azimuth) {
3729 light_dir[0] = light_direction.
x;
3730 light_dir[1] = light_direction.
y;
3731 light_dir[2] = light_direction.
z;
3732 ImGui::InputFloat3(
"Light Direction (Cartesian)", light_dir);
3733 light_direction.
x = light_dir[0];
3734 light_direction.
y = light_dir[1];
3735 light_direction.
z = light_dir[2];
3739 ImGui::SetWindowFontScale(1.25f);
3740 ImGui::Text(
"Location:");
3741 ImGui::SetWindowFontScale(1.0f);
3742 if (ImGui::Button(
"Update Location")) {
3746 ImGui::SetNextItemWidth(100);
3747 ImGui::InputFloat(
"Latitude", &latitude);
3749 randomizerParams(
"latitude");
3750 ImGui::OpenPopupOnItemClick(
"randomize_latitude", ImGuiPopupFlags_MouseButtonRight);
3753 ImGui::SetNextItemWidth(100);
3754 ImGui::InputFloat(
"Longitude", &longitude);
3756 randomizerParams(
"longitude");
3757 ImGui::OpenPopupOnItemClick(
"randomize_longitude", ImGuiPopupFlags_MouseButtonRight);
3759 ImGui::SetNextItemWidth(100);
3760 ImGui::InputInt(
"UTC Offset", &UTC_offset);
3762 randomizerParams(
"UTC_offset");
3763 ImGui::OpenPopupOnItemClick(
"randomize_UTC_offset", ImGuiPopupFlags_MouseButtonRight);
3765 ImGui::SetNextItemWidth(60);
3766 ImGui::RadioButton(
"CSV", is_weather_file_csv);
3767 if (ImGui::IsItemClicked())
3768 is_weather_file_csv =
true;
3770 ImGui::RadioButton(
"CIMIS", !is_weather_file_csv);
3771 if (ImGui::IsItemClicked())
3772 is_weather_file_csv =
false;
3773 std::string prev_weather_file;
3774 std::string *weather_file;
3775 if (is_weather_file_csv) {
3777 weather_file = &csv_weather_file;
3778 prev_weather_file = csv_weather_file;
3780 ImGui::Text(
"CIMIS");
3781 weather_file = &cimis_weather_file;
3782 prev_weather_file = cimis_weather_file;
3785 if (ImGui::Button(
"Weather File")) {
3787 if (!weather_file_.empty()) {
3788 *weather_file = weather_file_;
3790 if (is_weather_file_csv) {
3796 std::cout <<
"Failed to load weather file: " << *weather_file << std::endl;
3797 *weather_file = prev_weather_file;
3800 *weather_file = prev_weather_file;
3804 std::string shorten_weather_file = *weather_file;
3805 for (
char &c: shorten_weather_file) {
3810 size_t last_weather_file = shorten_weather_file.rfind(
'/');
3811 if (last_weather_file != std::string::npos) {
3812 shorten_weather_file = shorten_weather_file.substr(last_weather_file + 1);
3814 ImGui::Text(
"%s", shorten_weather_file.c_str());
3816 ImGui::SetWindowFontScale(1.25f);
3817 ImGui::Text(
"Ground:");
3818 ImGui::SetWindowFontScale(1.0f);
3819 if (ImGui::Button(
"Update Ground")) {
3821 updatePrimitiveTypes();
3826 if (ImGui::Button(
"Delete Ground")) {
3828 updatePrimitiveTypes();
3834 ImGui::RadioButton(
"Use Texture File", ground_flag == 1);
3835 if (ImGui::IsItemClicked())
3838 ImGui::RadioButton(
"Use Model File", ground_flag == 2);
3839 if (ImGui::IsItemClicked())
3841 if (ground_flag == 0) {
3843 ImGui::ColorEdit3(
"##ground_color_edit", ground_color);
3844 }
else if (ground_flag == 1) {
3846 ImGui::SetNextItemWidth(60);
3847 if (ImGui::Button(
"Ground Texture File")) {
3849 if (!ground_texture_file_.empty()) {
3850 ground_texture_file = ground_texture_file_;
3854 std::string shorten = ground_texture_file;
3855 for (
char &c: shorten) {
3860 size_t last = shorten.rfind(
'/');
3861 if (last != std::string::npos) {
3862 shorten = shorten.substr(last + 1);
3864 ImGui::Text(
"%s", shorten.c_str());
3865 }
else if (ground_flag == 2) {
3867 ImGui::SetNextItemWidth(60);
3868 if (ImGui::Button(
"Ground Model File")) {
3870 if (!ground_model_file_.empty()) {
3871 ground_model_file = ground_model_file_;
3875 ImGui::Text(
"%s",
shortenPath(ground_model_file).c_str());
3877 toggle_button(
"##use_ground_texture_color", &use_ground_texture);
3879 if (use_ground_texture) {
3881 ImGui::Text(
"Use Ground Texture Color");
3884 ImGui::ColorEdit3(
"##ground_color_edit", ground_color);
3886 ImGui::Text(
"Manually Set Ground Color");
3889 ImGui::SetNextItemWidth(60);
3890 ImGui::InputFloat(
"##domain_origin_x", &domain_origin.
x);
3892 randomizerParams(
"domain_origin_x");
3893 ImGui::OpenPopupOnItemClick(
"randomize_domain_origin_x", ImGuiPopupFlags_MouseButtonRight);
3895 ImGui::SetNextItemWidth(60);
3896 ImGui::InputFloat(
"##domain_origin_y", &domain_origin.
y);
3898 randomizerParams(
"domain_origin_y");
3899 ImGui::OpenPopupOnItemClick(
"randomize_domain_origin_y", ImGuiPopupFlags_MouseButtonRight);
3901 ImGui::SetNextItemWidth(60);
3902 ImGui::InputFloat(
"##domain_origin_z", &domain_origin.
z);
3904 randomizerParams(
"domain_origin_z");
3905 ImGui::OpenPopupOnItemClick(
"randomize_domain_origin_z", ImGuiPopupFlags_MouseButtonRight);
3907 ImGui::Text(
"Domain Origin");
3908 if (ground_flag == 1) {
3910 ImGui::SetNextItemWidth(100);
3911 ImGui::InputInt(
"##ground_resolution_x", &ground_resolution.
x);
3912 randomizePopup(
"ground_resolution_x",
createTaggedPtr(&ground_resolution.
x));
3913 randomizerParams(
"ground_resolution_x");
3914 ImGui::OpenPopupOnItemClick(
"randomize_ground_resolution_x", ImGuiPopupFlags_MouseButtonRight);
3916 ImGui::SetNextItemWidth(100);
3917 ImGui::InputInt(
"##ground_resolution_y", &ground_resolution.
y);
3918 randomizePopup(
"ground_resolution_y",
createTaggedPtr(&ground_resolution.
y));
3919 randomizerParams(
"ground_resolution_y");
3920 ImGui::OpenPopupOnItemClick(
"randomize_ground_resolution_y", ImGuiPopupFlags_MouseButtonRight);
3922 ImGui::Text(
"Ground Resolution");
3924 ImGui::SetNextItemWidth(50);
3925 ImGui::InputFloat(
"##domain_extent_x", &domain_extent.
x);
3927 randomizerParams(
"domain_extent_x");
3928 ImGui::OpenPopupOnItemClick(
"randomize_domain_extent_x", ImGuiPopupFlags_MouseButtonRight);
3930 ImGui::SetNextItemWidth(50);
3931 ImGui::InputFloat(
"##domain_extent_y", &domain_extent.
y);
3933 randomizerParams(
"domain_extent_y");
3934 ImGui::OpenPopupOnItemClick(
"randomize_domain_extent_y", ImGuiPopupFlags_MouseButtonRight);
3936 ImGui::Text(
"Domain Extent");
3938 ImGui::SetNextItemWidth(60);
3940 temp[0] = num_tiles.
x;
3941 temp[1] = num_tiles.
y;
3942 ImGui::InputInt2(
"Number of Tiles", temp);
3943 num_tiles.
x = temp[0];
3944 num_tiles.
y = temp[1];
3950void ProjectBuilder::objectTab() {
3951#ifdef ENABLE_HELIOS_VISUALIZER
3952 if (ImGui::Button(
"Load Object File")) {
3954 if (!new_obj_file.empty() && std::filesystem::exists(new_obj_file)) {
3955 if (std::filesystem::path(new_obj_file).extension() !=
".obj" && std::filesystem::path(new_obj_file).extension() !=
".ply") {
3956 std::cout <<
"Object file must have .obj or .ply extension." << std::endl;
3959 std::vector<uint> new_UUIDs;
3960 if (std::filesystem::path(new_obj_file).extension() ==
".obj") {
3962 }
else if (std::filesystem::path(new_obj_file).extension() ==
".ply") {
3966 std::filesystem::path mtl_path(new_obj_file);
3967 mtl_path.replace_extension(
"mtl");
3968 if (std::filesystem::exists(mtl_path)) {
3969 new_obj.use_texture_file =
true;
3971 new_obj.use_texture_file =
false;
3975 std::string default_object_label =
"object";
3976 std::string new_obj_label =
"object_0";
3978 while (objects_dict.find(new_obj_label) != objects_dict.end()) {
3980 new_obj_label = default_object_label +
"_" + std::to_string(count);
3982 obj_names_set.insert(new_obj_label);
3983 new_obj.index = obj_idx;
3985 new_obj.name = new_obj_label;
3986 new_obj.file = new_obj_file;
3987 new_obj.UUIDs = new_UUIDs;
3989 new_obj.position =
vec3(0, 0, 0);
3990 new_obj.prev_position =
vec3(0, 0, 0);
3991 new_obj.orientation =
vec3(0, 0, 0);
3992 new_obj.prev_orientation =
vec3(0, 0, 0);
3993 new_obj.scale =
vec3(1, 1, 1);
3994 new_obj.prev_scale =
vec3(1, 1, 1);
3996 new_obj.prev_color =
RGBcolor(0, 0, 1);
3997 new_obj.data_group =
"";
3998 new_obj.is_dirty =
false;
3999 current_obj = new_obj_label;
4000 objects_dict[new_obj_label] = new_obj;
4006 if (ImGui::BeginCombo(
"##obj_combo", current_obj.c_str())) {
4007 for (std::string obj_name: obj_names_set) {
4008 bool is_obj_selected = (current_obj == obj_name);
4009 if (ImGui::Selectable(obj_name.c_str(), is_obj_selected))
4010 current_obj = obj_name;
4011 if (is_obj_selected)
4012 ImGui::SetItemDefaultFocus();
4017 ImGui::Text(
"Select Object");
4018 if (!current_obj.empty()) {
4019 if (ImGui::Button(
"Delete Object")) {
4020 deleteObject(current_obj);
4022 if (objects_dict[current_obj].is_dirty) {
4024 ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
4025 ImGui::Text(
"update required");
4026 ImGui::PopStyleColor();
4028 ImGui::SetNextItemWidth(100);
4029 std::string prev_obj_name = objects_dict[current_obj].name;
4030 ImGui::InputText(
"##obj_name", &objects_dict[current_obj].name);
4031 if (objects_dict[current_obj].name != prev_obj_name && !objects_dict[current_obj].name.empty() && obj_names_set.find(objects_dict[current_obj].name) == obj_names_set.end()) {
4032 object temp_obj = objects_dict[prev_obj_name];
4033 current_obj = objects_dict[current_obj].name;
4034 std::map<std::string, object>::iterator delete_obj_iter = objects_dict.find(prev_obj_name);
4035 if (delete_obj_iter != objects_dict.end()) {
4036 objects_dict.erase(delete_obj_iter);
4038 objects_dict[current_obj] = temp_obj;
4039 obj_names_set.erase(prev_obj_name);
4040 obj_names_set.insert(current_obj);
4042 objects_dict[current_obj].name = prev_obj_name;
4045 ImGui::Text(
"Object Name");
4046 if (!current_obj.empty()) {
4048 ImGui::SetNextItemWidth(100);
4049 std::string prev_obj_data_group = objects_dict[current_obj].data_group;
4050 ImGui::InputText(
"##obj_data_group", &objects_dict[current_obj].data_group);
4051 if (objects_dict[current_obj].data_group ==
"All" || objects_dict[current_obj].data_group.empty()) {
4052 objects_dict[current_obj].data_group = prev_obj_data_group;
4054 if (!objects_dict[current_obj].data_group.empty() && prev_obj_data_group != objects_dict[current_obj].data_group) {
4058 std::string new_data_group = objects_dict[current_obj].data_group;
4060 int index = objects_dict[current_obj].index;
4065 ImGui::Text(
"Data Group");
4066 bool use_obj_texture = objects_dict[current_obj].use_texture_file;
4068 if (use_obj_texture != objects_dict[current_obj].use_texture_file) {
4069 objects_dict[current_obj].use_texture_file = use_obj_texture;
4070 objects_dict[current_obj].is_dirty =
true;
4075 if (!use_obj_texture) {
4078 col[0] = objects_dict[current_obj].color.r;
4079 col[1] = objects_dict[current_obj].color.g;
4080 col[2] = objects_dict[current_obj].color.b;
4081 ImGui::ColorEdit3(
"##obj_color_edit", col);
4082 if (objects_dict[current_obj].color.r != col[0] || objects_dict[current_obj].color.g != col[1] || objects_dict[current_obj].color.b != col[2]) {
4086 ImGui::Text(
"Object Color");
4089 ImGui::Text(
"Use Color from Texture File");
4092 ImGui::SetNextItemWidth(60);
4093 ImGui::InputFloat(
"##obj_scale_x", &objects_dict[current_obj].scale.x);
4094 randomizePopup(
"obj_scale_x_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].scale.x, &objects_dict[current_obj].is_dirty));
4095 randomizerParams(
"obj_scale_x_" + std::to_string(objects_dict[current_obj].index));
4096 ImGui::OpenPopupOnItemClick((
"randomize_obj_scale_x_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4098 ImGui::SetNextItemWidth(60);
4099 ImGui::InputFloat(
"##obj_scale_y", &objects_dict[current_obj].scale.y);
4100 randomizePopup(
"obj_scale_y_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].scale.y, &objects_dict[current_obj].is_dirty));
4101 randomizerParams(
"obj_scale_y_" + std::to_string(objects_dict[current_obj].index));
4102 ImGui::OpenPopupOnItemClick((
"randomize_obj_scale_y_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4104 ImGui::SetNextItemWidth(60);
4105 ImGui::InputFloat(
"##obj_scale_z", &objects_dict[current_obj].scale.z);
4106 randomizePopup(
"obj_scale_z_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].scale.z, &objects_dict[current_obj].is_dirty));
4107 randomizerParams(
"obj_scale_z_" + std::to_string(objects_dict[current_obj].index));
4108 ImGui::OpenPopupOnItemClick((
"randomize_obj_scale_z_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4110 ImGui::Text(
"Object Scale");
4112 ImGui::SetNextItemWidth(60);
4113 ImGui::InputFloat(
"##obj_position_x", &objects_dict[current_obj].position.x);
4114 randomizePopup(
"obj_position_x_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].position.x, &objects_dict[current_obj].is_dirty));
4115 randomizerParams(
"obj_position_x_" + std::to_string(objects_dict[current_obj].index));
4116 ImGui::OpenPopupOnItemClick((
"randomize_obj_position_x_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4118 ImGui::SetNextItemWidth(60);
4119 ImGui::InputFloat(
"##obj_position_y", &objects_dict[current_obj].position.y);
4120 randomizePopup(
"obj_position_y_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].position.y, &objects_dict[current_obj].is_dirty));
4121 randomizerParams(
"obj_position_y_" + std::to_string(objects_dict[current_obj].index));
4122 ImGui::OpenPopupOnItemClick((
"randomize_obj_position_y_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4124 ImGui::SetNextItemWidth(60);
4125 ImGui::InputFloat(
"##obj_position_z", &objects_dict[current_obj].position.z);
4126 randomizePopup(
"obj_position_z_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].position.z, &objects_dict[current_obj].is_dirty));
4127 randomizerParams(
"obj_position_z_" + std::to_string(objects_dict[current_obj].index));
4128 ImGui::OpenPopupOnItemClick((
"randomize_obj_position_z_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4130 ImGui::Text(
"Object Position");
4132 ImGui::SetNextItemWidth(60);
4133 ImGui::InputFloat(
"##obj_orientation_x", &objects_dict[current_obj].orientation.x);
4134 randomizePopup(
"obj_orientation_x_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].orientation.x, &objects_dict[current_obj].is_dirty));
4135 randomizerParams(
"obj_orientation_x_" + std::to_string(objects_dict[current_obj].index));
4136 ImGui::OpenPopupOnItemClick((
"randomize_obj_orientation_x_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4138 ImGui::SetNextItemWidth(60);
4139 ImGui::InputFloat(
"##obj_orientation_y", &objects_dict[current_obj].orientation.y);
4140 randomizePopup(
"obj_orientation_y_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].orientation.y, &objects_dict[current_obj].is_dirty));
4141 randomizerParams(
"obj_orientation_y_" + std::to_string(objects_dict[current_obj].index));
4142 ImGui::OpenPopupOnItemClick((
"randomize_obj_orientation_y_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4144 ImGui::SetNextItemWidth(60);
4145 ImGui::InputFloat(
"##obj_orientation_z", &objects_dict[current_obj].orientation.z);
4146 randomizePopup(
"obj_orientation_z_" + std::to_string(objects_dict[current_obj].index),
createTaggedPtr(&objects_dict[current_obj].orientation.z, &objects_dict[current_obj].is_dirty));
4147 randomizerParams(
"obj_orientation_z_" + std::to_string(objects_dict[current_obj].index));
4148 ImGui::OpenPopupOnItemClick((
"randomize_obj_orientation_z_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4150 ImGui::Text(
"Object Orientation");
4151 if (objects_dict[current_obj].position != objects_dict[current_obj].prev_position || objects_dict[current_obj].orientation != objects_dict[current_obj].prev_orientation ||
4152 objects_dict[current_obj].scale != objects_dict[current_obj].prev_scale || objects_dict[current_obj].color != objects_dict[current_obj].prev_color) {
4153 objects_dict[current_obj].is_dirty =
true;
4155 if (objects_dict[current_obj].is_dirty && !ImGui::IsAnyItemActive() && !ImGui::IsAnyItemFocused()) {
4164void ProjectBuilder::objectTab(std::string curr_obj_name,
int id) {
4165#ifdef ENABLE_HELIOS_VISUALIZER
4166 if (ImGui::Button(
"Delete Object")) {
4167 deleteObject(curr_obj_name);
4170 ImGui::SetNextItemWidth(100);
4171 std::string prev_obj_name = objects_dict[curr_obj_name].name;
4172 ImGui::InputText((
"##obj_name_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].name);
4173 if (objects_dict[curr_obj_name].name != prev_obj_name && objects_dict.find(curr_obj_name) == objects_dict.end() && !objects_dict[curr_obj_name].name.empty()) {
4174 object temp_obj = objects_dict[curr_obj_name];
4175 curr_obj_name = objects_dict[curr_obj_name].name;
4176 std::map<std::string, object>::iterator delete_obj_iter = objects_dict.find(prev_obj_name);
4177 if (delete_obj_iter != objects_dict.end()) {
4178 objects_dict.erase(delete_obj_iter);
4181 objects_dict[objects_dict[curr_obj_name].name] = temp_obj;
4183 obj_names_set.erase(prev_obj_name);
4184 obj_names_set.insert(objects_dict[curr_obj_name].name);
4186 objects_dict[curr_obj_name].name = prev_obj_name;
4189 ImGui::Text(
"Object Name");
4191 vec3 prev_obj_scale =
vec3(objects_dict[curr_obj_name].scale);
4192 ImGui::SetNextItemWidth(60);
4193 ImGui::InputFloat((
"##obj_scale_x_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].scale.x);
4194 randomizePopup(
"obj_scale_x_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].scale.x, &objects_dict[curr_obj_name].is_dirty));
4195 randomizerParams(
"obj_scale_x_" + std::to_string(objects_dict[curr_obj_name].index));
4196 ImGui::OpenPopupOnItemClick((
"randomize_obj_scale_x_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4198 ImGui::SetNextItemWidth(60);
4199 ImGui::InputFloat((
"##obj_scale_y_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].scale.y);
4200 randomizePopup(
"obj_scale_y_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].scale.y, &objects_dict[curr_obj_name].is_dirty));
4201 randomizerParams(
"obj_scale_y_" + std::to_string(objects_dict[curr_obj_name].index));
4202 ImGui::OpenPopupOnItemClick((
"randomize_obj_scale_y_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4204 ImGui::SetNextItemWidth(60);
4205 ImGui::InputFloat((
"##obj_scale_z_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].scale.z);
4206 randomizePopup(
"obj_scale_z_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].scale.z, &objects_dict[curr_obj_name].is_dirty));
4207 randomizerParams(
"obj_scale_z_" + std::to_string(objects_dict[curr_obj_name].index));
4208 ImGui::OpenPopupOnItemClick((
"randomize_obj_scale_z_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4210 ImGui::Text(
"Object Scale");
4211 if (prev_obj_scale != objects_dict[curr_obj_name].scale) {
4212 objects_dict[curr_obj_name].is_dirty =
true;
4215 ImGui::SetNextItemWidth(60);
4216 vec3 prev_obj_pos =
vec3(objects_dict[curr_obj_name].scale);
4217 ImGui::InputFloat((
"##obj_position_x_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].position.x);
4218 randomizePopup(
"obj_position_x_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].position.x, &objects_dict[curr_obj_name].is_dirty));
4219 randomizerParams(
"obj_position_x_" + std::to_string(objects_dict[curr_obj_name].index));
4220 ImGui::OpenPopupOnItemClick((
"randomize_obj_position_x_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4222 ImGui::SetNextItemWidth(60);
4223 ImGui::InputFloat((
"##obj_position_y_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].position.y);
4224 randomizePopup(
"obj_position_y_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].position.y, &objects_dict[curr_obj_name].is_dirty));
4225 randomizerParams(
"obj_position_y_" + std::to_string(objects_dict[curr_obj_name].index));
4226 ImGui::OpenPopupOnItemClick((
"randomize_obj_position_y_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4228 ImGui::SetNextItemWidth(60);
4229 ImGui::InputFloat((
"##obj_position_z_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].position.z);
4230 randomizePopup(
"obj_position_z_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].position.z, &objects_dict[curr_obj_name].is_dirty));
4231 randomizerParams(
"obj_position_z_" + std::to_string(objects_dict[curr_obj_name].index));
4232 ImGui::OpenPopupOnItemClick((
"randomize_obj_position_z_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4234 ImGui::Text(
"Object Position");
4235 if (prev_obj_pos != objects_dict[curr_obj_name].position) {
4236 objects_dict[curr_obj_name].is_dirty =
true;
4239 ImGui::SetNextItemWidth(60);
4240 vec3 prev_obj_orientation =
vec3(objects_dict[curr_obj_name].orientation);
4241 ImGui::InputFloat((
"##obj_orientation_x_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].orientation.x);
4242 randomizePopup(
"obj_orientation_x_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].orientation.x, &objects_dict[curr_obj_name].is_dirty));
4243 randomizerParams(
"obj_orientation_x_" + std::to_string(objects_dict[curr_obj_name].index));
4244 ImGui::OpenPopupOnItemClick((
"randomize_obj_orientation_x_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4246 ImGui::SetNextItemWidth(60);
4247 ImGui::InputFloat((
"##obj_orientation_y_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].orientation.y);
4248 randomizePopup(
"obj_orientation_y_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].orientation.y, &objects_dict[curr_obj_name].is_dirty));
4249 randomizerParams(
"obj_orientation_y_" + std::to_string(objects_dict[curr_obj_name].index));
4250 ImGui::OpenPopupOnItemClick((
"randomize_obj_orientation_y_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4252 ImGui::SetNextItemWidth(60);
4253 ImGui::InputFloat((
"##obj_orientation_z_" + std::to_string(
id)).c_str(), &objects_dict[curr_obj_name].orientation.z);
4254 randomizePopup(
"obj_orientation_z_" + std::to_string(objects_dict[curr_obj_name].index),
createTaggedPtr(&objects_dict[curr_obj_name].orientation.z, &objects_dict[curr_obj_name].is_dirty));
4255 randomizerParams(
"obj_orientation_z_" + std::to_string(objects_dict[curr_obj_name].index));
4256 ImGui::OpenPopupOnItemClick((
"randomize_obj_orientation_z_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4258 ImGui::Text(
"Object Orientation");
4259 if (prev_obj_orientation != objects_dict[curr_obj_name].orientation) {
4260 objects_dict[curr_obj_name].is_dirty =
true;
4262 if (objects_dict[current_obj].is_dirty && !ImGui::IsAnyItemActive() && !ImGui::IsAnyItemFocused()) {
4268void ProjectBuilder::radiationTab() {
4269#if defined(ENABLE_HELIOS_VISUALIZER) && defined(ENABLE_RADIATION_MODEL)
4271 ImGui::SetNextItemWidth(60);
4272 if (ImGui::Button(
"Load XML Library File")) {
4274 if (!new_xml_library_file.empty() && std::filesystem::exists(new_xml_library_file)) {
4275 if (xml_library_files.find(new_xml_library_file) == xml_library_files.end()) {
4276 xml_library_files.insert(new_xml_library_file);
4277 std::vector<std::string> current_spectra_file =
get_xml_node_values(new_xml_library_file,
"label",
"globaldata_vec2");
4278 for (
int i = 0; i < current_spectra_file.size(); i++) {
4279 possible_spectra.insert(current_spectra_file[i]);
4286 ImGui::SetWindowFontScale(1.25f);
4287 ImGui::Text(
"Global Properties:");
4288 ImGui::SetWindowFontScale(1.0f);
4290 ImGui::Text(
"Enforce Periodic Boundary Condition:");
4292 bool prev_cond_x = enforce_periodic_boundary_x;
4293 ImGui::Checkbox(
"x###periodic_boundary_x", &enforce_periodic_boundary_x);
4295 bool prev_cond_y = enforce_periodic_boundary_y;
4296 ImGui::Checkbox(
"y###periodic_boundary_y", &enforce_periodic_boundary_y);
4297 if (prev_cond_x != enforce_periodic_boundary_x || prev_cond_y != enforce_periodic_boundary_y) {
4298 if (enforce_periodic_boundary_x && enforce_periodic_boundary_y)
4300 else if (enforce_periodic_boundary_x)
4302 else if (enforce_periodic_boundary_y)
4308 ImGui::SetNextItemWidth(60);
4309 float prev_value = diffuse_extinction_coeff;
4310 ImGui::InputFloat(
"Diffuse Extinction Coefficient", &diffuse_extinction_coeff);
4311 if (prev_value != diffuse_extinction_coeff) {
4314 randomizePopup(
"diffuse_extinction_coeff",
createTaggedPtr(&diffuse_extinction_coeff));
4315 randomizerParams(
"diffuse_extinction_coeff");
4316 ImGui::OpenPopupOnItemClick(
"randomize_diffuse_extinction_coeff", ImGuiPopupFlags_MouseButtonRight);
4318 ImGui::SetNextItemWidth(60);
4319 prev_value = air_turbidity;
4320 ImGui::InputFloat(
"Air Turbidity", &air_turbidity);
4321 if (prev_value != air_turbidity) {
4322 if (air_turbidity > 0) {
4324 }
else if (air_turbidity < 0) {
4327 if (air_turbidity > 0 && air_turbidity < 1) {
4334 randomizerParams(
"air_turbidity");
4335 ImGui::OpenPopupOnItemClick(
"randomize_air_turbidity", ImGuiPopupFlags_MouseButtonRight);
4337 ImGui::SetNextItemWidth(250);
4339 if (ImGui::BeginCombo(
"##combo_solar_direct_spectrum", solar_direct_spectrum.c_str())) {
4340 for (
auto &spectra: possible_spectra) {
4341 bool is_solar_direct_spectrum_selected = (solar_direct_spectrum == spectra);
4342 if (ImGui::Selectable(spectra.c_str(), is_solar_direct_spectrum_selected))
4343 solar_direct_spectrum = spectra;
4344 if (is_solar_direct_spectrum_selected)
4345 ImGui::SetItemDefaultFocus();
4350 ImGui::Text(
"Solar Direct Spectrum");
4352 ImGui::SetWindowFontScale(1.25f);
4353 ImGui::Text(
"Add Band:");
4354 ImGui::SetWindowFontScale(1.0f);
4358 if (enable_wavelength) {
4359 ImGui::Text(
"Wavelength Min:");
4361 ImGui::SetNextItemWidth(60);
4362 ImGui::InputFloat(
"##wavelength_min", &wavelength_min);
4364 ImGui::Text(
"Max:");
4366 ImGui::SetNextItemWidth(60);
4367 ImGui::InputFloat(
"##wavelength_max", &wavelength_max);
4369 ImGui::Text(
"No Specified Wavelength");
4372 ImGui::Text(
"Label:");
4374 ImGui::SetNextItemWidth(100);
4375 ImGui::InputText(
"##new_band_label", &new_band_label);
4377 ImGui::Text(
"Emission:");
4379 ImGui::Checkbox(
"##enable_emission", &enable_emission);
4381 if (ImGui::Button(
"Add Band")) {
4382 if (enable_wavelength) {
4383 addBand(new_band_label, wavelength_min, wavelength_max, enable_emission);
4385 addBand(new_band_label, enable_emission);
4386 bandlabels_set_wavelength.insert(new_band_label);
4390 ImGui::SetWindowFontScale(1.25f);
4391 ImGui::Text(
"Band Properties:");
4392 ImGui::SetWindowFontScale(1.0f);
4394 if (ImGui::BeginCombo(
"##combo_current_band", current_band.c_str())) {
4395 for (std::string band: bandlabels_set) {
4396 bool is_current_band_selected = (current_band == band);
4397 if (ImGui::Selectable(band.c_str(), is_current_band_selected))
4398 current_band = band;
4399 if (is_current_band_selected)
4400 ImGui::SetItemDefaultFocus();
4405 ImGui::Text(
"Select Band");
4407 int prev_direct_ray_count;
4408 ImGui::SetNextItemWidth(100);
4409 if (current_band ==
"All") {
4410 prev_direct_ray_count = direct_ray_count;
4411 ImGui::InputInt(
"Direct Ray Count", &direct_ray_count);
4412 randomizePopup(
"direct_ray_count",
createTaggedPtr(&direct_ray_count));
4413 randomizerParams(
"direct_ray_count");
4414 ImGui::OpenPopupOnItemClick(
"randomize_direct_ray_count", ImGuiPopupFlags_MouseButtonRight);
4415 if (direct_ray_count != prev_direct_ray_count) {
4416 for (std::string band: bandlabels) {
4418 direct_ray_count_dict[band] = direct_ray_count;
4422 prev_direct_ray_count = direct_ray_count_dict[current_band];
4423 ImGui::InputInt(
"Direct Ray Count", &direct_ray_count_dict[current_band]);
4424 randomizePopup(
"direct_ray_count_" + current_band,
createTaggedPtr(&direct_ray_count_dict[current_band]));
4425 randomizerParams(
"direct_ray_count_" + current_band);
4426 ImGui::OpenPopupOnItemClick((
"randomize_direct_ray_count_" + current_band).c_str(), ImGuiPopupFlags_MouseButtonRight);
4427 if (direct_ray_count_dict[current_band] != prev_direct_ray_count) {
4432 ImGui::SetNextItemWidth(100);
4433 int prev_diffuse_ray_count;
4434 if (current_band ==
"All") {
4435 prev_diffuse_ray_count = diffuse_ray_count;
4436 ImGui::InputInt(
"Diffuse Ray Count", &diffuse_ray_count);
4437 randomizePopup(
"diffuse_ray_count",
createTaggedPtr(&diffuse_ray_count));
4438 randomizerParams(
"diffuse_ray_count");
4439 ImGui::OpenPopupOnItemClick(
"randomize_diffuse_ray_count", ImGuiPopupFlags_MouseButtonRight);
4440 if (diffuse_ray_count != prev_diffuse_ray_count) {
4441 for (std::string band: bandlabels) {
4443 diffuse_ray_count_dict[band] = diffuse_ray_count;
4447 prev_diffuse_ray_count = diffuse_ray_count_dict[current_band];
4448 ImGui::InputInt(
"Diffuse Ray Count", &diffuse_ray_count_dict[current_band]);
4449 randomizePopup(
"diffuse_ray_count_" + current_band,
createTaggedPtr(&diffuse_ray_count_dict[current_band]));
4450 randomizerParams(
"diffuse_ray_count_" + current_band);
4451 ImGui::OpenPopupOnItemClick((
"randomize_diffuse_ray_count_" + current_band).c_str(), ImGuiPopupFlags_MouseButtonRight);
4452 if (diffuse_ray_count_dict[current_band] != prev_diffuse_ray_count) {
4457 ImGui::SetNextItemWidth(100);
4458 int prev_scattering_depth;
4459 if (current_band ==
"All") {
4460 prev_scattering_depth = scattering_depth;
4461 ImGui::InputInt(
"Scattering Depth", &scattering_depth);
4462 randomizePopup(
"scattering_depth",
createTaggedPtr(&scattering_depth));
4463 randomizerParams(
"scattering_depth");
4464 ImGui::OpenPopupOnItemClick(
"randomize_scattering_depth", ImGuiPopupFlags_MouseButtonRight);
4465 if (scattering_depth <= 0) {
4466 scattering_depth = prev_scattering_depth;
4468 if (prev_scattering_depth != scattering_depth) {
4469 for (std::string band: bandlabels) {
4471 scattering_depth_dict[band] = scattering_depth;
4475 prev_scattering_depth = scattering_depth_dict[current_band];
4476 ImGui::InputInt(
"Scattering Depth", &scattering_depth_dict[current_band]);
4477 randomizePopup(
"scattering_depth_" + current_band,
createTaggedPtr(&scattering_depth_dict[current_band]));
4478 randomizerParams(
"scattering_depth_" + current_band);
4479 ImGui::OpenPopupOnItemClick((
"randomize_scattering_depth_" + current_band).c_str(), ImGuiPopupFlags_MouseButtonRight);
4480 if (scattering_depth_dict[current_band] <= 0) {
4481 scattering_depth_dict[current_band] = prev_scattering_depth;
4483 if (prev_scattering_depth != scattering_depth_dict[current_band]) {
4488 ImGui::SetWindowFontScale(1.25f);
4489 ImGui::Text(
"Radiative Properties:");
4490 ImGui::SetWindowFontScale(1.0f);
4491 ImGui::SetNextItemWidth(100);
4498 ImGui::SetNextItemWidth(150);
4499 if (ImGui::BeginCombo(
"##data_group_primitive", current_data_group.c_str())) {
4500 for (std::string data_group: data_groups_set) {
4501 bool is_data_group_selected = (current_data_group == data_group);
4502 if (ImGui::Selectable(data_group.c_str(), is_data_group_selected))
4503 current_data_group = data_group;
4504 if (is_data_group_selected)
4505 ImGui::SetItemDefaultFocus();
4510 ImGui::SetNextItemWidth(100);
4511 ImGui::Text(
"Select Data Group");
4519 ImGui::SetNextItemWidth(150);
4520 if (ImGui::BeginCombo(
"##combo_primitive", current_primitive.c_str())) {
4521 for (
int m = 0; m < primitive_names.size(); m++) {
4522 bool is_primitive_selected = (current_primitive == primitive_names[m]);
4523 if (ImGui::Selectable(primitive_names[m].c_str(), is_primitive_selected))
4524 current_primitive = primitive_names[m];
4525 if (is_primitive_selected)
4526 ImGui::SetItemDefaultFocus();
4531 ImGui::SetNextItemWidth(100);
4532 ImGui::Text(
"Select Primitive Type");
4533 if (current_data_group ==
"All") {
4535 ImGui::Text(
"Reflectivity:");
4536 std::string toggle_display_reflectivity =
"Manual Entry";
4537 bool reflectivity_continuous = primitive_continuous[current_primitive][0];
4538 toggle_button(
"##reflectivity_toggle", &reflectivity_continuous);
4539 if (reflectivity_continuous != primitive_continuous[current_primitive][0]) {
4540 if (current_primitive ==
"All") {
4541 for (
auto &prim_values: primitive_continuous) {
4542 primitive_continuous[prim_values.first][0] = reflectivity_continuous;
4545 primitive_continuous[current_primitive][0] = reflectivity_continuous;
4547 if (primitive_continuous[current_primitive][0]) {
4548 toggle_display_reflectivity =
"File Entry";
4551 ImGui::SetNextItemWidth(250);
4552 if (!primitive_continuous[current_primitive][0]) {
4553 ImGui::Text(
"Select band:");
4555 ImGui::SetNextItemWidth(60);
4556 if (ImGui::BeginCombo(
"##combo_band_reflectivity", current_band_reflectivity.c_str())) {
4557 for (
int n = 0; n < bandlabels.size(); n++) {
4558 bool is_band_selected = (current_band_reflectivity == bandlabels[n]);
4559 if (ImGui::Selectable(bandlabels[n].c_str(), is_band_selected))
4560 current_band_reflectivity = bandlabels[n];
4561 if (is_band_selected)
4562 ImGui::SetItemDefaultFocus();
4567 ImGui::Text(
"Enter value:");
4569 ImGui::SetNextItemWidth(80);
4570 if (current_primitive ==
"All") {
4571 float prev_reflectivity = reflectivity;
4572 ImGui::InputFloat(
"##reflectivity_all", &reflectivity);
4573 if (reflectivity != prev_reflectivity) {
4574 for (
auto &prim_values: primitive_values[current_band_reflectivity]) {
4575 primitive_values[current_band_reflectivity][prim_values.first][0] = reflectivity;
4579 ImGui::InputFloat(
"##reflectivity", &primitive_values[current_band_reflectivity][current_primitive][0]);
4582 std::string reflectivity_prev = primitive_spectra[current_primitive][0];
4583 if (ImGui::BeginCombo(
"##reflectivity_combo_all", reflectivity_prev.c_str())) {
4584 for (
auto &spectra: possible_spectra) {
4585 bool is_spectra_selected = (primitive_spectra[current_primitive][0] == spectra);
4586 if (ImGui::Selectable(spectra.c_str(), is_spectra_selected))
4587 primitive_spectra[current_primitive][0] = spectra;
4588 if (is_spectra_selected)
4589 ImGui::SetItemDefaultFocus();
4593 if (current_primitive ==
"All" && reflectivity_prev != primitive_spectra[current_primitive][0]) {
4594 for (
auto &prim_spectrum: primitive_spectra) {
4595 primitive_spectra[prim_spectrum.first][0] = primitive_spectra[current_primitive][0];
4600 ImGui::Text(
"%s", toggle_display_reflectivity.c_str());
4602 ImGui::Text(
"Transmissivity:");
4603 std::string toggle_display_transmissivity =
"Manual Entry";
4604 bool transmissivity_continuous = primitive_continuous[current_primitive][1];
4605 toggle_button(
"##transmissivity_toggle", &transmissivity_continuous);
4606 if (transmissivity_continuous != primitive_continuous[current_primitive][1]) {
4607 if (current_primitive ==
"All") {
4608 for (
auto &prim_values: primitive_continuous) {
4609 primitive_continuous[prim_values.first][1] = transmissivity_continuous;
4612 primitive_continuous[current_primitive][1] = transmissivity_continuous;
4614 if (primitive_continuous[current_primitive][1]) {
4615 toggle_display_transmissivity =
"File Entry";
4618 ImGui::SetNextItemWidth(250);
4619 if (!primitive_continuous[current_primitive][1]) {
4620 ImGui::Text(
"Select band:");
4622 ImGui::SetNextItemWidth(60);
4623 if (ImGui::BeginCombo(
"##combo_band_transmissivity", current_band_transmissivity.c_str())) {
4624 for (
int n = 0; n < bandlabels.size(); n++) {
4625 bool is_band_selected = (current_band_transmissivity == bandlabels[n]);
4626 if (ImGui::Selectable(bandlabels[n].c_str(), is_band_selected))
4627 current_band_transmissivity = bandlabels[n];
4628 if (is_band_selected)
4629 ImGui::SetItemDefaultFocus();
4634 ImGui::Text(
"Enter value:");
4636 ImGui::SetNextItemWidth(80);
4637 if (current_primitive ==
"All") {
4638 float prev_transmissivity = transmissivity;
4639 ImGui::InputFloat(
"##transmissivity_all", &transmissivity);
4640 if (transmissivity != prev_transmissivity) {
4641 for (
auto &prim_values: primitive_values[current_band_transmissivity]) {
4642 primitive_values[current_band_transmissivity][prim_values.first][1] = transmissivity;
4646 ImGui::InputFloat(
"##transmissivity", &primitive_values[current_band_transmissivity][current_primitive][1]);
4649 std::string transmissivity_prev = primitive_spectra[current_primitive][1];
4650 if (ImGui::BeginCombo(
"##transmissivity_combo", transmissivity_prev.c_str())) {
4651 for (
auto &spectra: possible_spectra) {
4652 bool is_spectra_selected = (primitive_spectra[current_primitive][1] == spectra);
4653 if (ImGui::Selectable(spectra.c_str(), is_spectra_selected))
4654 primitive_spectra[current_primitive][1] = spectra;
4655 if (is_spectra_selected)
4656 ImGui::SetItemDefaultFocus();
4660 if (current_primitive ==
"All" && transmissivity_prev != primitive_spectra[current_primitive][1]) {
4661 for (
auto &prim_spectrum: primitive_spectra) {
4662 primitive_spectra[prim_spectrum.first][1] = primitive_spectra[current_primitive][1];
4667 ImGui::Text(
"%s", toggle_display_transmissivity.c_str());
4669 ImGui::Text(
"Emissivity:");
4672 ImGui::Dummy(ImVec2(35.f, 0.f));
4674 ImGui::Text(
"Select band:");
4676 ImGui::SetNextItemWidth(60);
4677 if (ImGui::BeginCombo(
"##combo_band_emissivity", current_band_emissivity.c_str())) {
4678 for (std::string band: bandlabels_set_emissivity) {
4679 bool is_band_selected = (current_band_emissivity == band);
4680 if (ImGui::Selectable(band.c_str(), is_band_selected))
4681 current_band_emissivity = band;
4682 if (is_band_selected)
4683 ImGui::SetItemDefaultFocus();
4688 ImGui::Text(
"Enter value:");
4690 ImGui::SetNextItemWidth(80);
4691 if (current_primitive ==
"All") {
4692 float prev_emissivity = emissivity;
4693 ImGui::InputFloat(
"##emissivity_all", &emissivity);
4694 if (emissivity != prev_emissivity) {
4695 for (
auto &prim_values: primitive_values[current_band_emissivity]) {
4696 primitive_values[current_band_emissivity][prim_values.first][2] = emissivity;
4700 ImGui::InputFloat(
"##emissivity", &primitive_values[current_band_emissivity][current_primitive][2]);
4703 ImGui::Text(
"Manual Entry");
4706 ImGui::Text(
"Reflectivity:");
4707 std::string toggle_display_reflectivity =
"Manual Entry";
4708 bool reflectivity_continuous = primitive_continuous_dict[current_data_group][current_primitive][0];
4709 toggle_button(
"##reflectivity_toggle", &reflectivity_continuous);
4710 if (reflectivity_continuous != primitive_continuous_dict[current_data_group][current_primitive][0]) {
4711 if (current_primitive ==
"All") {
4712 for (
auto &prim_values: primitive_continuous_dict[current_data_group]) {
4713 primitive_continuous_dict[current_data_group][prim_values.first][0] = reflectivity_continuous;
4716 primitive_continuous_dict[current_data_group][current_primitive][0] = reflectivity_continuous;
4718 if (primitive_continuous_dict[current_data_group][current_primitive][0]) {
4719 toggle_display_reflectivity =
"File Entry";
4722 ImGui::SetNextItemWidth(250);
4723 if (!primitive_continuous_dict[current_data_group][current_primitive][0]) {
4724 ImGui::Text(
"Select band:");
4726 ImGui::SetNextItemWidth(60);
4727 if (ImGui::BeginCombo(
"##combo_band_reflectivity", current_band_reflectivity.c_str())) {
4728 for (
int n = 0; n < bandlabels.size(); n++) {
4729 bool is_band_selected = (current_band_reflectivity == bandlabels[n]);
4730 if (ImGui::Selectable(bandlabels[n].c_str(), is_band_selected))
4731 current_band_reflectivity = bandlabels[n];
4732 if (is_band_selected)
4733 ImGui::SetItemDefaultFocus();
4738 ImGui::Text(
"Enter value:");
4740 ImGui::SetNextItemWidth(80);
4741 if (current_primitive ==
"All") {
4742 float prev_reflectivity = reflectivity;
4743 ImGui::InputFloat(
"##reflectivity_all", &reflectivity);
4744 if (reflectivity != prev_reflectivity) {
4745 for (
auto &prim_values: primitive_values_dict[current_data_group][current_band_reflectivity]) {
4746 primitive_values_dict[current_data_group][current_band_reflectivity][prim_values.first][0] = reflectivity;
4750 ImGui::InputFloat(
"##reflectivity", &primitive_values_dict[current_data_group][current_band_reflectivity][current_primitive][0]);
4753 std::string reflectivity_prev = primitive_spectra_dict[current_data_group][current_primitive][0];
4754 if (ImGui::BeginCombo(
"##reflectivity_combo", reflectivity_prev.c_str())) {
4755 for (
auto &spectra: possible_spectra) {
4756 bool is_spectra_selected = (primitive_spectra_dict[current_data_group][current_primitive][0] == spectra);
4757 if (ImGui::Selectable(spectra.c_str(), is_spectra_selected))
4758 primitive_spectra_dict[current_data_group][current_primitive][0] = spectra;
4759 if (is_spectra_selected)
4760 ImGui::SetItemDefaultFocus();
4764 if (current_primitive ==
"All" && reflectivity_prev != primitive_spectra_dict[current_data_group][current_primitive][0]) {
4765 for (
auto &prim_spectrum: primitive_spectra_dict[current_data_group]) {
4766 primitive_spectra_dict[current_data_group][prim_spectrum.first][0] = primitive_spectra_dict[current_data_group][current_primitive][0];
4771 ImGui::TextUnformatted(
"%s", toggle_display_reflectivity.c_str());
4773 ImGui::Text(
"Transmissivity:");
4774 std::string toggle_display_transmissivity =
"Manual Entry";
4775 bool transmissivity_continuous = primitive_continuous_dict[current_data_group][current_primitive][1];
4776 toggle_button(
"##transmissivity_toggle", &transmissivity_continuous);
4777 if (transmissivity_continuous != primitive_continuous_dict[current_data_group][current_primitive][1]) {
4778 if (current_primitive ==
"All") {
4779 for (
auto &prim_values: primitive_continuous_dict[current_data_group]) {
4780 primitive_continuous_dict[current_data_group][prim_values.first][1] = transmissivity_continuous;
4783 primitive_continuous_dict[current_data_group][current_primitive][1] = transmissivity_continuous;
4785 if (primitive_continuous_dict[current_data_group][current_primitive][1]) {
4786 toggle_display_transmissivity =
"File Entry";
4789 ImGui::SetNextItemWidth(250);
4790 if (!primitive_continuous_dict[current_data_group][current_primitive][1]) {
4791 ImGui::Text(
"Select band:");
4793 ImGui::SetNextItemWidth(60);
4794 if (ImGui::BeginCombo(
"##combo_band_transmissivity", current_band_transmissivity.c_str())) {
4795 for (
int n = 0; n < bandlabels.size(); n++) {
4796 bool is_band_selected = (current_band_transmissivity == bandlabels[n]);
4797 if (ImGui::Selectable(bandlabels[n].c_str(), is_band_selected))
4798 current_band_transmissivity = bandlabels[n];
4799 if (is_band_selected)
4800 ImGui::SetItemDefaultFocus();
4805 ImGui::Text(
"Enter value:");
4807 ImGui::SetNextItemWidth(80);
4808 if (current_primitive ==
"All") {
4809 float prev_transmissivity = transmissivity;
4810 ImGui::InputFloat(
"##transmissivity_all", &transmissivity);
4811 if (transmissivity != prev_transmissivity) {
4812 for (
auto &prim_values: primitive_values_dict[current_data_group][current_band_transmissivity]) {
4813 primitive_values_dict[current_data_group][current_band_transmissivity][prim_values.first][1] = transmissivity;
4817 ImGui::InputFloat(
"##transmissivity", &primitive_values_dict[current_data_group][current_band_transmissivity][current_primitive][1]);
4820 std::string transmissivity_prev = primitive_spectra_dict[current_data_group][current_primitive][1];
4821 if (ImGui::BeginCombo(
"##transmissivity_combo", transmissivity_prev.c_str())) {
4822 for (
auto &spectra: possible_spectra) {
4823 bool is_spectra_selected = (primitive_spectra_dict[current_data_group][current_primitive][1] == spectra);
4824 if (ImGui::Selectable(spectra.c_str(), is_spectra_selected))
4825 primitive_spectra_dict[current_data_group][current_primitive][1] = spectra;
4826 if (is_spectra_selected)
4827 ImGui::SetItemDefaultFocus();
4831 if (current_primitive ==
"All" && transmissivity_prev != primitive_spectra_dict[current_data_group][current_primitive][1]) {
4832 for (
auto &prim_spectrum: primitive_spectra_dict[current_data_group]) {
4833 primitive_spectra_dict[current_data_group][prim_spectrum.first][1] = primitive_spectra_dict[current_data_group][current_primitive][1];
4838 ImGui::TextUnformatted(
"%s", toggle_display_transmissivity.c_str());
4840 ImGui::Text(
"Emissivity:");
4843 ImGui::Dummy(ImVec2(35.f, 0.f));
4845 ImGui::Text(
"Select band:");
4847 ImGui::SetNextItemWidth(60);
4848 if (ImGui::BeginCombo(
"##combo_band_emissivity", current_band_emissivity.c_str())) {
4849 for (std::string band: bandlabels_set_emissivity) {
4850 bool is_band_selected = (current_band_emissivity == band);
4851 if (ImGui::Selectable(band.c_str(), is_band_selected))
4852 current_band_emissivity = band;
4853 if (is_band_selected)
4854 ImGui::SetItemDefaultFocus();
4859 ImGui::Text(
"Enter value:");
4861 ImGui::SetNextItemWidth(80);
4862 if (current_primitive ==
"All") {
4863 float prev_emissivity = emissivity;
4864 ImGui::InputFloat(
"##emissivity_all", &emissivity);
4865 if (emissivity != prev_emissivity) {
4866 for (
auto &prim_values: primitive_values_dict[current_data_group][current_band_emissivity]) {
4867 primitive_values_dict[current_data_group][current_band_emissivity][prim_values.first][2] = emissivity;
4871 ImGui::InputFloat(
"##emissivity", &primitive_values_dict[current_data_group][current_band_emissivity][current_primitive][2]);
4874 ImGui::Text(
"Manual Entry");
4877 if (ImGui::Button(
"Run Radiation")) {
4878 const char *font_name =
"LCD";
4888void ProjectBuilder::rigTab() {
4889#if defined(ENABLE_HELIOS_VISUALIZER) && defined(ENABLE_RADIATION_MODEL)
4890 std::string current_cam_position =
"0";
4891 if (ImGui::BeginCombo(
"##rig_combo", current_rig.c_str())) {
4892 for (
auto rig_label: rig_labels_set) {
4893 bool is_rig_selected = (current_rig == rig_label);
4894 if (ImGui::Selectable(rig_label.c_str(), is_rig_selected))
4895 current_rig = rig_label;
4896 current_cam_position =
"0";
4897 if (is_rig_selected)
4898 ImGui::SetItemDefaultFocus();
4903 if (ImGui::Button(
"Add Rig")) {
4904 std::string default_rig_label =
"rig";
4905 std::string new_rig_label =
"rig_0";
4907 while (rig_dict.find(new_rig_label) != rig_dict.end()) {
4909 new_rig_label = default_rig_label +
"_" + std::to_string(count);
4913 if (!current_rig.empty()) {
4919 if (ImGui::Button(
"Delete Rig")) {
4923 ImGui::SetNextItemWidth(100);
4924 std::string prev_rig_name = rig_labels[rig_dict[current_rig]];
4925 ImGui::InputText(
"##rig_name", &rig_labels[rig_dict[current_rig]]);
4926 if (rig_labels[rig_dict[current_rig]] != prev_rig_name && rig_dict.find(rig_labels[rig_dict[current_rig]]) == rig_dict.end() && !rig_labels[rig_dict[current_rig]].empty()) {
4927 int temp = rig_dict[current_rig];
4928 current_rig = rig_labels[rig_dict[current_rig]];
4929 std::map<std::string, int>::iterator current_rig_iter = rig_dict.find(prev_rig_name);
4930 if (current_rig_iter != rig_dict.end()) {
4931 rig_dict.erase(current_rig_iter);
4933 rig_dict[current_rig] = temp;
4934 rig_labels_set.erase(prev_rig_name);
4935 rig_labels_set.insert(rig_labels[rig_dict[current_rig]]);
4937 std::string new_name = rig_labels[rig_dict[current_rig]];
4938 rig renamed_rig = rig_dict_.at(prev_rig_name);
4939 rig_dict_.erase(prev_rig_name);
4940 rig_dict_.insert({new_name, renamed_rig});
4942 rig_labels[rig_dict[current_rig]] = prev_rig_name;
4945 ImGui::Text(
"Rig Name");
4947 ImGui::Text(
"Write:");
4949 int rig_index = rig_dict[current_rig];
4950 if (rig_index >= write_depth.size()) {
4951 helios_runtime_error(
"ERROR (ProjectBuilder::rigTab): rig_dict[" + current_rig +
"] = " + std::to_string(rig_index) +
" is out of bounds for write_depth vector of size " + std::to_string(write_depth.size()));
4953 bool write_depth_ = write_depth[rig_index];
4954 ImGui::Checkbox(
"Depth Images", &write_depth_);
4955 write_depth[rig_dict[current_rig]] = write_depth_;
4957 bool write_norm_depth_ = write_norm_depth[rig_dict[current_rig]];
4958 ImGui::Checkbox(
"Norm Depth Images", &write_norm_depth_);
4959 write_norm_depth[rig_dict[current_rig]] = write_norm_depth_;
4961 bool write_segmentation_ = write_segmentation_mask[rig_dict[current_rig]];
4962 ImGui::Checkbox(
"Segmentation Masks", &write_segmentation_);
4963 write_segmentation_mask[rig_dict[current_rig]] = write_segmentation_;
4965 if (ImGui::BeginPopup(
"multi_select_popup")) {
4966 for (
auto &box_pair: bounding_boxes) {
4967 ImGui::Selectable(box_pair.first.c_str(), &box_pair.second, ImGuiSelectableFlags_DontClosePopups);
4971 if (ImGui::Button(
"Select Labeled Objects")) {
4972 ImGui::OpenPopup(
"multi_select_popup");
4975 if (ImGui::Button(
"Refresh List")) {
4976 refreshBoundingBoxObjectList();
4980 ImGui::Text(
"Objects:");
4982 for (
auto &box_pair: bounding_boxes) {
4983 if (box_pair.second) {
4984 ImGui::SameLine(), ImGui::Text(
"%i. %s", idx, box_pair.first.c_str());
4990 col[0] = rig_colors[rig_dict[current_rig]].r;
4991 col[1] = rig_colors[rig_dict[current_rig]].g;
4992 col[2] = rig_colors[rig_dict[current_rig]].b;
4993 ImGui::ColorEdit3(
"##rig_color_edit", col);
4996 ImGui::Text(
"Rig Color");
5017 ImGui::Text(
"Cameras:");
5018 for (
int i = 0; i < camera_names.size(); i++) {
5019 std::string &camera_name = camera_names[i];
5021 ImGui::SetNextItemWidth(60);
5023 std::set curr_set = rig_camera_labels[rig_dict[current_rig]];
5027 bool isCameraSelected = curr_set.find(camera_name) != curr_set.end();
5029 if (ImGui::Checkbox(camera_name.c_str(), &isCameraSelected)) {
5030 if (isCameraSelected) {
5031 rig_camera_labels[rig_dict[current_rig]].insert(camera_name);
5033 rig_camera_labels[rig_dict[current_rig]].erase(camera_name);
5039 ImGui::Text(
"Lights:");
5040 for (
int i = 0; i < light_names.size(); i++) {
5041 std::string &light_name = light_names[i];
5043 ImGui::SetNextItemWidth(60);
5045 std::set curr_rig_light = rig_light_labels[rig_dict[current_rig]];
5046 bool isLightSelected = curr_rig_light.find(light_name) != curr_rig_light.end();
5048 if (ImGui::Checkbox(light_name.c_str(), &isLightSelected)) {
5049 if (isLightSelected) {
5050 rig_light_labels[rig_dict[current_rig]].insert(light_name);
5052 rig_light_labels[rig_dict[current_rig]].erase(light_name);
5058 std::stringstream cam_pos_value;
5059 cam_pos_value << current_cam_position.c_str();
5060 int current_cam_position_;
5061 cam_pos_value >> current_cam_position_;
5062 current_keypoint = std::to_string(keypoint_frames[rig_dict[current_rig]][current_cam_position_]);
5063 std::string modified_current_keypoint = std::to_string(keypoint_frames[rig_dict[current_rig]][current_cam_position_] + 1);
5064 if (ImGui::BeginCombo(
"##cam_combo", modified_current_keypoint.c_str())) {
5065 for (
int n = 1; n <= camera_position_vec[rig_dict[current_rig]].size(); n++) {
5066 std::string select_cam_position = std::to_string(n - 1);
5067 std::string selected_keypoint = std::to_string(keypoint_frames[rig_dict[current_rig]][n - 1]);
5068 bool is_pos_selected = (current_cam_position == select_cam_position);
5069 std::string modified_selected_keypoint = std::to_string(keypoint_frames[rig_dict[current_rig]][n - 1] + 1);
5070 if (ImGui::Selectable(modified_selected_keypoint.c_str(), is_pos_selected)) {
5071 current_cam_position = std::to_string(n - 1);
5073 if (is_pos_selected)
5074 ImGui::SetItemDefaultFocus();
5078 cam_pos_value << current_cam_position.c_str();
5079 cam_pos_value >> current_cam_position_;
5081 if (ImGui::Button(
"Add Keypoint")) {
5082 camera_position_vec[rig_dict[current_rig]].push_back(camera_position_vec[rig_dict[current_rig]][current_cam_position_]);
5083 camera_lookat_vec[rig_dict[current_rig]].push_back(camera_lookat_vec[rig_dict[current_rig]][current_cam_position_]);
5084 keypoint_frames[rig_dict[current_rig]].push_back(keypoint_frames[rig_dict[current_rig]].back() + 1);
5088 ImGui::SetNextItemWidth(80);
5089 int modified_keypoint_frame = keypoint_frames[rig_dict[current_rig]][current_cam_position_] + 1;
5090 ImGui::InputInt(
"Keypoint Frame", &modified_keypoint_frame);
5091 if (modified_keypoint_frame != keypoint_frames[rig_dict[current_rig]][current_cam_position_] + 1) {
5092 keypoint_frames[rig_dict[current_rig]][current_cam_position_] = modified_keypoint_frame - 1;
5095 vec3 prev_rig_position_ = camera_position_vec[rig_dict[current_rig]][current_cam_position_];
5096 ImGui::SetNextItemWidth(60);
5097 ImGui::InputFloat(
"##camera_position_x", &camera_position_vec[rig_dict[current_rig]][current_cam_position_].x);
5098 randomizePopup(
"camera_position_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_),
createTaggedPtr(&camera_position_vec[rig_dict[current_rig]][current_cam_position_].x));
5099 randomizerParams(
"camera_position_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
5100 ImGui::OpenPopupOnItemClick((
"randomize_camera_position_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
5102 ImGui::SetNextItemWidth(60);
5103 ImGui::InputFloat(
"##camera_position_y", &camera_position_vec[rig_dict[current_rig]][current_cam_position_].y);
5104 randomizePopup(
"camera_position_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_),
createTaggedPtr(&camera_position_vec[rig_dict[current_rig]][current_cam_position_].y));
5105 randomizerParams(
"camera_position_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
5106 ImGui::OpenPopupOnItemClick((
"randomize_camera_position_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
5108 ImGui::SetNextItemWidth(60);
5109 ImGui::InputFloat(
"##camera_position_z", &camera_position_vec[rig_dict[current_rig]][current_cam_position_].z);
5110 randomizePopup(
"camera_position_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_),
createTaggedPtr(&camera_position_vec[rig_dict[current_rig]][current_cam_position_].z));
5111 randomizerParams(
"camera_position_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
5112 ImGui::OpenPopupOnItemClick((
"randomize_camera_position_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
5114 ImGui::Text(
"Rig Position");
5116 ImGui::Button(
"Add Noise###position");
5117 noisePopup(
"rig_position_noise_" + std::to_string(rig_dict[current_rig]), rig_lookat_noise[rig_dict[current_rig]]);
5118 ImGui::OpenPopupOnItemClick((
"rig_position_noise_" + std::to_string(rig_dict[current_rig])).c_str(), ImGuiPopupFlags_MouseButtonLeft);
5120 vec3 prev_rig_lookat_ = camera_lookat_vec[rig_dict[current_rig]][current_cam_position_];
5121 ImGui::SetNextItemWidth(60);
5122 ImGui::InputFloat(
"##camera_lookat_x", &camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].x);
5123 randomizePopup(
"camera_lookat_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_),
createTaggedPtr(&camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].x));
5124 randomizerParams(
"camera_lookat_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
5125 ImGui::OpenPopupOnItemClick((
"randomize_camera_lookat_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
5127 ImGui::SetNextItemWidth(60);
5128 ImGui::InputFloat(
"##camera_lookat_y", &camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].y);
5129 randomizePopup(
"camera_lookat_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_),
createTaggedPtr(&camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].y));
5130 randomizerParams(
"camera_lookat_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
5131 ImGui::OpenPopupOnItemClick((
"randomize_camera_lookat_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
5133 ImGui::SetNextItemWidth(60);
5134 ImGui::InputFloat(
"##camera_lookat_z", &camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].z);
5135 randomizePopup(
"camera_lookat_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_),
createTaggedPtr(&camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].z));
5136 randomizerParams(
"camera_lookat_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
5137 ImGui::OpenPopupOnItemClick((
"randomize_camera_lookat_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
5139 ImGui::Text(
"Rig Lookat");
5141 ImGui::Button(
"Add Noise###lookat");
5142 noisePopup(
"rig_lookat_noise_" + std::to_string(rig_dict[current_rig]), rig_lookat_noise[rig_dict[current_rig]]);
5143 ImGui::OpenPopupOnItemClick((
"rig_lookat_noise_" + std::to_string(rig_dict[current_rig])).c_str(), ImGuiPopupFlags_MouseButtonLeft);
5145 ImGui::SetNextItemWidth(80);
5146 ImGui::InputInt(
"Total Number of Frames", &num_images_vec[rig_dict[current_rig]]);
5147 num_images_vec[rig_dict[current_rig]] = std::max(num_images_vec[rig_dict[current_rig]], *std::max_element(keypoint_frames[rig_dict[current_rig]].begin(), keypoint_frames[rig_dict[(std::string) current_rig]].end()) + 1);
5149 if (prev_rig_position_ != camera_position_vec[rig_dict[current_rig]][current_cam_position_] || prev_rig_lookat_ != camera_lookat_vec[rig_dict[current_rig]][current_cam_position_]) {
5154 if (ImGui::Button(
"Record Images")) {
5155 if (band_group_names.empty()) {
5156 std::cout <<
"At least 1 band group (a group of 1 or 3 bands) must be defined to record images." << std::endl;
5159 const char *font_name =
"LCD";
5162 updatePrimitiveTypes();
5167 }
catch (
const std::runtime_error &e) {
5168 std::cerr <<
"Record failed due to exception: " << e.what() << std::endl;
5178void ProjectBuilder::rigTab(std::string curr_rig_name,
int id) {
5179#if defined(ENABLE_HELIOS_VISUALIZER) && defined(ENABLE_RADIATION_MODEL)
5180 ImGui::SetNextItemWidth(100);
5181 std::string prev_rig_name = rig_labels[rig_dict[curr_rig_name]];
5182 ImGui::InputText(
"##rig_name", &rig_labels[rig_dict[curr_rig_name]]);
5183 if (rig_labels[rig_dict[curr_rig_name]] != prev_rig_name && rig_labels_set.find(rig_labels[rig_dict[curr_rig_name]]) == rig_labels_set.end() && !rig_labels[rig_dict[curr_rig_name]].empty()) {
5184 rig_labels_set.erase(prev_rig_name);
5185 int temp = rig_dict[curr_rig_name];
5186 rig_labels_set.insert(rig_labels[temp]);
5187 curr_rig_name = rig_labels[rig_dict[curr_rig_name]];
5188 std::map<std::string, int>::iterator current_rig_iter = rig_dict.find(prev_rig_name);
5189 if (current_rig_iter != rig_dict.end()) {
5190 rig_dict.erase(current_rig_iter);
5192 rig_dict[curr_rig_name] = temp;
5194 rig_labels_set.erase(prev_rig_name);
5195 rig_labels_set.insert(rig_labels[rig_dict[curr_rig_name]]);
5197 rig_labels[rig_dict[curr_rig_name]] = prev_rig_name;
5200 ImGui::Text(
"Rig Name");
5201 int current_cam_position_ = 0;
5203 vec3 prev_rig_position =
vec3(camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_]);
5204 ImGui::SetNextItemWidth(60);
5205 ImGui::InputFloat(
"##camera_position_x", &camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_].x);
5207 ImGui::SetNextItemWidth(60);
5208 ImGui::InputFloat(
"##camera_position_y", &camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_].y);
5210 ImGui::SetNextItemWidth(60);
5211 ImGui::InputFloat(
"##camera_position_z", &camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_].z);
5213 ImGui::Text(
"Rig Position");
5215 vec3 prev_rig_lookat =
vec3(camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_]);
5216 ImGui::SetNextItemWidth(60);
5217 ImGui::InputFloat(
"##camera_lookat_x", &camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_].x);
5219 ImGui::SetNextItemWidth(60);
5220 ImGui::InputFloat(
"##camera_lookat_y", &camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_].y);
5222 ImGui::SetNextItemWidth(60);
5223 ImGui::InputFloat(
"##camera_lookat_z", &camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_].z);
5225 ImGui::Text(
"Rig Lookat");
5227 if (prev_rig_position != camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_] || prev_rig_lookat != camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_]) {
5233void ProjectBuilder::lightTab() {
5234#if defined(ENABLE_HELIOS_VISUALIZER) && defined(ENABLE_RADIATION_MODEL)
5236 ImGui::SetNextItemWidth(60);
5237 if (ImGui::Button(
"Load XML Library File")) {
5239 if (!new_xml_library_file.empty() && std::filesystem::exists(new_xml_library_file)) {
5240 if (light_xml_library_files.find(new_xml_library_file) == light_xml_library_files.end()) {
5241 light_xml_library_files.insert(new_xml_library_file);
5242 std::vector<std::string> current_light_file =
get_xml_node_values(new_xml_library_file,
"label",
"globaldata_vec2");
5243 possible_light_spectra.insert(possible_light_spectra.end(), current_light_file.begin(), current_light_file.end());
5248 if (ImGui::BeginCombo(
"##light_combo", current_light.c_str())) {
5249 for (
int n = 0; n < light_names.size(); n++) {
5250 bool is_light_selected = (current_light == light_names[n]);
5251 if (ImGui::Selectable(light_names[n].c_str(), is_light_selected))
5252 current_light = light_names[n];
5253 if (is_light_selected)
5254 ImGui::SetItemDefaultFocus();
5259 if (ImGui::Button(
"Add Light")) {
5260 std::string default_light_name =
"light";
5261 std::string new_light_name =
"light_0";
5263 while (light_dict.find(new_light_name) != light_dict.end()) {
5265 new_light_name = default_light_name +
"_" + std::to_string(count);
5267 light_dict.insert({new_light_name, scast<int>(light_names.size())});
5268 light_spectra.push_back(light_spectra[light_dict[current_light]]);
5269 light_types.push_back(light_types[light_dict[current_light]]);
5270 light_direction_vec.push_back(light_direction_vec[light_dict[current_light]]);
5271 light_direction_sph_vec.push_back(light_direction_sph_vec[light_dict[current_light]]);
5272 light_rotation_vec.push_back(light_rotation_vec[light_dict[current_light]]);
5273 light_size_vec.push_back(light_size_vec[light_dict[current_light]]);
5274 light_radius_vec.push_back(light_radius_vec[light_dict[current_light]]);
5275 light_names.push_back(new_light_name);
5276 light_flux_vec.push_back(light_flux_vec[light_dict[current_light]]);
5277 std::string parent =
"light";
5278 pugi::xml_node light_block = helios.child(parent.c_str());
5279 pugi::xml_node new_light_node = helios.append_copy(light_block);
5280 std::string name =
"label";
5281 pugi::xml_attribute node_label = new_light_node.attribute(name.c_str());
5282 node_label.set_value(new_light_name.c_str());
5283 current_light = new_light_name;
5285 ImGui::SetNextItemWidth(100);
5286 std::string prev_light_name = light_names[light_dict[current_light]];
5287 ImGui::InputText(
"##light_name", &light_names[light_dict[current_light]]);
5288 if (light_names[light_dict[current_light]] != prev_light_name) {
5289 int temp = light_dict[current_light];
5290 current_light = light_names[light_dict[current_light]];
5291 std::map<std::string, int>::iterator current_light_iter = light_dict.find(prev_light_name);
5292 if (current_light_iter != light_dict.end()) {
5293 light_dict.erase(current_light_iter);
5295 light_dict[current_light] = temp;
5298 ImGui::Text(
"Light Label");
5300 std::string prev_light_spectra = light_spectra[light_dict[current_light]];
5301 if (ImGui::BeginCombo(
"##light_spectra_combo", light_spectra[light_dict[current_light]].c_str())) {
5302 for (
int n = 0; n < possible_light_spectra.size(); n++) {
5303 bool is_light_spectra_selected = (light_spectra[light_dict[current_light]] == possible_light_spectra[n]);
5304 if (ImGui::Selectable(possible_light_spectra[n].c_str(), is_light_spectra_selected))
5305 light_spectra[light_dict[current_light]] = possible_light_spectra[n];
5306 if (is_light_spectra_selected)
5307 ImGui::SetItemDefaultFocus();
5312 ImGui::Text(
"Light Spectrum");
5314 if (ImGui::BeginCombo(
"##light_type_combo", light_types[light_dict[current_light]].c_str())) {
5315 for (
int n = 0; n < all_light_types.size(); n++) {
5316 bool is_type_selected = (light_types[light_dict[current_light]] == all_light_types[n]);
5317 if (ImGui::Selectable(all_light_types[n].c_str(), is_type_selected)) {
5318 light_types[light_dict[current_light]] = all_light_types[n];
5320 if (is_type_selected)
5321 ImGui::SetItemDefaultFocus();
5326 ImGui::Text(
"Light Type");
5333 if (light_types[light_dict[(std::string) current_light]] ==
"collimated" || light_types[light_dict[(std::string) current_light]] ==
"sunsphere") {
5334 ImGui::SetNextItemWidth(90);
5335 ImGui::InputFloat(
"##light_direction_x", &light_direction_vec[light_dict[current_light]].x);
5336 randomizePopup(
"light_direction_x_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_direction_vec[light_dict[current_light]].x));
5337 randomizerParams(
"light_direction_x_" + std::to_string(light_dict[current_light]));
5338 ImGui::OpenPopupOnItemClick((
"light_direction_x_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5340 ImGui::SetNextItemWidth(90);
5341 ImGui::InputFloat(
"##light_direction_y", &light_direction_vec[light_dict[current_light]].y);
5342 randomizePopup(
"light_direction_y_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_direction_vec[light_dict[current_light]].y));
5343 randomizerParams(
"light_direction_y_" + std::to_string(light_dict[current_light]));
5344 ImGui::OpenPopupOnItemClick((
"light_direction_y_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5346 ImGui::SetNextItemWidth(90);
5347 ImGui::InputFloat(
"##light_direction_z", &light_direction_vec[light_dict[current_light]].z);
5348 randomizePopup(
"light_direction_z_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_direction_vec[light_dict[current_light]].z));
5349 randomizerParams(
"light_direction_z_" + std::to_string(light_dict[current_light]));
5350 ImGui::OpenPopupOnItemClick((
"light_direction_z_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5352 ImGui::Text(
"Light Direction");
5355 ImGui::SetNextItemWidth(90);
5356 ImGui::InputFloat(
"##source_flux", &light_flux_vec[light_dict[current_light]]);
5357 randomizePopup(
"source_flux_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_flux_vec[light_dict[current_light]]));
5358 randomizerParams(
"source_flux_" + std::to_string(light_dict[current_light]));
5359 ImGui::OpenPopupOnItemClick((
"source_flux_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5361 ImGui::Text(
"Source Flux");
5364 if (light_types[light_dict[current_light]] ==
"disk" || light_types[light_dict[current_light]] ==
"rectangle") {
5365 ImGui::SetNextItemWidth(90);
5366 ImGui::InputFloat(
"##light_rotation_x", &light_rotation_vec[light_dict[current_light]].x);
5367 randomizePopup(
"light_rotation_x_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_rotation_vec[light_dict[current_light]].x));
5368 randomizerParams(
"light_rotation_x_" + std::to_string(light_dict[current_light]));
5369 ImGui::OpenPopupOnItemClick((
"light_rotation_x_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5371 ImGui::SetNextItemWidth(90);
5372 ImGui::InputFloat(
"##light_rotation_y", &light_rotation_vec[light_dict[current_light]].y);
5373 randomizePopup(
"light_rotation_y_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_rotation_vec[light_dict[current_light]].y));
5374 randomizerParams(
"light_rotation_y_" + std::to_string(light_dict[current_light]));
5375 ImGui::OpenPopupOnItemClick((
"light_rotation_y_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5377 ImGui::SetNextItemWidth(90);
5378 ImGui::InputFloat(
"##light_rotation_z", &light_rotation_vec[light_dict[current_light]].z);
5379 randomizePopup(
"light_rotation_z_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_rotation_vec[light_dict[current_light]].z));
5380 randomizerParams(
"light_rotation_z_" + std::to_string(light_dict[current_light]));
5381 ImGui::OpenPopupOnItemClick((
"light_rotation_z_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5383 ImGui::Text(
"Light Rotation");
5386 if (light_types[light_dict[current_light]] ==
"rectangle") {
5387 ImGui::SetNextItemWidth(90);
5388 ImGui::InputFloat(
"##light_size_x", &light_size_vec[light_dict[current_light]].x);
5389 randomizePopup(
"light_size_x_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_size_vec[light_dict[current_light]].x));
5390 randomizerParams(
"light_size_x_" + std::to_string(light_dict[current_light]));
5391 ImGui::OpenPopupOnItemClick((
"light_size_x_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5393 ImGui::SetNextItemWidth(90);
5394 ImGui::InputFloat(
"##light_size_y", &light_size_vec[light_dict[current_light]].y);
5395 randomizePopup(
"light_size_y_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_size_vec[light_dict[current_light]].y));
5396 randomizerParams(
"light_size_y_" + std::to_string(light_dict[current_light]));
5397 ImGui::OpenPopupOnItemClick((
"light_size_y_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5399 ImGui::Text(
"Light Size");
5402 if (light_types[light_dict[current_light]] ==
"disk" || light_types[light_dict[current_light]] ==
"sphere") {
5403 ImGui::SetNextItemWidth(90);
5404 ImGui::InputFloat(
"##light_radius", &light_radius_vec[light_dict[current_light]]);
5405 randomizePopup(
"light_radius_" + std::to_string(light_dict[current_light]),
createTaggedPtr(&light_radius_vec[light_dict[current_light]]));
5406 randomizerParams(
"light_radius_" + std::to_string(light_dict[current_light]));
5407 ImGui::OpenPopupOnItemClick((
"light_radius_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
5409 ImGui::Text(
"Light Radius");
5416void ProjectBuilder::canopyTab(std::string curr_canopy_name,
int id) {
5417#if defined(ENABLE_PLANT_ARCHITECTURE) && defined(ENABLE_HELIOS_VISUALIZER)
5418 if (ImGui::Button(
"Update Canopy")) {
5419 updateCanopy(curr_canopy_name);
5421 canopy_dict[current_canopy].is_dirty =
false;
5424 if (ImGui::Button(
"Delete Canopy")) {
5425 deleteCanopy(curr_canopy_name);
5427 canopy_dict[current_canopy].is_dirty =
false;
5429 if (canopy_dict[curr_canopy_name].is_dirty) {
5431 ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255));
5432 ImGui::Text(
"update required");
5433 ImGui::PopStyleColor();
5435 ImGui::SetNextItemWidth(100);
5436 std::string prev_canopy_name = canopy_dict[curr_canopy_name].label;
5437 ImGui::InputText(
"##canopy_name", &canopy_dict[curr_canopy_name].label);
5438 if (canopy_dict[curr_canopy_name].label != prev_canopy_name && canopy_labels_set.find(canopy_dict[curr_canopy_name].label) == canopy_labels_set.end() && !canopy_dict[curr_canopy_name].label.empty()) {
5439 canopy temp = canopy_dict[curr_canopy_name];
5440 curr_canopy_name = canopy_dict[curr_canopy_name].label;
5441 std::map<std::string, canopy>::iterator current_canopy_iter = canopy_dict.find(prev_canopy_name);
5442 if (current_canopy_iter != canopy_dict.end()) {
5443 canopy_dict.erase(current_canopy_iter);
5445 canopy_dict[curr_canopy_name] = temp;
5447 canopy_labels_set.erase(prev_canopy_name);
5448 canopy_labels_set.insert(canopy_dict[curr_canopy_name].label);
5450 canopy_dict[curr_canopy_name].label = prev_canopy_name;
5452 vec3 prev_canopy_origin_ =
vec3(canopy_dict[curr_canopy_name].origin);
5453 ImGui::SetNextItemWidth(60);
5454 ImGui::InputFloat(
"##canopy_origin_x", &canopy_dict[curr_canopy_name].origin.x);
5456 ImGui::SetNextItemWidth(60);
5457 ImGui::InputFloat(
"##canopy_origin_y", &canopy_dict[curr_canopy_name].origin.y);
5459 ImGui::SetNextItemWidth(60);
5460 ImGui::InputFloat(
"##canopy_origin_z", &canopy_dict[curr_canopy_name].origin.z);
5462 ImGui::Text(
"Canopy Origin");
5464 int2 prev_plant_count_ =
int2(canopy_dict[curr_canopy_name].plant_count);
5465 ImGui::SetNextItemWidth(100);
5466 ImGui::InputInt(
"##plant_count_x", &canopy_dict[curr_canopy_name].plant_count.x);
5468 ImGui::SetNextItemWidth(100);
5469 ImGui::InputInt(
"##plant_count_y", &canopy_dict[curr_canopy_name].plant_count.y);
5471 ImGui::Text(
"Plant Count");
5473 vec2 prev_plant_spacing_ =
vec2(canopy_dict[curr_canopy_name].plant_spacing);
5474 ImGui::SetNextItemWidth(50);
5475 ImGui::InputFloat(
"##plant_spacing_x", &canopy_dict[curr_canopy_name].plant_spacing.x);
5477 ImGui::SetNextItemWidth(50);
5478 ImGui::InputFloat(
"##plant_spacing_y", &canopy_dict[curr_canopy_name].plant_spacing.y);
5480 ImGui::Text(
"Plant Spacing");
5482 std::string prev_plant_library_ = canopy_dict[curr_canopy_name].library_name;
5483 ImGui::SetNextItemWidth(250);
5484 dropDown(
"Plant Library###dropdown", canopy_dict[curr_canopy_name].library_name_verbose, plant_types_verbose);
5485 canopy_dict[curr_canopy_name].library_name = plant_type_lookup[canopy_dict[curr_canopy_name].library_name_verbose];
5487 float prev_plant_age_ = canopy_dict[curr_canopy_name].age;
5488 ImGui::SetNextItemWidth(80);
5489 ImGui::InputFloat(
"Plant Age", &canopy_dict[curr_canopy_name].age);
5491 float prev_ground_clipping_height_ = canopy_dict[curr_canopy_name].ground_clipping_height;
5492 ImGui::SetNextItemWidth(80);
5493 ImGui::InputFloat(
"Ground Clipping Height", &canopy_dict[curr_canopy_name].ground_clipping_height);
5494 if (prev_canopy_origin_ != canopy_dict[curr_canopy_name].origin || prev_plant_count_ != canopy_dict[curr_canopy_name].plant_count || prev_plant_spacing_ != canopy_dict[curr_canopy_name].plant_spacing ||
5495 prev_plant_library_ != canopy_dict[curr_canopy_name].library_name || prev_plant_age_ != canopy_dict[curr_canopy_name].age || prev_ground_clipping_height_ != canopy_dict[curr_canopy_name].ground_clipping_height) {
5496 canopy_dict[curr_canopy_name].is_dirty =
true;
5501void ProjectBuilder::saveCanopy(std::string file_name, std::vector<uint> canopy_ID_vec,
vec3 position, std::string file_extension)
const {
5502#ifdef ENABLE_PLANT_ARCHITECTURE
5503 std::vector<std::string> primitive_data_vec = {
"object_label"};
5504 std::vector<uint> canopy_primID_vec;
5505 std::vector<uint> canopy_objID_vec;
5507 for (
int i = 0; i < canopy_ID_vec.size(); i++) {
5510 canopy_primID_vec.insert(canopy_primID_vec.end(), canopy_prim_UUIDs.begin(), canopy_prim_UUIDs.end());
5511 canopy_objID_vec.insert(canopy_objID_vec.end(), canopy_obj_UUIDs.begin(), canopy_obj_UUIDs.end());
5513 for (
uint objID: canopy_objID_vec) {
5516 if (file_extension ==
"obj") {
5517 context->
writeOBJ(file_name, canopy_primID_vec, primitive_data_vec,
true);
5518 }
else if (file_extension ==
"ply") {
5521 for (
uint objID: canopy_objID_vec) {
5527void ProjectBuilder::saveCanopy(std::string file_name_base, std::vector<uint> canopy_ID_vec, std::vector<helios::vec3> positions, std::string file_extension)
const {
5528#ifdef ENABLE_PLANT_ARCHITECTURE
5529 std::vector<std::string> primitive_data_vec = {
"object_label"};
5530 std::vector<std::vector<uint>> canopy_primID_vec;
5531 std::vector<std::vector<uint>> canopy_objID_vec;
5533 for (
int i = 0; i < canopy_ID_vec.size(); i++) {
5536 canopy_primID_vec.push_back(canopy_prim_UUIDs);
5537 canopy_objID_vec.push_back(canopy_obj_UUIDs);
5539 for (
int i = 0; i < canopy_objID_vec.size(); i++) {
5540 for (
uint objID: canopy_objID_vec[i]) {
5544 std::filesystem::path file_path(file_name_base);
5545 std::string ext = file_path.extension().string();
5546 file_path.replace_extension(
"");
5547 std::string file_name = file_path.string();
5548 if (file_extension ==
"obj") {
5549 for (
int i = 0; i < canopy_primID_vec.size(); i++) {
5550 context->
writeOBJ(file_name +
"_" + std::to_string(i) + ext, canopy_primID_vec[i], primitive_data_vec,
true);
5552 }
else if (file_extension ==
"ply") {
5555 for (
int i = 0; i < canopy_objID_vec.size(); i++) {
5556 for (
uint objID: canopy_objID_vec[i]) {
5563void ProjectBuilder::addBand(std::string label,
float wavelength_min,
float wavelength_max,
bool enable_emission) {
5564#ifdef ENABLE_RADIATION_MODEL
5565 if (label.empty()) {
5566 std::cout <<
"Failed to add band. Please specify a band label." << std::endl;
5569 if (bandlabels_set.find(label) != bandlabels_set.end()) {
5570 std::cout <<
"Failed to add band. Band with the specified name already exists." << std::endl;
5573 if (wavelength_min > wavelength_max) {
5574 std::cout <<
"Failed to add band. Invalid wavelength minimum and maximum." << std::endl;
5577 bandlabels.push_back(label);
5578 bandlabels_set.insert(label);
5579 primitive_values[label] = {{
"All", {reflectivity, transmissivity, emissivity}},
5580 {
"ground", {ground_reflectivity, ground_transmissivity, ground_emissivity}},
5581 {
"leaf", {leaf_reflectivity, leaf_transmissivity, leaf_emissivity}},
5582 {
"petiolule", {petiolule_reflectivity, petiolule_transmissivity, petiolule_emissivity}},
5583 {
"petiole", {petiole_reflectivity, petiole_transmissivity, petiole_emissivity}},
5584 {
"internode", {internode_reflectivity, internode_transmissivity, internode_emissivity}},
5585 {
"peduncle", {peduncle_reflectivity, peduncle_transmissivity, peduncle_emissivity}},
5586 {
"petal", {petal_reflectivity, petal_transmissivity, petal_emissivity}},
5587 {
"pedicel", {pedicel_reflectivity, pedicel_transmissivity, pedicel_emissivity}},
5588 {
"fruit", {fruit_reflectivity, fruit_transmissivity, fruit_emissivity}}};
5589 for (
auto &primitive_values_pair: primitive_values_dict) {
5590 primitive_values_dict[primitive_values_pair.first][label] = {{
"All", {reflectivity, transmissivity, emissivity}},
5591 {
"ground", {ground_reflectivity, ground_transmissivity, ground_emissivity}},
5592 {
"leaf", {leaf_reflectivity, leaf_transmissivity, leaf_emissivity}},
5593 {
"petiolule", {petiolule_reflectivity, petiolule_transmissivity, petiolule_emissivity}},
5594 {
"petiole", {petiole_reflectivity, petiole_transmissivity, petiole_emissivity}},
5595 {
"internode", {internode_reflectivity, internode_transmissivity, internode_emissivity}},
5596 {
"peduncle", {peduncle_reflectivity, peduncle_transmissivity, peduncle_emissivity}},
5597 {
"petal", {petal_reflectivity, petal_transmissivity, petal_emissivity}},
5598 {
"pedicel", {pedicel_reflectivity, pedicel_transmissivity, pedicel_emissivity}},
5599 {
"fruit", {fruit_reflectivity, fruit_transmissivity, fruit_emissivity}}};
5603 if (!enable_emission) {
5606 bandlabels_set_emissivity.insert(label);
5609 direct_ray_count_dict.insert({label, direct_ray_count});
5611 diffuse_ray_count_dict.insert({label, diffuse_ray_count});
5613 scattering_depth_dict.insert({label, scattering_depth});
5617void ProjectBuilder::addBand(std::string label,
bool enable_emission) {
5618#ifdef ENABLE_RADIATION_MODEL
5619 if (label.empty()) {
5620 std::cout <<
"Failed to add band. Please specify a band label." << std::endl;
5623 if (bandlabels_set.find(label) != bandlabels_set.end()) {
5624 std::cout <<
"Failed to add band. Band with the specified name already exists." << std::endl;
5627 bandlabels.push_back(label);
5628 bandlabels_set.insert(label);
5629 primitive_values[label] = {{
"All", {reflectivity, transmissivity, emissivity}},
5630 {
"ground", {ground_reflectivity, ground_transmissivity, ground_emissivity}},
5631 {
"leaf", {leaf_reflectivity, leaf_transmissivity, leaf_emissivity}},
5632 {
"petiolule", {petiolule_reflectivity, petiolule_transmissivity, petiolule_emissivity}},
5633 {
"petiole", {petiole_reflectivity, petiole_transmissivity, petiole_emissivity}},
5634 {
"internode", {internode_reflectivity, internode_transmissivity, internode_emissivity}},
5635 {
"peduncle", {peduncle_reflectivity, peduncle_transmissivity, peduncle_emissivity}},
5636 {
"petal", {petal_reflectivity, petal_transmissivity, petal_emissivity}},
5637 {
"pedicel", {pedicel_reflectivity, pedicel_transmissivity, pedicel_emissivity}},
5638 {
"fruit", {fruit_reflectivity, fruit_transmissivity, fruit_emissivity}}};
5639 for (
auto &primitive_values_pair: primitive_values_dict) {
5640 primitive_values_dict[primitive_values_pair.first][label] = {{
"All", {reflectivity, transmissivity, emissivity}},
5641 {
"ground", {ground_reflectivity, ground_transmissivity, ground_emissivity}},
5642 {
"leaf", {leaf_reflectivity, leaf_transmissivity, leaf_emissivity}},
5643 {
"petiolule", {petiolule_reflectivity, petiolule_transmissivity, petiolule_emissivity}},
5644 {
"petiole", {petiole_reflectivity, petiole_transmissivity, petiole_emissivity}},
5645 {
"internode", {internode_reflectivity, internode_transmissivity, internode_emissivity}},
5646 {
"peduncle", {peduncle_reflectivity, peduncle_transmissivity, peduncle_emissivity}},
5647 {
"petal", {petal_reflectivity, petal_transmissivity, petal_emissivity}},
5648 {
"pedicel", {pedicel_reflectivity, pedicel_transmissivity, pedicel_emissivity}},
5649 {
"fruit", {fruit_reflectivity, fruit_transmissivity, fruit_emissivity}}};
5653 if (!enable_emission) {
5656 bandlabels_set_emissivity.insert(label);
5659 direct_ray_count_dict.insert({label, direct_ray_count});
5661 diffuse_ray_count_dict.insert({label, diffuse_ray_count});
5663 scattering_depth_dict.insert({label, scattering_depth});
5668#ifdef ENABLE_HELIOS_VISUALIZER
5669void ProjectBuilder::randomizePopup(std::string popup_name,
taggedPtr ptr) {
5670 std::string popup =
"randomize_" + popup_name;
5671 if (ImGui::BeginPopup(popup.c_str())) {
5672 ImGui::Text(
"Random Distribution");
5673 ImGui::SetNextItemWidth(150);
5674 if (ImGui::BeginCombo(
"##combo_distribution", current_distribution.c_str())) {
5675 for (
int n = 0; n < distribution_names.size(); n++) {
5676 bool is_dist_selected = (current_distribution == distribution_names[n]);
5677 if (ImGui::Selectable(distribution_names[n].c_str(), is_dist_selected))
5678 current_distribution = distribution_names[n];
5679 if (is_dist_selected)
5680 ImGui::SetItemDefaultFocus();
5684 if (current_distribution ==
"Normal (Gaussian)") {
5685 ImGui::SetNextItemWidth(150);
5686 ImGui::InputFloat(
"Mean", &curr_distribution_params[0]);
5687 ImGui::SetNextItemWidth(150);
5688 ImGui::InputFloat(
"Variance", &curr_distribution_params[1]);
5690 if (current_distribution ==
"Uniform") {
5691 ImGui::SetNextItemWidth(150);
5692 ImGui::InputFloat(
"Lower Bound", &curr_distribution_params[0]);
5693 ImGui::SetNextItemWidth(150);
5694 ImGui::InputFloat(
"Upper Bound", &curr_distribution_params[1]);
5696 if (current_distribution ==
"Weibull") {
5697 ImGui::SetNextItemWidth(150);
5698 ImGui::InputFloat(
"Shape (k)", &curr_distribution_params[0]);
5699 ImGui::SetNextItemWidth(150);
5700 ImGui::InputFloat(u8
"Scale (\u03bb)", &curr_distribution_params[1]);
5702 if (current_distribution !=
"N/A") {
5703 ImGui::Checkbox(
"Randomize for Every Image", &randomize_repeatedly);
5705 if (ImGui::Button(
"Apply")) {
5707 ImGui::CloseCurrentPopup();
5713void ProjectBuilder::randomizePopup(std::string popup_name,
taggedPtr ptr) {
5719#ifdef ENABLE_HELIOS_VISUALIZER
5720void ProjectBuilder::noisePopup(std::string popup_name, std::vector<distribution> &dist_vec) {
5721 std::string popup = popup_name;
5722 if (ImGui::BeginPopup(popup.c_str())) {
5723 ImGui::Text(
"Add Random Noise Along Path");
5724 ImGui::SetNextItemWidth(100);
5725 if (ImGui::BeginCombo(
"##axis_combo", current_axis.c_str())) {
5726 for (
auto axis: possible_axes) {
5727 bool is_axis_selected = (current_axis == axis);
5728 if (ImGui::Selectable(axis.c_str(), is_axis_selected))
5729 current_axis = axis;
5730 if (is_axis_selected)
5731 ImGui::SetItemDefaultFocus();
5736 ImGui::Text(
"Axis");
5737 ImGui::SetNextItemWidth(150);
5738 if (ImGui::BeginCombo(
"##combo_distribution", current_distribution.c_str())) {
5739 for (
int n = 0; n < distribution_names.size(); n++) {
5740 bool is_dist_selected = (current_distribution == distribution_names[n]);
5741 if (ImGui::Selectable(distribution_names[n].c_str(), is_dist_selected))
5742 current_distribution = distribution_names[n];
5743 if (is_dist_selected)
5744 ImGui::SetItemDefaultFocus();
5749 ImGui::Text(
"Distribution");
5750 if (current_distribution ==
"Normal (Gaussian)") {
5751 ImGui::SetNextItemWidth(150);
5752 ImGui::InputFloat(
"Mean", &curr_distribution_params[0]);
5753 ImGui::SetNextItemWidth(150);
5754 ImGui::InputFloat(
"Variance", &curr_distribution_params[1]);
5756 if (current_distribution ==
"Uniform") {
5757 ImGui::SetNextItemWidth(150);
5758 ImGui::InputFloat(
"Lower Bound", &curr_distribution_params[0]);
5759 ImGui::SetNextItemWidth(150);
5760 ImGui::InputFloat(
"Upper Bound", &curr_distribution_params[1]);
5762 if (current_distribution ==
"Weibull") {
5763 ImGui::SetNextItemWidth(150);
5764 ImGui::InputFloat(
"Shape (k)", &curr_distribution_params[0]);
5765 ImGui::SetNextItemWidth(150);
5766 ImGui::InputFloat(u8
"Scale (\u03bb)", &curr_distribution_params[1]);
5769 if (current_axis ==
"X") {
5771 }
else if (current_axis ==
"Y") {
5776 if (ImGui::Button(
"Apply")) {
5778 if (current_distribution ==
"Normal (Gaussian)") {
5779 dist_union.normal =
new std::normal_distribution<float>;
5780 *dist_union.normal = std::normal_distribution<float>(curr_distribution_params[0], curr_distribution_params[1]);
5781 dist_vec[idx].dist = dist_union;
5782 dist_vec[idx].flag = 0;
5783 dist_vec[idx].repeat = 0;
5785 if (current_distribution ==
"Uniform") {
5786 dist_union.uniform =
new std::uniform_real_distribution<float>;
5787 *dist_union.uniform = std::uniform_real_distribution<float>(curr_distribution_params[0], curr_distribution_params[1]);
5788 dist_vec[idx].dist = dist_union;
5789 dist_vec[idx].flag = 1;
5790 dist_vec[idx].repeat = 0;
5792 if (current_distribution ==
"Weibull") {
5793 dist_union.weibull =
new std::weibull_distribution<float>;
5794 *dist_union.weibull = std::weibull_distribution<float>(curr_distribution_params[0], curr_distribution_params[1]);
5795 dist_vec[idx].dist = dist_union;
5796 dist_vec[idx].flag = 2;
5797 dist_vec[idx].repeat = 0;
5799 if (current_distribution ==
"N/A") {
5800 dist_vec[idx].flag = -1;
5801 dist_vec[idx].repeat = 0;
5804 ImGui::CloseCurrentPopup();
5810void ProjectBuilder::noisePopup(std::string popup_name, std::vector<distribution> &dist_vec) {
5817 if (current_distribution ==
"N/A") {
5818 distribution_types[var_name] =
"N/A";
5820 if (current_distribution ==
"Normal (Gaussian)") {
5821 std::normal_distribution<float> curr_dist_normal(curr_distribution_params[0], curr_distribution_params[1]);
5822 distribution_dict[var_name] = distributions.size();
5824 distribution_types[var_name] =
"Normal (Gaussian)";
5826 if (current_distribution ==
"Uniform") {
5827 std::uniform_real_distribution<float> curr_dist_uniform(curr_distribution_params[0], curr_distribution_params[1]);
5828 distribution_dict[var_name] = distributions.size();
5829 distributions.push_back(
createDistribution(curr_dist_uniform, randomize_repeatedly));
5830 distribution_types[var_name] =
"Uniform";
5832 if (current_distribution ==
"Weibull") {
5833 std::weibull_distribution<float> curr_dist_weibull(curr_distribution_params[0], curr_distribution_params[1]);
5834 distribution_dict[var_name] = distributions.size();
5835 distributions.push_back(
createDistribution(curr_dist_weibull, randomize_repeatedly));
5836 distribution_types[var_name] =
"Weibull";
5838 distribution_params[var_name] = curr_distribution_params;
5839 randomized_variable_lookup[var_name] = ptr;
5845 if (dist.flag == -1) {
5846 distribution_dict[var_name] = distributions.size();
5847 distributions.push_back(dist);
5848 distribution_types[var_name] =
"N/A";
5849 distribution_params[var_name] = std::vector<float>{0.0, 0.0};
5851 if (dist.flag == 0) {
5852 distribution_dict[var_name] = distributions.size();
5853 distributions.push_back(dist);
5854 distribution_types[var_name] =
"Normal (Gaussian)";
5855 distribution_params[var_name] = std::vector<float>{dist.dist.normal->mean(), dist.dist.normal->stddev()};
5857 if (current_distribution ==
"Uniform") {
5858 distribution_dict[var_name] = distributions.size();
5859 distributions.push_back(dist);
5860 distribution_types[var_name] =
"Uniform";
5861 distribution_params[var_name] = std::vector<float>{dist.dist.uniform->a(), dist.dist.uniform->b()};
5863 if (current_distribution ==
"Weibull") {
5864 distribution_dict[var_name] = distributions.size();
5865 distributions.push_back(dist);
5866 distribution_types[var_name] =
"Weibull";
5867 distribution_params[var_name] = std::vector<float>{dist.dist.weibull->a(), dist.dist.weibull->b()};
5869 randomized_variable_lookup[var_name] = ptr;
5875 for (std::pair<std::string, int> dist_pair: distribution_dict) {
5876 std::string var_name = dist_pair.first;
5878 if (randomize_all || dist.repeat) {
5919 u.normal =
new std::normal_distribution<float>;
5927 u.uniform =
new std::uniform_real_distribution<float>;
5935 u.weibull =
new std::weibull_distribution<float>;
5941#ifdef ENABLE_HELIOS_VISUALIZER
5942void ProjectBuilder::randomizerParams(std::string var_name) {
5943 if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
5944 if (distribution_params.find(var_name) != distribution_params.end()) {
5945 curr_distribution_params = distribution_params[var_name];
5947 curr_distribution_params = std::vector<float>{0, 0};
5949 if (distribution_types.find(var_name) != distribution_types.end()) {
5950 current_distribution = distribution_types[var_name];
5952 current_distribution =
"N/A";
5954 if (current_distribution !=
"N/A") {
5955 randomize_repeatedly = distributions[distribution_dict[var_name]].repeat;
5960void ProjectBuilder::randomizerParams(std::string var_name) {
5966 if (distribution_types.find(var_name) == distribution_types.end() || distribution_types[var_name] ==
"N/A") {
5969 distribution d = distributions[distribution_dict[var_name]];
5970 taggedPtr t = randomized_variable_lookup[var_name];
5971 float sampled_value;
5973 std::normal_distribution<float> normal = *d.dist.normal;
5974 sampled_value = normal(generator);
5976 *t.ptr.i = (int) sampled_value;
5978 *t.ptr.f = sampled_value;
5980 }
else if (d.flag == 1) {
5981 std::uniform_real_distribution<float> uniform = *d.dist.uniform;
5982 sampled_value = uniform(generator);
5984 *t.ptr.i = (int) sampled_value;
5986 *t.ptr.f = sampled_value;
5988 }
else if (d.flag == 2) {
5989 std::weibull_distribution<float> weibull = *d.dist.weibull;
5990 sampled_value = weibull(generator);
5992 *t.ptr.i = (int) sampled_value;
5994 *t.ptr.f = sampled_value;
6008 for (
int canopy_idx: dirty_canopies) {
6011 for (
int object_idx: dirty_objects) {
6014 dirty_canopies.clear();
6015 dirty_objects.clear();
6020 for (std::pair<std::string, std::string> var_pair: distribution_types) {
6025#ifdef ENABLE_HELIOS_VISUALIZER
6026void ProjectBuilder::outputConsole() {
6030 std::streambuf *prev_buf = std::cout.rdbuf();
6031 std::string buffer = captured_cout.str();
6032 std::size_t buffer_size = buffer.size();
6033 ImGui::BeginChild(
"##console", ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 5), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar);
6034 ImGui::TextUnformatted(buffer.c_str());
6035 if (buffer_size != last_console_size) {
6036 ImGui::SetScrollHereY(1.0f);
6039 last_console_size = buffer_size;
6040 std::cout.rdbuf(prev_buf);
6043void ProjectBuilder::outputConsole() {
6050 if (obj_type ==
"obj") {
6051 curr_color = &objects_dict[curr_obj].color;
6053 if (obj_type ==
"rig" || obj_type ==
"arrow" || obj_type ==
"camera") {
6054 curr_color = &rig_colors[rig_dict[curr_obj]];
6059 if (curr_color->
r != new_color[0] || curr_color->
g != new_color[1] || curr_color->
b != new_color[2]) {
6062 curr_color->
r = new_color[0];
6063 curr_color->
g = new_color[1];
6064 curr_color->
b = new_color[2];
6067 if (obj_type ==
"obj") {
6068 std::string obj_material =
"projectbuilder_obj_" + curr_obj;
6075 if (obj_type ==
"rig") {
6076 if (arrow_dict.find(curr_obj) != arrow_dict.end()) {
6077 std::string arrow_material =
"projectbuilder_rig_arrow_" + curr_obj;
6080 for (std::vector<uint> &arrow: arrow_dict.at(curr_obj)) {
6086 if (camera_models_dict.find(curr_obj) != camera_models_dict.end()) {
6087 std::string camera_material =
"projectbuilder_rig_camera_" + curr_obj;
6095 if (obj_type ==
"arrow") {
6096 if (arrow_dict.find(curr_obj) != arrow_dict.end()) {
6097 std::string arrow_material =
"projectbuilder_arrow_" + curr_obj;
6100 for (std::vector<uint> &arrow: arrow_dict.at(curr_obj)) {
6107 if (obj_type ==
"camera") {
6108 if (camera_models_dict.find(curr_obj) != camera_models_dict.end()) {
6109 std::string camera_material =
"projectbuilder_camera_" + curr_obj;
6122 if (objects_dict[curr_obj].use_texture_file && objects_dict[curr_obj].is_dirty) {
6124 if (std::filesystem::path(objects_dict[curr_obj].file).extension() ==
".obj") {
6125 objects_dict[curr_obj].UUIDs =
context->
loadOBJ(objects_dict[curr_obj].file.c_str());
6126 }
else if (std::filesystem::path(objects_dict[curr_obj].file).extension() ==
".ply") {
6127 objects_dict[curr_obj].UUIDs =
context->
loadPLY(objects_dict[curr_obj].file.c_str());
6137 objects_dict[curr_obj].prev_scale = objects_dict[curr_obj].scale;
6138 objects_dict[curr_obj].prev_orientation = objects_dict[curr_obj].orientation;
6139 objects_dict[curr_obj].prev_position = objects_dict[curr_obj].position;
6141 if (objects_dict[curr_obj].scale != objects_dict[curr_obj].prev_scale) {
6143 obj_scale_.
x = objects_dict[curr_obj].scale.x / objects_dict[curr_obj].prev_scale.x;
6144 obj_scale_.
y = objects_dict[curr_obj].scale.y / objects_dict[curr_obj].prev_scale.y;
6145 obj_scale_.
z = objects_dict[curr_obj].scale.z / objects_dict[curr_obj].prev_scale.z;
6156 objects_dict[curr_obj].prev_scale = objects_dict[curr_obj].scale;
6158 if (objects_dict[curr_obj].orientation != objects_dict[curr_obj].prev_orientation) {
6164 context->
rotateObject(objects_dict[curr_obj].objID,
deg2rad(objects_dict[curr_obj].orientation.x - objects_dict[curr_obj].prev_orientation.x), objects_dict[curr_obj].prev_position,
make_vec3(1, 0, 0));
6165 context->
rotateObject(objects_dict[curr_obj].objID,
deg2rad(objects_dict[curr_obj].orientation.y - objects_dict[curr_obj].prev_orientation.y), objects_dict[curr_obj].prev_position,
make_vec3(0, 1, 0));
6166 context->
rotateObject(objects_dict[curr_obj].objID,
deg2rad(objects_dict[curr_obj].orientation.z - objects_dict[curr_obj].prev_orientation.z), objects_dict[curr_obj].prev_position,
make_vec3(0, 0, 1));
6167 objects_dict[curr_obj].prev_orientation = objects_dict[curr_obj].orientation;
6169 if (objects_dict[curr_obj].position != objects_dict[curr_obj].prev_position) {
6171 context->
translateObject(objects_dict[curr_obj].objID, objects_dict[curr_obj].position - objects_dict[curr_obj].prev_position);
6172 objects_dict[curr_obj].prev_position = objects_dict[curr_obj].position;
6174 objects_dict[curr_obj].prev_color = objects_dict[curr_obj].color;
6175 objects_dict[curr_obj].is_dirty =
false;
6185 deleteCameraModels();
6186 camera_models_dict.clear();
6187 updateCameraModels();
6195 int delete_idx = rig_dict[curr_rig];
6196 rig_dict.erase(rig_dict.find(curr_rig));
6197 rig_labels_set.erase(curr_rig);
6199 if (!rig_labels_set.empty() && current_rig == curr_rig) {
6200 current_rig = *rig_labels_set.begin();
6209 new_rig.label = new_rig_label;
6211 if (current_rig.empty()) {
6213 new_rig.position = default_rig.position;
6214 new_rig.lookat = default_rig.position;
6215 new_rig.camera_labels = default_rig.camera_labels;
6216 new_rig.position_noise = default_rig.position_noise;
6217 new_rig.lookat_noise = default_rig.lookat_noise;
6218 new_rig.camera_positions = default_rig.camera_positions;
6219 new_rig.camera_lookats = default_rig.camera_lookats;
6220 new_rig.color = default_rig.color;
6221 new_rig.num_images = default_rig.num_images;
6222 new_rig.keypoint_frames = default_rig.keypoint_frames;
6225 rig curr_rig = rig_dict_.at(current_rig);
6227 new_rig.label = curr_rig.label;
6228 new_rig.position = curr_rig.position;
6229 new_rig.lookat = curr_rig.lookat;
6230 new_rig.camera_labels = curr_rig.camera_labels;
6231 new_rig.position_noise = curr_rig.position_noise;
6232 new_rig.lookat_noise = curr_rig.lookat_noise;
6233 new_rig.camera_positions = curr_rig.camera_positions;
6234 new_rig.camera_lookats = curr_rig.camera_lookats;
6235 new_rig.color = curr_rig.color;
6236 new_rig.num_images = curr_rig.num_images;
6237 new_rig.keypoint_frames = curr_rig.keypoint_frames;
6240 rig_dict_.insert({new_rig_label, new_rig});
6242 rig_dict.insert({new_rig_label, scast<int>(rig_labels.size())});
6243 camera_positions.push_back(camera_position);
6244 camera_lookats.push_back(camera_lookat);
6245 camera_labels.push_back(camera_label);
6246 camera_position_vec.push_back(camera_position_vec[rig_dict[current_rig]]);
6247 camera_lookat_vec.push_back(camera_lookat_vec[rig_dict[current_rig]]);
6248 rig_labels.push_back(new_rig_label);
6249 rig_labels_set.insert(new_rig_label);
6250 rig_camera_labels.push_back(rig_camera_labels[rig_dict[current_rig]]);
6251 rig_light_labels.push_back(rig_light_labels[rig_dict[current_rig]]);
6252 keypoint_frames.push_back(keypoint_frames[rig_dict[current_rig]]);
6253 num_images_vec.push_back(num_images_vec[rig_dict[current_rig]]);
6254 rig_colors.push_back(rig_colors[rig_dict[current_rig]]);
6259 write_depth.push_back(
false);
6260 write_norm_depth.push_back(
false);
6261 write_segmentation_mask.push_back(
false);
6264 std::string parent =
"rig";
6265 pugi::xml_node rig_block = helios.child(parent.c_str());
6266 pugi::xml_node new_rig_node = helios.append_copy(rig_block);
6267 std::string name =
"label";
6268 pugi::xml_attribute node_label = new_rig_node.attribute(name.c_str());
6269 node_label.set_value(new_rig_label.c_str());
6270 current_rig = new_rig_label;
6274#ifdef ENABLE_HELIOS_VISUALIZER
6275void ProjectBuilder::dropDown(std::string widget_name, std::string &selected, std::vector<std::string> choices) {
6276 if (ImGui::BeginCombo(widget_name.c_str(), selected.c_str())) {
6277 for (
int n = 0; n < choices.size(); n++) {
6278 bool is_selected = (selected == choices[n]);
6279 if (ImGui::Selectable(choices[n].c_str(), is_selected))
6280 selected = choices[n];
6282 ImGui::SetItemDefaultFocus();
6289void ProjectBuilder::dropDown(std::string widget_name, std::string &selected, std::set<std::string> choices) {
6290 if (ImGui::BeginCombo(widget_name.c_str(), selected.c_str())) {
6291 for (std::string choice: choices) {
6292 bool is_selected = (selected == choice);
6293 if (ImGui::Selectable(choice.c_str(), is_selected))
6296 ImGui::SetItemDefaultFocus();
6302void ProjectBuilder::dropDown(std::string widget_name, std::string &selected, std::vector<std::string> choices) {
6306void ProjectBuilder::dropDown(std::string widget_name, std::string &selected, std::set<std::string> choices) {
6311void ProjectBuilder::deleteCanopy(
const std::string &
canopy) {
6312#ifdef ENABLE_PLANT_ARCHITECTURE
6313 for (
auto plant_instance: canopy_dict[
canopy].IDs) {
6316 canopy_dict.erase(
canopy);
6317 canopy_labels_set.erase(
canopy);
6318 if (!canopy_labels_set.empty() && current_canopy ==
canopy) {
6319 current_canopy = *canopy_labels_set.begin();
6321 current_canopy =
"";
6329void ProjectBuilder::deleteObject(
const std::string &
obj) {
6331 objects_dict.erase(
obj);
6332 obj_names_set.erase(
obj);
6333 if (!obj_names_set.empty()) {
6334 current_obj = *obj_names_set.begin();
6343void ProjectBuilder::updateCanopy(
const std::string &
canopy) {
6344#ifdef ENABLE_PLANT_ARCHITECTURE
6345 for (
auto plant_instance: canopy_dict[
canopy].IDs) {
6353 canopy_dict[
canopy].individual_plant_locations = curr_plant_locations;
6356 primitive_UUIDs[
"leaf"] = leaf_UUIDs;
6358 primitive_UUIDs[
"internode"] = internode_UUIDs;
6360 primitive_UUIDs[
"petiole"] = petiole_UUIDs;
6362 primitive_UUIDs[
"peduncle"] = peduncle_UUIDs;
6366 if (petal_UUIDs.empty() && sepal_UUIDs.empty()) {
6367 petal_UUIDs = flower_UUIDs;
6368 sepal_UUIDs.clear();
6371 primitive_UUIDs[
"petal"] = petal_UUIDs;
6372 primitive_UUIDs[
"sepal"] = sepal_UUIDs;
6373 primitive_UUIDs[
"flower"] = flower_UUIDs;
6375 canopy_dict[
canopy].IDs = new_canopy_IDs;
6376 canopy_dict[
canopy].is_dirty =
false;
6381void ProjectBuilder::addCanopy() {
6382 std::string default_canopy_label =
"canopy";
6383 std::string new_canopy_label =
"canopy_0";
6385 while (canopy_dict.find(new_canopy_label) != canopy_dict.end()) {
6387 new_canopy_label = default_canopy_label +
"_" + std::to_string(count);
6390 new_canopy.idx = canopy_idx;
6391 canopy_labels_set.insert(new_canopy_label);
6393 new_canopy.age = plant_age;
6394 new_canopy.ground_clipping_height = ground_clipping_height;
6395 new_canopy.label = new_canopy_label;
6396 new_canopy.library_name = plant_library_name;
6397 new_canopy.library_name_verbose = plant_library_name_verbose;
6398 new_canopy.IDs = std::vector<unsigned int>{};
6399 new_canopy.individual_plant_locations = std::vector<vec3>{};
6400 new_canopy.plant_spacing = plant_spacing;
6401 new_canopy.plant_count = plant_count;
6402 new_canopy.origin = canopy_origin;
6403 new_canopy.data_group =
"";
6404 canopy_dict[new_canopy.label] = new_canopy;
6406 current_canopy = new_canopy_label;
6410#ifdef ENABLE_HELIOS_VISUALIZER
6411void ProjectBuilder::refreshVisualization() {
6412 const char *font_name =
"LCD";
6417 if (enable_coordinate_axes) {
6421 updatePrimitiveTypes();
6424void ProjectBuilder::refreshVisualization() {
6430#ifdef ENABLE_HELIOS_VISUALIZER
6431void ProjectBuilder::recordPopup() {
6432 if (ImGui::BeginPopup(
"repeat_record")) {
6433 ImGui::SetNextItemWidth(100);
6434 ImGui::InputInt(
"Number of Recordings", &num_recordings);
6435 num_recordings = std::max(num_recordings, 1);
6440void ProjectBuilder::recordPopup() {
6450 location.
UTC_offset =
static_cast<float>(UTC_offset);
6459 ground_UUIDs.clear();
6460 primitive_UUIDs[
"ground"].clear();
6463 if (!ground_model_file.empty() && ground_flag == 2 && use_ground_texture) {
6467 }
else if (!ground_texture_file.empty() && ground_flag == 1 && use_ground_texture) {
6468 if (num_tiles.
x > 1 || num_tiles.
y > 1 || ground_resolution.
x > 1 || ground_resolution.
y > 1) {
6469 buildTiledGround(domain_origin, domain_extent, num_tiles, ground_resolution, ground_texture_file.c_str(), 0.f);
6476 }
else if (ground_flag == 1 && !use_ground_texture) {
6478 ground_color_.
r = ground_color[0];
6479 ground_color_.
g = ground_color[1];
6480 ground_color_.
b = ground_color[2];
6482 if (num_tiles.
x > 1 || num_tiles.
y > 1 || ground_resolution.
x > 1 || ground_resolution.
y > 1) {
6483 buildTiledGround(domain_origin, domain_extent, num_tiles, ground_resolution, ground_color_, 0.f);
6486 std::string ground_material =
"projectbuilder_ground";
6498 }
else if (ground_flag == 2 && !use_ground_texture) {
6500 ground_color_.
r = ground_color[0];
6501 ground_color_.
g = ground_color[1];
6502 ground_color_.
b = ground_color[2];
6507 std::string ground_material =
"projectbuilder_ground";
6518 ground_UUIDs.clear();
6524 primitive_UUIDs[
"ground"] = ground_UUIDs;
6532 ground_UUIDs.clear();
6533 primitive_UUIDs[
"ground"].clear();
6536#ifdef ENABLE_HELIOS_VISUALIZER
6537void ProjectBuilder::refreshVisualizationTypes() {
6539 visualization_types_primitive.clear();
6540 for (
auto &data:
context->listAllPrimitiveDataLabels()) {
6541 visualization_types_primitive.insert(data);
6546 visualization_types_object.clear();
6547 for (
auto &data:
context->listAllObjectDataLabels()) {
6548 visualization_types_object.insert(data);
6552void ProjectBuilder::refreshVisualizationTypes() {
6559 std::string shorten_path = path_name;
6560 for (
char &c: shorten_path) {
6565 size_t last_file = shorten_path.rfind(
'/');
6566 if (last_file != std::string::npos) {
6567 shorten_path = shorten_path.substr(last_file + 1);
6569 return shorten_path;
6574 bounding_boxes_map.clear();
6576 for (
auto &box_pair: bounding_boxes) {
6577 if (box_pair.second) {
6578 bounding_boxes_map[box_pair.first] = idx;
6599 ground_UUIDs.clear();
6600 primitive_UUIDs[
"ground"].clear();
6602 vec2 dx_tile(ground_extent.
x /
float(texture_subtiles.
x), ground_extent.
y /
float(texture_subtiles.
y));
6604 vec2 dx_subpatch(dx_tile.
x /
float(texture_subpatches.
x), dx_tile.
y /
float(texture_subpatches.
y));
6606 std::vector<uint> UUIDs;
6607 for (
int j = 0; j < texture_subtiles.
y; j++) {
6608 for (
int i = 0; i < texture_subtiles.
x; i++) {
6610 vec3 center = ground_origin +
make_vec3(-0.5f * ground_extent.
x + (
float(i) + 0.5f) * dx_tile.
x, -0.5f * ground_extent.
y + (
float(j) + 0.5f) * dx_tile.
y, 0);
6612 if (ground_rotation != 0) {
6618 ground_UUIDs.insert(ground_UUIDs.begin(), UUIDs.begin(), UUIDs.end());
6626 primitive_UUIDs[
"ground"] = ground_UUIDs;
6634 ground_UUIDs.clear();
6635 primitive_UUIDs[
"ground"].clear();
6637 vec2 dx_tile(ground_extent.
x /
float(texture_subtiles.
x), ground_extent.
y /
float(texture_subtiles.
y));
6639 vec2 dx_subpatch(dx_tile.
x /
float(texture_subpatches.
x), dx_tile.
y /
float(texture_subpatches.
y));
6641 std::vector<uint> UUIDs;
6642 for (
int j = 0; j < texture_subtiles.
y; j++) {
6643 for (
int i = 0; i < texture_subtiles.
x; i++) {
6645 vec3 center = ground_origin +
make_vec3(-0.5f * ground_extent.
x + (
float(i) + 0.5f) * dx_tile.
x, -0.5f * ground_extent.
y + (
float(j) + 0.5f) * dx_tile.
y, 0);
6647 if (ground_rotation != 0) {
6653 ground_UUIDs.insert(ground_UUIDs.begin(), UUIDs.begin(), UUIDs.end());
6661 primitive_UUIDs[
"ground"] = ground_UUIDs;
6664void ProjectBuilder::refreshBoundingBoxObjectList() {
6666 std::set<std::string> primitive_data_labels;
6667 for (
auto &primitive_UUID:
context->getAllUUIDs()) {
6668 for (std::string data:
context->listPrimitiveData(primitive_UUID)) {
6669 primitive_data_labels.insert(data);
6673 for (
const std::string &data: primitive_data_labels) {
6675 if (bounding_boxes.find(data) == bounding_boxes.end()) {
6676 bounding_boxes.insert({data,
false});
6677 bounding_boxes_primitive.insert(data);
6683 std::set<std::string> object_data_labels;
6684 for (
auto &object_UUID:
context->getAllObjectIDs()) {
6685 for (std::string data:
context->listObjectData(object_UUID)) {
6686 object_data_labels.insert(data);
6690 for (
const std::string &data: object_data_labels) {
6692 if (bounding_boxes.find(data) == bounding_boxes.end()) {
6693 bounding_boxes.insert({data,
false});
6694 bounding_boxes_object.insert(data);
6701void ProjectBuilder::globalCalculation() {
6703 std::vector<uint> relevant_UUIDs{};
6704 if (calculation_selection_datagroup[
"All"]) {
6705 for (
auto &prim_pair: primitive_UUIDs) {
6706 if (calculation_selection_primitive[prim_pair.first] || calculation_selection_primitive[
"All"]) {
6707 relevant_UUIDs.insert(relevant_UUIDs.end(), prim_pair.second.begin(), prim_pair.second.end());
6711 for (
auto &
obj: objects_dict) {
6712 if (calculation_selection_datagroup[
obj.second.data_group]) {
6713 for (
auto &prim_pair: calculation_selection_primitive) {
6714 if (prim_pair.second || calculation_selection_primitive[
"All"]) {
6716 relevant_UUIDs.insert(relevant_UUIDs.end(), new_UUIDs.begin(), new_UUIDs.end());
6721 for (
auto &
canopy: canopy_dict) {
6722 if (calculation_selection_datagroup[
canopy.second.data_group]) {
6723 std::vector<uint> canopy_UUIDs;
6724 for (
auto &plant_id:
canopy.second.IDs) {
6725#ifdef ENABLE_PLANT_ARCHITECTURE
6727 canopy_UUIDs.insert(canopy_UUIDs.end(), plant_UUIDs.begin(), plant_UUIDs.end());
6730 for (
auto &prim_pair: calculation_selection_primitive) {
6731 if (prim_pair.second || calculation_selection_primitive[
"All"]) {
6733 relevant_UUIDs.insert(relevant_UUIDs.end(), new_UUIDs.begin(), new_UUIDs.end());
6741 if (std::find(globalVars.begin(), globalVars.end(), calculation_variables_global[0]) != globalVars.end()) {
6743 }
else if (curr_aggregation ==
"Mean") {
6745 }
else if (calculation_aggregations[0] ==
"Sum") {
6747 }
else if (calculation_aggregations[0] ==
"Area Weighted Mean") {
6749 }
else if (calculation_aggregations[0] ==
"Area Weighted Sum") {
6752 for (
int i = 0; i < calculation_operators_global.size(); i++) {
6753 float prev_res = calculation_result_global;
6754 if (calculation_aggregations[i] ==
"Mean") {
6756 }
else if (calculation_aggregations[i] ==
"Sum") {
6758 }
else if (calculation_aggregations[i] ==
"Area Weighted Mean") {
6760 }
else if (calculation_aggregations[i] ==
"Area Weighted Sum") {
6763 std::string curr_op = calculation_operators_global[i];
6764 if (curr_op ==
"+") {
6765 calculation_result_global = prev_res + calculation_result_global;
6766 }
else if (curr_op ==
"-") {
6767 calculation_result_global = prev_res - calculation_result_global;
6768 }
else if (curr_op ==
"/") {
6769 calculation_result_global = prev_res / calculation_result_global;
6770 }
else if (curr_op ==
"x") {
6771 calculation_result_global = prev_res * calculation_result_global;
6777void ProjectBuilder::savePrimitiveCalculation() {
6779 std::vector<uint> relevant_UUIDs{};
6780 if (calculation_selection_datagroup[
"All"]) {
6781 for (
auto &prim_pair: primitive_UUIDs) {
6782 if (calculation_selection_primitive[prim_pair.first] || calculation_selection_primitive[
"All"]) {
6783 relevant_UUIDs.insert(relevant_UUIDs.end(), prim_pair.second.begin(), prim_pair.second.end());
6787 for (
auto &
obj: objects_dict) {
6788 if (calculation_selection_datagroup[
obj.second.data_group]) {
6789 for (
auto &prim_pair: calculation_selection_primitive) {
6790 if (prim_pair.second || calculation_selection_primitive[
"All"]) {
6792 relevant_UUIDs.insert(relevant_UUIDs.end(), new_UUIDs.begin(), new_UUIDs.end());
6797 for (
auto &
canopy: canopy_dict) {
6798 if (calculation_selection_datagroup[
canopy.second.data_group]) {
6799 std::vector<uint> canopy_UUIDs;
6800 for (
auto &plant_id:
canopy.second.IDs) {
6801#ifdef ENABLE_PLANT_ARCHITECTURE
6803 canopy_UUIDs.insert(canopy_UUIDs.end(), plant_UUIDs.begin(), plant_UUIDs.end());
6806 for (
auto &prim_pair: calculation_selection_primitive) {
6807 if (prim_pair.second || calculation_selection_primitive[
"All"]) {
6809 relevant_UUIDs.insert(relevant_UUIDs.end(), new_UUIDs.begin(), new_UUIDs.end());
6815 for (
auto &UUID: relevant_UUIDs) {
6818 refreshVisualizationTypes();
6822void ProjectBuilder::runRadiation() {
6823#ifdef ENABLE_RADIATION_MODEL
6824 for (std::string band_group_name: band_group_names) {
6825 bandGroup curr_band_group = band_group_lookup[band_group_name];
6826 if (!curr_band_group.grayscale) {