1.3.49
 
Loading...
Searching...
No Matches
ProjectBuilder.cpp
1#ifdef _WIN32
2#ifndef NOMINMAX
3#define NOMINMAX
4#endif
5#define WIN32_LEAN_AND_MEAN
6#include <windows.h>
7#include <commdlg.h>
8#elif defined(__APPLE__)
9#ifdef ENABLE_HELIOS_VISUALIZER
10#include <nfd.h>
11#endif
12#elif defined(__linux__)
13#ifdef ENABLE_HELIOS_VISUALIZER
14#include <nfd.h>
15#endif
16#endif
17
18// OpenGL/ImGui includes - must come after Windows headers but before ProjectBuilder.h
19#ifdef ENABLE_HELIOS_VISUALIZER
20// IMPORTANT: glew.h must be included before any OpenGL headers (including GLFW)
21#include "glew.h"
22// IMGUI
23#define GLFW_INCLUDE_NONE // Prevent GLFW from including OpenGL headers
24#include "GLFW/glfw3.h"
25#include "backends/imgui_impl_glfw.h"
26#include "backends/imgui_impl_opengl3.h"
27#include "imgui.h"
28#include "imgui_internal.h"
29#include "misc/cpp/imgui_stdlib.h"
30#endif // HELIOS_VISUALIZER
31
32#include "ProjectBuilder.h"
33
34#ifdef ENABLE_BOUNDARYLAYERCONDUCTANCEMODEL
35const bool enable_blconductance = true;
36#else
37const bool enable_blconductance = false;
38#endif // BOUNDARYLAYERCONDUCTANCEMODEL
39
40#ifdef ENABLE_ENERGYBALANCEMODEL
41const bool enable_energybalance = true;
42#else
43const bool enable_energybalance = false;
44#endif // ENERGYBALANCEMODEL
45
46#ifdef ENABLE_PLANT_ARCHITECTURE
47const bool enable_plantarchitecture = true;
48#else
49const bool enable_plantarchitecture = false;
50#endif // PLANT_ARCHITECTURE
51
52#ifdef ENABLE_RADIATION_MODEL
53const bool enable_radiation = true;
54#else
55const bool enable_radiation = false;
56#endif // RADIATION_MODEL
57
58#ifdef ENABLE_SOLARPOSITION
59const bool enable_solarposition = true;
60#else
61const bool enable_solarposition = false;
62#endif // SOLARPOSITION
63
64#ifdef ENABLE_HELIOS_VISUALIZER
65const bool enable_visualizer = true;
66#else
67const bool enable_visualizer = false;
68#endif // HELIOS_VISUALIZER
69
70
71using namespace helios;
72
73
74std::string vec_to_string(const int2 &v) {
75 std::ostringstream oss;
76 oss << v.x << " " << v.y;
77 return oss.str();
78}
79
80std::string vec_to_string(const vec2 &v) {
81 std::ostringstream oss;
82 oss << v.x << " " << v.y;
83 return oss.str();
84}
85
86std::string vec_to_string(const vec3 &v) {
87 std::ostringstream oss;
88 oss << v.x << " " << v.y << " " << v.z;
89 return oss.str();
90}
91
92std::vector<vec3> interpolate(const std::vector<int> &keypoints, const std::vector<helios::vec3> &positions, int num_points) {
93 std::vector<vec3> pos = positions;
94 std::vector<vec3> result(num_points);
95 std::vector<int> keypoints_sorted = keypoints;
96 std::sort(keypoints_sorted.begin(), keypoints_sorted.end());
97 std::map<int, int> keypoints_loc;
98 for (int i = 0; i < keypoints.size(); i++) {
99 keypoints_loc.insert({keypoints[i], i});
100 }
101 if (keypoints.size() == 1) {
102 std::fill(result.begin(), result.end(), pos[0]);
103 return result;
104 }
105 if (keypoints_sorted[keypoints_sorted.size() - 1] != num_points - 1) {
106 keypoints_sorted.push_back(num_points - 1);
107 keypoints_loc.insert({num_points - 1, static_cast<int>(keypoints.size())});
108 pos.push_back(pos[pos.size() - 1]);
109 }
110 for (int i = 0; i < keypoints_sorted.size() - 1; i++) {
111 int keypoint = keypoints_sorted[i];
112 int keypoint_idx = keypoints_loc[keypoints_sorted[i]];
113 int next_keypoint = keypoints_sorted[i + 1];
114 int next_keypoint_idx = keypoints_loc[keypoints_sorted[i + 1]];
115 std::vector<vec3> curr_positions = linspace(pos[keypoint_idx], pos[next_keypoint_idx], next_keypoint - keypoint + 1);
116 for (int j = 0; j < next_keypoint - keypoint + 1; j++) {
117 int idx = j + keypoint;
118 result[idx] = curr_positions[j];
119 }
120 }
121 return result;
122}
123
124void toggle_button(const char *str_id, bool *v) {
125#ifdef ENABLE_HELIOS_VISUALIZER
126 ImVec2 p = ImGui::GetCursorScreenPos();
127 ImDrawList *draw_list = ImGui::GetWindowDrawList();
128
129 float height = ImGui::GetFrameHeight();
130 float width = height * 1.55f;
131 float radius = height * 0.50f;
132
133 ImGui::InvisibleButton(str_id, ImVec2(width, height));
134 if (ImGui::IsItemClicked())
135 *v = !*v;
136
137 float t = *v ? 1.0f : 0.0f;
138
139 ImGuiContext &g = *GImGui;
140 const float ANIM_SPEED = 0.08f;
141 if (g.LastActiveId == g.CurrentWindow->GetID(str_id)) // && g.LastActiveIdTimer < ANIM_SPEED)
142 {
143 float t_anim = ImSaturate(g.LastActiveIdTimer / ANIM_SPEED);
144 t = *v ? (t_anim) : (1.0f - t_anim);
145 }
146
147 ImU32 col_bg;
148 if (ImGui::IsItemHovered())
149 col_bg = ImGui::GetColorU32(ImLerp(ImVec4(0.78f, 0.78f, 0.78f, 1.0f), ImVec4(0.64f, 0.83f, 0.34f, 1.0f), t));
150 else
151 col_bg = ImGui::GetColorU32(ImLerp(ImVec4(0.85f, 0.85f, 0.85f, 1.0f), ImVec4(0.56f, 0.83f, 0.26f, 1.0f), t));
152
153 draw_list->AddRectFilled(p, ImVec2(p.x + width, p.y + height), col_bg, height * 0.5f);
154 draw_list->AddCircleFilled(ImVec2(p.x + radius + t * (width - radius * 2.0f), p.y + radius), radius - 1.5f, IM_COL32(255, 255, 255, 255));
155#endif // HELIOS_VISUALIZER
156}
157
158std::string file_dialog() {
159 std::string file_name;
160#ifdef ENABLE_HELIOS_VISUALIZER
161#ifdef _WIN32
162 // save CWD
163 char CWD[MAX_PATH];
164 GetCurrentDirectory(MAX_PATH, CWD);
165
166 OPENFILENAME ofn;
167 char szFile[260] = {0};
168
169 ZeroMemory(&ofn, sizeof(ofn));
170 ofn.lStructSize = sizeof(ofn);
171 ofn.hwndOwner = nullptr;
172 ofn.lpstrFile = szFile;
173 ofn.nMaxFile = sizeof(szFile);
174 ofn.lpstrFilter = "All Files\0*.*\0Text Files\0*.txt\0";
175 ofn.nFilterIndex = 1;
176 ofn.lpstrFileTitle = nullptr;
177 ofn.nMaxFileTitle = 0;
178 ofn.lpstrInitialDir = nullptr;
179 ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
180
181 if (GetOpenFileName(&ofn)) {
182 std::cout << "Selected file: " << ofn.lpstrFile << std::endl;
183 } else {
184 std::cout << "No file selected." << std::endl;
185 return "";
186 }
187
188 // correct CWD
189 SetCurrentDirectory(CWD);
190
191 file_name = (std::string) ofn.lpstrFile;
192#elif defined(__APPLE__)
193 nfdchar_t *outPath = nullptr;
194 nfdresult_t result = NFD_OpenDialog(nullptr, nullptr, &outPath);
195
196 if (result == NFD_OKAY) {
197 // puts("Success!");
198 // puts(outPath);
199 file_name = std::string(outPath);
200 free(outPath);
201 } else if (result == NFD_CANCEL) {
202 puts("User pressed cancel.");
203 } else {
204 // printf("Error: %s\n", NFD_GetError() );
205 std::cout << "Error: " << NFD_GetError() << std::endl;
206 }
207#elif defined(__linux__)
208 nfdchar_t *outPath = nullptr;
209 nfdresult_t result = NFD_OpenDialog(nullptr, nullptr, &outPath);
210
211 if (result == NFD_OKAY) {
212 puts("Success!");
213 puts(outPath);
214 file_name = std::string(outPath);
215 free(outPath);
216 } else if (result == NFD_CANCEL) {
217 puts("User pressed cancel.");
218 } else {
219 // printf("Error: %s\n", NFD_GetError() );
220 std::cout << "Error: " << NFD_GetError() << std::endl;
221 }
222#endif
223
224#endif
225
226 return file_name;
227}
228
229
230std::string save_as_file_dialog(std::vector<std::string> extensions) {
231 std::string file_name;
232#ifdef ENABLE_HELIOS_VISUALIZER
233#ifdef _WIN32
234 // save CWD
235 char CWD[MAX_PATH];
236 GetCurrentDirectory(MAX_PATH, CWD);
237
238 OPENFILENAME ofn;
239 char szFile[260] = {0};
240
241 ZeroMemory(&ofn, sizeof(ofn));
242 ofn.lStructSize = sizeof(ofn);
243 ofn.hwndOwner = nullptr;
244 ofn.lpstrFile = szFile;
245 ofn.nMaxFile = sizeof(szFile);
246 std::string filterList = "";
247 for (std::string extension: extensions) {
248 std::string ext_lower = extension;
249 std::string ext_upper = extension;
250 std::transform(ext_lower.begin(), ext_lower.end(), ext_lower.begin(), ::tolower);
251 std::transform(ext_upper.begin(), ext_upper.end(), ext_upper.begin(), ::toupper);
252 filterList += ext_upper + " Files (*." + ext_lower + ")";
253 filterList += '\0';
254 filterList += "*." + ext_lower;
255 filterList += '\0';
256 }
257 filterList += '\0';
258 ofn.lpstrFilter = filterList.c_str();
259 ofn.nFilterIndex = 1;
260 ofn.lpstrFileTitle = nullptr;
261 ofn.nMaxFileTitle = 0;
262 ofn.lpstrInitialDir = nullptr;
263 ofn.Flags = OFN_PATHMUSTEXIST;
264
265 if (GetSaveFileName(&ofn)) {
266 std::cout << "Selected file: " << ofn.lpstrFile << std::endl;
267 } else {
268 std::cout << "No file selected." << std::endl;
269 return "";
270 }
271
272 std::string ext_ = extensions[ofn.nFilterIndex - 1];
273 std::transform(ext_.begin(), ext_.end(), ext_.begin(), ::tolower);
274 std::string ext = "." + ext_;
275
276 // correct CWD
277 SetCurrentDirectory(CWD);
278
279 file_name = (std::string) ofn.lpstrFile;
280
281 std::filesystem::path file_path(file_name);
282 if (file_path.extension().empty()) {
283 file_path.replace_extension(ext);
284 file_name = file_path.string();
285 }
286#elif defined(__APPLE__)
287 nfdchar_t *outPath = nullptr;
288 std::string filterList_ = "";
289 for (std::string extension: extensions) {
290 std::string ext_lower = extension;
291 std::transform(ext_lower.begin(), ext_lower.end(), ext_lower.begin(), ::tolower);
292 filterList_ += ext_lower + ",";
293 }
294 if (!filterList_.empty() && filterList_.back() == ',')
295 filterList_.pop_back();
296 const nfdchar_t *filterList = filterList_.c_str();
297 nfdresult_t result = NFD_SaveDialog(filterList, nullptr, &outPath);
298
299 if (result == NFD_OKAY) {
300 puts("Success!");
301 puts(outPath);
302 file_name = std::string(outPath);
303 free(outPath);
304
305 std::string ext_ = extensions[0];
306 std::transform(ext_.begin(), ext_.end(), ext_.begin(), ::tolower);
307 std::string ext = "." + ext_;
308 if (file_name.find('.') == std::string::npos)
309 file_name += ext;
310 } else if (result == NFD_CANCEL) {
311 puts("User pressed cancel.");
312 } else {
313 // printf("Error: %s\n", NFD_GetError() );
314 std::cout << "Error: " << NFD_GetError() << std::endl;
315 }
316#elif defined(__linux__)
317 nfdchar_t *outPath = nullptr;
318 std::string filterList_ = "";
319 for (std::string extension: extensions) {
320 std::string ext_lower = extension;
321 std::transform(ext_lower.begin(), ext_lower.end(), ext_lower.begin(), ::tolower);
322 filterList_ += ext_lower + ",";
323 }
324 if (!filterList_.empty() && filterList_.back() == ',')
325 filterList_.pop_back();
326 const nfdchar_t *filterList = filterList_.c_str();
327 nfdresult_t result = NFD_SaveDialog(filterList, nullptr, &outPath);
328
329 if (result == NFD_OKAY) {
330 puts("Success!");
331 puts(outPath);
332 file_name = std::string(outPath);
333 free(outPath);
334
335 std::string ext_ = extensions[0];
336 std::transform(ext_.begin(), ext_.end(), ext_.begin(), ::tolower);
337 std::string ext = "." + ext_;
338 if (file_name.find('.') == std::string::npos)
339 file_name += ext;
340 } else if (result == NFD_CANCEL) {
341 puts("User pressed cancel.");
342 } else {
343 // printf("Error: %s\n", NFD_GetError() );
344 std::cout << "Error: " << NFD_GetError() << std::endl;
345 }
346#endif
347#endif
348
349 return file_name;
350}
351
352
353std::vector<std::string> get_xml_node_values(const std::string &xml_input, const std::string &name, const std::string &parent) {
354 int counter = 0;
355 pugi::xml_document xml_library_doc;
356 std::vector<std::string> labels_vec{};
357 std::string xml_library_error = "Failed to load XML Library file";
358 if (!open_xml_file(xml_input, xml_library_doc, xml_library_error)) {
359 helios_runtime_error(xml_library_error);
360 }
361 pugi::xml_node helios = xml_library_doc.child("helios");
362 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
363 std::string default_value = "";
364 if (!p.attribute(name.c_str()).empty()) {
365 const char *node_str = p.attribute(name.c_str()).value();
366 default_value = (std::string) node_str;
367 }
368 labels_vec.push_back(default_value);
369 counter++;
370 }
371 return labels_vec;
372}
373
374
375void ProjectBuilder::deleteArrows() {
376 for (auto &arrow_vec: arrow_dict) {
377 for (std::vector<uint> arrow: arrow_vec.second) {
378 context->deletePrimitive(arrow);
379 }
380 }
381 arrow_dict.clear();
382}
383
384
385void ProjectBuilder::updateArrows() {
386#ifdef ENABLE_RADIATION_MODEL
387 for (auto rig_label_: rig_labels_set) {
388 arrow_count = 0;
389 std::string current_rig = rig_label_;
390 arrow_dict[current_rig] = std::vector<std::vector<uint>>{};
391 for (int i = 1; i < camera_position_vec[rig_dict[current_rig]].size(); i++) {
392 vec3 arrow_pos = camera_position_vec[rig_dict[current_rig]][i - 1];
393 vec3 arrow_direction_vec = arrow_pos - camera_position_vec[rig_dict[current_rig]][i];
394 SphericalCoord arrow_direction_sph = cart2sphere(arrow_direction_vec);
395 vec3 arrow_scale(0.35, 0.35, 0.35);
396 arrow_dict[current_rig].push_back(context->loadOBJ("plugins/radiation/camera_light_models/Arrow.obj", nullorigin, arrow_scale, nullrotation, RGB::blue, "YUP", true));
397 context->rotatePrimitive(arrow_dict.at(current_rig)[arrow_count], arrow_direction_sph.elevation, "x");
398 context->rotatePrimitive(arrow_dict.at(current_rig)[arrow_count], -arrow_direction_sph.azimuth, "z");
399 context->translatePrimitive(arrow_dict.at(current_rig)[arrow_count], arrow_pos);
400 context->setPrimitiveData(arrow_dict.at(current_rig)[arrow_count], "twosided_flag", uint(3));
401 arrow_count++;
402 }
403 float col[3];
404 RGBcolor rig_color = rig_colors[rig_dict[current_rig]];
405 col[0] = rig_color.r;
406 col[1] = rig_color.g;
407 col[2] = rig_color.b;
408 updateColor(current_rig, "arrow", col);
409 }
410#endif
411}
412
413
414void ProjectBuilder::deleteCameraModels() {
415 for (auto &camera_model: camera_models_dict) {
416 context->deletePrimitive(camera_model.second);
417 }
418 camera_models_dict.clear();
419}
420
421
422void ProjectBuilder::updateCameraModels() {
423#ifdef ENABLE_RADIATION_MODEL
424 for (auto rig_label_: rig_labels_set) {
425 int camera_idx = rig_dict[rig_label_];
426 camera_models_dict[rig_label_] = std::vector<uint>{};
427 vec3 camera_pos = camera_position_vec[camera_idx][0];
428 vec3 camera_direction_vec = camera_lookat_vec[camera_idx][0] - camera_pos;
429 SphericalCoord camera_direction_sph = cart2sphere(camera_direction_vec);
430 vec3 camera_scale(1.0, 1.0, 1.0);
431 camera_models_dict[rig_label_] = context->loadOBJ("plugins/radiation/camera_light_models/Camera.obj", nullorigin, camera_scale, nullrotation, RGB::blue, "ZUP", true);
432 context->rotatePrimitive(camera_models_dict.at(rig_label_), camera_direction_sph.elevation, "x");
433 context->rotatePrimitive(camera_models_dict.at(rig_label_), -camera_direction_sph.azimuth, "z");
434 context->translatePrimitive(camera_models_dict.at(rig_label_), camera_pos);
435 context->setPrimitiveData(camera_models_dict.at(rig_label_), "twosided_flag", uint(3));
436 float col[3];
437 RGBcolor rig_color = rig_colors[camera_idx];
438 col[0] = rig_color.r;
439 col[1] = rig_color.g;
440 col[2] = rig_color.b;
441 updateColor(rig_label_, "camera", col);
442 }
443#endif
444}
445
446
447void ProjectBuilder::updatePrimitiveTypes() {
448 std::vector<uint> allUUIDs = context->getAllUUIDs();
449 // Clear current primitive data
450 primitive_names.clear();
451 primitive_names_set.clear();
452 primitive_UUIDs.clear();
453 // primitive_continuous.clear();
454 // primitive_values.clear();
455 // primitive_spectra.clear();
456 //
457 primitive_names.push_back("All");
458 primitive_names_set.insert("All");
459 // primitive_continuous.insert({"All", {false, false, false}});
460 // primitive_spectra.insert({"All", {reflectivity_spectrum, transmissivity_spectrum, emissivity_spectrum}});
461 for (auto &primitive_UUID: allUUIDs) {
462 std::string default_value;
463 if (context->doesPrimitiveDataExist(primitive_UUID, "object_label")) {
464 context->getPrimitiveData(primitive_UUID, "object_label", default_value);
465 if (primitive_names_set.find(default_value) == primitive_names_set.end()) {
466 primitive_names.push_back(default_value);
467 primitive_names_set.insert(default_value);
468 }
469 if (primitive_UUIDs.find(default_value) == primitive_UUIDs.end()) {
470 std::vector<uint> new_UUIDs;
471 // primitive_addresses[default_value] = &new_UUIDs;
472 primitive_UUIDs.insert({default_value, new_UUIDs});
473 }
474 primitive_UUIDs[default_value].push_back(primitive_UUID);
475 if (primitive_continuous.find(default_value) == primitive_continuous.end()) {
476 primitive_continuous.insert({default_value, {false, false, false}});
477 for (std::string band: bandlabels) {
478 primitive_values[band].insert({default_value, {reflectivity, transmissivity, emissivity}});
479 }
480 primitive_spectra.insert({default_value, {reflectivity_spectrum, transmissivity_spectrum, emissivity_spectrum}});
481 }
482 }
483 current_primitive = "All";
484 }
485 // for (auto it = bounding_boxes.begin(); it != bounding_boxes.end(); /* no increment here */) {
486 // if (primitive_names_set.find(it->first) == primitive_names_set.end()) {
487 // it = bounding_boxes.erase(it);
488 // }else {
489 // ++it;
490 // }
491 // }
492 // for (auto& prim : primitive_names_set){
493 // if (prim == "All"){
494 // continue;
495 // }
496 // if (bounding_boxes.find(prim) == bounding_boxes.end()){
497 // bounding_boxes[prim] = false;
498 // }
499 // }
500 // context->setPrimitiveData
501 // context->setPrimitiveData(); type uint or int
502}
503
504
505void ProjectBuilder::updateDataGroups() {
506 data_groups_set.clear();
507 data_groups_set.insert("All");
508 std::vector<uint> all_UUIDs = context->getAllUUIDs();
509 for (uint UUID: all_UUIDs) {
510 std::string curr_data_group = "";
511 if (!context->doesPrimitiveDataExist(UUID, "data_group"))
512 continue;
513 context->getPrimitiveData(UUID, "data_group", curr_data_group);
514 if (!curr_data_group.empty()) {
515 data_groups_set.insert(curr_data_group);
516 }
517 }
518 for (std::string data_group: data_groups_set) { // initialize new data_groups if necessary
519 if (primitive_continuous_dict.find(data_group) == primitive_continuous_dict.end()) {
520 primitive_continuous_dict[data_group] = primitive_continuous;
521 }
522 if (primitive_spectra_dict.find(data_group) == primitive_spectra_dict.end()) {
523 primitive_spectra_dict[data_group] = primitive_spectra;
524 }
525 if (primitive_values_dict.find(data_group) == primitive_values_dict.end()) {
526 primitive_values_dict[data_group] = primitive_values;
527 }
528 }
529}
530
531
533 for (std::pair<std::string, std::vector<uint>> primitive_pair: primitive_UUIDs) {
534 if (primitive_continuous[primitive_pair.first].empty())
535 continue;
536 if (!primitive_continuous[primitive_pair.first][0]) {
537 for (std::string band: bandlabels) {
538 float reflectivity = primitive_values[band][primitive_pair.first][0];
539 std::string reflectivity_band = "reflectivity_" + band;
540 context->setPrimitiveData(primitive_pair.second, reflectivity_band.c_str(), reflectivity);
541 }
542 } else {
543 std::string reflectivity_spectrum = primitive_spectra[primitive_pair.first][0];
544 if (!reflectivity_spectrum.empty()) {
545 context->setPrimitiveData(primitive_UUIDs[primitive_pair.first], "reflectivity_spectrum", reflectivity_spectrum);
546 } else {
547 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;
548 }
549 }
550 if (!primitive_continuous[primitive_pair.first][1]) {
551 for (std::string band: bandlabels) {
552 float transmissivity = primitive_values[band][primitive_pair.first][1];
553 std::string transmissivity_band = "transmissivity_" + band;
554 context->setPrimitiveData(primitive_pair.second, transmissivity_band.c_str(), transmissivity);
555 }
556 } else {
557 std::string transmissivity_spectrum = primitive_spectra[primitive_pair.first][1];
558 if (!transmissivity_spectrum.empty()) {
559 context->setPrimitiveData(primitive_UUIDs[primitive_pair.first], "transmissivity_spectrum", transmissivity_spectrum);
560 } else {
561 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;
562 }
563 }
564 if (!primitive_continuous[primitive_pair.first][2]) {
565 for (std::string band: bandlabels) {
566 if (bandlabels_set_emissivity.find(band) != bandlabels_set_emissivity.end())
567 continue;
568 float emissivity = primitive_values[band][primitive_pair.first][2];
569 std::string emissivity_band = "emissivity_" + band;
570 context->setPrimitiveData(primitive_pair.second, emissivity_band.c_str(), emissivity);
571 }
572 } else {
573 std::string emissivity_spectrum = primitive_spectra[primitive_pair.first][2];
574 if (!emissivity_spectrum.empty()) {
575 context->setPrimitiveData(primitive_UUIDs[primitive_pair.first], "emissivity_spectrum", emissivity_spectrum);
576 } else {
577 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;
578 }
579 }
580 }
581 std::vector<uint> all_UUIDs = context->getAllUUIDs();
582 for (uint UUID: all_UUIDs) {
583 if (!context->doesPrimitiveDataExist(UUID, "data_group"))
584 continue;
585 // Get data group of UUID
586 std::string curr_data_group;
587 context->getPrimitiveData(UUID, "data_group", curr_data_group);
588 // Get primitive type of UUID
589 std::string curr_prim_type;
590 if (context->doesPrimitiveDataExist(UUID, "object_label")) {
591 context->getPrimitiveData(UUID, "object_label", curr_prim_type);
592 } else {
593 curr_prim_type = "All";
594 }
595 if (primitive_continuous_dict[curr_data_group][curr_prim_type].empty())
596 continue;
597 if (!primitive_continuous_dict[curr_data_group][curr_prim_type][0]) {
598 for (std::string band: bandlabels) {
599 float reflectivity = primitive_values_dict[curr_data_group][band][curr_prim_type][0];
600 std::string reflectivity_band = "reflectivity_" + band;
601 context->setPrimitiveData(UUID, reflectivity_band.c_str(), reflectivity);
602 }
603 } else {
604 std::string reflectivity_spectrum = primitive_spectra_dict[curr_data_group][curr_prim_type][0];
605 if (!reflectivity_spectrum.empty()) {
606 context->setPrimitiveData(UUID, "reflectivity_spectrum", reflectivity_spectrum);
607 } else {
608 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;
609 }
610 }
611 if (!primitive_continuous_dict[curr_data_group][curr_prim_type][1]) {
612 for (std::string band: bandlabels) {
613 float transmissivity = primitive_values_dict[curr_data_group][band][curr_prim_type][1];
614 std::string transmissivity_band = "transmissivity_" + band;
615 context->setPrimitiveData(UUID, transmissivity_band.c_str(), transmissivity);
616 }
617 } else {
618 std::string transmissivity_spectrum = primitive_spectra_dict[curr_data_group][curr_prim_type][1];
619 if (!transmissivity_spectrum.empty()) {
620 context->setPrimitiveData(UUID, "transmissivity_spectrum", transmissivity_spectrum);
621 } else {
622 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;
623 }
624 }
625 if (!primitive_continuous_dict[curr_data_group][curr_prim_type][2]) {
626 for (std::string band: bandlabels) {
627 if (bandlabels_set_emissivity.find(band) != bandlabels_set_emissivity.end())
628 continue;
629 float emissivity = primitive_values_dict[curr_data_group][band][curr_prim_type][2];
630 std::string emissivity_band = "emissivity_" + band;
631 context->setPrimitiveData(UUID, emissivity_band.c_str(), emissivity);
632 }
633 } else {
634 std::string emissivity_spectrum = primitive_spectra_dict[curr_data_group][curr_prim_type][2];
635 if (!emissivity_spectrum.empty()) {
636 context->setPrimitiveData(UUID, "emissivity_spectrum", emissivity_spectrum);
637 } else {
638 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;
639 }
640 }
641 }
642#ifdef ENABLE_RADIATION_MODEL
644#endif
645}
646
648#ifdef ENABLE_RADIATION_MODEL
649 for (std::string rig_label: rig_labels_set) {
650 int rig_index = rig_dict[rig_label];
651 for (std::string rig_camera_label: rig_camera_labels[rig_index]) {
652 int camera_index = camera_dict[rig_camera_label];
653
654 /* Load properties of camera */
656 cameraproperties->camera_resolution = camera_resolutions[camera_index];
657 cameraproperties->focal_plane_distance = focal_plane_distances[camera_index];
658 cameraproperties->lens_diameter = lens_diameters[camera_index];
659 cameraproperties->FOV_aspect_ratio = FOV_aspect_ratios[camera_index];
660 cameraproperties->HFOV = HFOVs[camera_index];
661
662 /* Create new camera */
663 std::string camera_label_ = rig_label + "_" + rig_camera_label;
664 vec3 camera_position_ = camera_positions[rig_index];
665 vec3 camera_lookat_ = camera_lookats[rig_index];
666 radiation->addRadiationCamera(camera_label_, bandlabels, camera_position_, camera_lookat_, *cameraproperties, 100);
667 for (auto &band: bandlabels) {
668 radiation->setCameraSpectralResponse(camera_label_, band, camera_calibrations[camera_index][band]);
669 }
671 }
672 }
673 for (std::string band_group_name: band_group_names) {
674 bandGroup curr_band_group = band_group_lookup[band_group_name];
675 if (!curr_band_group.grayscale) {
676 radiation->runBand(curr_band_group.bands);
677 } else {
678 radiation->runBand(std::vector<std::string>{curr_band_group.bands[0]});
679 }
680 }
681#endif // RADIATION_MODEL
682}
683
685#ifdef ENABLE_RADIATION_MODEL
686 deleteArrows();
687 deleteCameraModels();
688 randomize(true);
690 for (int _ = 0; _ < num_recordings; _++) {
692 // std::time_t now = std::time(nullptr);
693 // std::tm* tm_ptr = std::localtime(&now);
694 // std::ostringstream oss;
695 // oss << std::put_time(tm_ptr, "%Y-%m-%d %H:%M:%S");
696 // std::string image_dir = "./saved-" + oss.str() + "/";
697 // std::filesystem::create_directory("saved-" + oss.str());
698 std::string image_dir = "./saved/";
699 std::string image_dir_base = "./saved_";
700 int image_dir_idx = 0;
701 while (std::filesystem::exists(image_dir)) {
702 image_dir = image_dir_base + std::to_string(image_dir_idx) + "/";
703 image_dir_idx++;
704 }
705 std::filesystem::create_directory(image_dir);
706 std::cout << "Saving images to " << image_dir << std::endl;
707 // Create classes.names file
708 std::ofstream classes_names_file(image_dir + "classes.names");
709 if (classes_names_file.is_open()) {
710 std::vector<std::string> classes(bounding_boxes_map.size());
711 for (auto &bbox_pair: bounding_boxes_map) {
712 classes[bbox_pair.second] = bbox_pair.first;
713 }
714 for (std::string cls: classes) {
715 classes_names_file << cls << std::endl;
716 }
717 }
718 //
719 std::vector<uint> temp_lights{};
720 for (std::string rig_label: rig_labels_set) {
721 int rig_index = rig_dict[rig_label];
722 std::vector<vec3> interpolated_camera_positions = interpolate(keypoint_frames[rig_index], camera_position_vec[rig_index], num_images_vec[rig_index]);
723 std::vector<vec3> interpolated_camera_lookats = interpolate(keypoint_frames[rig_index], camera_lookat_vec[rig_index], num_images_vec[rig_index]);
724 // ADD RIG LIGHTS
725 for (std::string light: rig_light_labels[rig_dict[rig_label]]) {
726 int light_idx = light_dict[light];
727 uint new_light_UUID;
728 if (light_types[light_idx] == "sphere") {
729 new_light_UUID = radiation->addSphereRadiationSource(interpolated_camera_positions[0], light_radius_vec[light_idx]);
730 temp_lights.push_back(new_light_UUID);
731 } else if (light_types[light_dict[light]] == "rectangle") {
732 new_light_UUID = radiation->addRectangleRadiationSource(interpolated_camera_positions[0], light_size_vec[light_idx], light_rotation_vec[light_idx]);
733 temp_lights.push_back(new_light_UUID);
734 } else if (light_types[light_dict[light]] == "disk") {
735 new_light_UUID = radiation->addDiskRadiationSource(interpolated_camera_positions[0], light_radius_vec[light_idx], light_rotation_vec[light_idx]);
736 temp_lights.push_back(new_light_UUID);
737 }
738 for (auto &band: bandlabels) {
739 radiation->setSourceFlux(new_light_UUID, band, light_flux_vec[light_idx]);
740 }
741 }
742 // radiation->updateGeometry(); // TODO: figure out why we can't move updateGeometry here
743 // radiation->setSourceFlux(light_UUID, band, flux_value)
744 //
745 for (int i = 0; i < interpolated_camera_positions.size(); i++) {
746 // SET LIGHT POSITIONS
747 for (uint light_ID: temp_lights) {
748 radiation->setSourcePosition(light_ID, interpolated_camera_positions[i]);
749 }
750 // radiation->setSourceFlux(light_UUID, band, flux_value)
751 //
752 for (std::string rig_camera_label: rig_camera_labels[rig_index]) {
753 int camera_index = camera_dict[rig_camera_label];
754 std::string cameralabel = rig_label + "_" + rig_camera_label;
755 radiation->setCameraPosition(cameralabel, interpolated_camera_positions[i]);
756 radiation->setCameraLookat(cameralabel, interpolated_camera_lookats[i]);
757 }
759 for (std::string band_group_name: band_group_names) {
760 bandGroup curr_band_group = band_group_lookup[band_group_name];
761 if (!curr_band_group.grayscale) {
762 radiation->runBand(curr_band_group.bands);
763 } else {
764 radiation->runBand(std::vector<std::string>{curr_band_group.bands[0]});
765 }
766 }
767 for (std::string rig_camera_label: rig_camera_labels[rig_index]) {
768 std::string cameralabel = rig_label + "_" + rig_camera_label;
769 // Write Images
770 for (std::string band_group_name: band_group_names) {
771 bandGroup curr_band_group = band_group_lookup[band_group_name];
772 std::vector<std::string> band_group_vec;
773 if (!curr_band_group.grayscale) {
774 band_group_vec = curr_band_group.bands;
775 } else {
776 band_group_vec = std::vector<std::string>{curr_band_group.bands[0]};
777 }
778 radiation->writeCameraImage(cameralabel, band_group_vec, band_group_name + std::to_string(i), image_dir + rig_label + '/');
779 if (band_group_lookup[band_group_name].norm) {
780 radiation->writeNormCameraImage(cameralabel, band_group_vec, band_group_name + "_norm" + std::to_string(i), image_dir + rig_label + '/');
781 }
782 }
783 if (write_depth[rig_dict[current_rig]])
784 radiation->writeDepthImageData(cameralabel, "depth" + std::to_string(i), image_dir + rig_label + '/');
785 if (write_norm_depth[rig_dict[current_rig]])
786 radiation->writeNormDepthImage(cameralabel, "normdepth" + std::to_string(i), 3, image_dir + rig_label + '/');
787 //
788 // Bounding boxes for all primitive types
789 for (std::string band_group_: band_group_names) {
790 for (std::string primitive_name: primitive_names) {
791 if (!primitive_name.empty()) {
792 primitive_name[0] = std::tolower(static_cast<unsigned char>(primitive_name[0]));
793 }
794 }
795 for (auto &box_pair: bounding_boxes_map)
796 radiation->writeImageBoundingBoxes_ObjectData(cameralabel, box_pair.first, box_pair.second, band_group_ + std::to_string(i), image_dir + rig_label + '/', true);
797 }
798 //
799 }
800 }
801 // REMOVE RIG LIGHTS
802 for (uint temp_light: temp_lights) {
803 radiation->deleteRadiationSource(temp_light);
804 }
805 temp_lights.clear();
806 //
807 }
808 randomize(false);
809 }
810 updateArrows();
811 updateCameraModels();
813#endif // RADIATION_MODEL
814}
815
817 context = new Context();
818
819// if (enable_plantarchitecture){
820#ifdef ENABLE_PLANT_ARCHITECTURE
822#ifdef ENABLE_RADIATION_MODEL
823 plantarchitecture->optionalOutputObjectData(std::vector<std::string>{"plantID", "leafID", "peduncleID", "closedflowerID", "openflowerID", "fruitID", "rank", "age", "carbohydrate_concentration"});
824#endif
825 std::cout << "Loaded PlantArchitecture plugin." << std::endl;
826// }else{
827#else
828 std::cout << "Excluding PlantArchitecture plugin." << std::endl;
829// } //PLANT_ARCHITECTURE
830#endif // PLANT_ARCHITECTURE
831
832 InitializeSimulation(xml_input_file, context);
833
834// if (enable_plantarchitecture){
835#ifdef ENABLE_PLANT_ARCHITECTURE
836 BuildGeometry(xml_input_file, plantarchitecture, context, canopy_IDs, individual_plant_locations);
837 context->getGlobalData("ground_UUIDs", ground_UUIDs);
838// } //PLANT_ARCHITECTURE
839#endif // PLANT_ARCHITECTURE
840
841// if (enable_radiation){
842#ifdef ENABLE_RADIATION_MODEL
844 std::cout << "Loaded Radiation plugin." << std::endl;
845// }else{
846#else
847 std::cout << "Excluding Radiation plugin." << std::endl;
848// } //RADIATION_MODEL
849#endif // RADIATION_MODEL
850
851// if (enable_solarposition){
852#ifdef ENABLE_SOLARPOSITION
854 std::cout << "Loaded SolarPosition plugin." << std::endl;
855// }else{
856#else
857 std::cout << "Excluding SolarPosition plugin." << std::endl;
858// } //SOLARPOSITION
859#endif // SOLARPOSITION
860
861// if (enable_radiation){
862#ifdef ENABLE_RADIATION_MODEL
863 InitializeRadiation(xml_input_file, solarposition, radiation, context);
864// } //RADIATION_MODEL
865#endif // RADIATION_MODEL
866
867// if (enable_energybalance){
868#ifdef ENABLE_ENERGYBALANCEMODEL
870 std::cout << "Loaded EnergyBalance plugin." << std::endl;
871// }else{
872#else
873 std::cout << "Excluding EnergyBalance plugin." << std::endl;
874// } //ENERGYBALANCEMODEL
875#endif // ENERGYBALANCEMODEL
876
877// if (enable_blconductance){
878#ifdef ENABLE_BOUNDARYLAYERCONDUCTANCEMODEL
880 std::cout << "Loaded BoundaryLayerConductance plugin." << std::endl;
881// }else{
882#else
883 std::cout << "Excluding BoundaryLayerConductance plugin." << std::endl;
884// } //BOUNDARYLAYERCONDUCTANCEMODEL
885#endif // BOUNDARYLAYERCONDUCTANCEMODEL
886
887// if (enable_blconductance && enable_energybalance){
888#if defined(ENABLE_ENERGYBALANCEMODEL) && defined(ENABLE_BOUNDARYLAYERCONDUCTANCEMODEL)
889 InitializeEnergyBalance(xml_input_file, boundarylayerconductance, energybalancemodel, context);
890// } //BOUNDARYLAYERCONDUCTANCEMODE && ENERGYBALANCEMODEL
891#endif // BOUNDARYLAYERCONDUCTANCEMODE && ENERGYBALANCEMODEL
892
893#ifdef ENABLE_CANOPY_GENERATOR
895 std::cout << "Loaded CanopyGenerator plugin." << std::endl;
896// }else{
897#else
898 std::cout << "Excluding CanopyGenerator plugin." << std::endl;
899// } //CANOPYGENERATOR
900#endif // CANOPYGENERATOR
901
902 // -- main time loop -- //
903 if (enable_radiation) {
904 assert(context->doesGlobalDataExist("air_turbidity"));
905 context->getGlobalData("air_turbidity", turbidity);
906 }
907
908 if (enable_radiation) {
909 assert(context->doesGlobalDataExist("diffuse_extinction_coeff"));
910 context->getGlobalData("diffuse_extinction_coeff", diffuse_extinction_coeff);
911 }
912
913 if (enable_radiation) {
914 assert(context->doesGlobalDataExist("sun_ID"));
915 context->getGlobalData("sun_ID", sun_ID);
916 }
917
918 // bandlabels = {"red", "green", "blue"};
919
920 if (enable_plantarchitecture) {
921 context->getGlobalData("ground_UUIDs", ground_UUIDs);
922 context->getGlobalData("leaf_UUIDs", leaf_UUIDs);
923
924 primitive_UUIDs["ground"] = ground_UUIDs;
925 primitive_UUIDs["leaf"] = leaf_UUIDs;
926 // assert( !ground_UUIDs.empty() );
927 // assert( !leaf_UUIDs.empty() );
928 context->setPrimitiveData(ground_UUIDs, "object_label", "ground");
929 context->setPrimitiveData(leaf_UUIDs, "object_label", "leaf");
930 }
931
932 // Update reflectivity, transmissivity, & emissivity for each band / primitive_type
933 if (!open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
934 helios_runtime_error(xml_error_string);
935 }
936 xmlGetValues();
937 updateGround(); // TODO: add repeat ground to buildGeometry
938 updatePrimitiveTypes();
939 updateSpectra(); // TODO: add update geometry at end
940
941 ground_area = context->sumPrimitiveSurfaceArea(ground_UUIDs);
942
943 timeseries_variables = context->listTimeseriesVariables();
944
945 if (timeseries_variables.empty()) {
946 std::cout << "No timeseries data was loaded. Skipping time loop." << std::endl;
947 } else {
948
949 uint num_time_points = context->getTimeseriesLength(timeseries_variables.front().c_str());
950 for (uint timestep = 0; timestep < num_time_points; timestep++) {
951
952 context->setCurrentTimeseriesPoint(timeseries_variables.front().c_str(), timestep);
953
954 std::cout << "Timestep " << timestep << ": " << context->getDate() << " " << context->getTime() << std::endl;
955
956 if (context->doesTimeseriesVariableExist("air_temperature")) {
957 air_temperature = context->queryTimeseriesData("air_temperature", timestep);
958 }
959 context->setPrimitiveData(context->getAllUUIDs(), "air_temperature", air_temperature);
960
961 if (context->doesTimeseriesVariableExist("air_humidity")) {
962 air_humidity = context->queryTimeseriesData("air_humidity", timestep);
963 if (air_humidity > 1) {
964 // try dividing by 100
965 air_humidity /= 100.f;
966 if (air_humidity > 1) {
967 std::cout << "WARNING: air_humidity must be between 0 and 1. Setting to default value of 0.5." << std::endl;
968 air_humidity = 0.5f;
969 } else {
970 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;
971 }
972 }
973 }
974 context->setPrimitiveData(context->getAllUUIDs(), "air_humidity", air_humidity);
975
976// if (enable_solarposition && enable_radiation){
977#ifdef ENABLE_RADIATION_MODEL
978 sun_dir_vec = solarposition->getSunDirectionVector();
979
980 radiation->setSourcePosition(sun_ID, sun_dir_vec);
981
982 if (diffuse_extinction_coeff > 0) {
983 radiation->setDiffuseRadiationExtinctionCoeff("PAR", diffuse_extinction_coeff, sun_dir_vec);
984 radiation->setDiffuseRadiationExtinctionCoeff("NIR", diffuse_extinction_coeff, sun_dir_vec);
985 }
986
987 R_PAR_dir = solarposition->getSolarFluxPAR(101000, air_temperature, air_humidity, turbidity);
988 R_NIR_dir = solarposition->getSolarFluxNIR(101000, air_temperature, air_humidity, turbidity);
989 fdiff = solarposition->getDiffuseFraction(101000, air_temperature, air_humidity, turbidity);
990
991 radiation->setSourceFlux(sun_ID, "PAR", R_PAR_dir * (1.f - fdiff));
992 radiation->setDiffuseRadiationFlux("PAR", R_PAR_dir * fdiff);
993 radiation->setSourceFlux(sun_ID, "NIR", R_NIR_dir * (1.f - fdiff));
994 radiation->setDiffuseRadiationFlux("NIR", R_NIR_dir * fdiff);
995
996 // Run the radiation model
997 radiation->runBand({"PAR", "NIR", "LW"});
998// } //SOLARPOSITION && RADIATION_MODEL
999#endif // SOLARPOSITION && RADIATION_MODEL
1000
1001 context->calculatePrimitiveDataAreaWeightedSum(leaf_UUIDs, "radiation_flux_PAR", PAR_absorbed);
1002 PAR_absorbed /= ground_area;
1003
1004 context->calculatePrimitiveDataAreaWeightedSum(leaf_UUIDs, "radiation_flux_NIR", NIR_absorbed);
1005 NIR_absorbed /= ground_area;
1006
1007 context->calculatePrimitiveDataAreaWeightedSum(leaf_UUIDs, "radiation_flux_LW", LW_absorbed);
1008 LW_absorbed /= ground_area;
1009
1010 std::cout << "Absorbed PAR: " << PAR_absorbed << " W/m^2" << std::endl;
1011 std::cout << "Absorbed NIR: " << NIR_absorbed << " W/m^2" << std::endl;
1012 std::cout << "Absorbed LW: " << LW_absorbed << " W/m^2" << std::endl;
1013 }
1014 // RIG BLOCK
1015 // *** Loading any XML files needed for cameras *** //
1016 for (auto &xml_file: camera_xml_library_files) {
1017 if (xml_file.empty() || !std::filesystem::exists(xml_file)) {
1018 std::cout << "WARNING: Could not find camera XML library file: " + xml_file << ". Skipping..." << std::endl;
1019 continue;
1020 }
1021 context->loadXML(xml_file.c_str());
1022 }
1023 // *** Loading any XML files needed for lights *** //
1024 for (auto &xml_file: light_xml_library_files) {
1025 if (xml_file.empty() || !std::filesystem::exists(xml_file)) {
1026 std::cout << "WARNING: Could not find light XML library file: " + xml_file << ". Skipping..." << std::endl;
1027 continue;
1028 }
1029 context->loadXML(xml_file.c_str());
1030 }
1031
1032// if (enable_solarposition && enable_radiation){
1033#ifdef ENABLE_RADIATION_MODEL
1034
1035 radiation->setSourceSpectrum(sun_ID, solar_direct_spectrum);
1036
1038 radiation->disableEmission("red");
1039 // radiation->setSourceFlux(sun_ID, "red", 2.f);
1040 radiation->setScatteringDepth("red", 2);
1041
1042 radiation->copyRadiationBand("red", "green");
1043 radiation->copyRadiationBand("red", "blue");
1044
1045 radiation->enforcePeriodicBoundary("xy"); // TODO: make this a user setting
1046// } //SOLARPOSITION && RADIATION_MODEL
1047#endif // SOLARPOSITION && RADIATION_MODEL
1048 }
1049 // RIG BLOCK
1050 num_images = 5;
1051 updateArrows();
1052 updateCameras();
1053 updateCameraModels();
1054
1055 helios = xmldoc.child("helios");
1056
1057 refreshVisualizationTypes();
1058
1059 built = true;
1060}
1061
1062
1063void ProjectBuilder::buildFromXML(std::string xml_path) {
1064 xml_input_file = xml_path;
1065 buildFromXML();
1066}
1067
1068
1069std::map<std::string, int> ProjectBuilder::getNodeLabels(const std::string &name, const std::string &parent, std::vector<std::string> &labels_vec) {
1070 int counter = 0;
1071 std::map<std::string, int> labels_dict = {};
1072 helios = xmldoc.child("helios");
1073 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1074 std::string default_value = "canopy_0";
1075 if (!p.attribute(name.c_str()).empty()) {
1076 const char *node_str = p.attribute(name.c_str()).value();
1077 default_value = (std::string) node_str;
1078 }
1079 labels_vec.push_back(default_value);
1080 labels_dict.insert({default_value, counter});
1081 counter++;
1082 }
1083 return labels_dict;
1084}
1085
1086
1087void ProjectBuilder::getKeypoints(const std::string &name, const std::string &parent, std::vector<std::vector<int>> &keypoints) {
1088 helios = xmldoc.child("helios");
1089 const char *rig_ = "rig";
1090 for (pugi::xml_node rig = helios.child(rig_); rig; rig = rig.next_sibling(rig_)) {
1091 int count = 0;
1092 std::vector<int> curr_keypoints;
1093 for (pugi::xml_node p = rig.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1094 std::string default_value = std::to_string(count);
1095 if (!p.attribute(name.c_str()).empty()) {
1096 const char *node_str = p.attribute(name.c_str()).value();
1097 default_value = (std::string) node_str;
1098 }
1099 std::stringstream keypoint_value;
1100 keypoint_value << default_value.c_str();
1101 int keypoint_;
1102 keypoint_value >> keypoint_;
1103 curr_keypoints.push_back(keypoint_);
1104 count++;
1105 }
1106 keypoints.push_back(curr_keypoints);
1107 }
1108}
1109
1110void ProjectBuilder::setKeypoints(const std::string &name, const std::string &parent, std::vector<std::vector<int>> &keypoints) {
1111 helios = xmldoc.child("helios");
1112 const char *rig_ = "rig";
1113 int rig_count = 0;
1114 for (pugi::xml_node rig = helios.child(rig_); rig; rig = rig.next_sibling(rig_)) {
1115 int count = 0;
1116 for (pugi::xml_node p = rig.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1117 std::string default_value = std::to_string(count);
1118 p.append_attribute(name.c_str());
1119 p.attribute(name.c_str()).set_value(keypoints[rig_count][count]);
1120 count++;
1121 }
1122 rig_count++;
1123 }
1124} // TODO: test this function
1125
1126void ProjectBuilder::xmlGetValue(const std::string &name, const std::string &parent, int &default_value) {
1127 helios = xmldoc.child("helios");
1128 pugi::xml_node p = helios;
1129 if (parent != "helios") {
1130 p = helios.child(parent.c_str());
1131 }
1132 pugi::xml_node node;
1133 node = p.child(name.c_str());
1134 if (node.empty()) {
1135 std::cout << "WARNING: No value given for '" << name << "'. Using default value of " << default_value << std::endl;
1136 } else {
1137 const char *node_str = node.child_value();
1138 if (!parse_int(node_str, default_value)) {
1139 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1140 } else if (default_value < 0) {
1141 helios_runtime_error("ERROR: Value given for '" + name + "' must be greater than or equal to 0.");
1142 }
1143 }
1144}
1145
1146void ProjectBuilder::xmlGetValue(const std::string &name, const std::string &parent, float &default_value) {
1147 helios = xmldoc.child("helios");
1148 pugi::xml_node p = helios;
1149 if (parent != "helios") {
1150 p = helios.child(parent.c_str());
1151 }
1152 pugi::xml_node node;
1153 node = p.child(name.c_str());
1154 if (node.empty()) {
1155 std::cout << "WARNING: No value given for '" << name << "'. Using default value of " << default_value << std::endl;
1156 } else {
1157 const char *node_str = node.child_value();
1158 if (!parse_float(node_str, default_value)) {
1159 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1160 }
1161 // else if( default_value<0 ){
1162 // helios_runtime_error("ERROR: Value given for '" + name + "' must be greater than or equal to 0.");
1163 // }
1164 }
1165}
1166
1167void ProjectBuilder::xmlGetValue(const std::string &name, const std::string &parent, std::string &default_value) {
1168 helios = xmldoc.child("helios");
1169 pugi::xml_node p = helios;
1170 if (parent != "helios") {
1171 p = helios.child(parent.c_str());
1172 }
1173 pugi::xml_node node;
1174 node = p.child(name.c_str());
1175 if (node.empty()) {
1176 std::cout << "WARNING: No value given for '" << name << "'. Using default value of " << default_value << std::endl;
1177 } else {
1178 const char *node_str = node.child_value();
1179 default_value = node_str;
1180 }
1181}
1182
1183void ProjectBuilder::xmlGetValue(const std::string &name, const std::string &parent, vec2 &default_value) {
1184 helios = xmldoc.child("helios");
1185 pugi::xml_node p = helios;
1186 if (parent != "helios") {
1187 p = helios.child(parent.c_str());
1188 }
1189 pugi::xml_node node;
1190 node = p.child(name.c_str());
1191 if (node.empty()) {
1192 std::cout << "WARNING: No value given for '" << name << "'. Using default value of " << default_value << std::endl;
1193 } else {
1194 const char *node_str = node.child_value();
1195 if (!parse_vec2(node_str, default_value)) {
1196 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1197 } else if (default_value.x <= 0 || default_value.y <= 0) {
1198 helios_runtime_error("ERROR: Value given for '" + name + "' must be greater than 0.");
1199 }
1200 }
1201}
1202
1203void ProjectBuilder::xmlGetValue(const std::string &name, const std::string &parent, vec3 &default_value) {
1204 helios = xmldoc.child("helios");
1205 pugi::xml_node p = helios;
1206 if (parent != "helios") {
1207 p = helios.child(parent.c_str());
1208 }
1209 pugi::xml_node node;
1210 node = p.child(name.c_str());
1211 if (node.empty()) {
1212 std::cout << "WARNING: No value given for '" << name << "'. Using default value of " << default_value << std::endl;
1213 } else {
1214 const char *node_str = node.child_value();
1215 if (!parse_vec3(node_str, default_value)) {
1216 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1217 }
1218 }
1219}
1220
1221
1222void ProjectBuilder::xmlGetValue(const std::string &name, const std::string &parent, int2 &default_value) {
1223 helios = xmldoc.child("helios");
1224 pugi::xml_node p = helios;
1225 if (parent != "helios") {
1226 p = helios.child(parent.c_str());
1227 }
1228 pugi::xml_node node;
1229 node = p.child(name.c_str());
1230 if (node.empty()) {
1231 std::cout << "WARNING: No value given for '" << name << "'. Using default value of " << default_value << std::endl;
1232 } else {
1233 const char *node_str = node.child_value();
1234 if (!parse_int2(node_str, default_value)) {
1235 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1236 } else if (default_value.x <= 0 || default_value.y <= 0) {
1237 helios_runtime_error("ERROR: Value given for '" + name + "' must be greater than 0.");
1238 }
1239 }
1240}
1241
1242
1243void ProjectBuilder::xmlGetDistribution(const std::string &name, const std::string &parent, distribution &distribution) {
1244 helios = xmldoc.child("helios");
1245 pugi::xml_node p = helios;
1246 if (parent != "helios") {
1247 p = helios.child(parent.c_str());
1248 }
1249 pugi::xml_node node;
1250 node = p.child(name.c_str());
1251 if (node.empty()) {
1252 std::cout << "WARNING: No distribution given for '" << name << "'. Using default distribution of N/A." << std::endl;
1253 distribution.flag = -1;
1254 } else {
1255 const char *node_str = node.child_value();
1256 if (!parse_distribution(node_str, distribution)) {
1257 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1258 }
1259 }
1260}
1261
1262
1263void ProjectBuilder::xmlSetDistribution(const std::string &name, const std::string &parent, distribution &distribution) {
1264 helios = xmldoc.child("helios");
1265 pugi::xml_node p = helios;
1266 if (parent != "helios") {
1267 p = helios.child(parent.c_str());
1268 }
1269 pugi::xml_node node;
1270 node = p.child(name.c_str());
1271 if (!node) {
1272 node = p.append_child(name.c_str());
1273 }
1274 std::string dist_type;
1275 std::string param_1;
1276 std::string param_2;
1277 std::string repeat;
1278 if (distribution.flag == 0) {
1279 dist_type = "normal";
1280 param_1 = std::to_string(distribution.dist.normal->mean());
1281 param_2 = std::to_string(distribution.dist.normal->stddev());
1282 repeat = std::to_string(distribution.repeat);
1283 } else if (distribution.flag == 1) {
1284 dist_type = "uniform";
1285 param_1 = std::to_string(distribution.dist.uniform->a());
1286 param_2 = std::to_string(distribution.dist.uniform->b());
1287 repeat = std::to_string(distribution.repeat);
1288 } else if (distribution.flag == 2) {
1289 dist_type = "weibull";
1290 param_1 = std::to_string(distribution.dist.weibull->a());
1291 param_2 = std::to_string(distribution.dist.weibull->b());
1292 repeat = std::to_string(distribution.repeat);
1293 } else if (distribution.flag == -1) {
1294 dist_type = "N/A";
1295 param_1 = "0";
1296 param_2 = "0";
1297 repeat = "0";
1298 }
1299 node.text().set((dist_type + " " + param_1 + " " + param_2 + " " + repeat).c_str());
1300}
1301
1302
1303bool parse_distribution(const std::string &input_string, distribution &converted_distribution) {
1304 std::istringstream vecstream(input_string);
1305 std::vector<std::string> tmp_s(4);
1306 vecstream >> tmp_s[0];
1307 vecstream >> tmp_s[1];
1308 vecstream >> tmp_s[2];
1309 vecstream >> tmp_s[3];
1310 std::string dist_type;
1311 std::vector<float> dist_params = {0.0, 0.0};
1312 int repeat = 0;
1313 if (!parse_float(tmp_s[1], dist_params[0]) || !parse_float(tmp_s[2], dist_params[1]) || !parse_int(tmp_s[3], repeat)) {
1314 return false;
1315 }
1316 distUnion dist{};
1317 if (dist_type == "normal") {
1318 dist.normal = new std::normal_distribution<float>;
1319 *dist.normal = std::normal_distribution<float>(dist_params[0], dist_params[1]);
1320 converted_distribution.dist = dist;
1321 converted_distribution.flag = 0;
1322 converted_distribution.repeat = (bool) repeat;
1323 } else if (dist_type == "uniform") {
1324 dist.uniform = new std::uniform_real_distribution<float>;
1325 *dist.uniform = std::uniform_real_distribution<float>(dist_params[0], dist_params[1]);
1326 converted_distribution.dist = dist;
1327 converted_distribution.flag = 1;
1328 converted_distribution.repeat = (bool) repeat;
1329 } else if (dist_type == "weibull") {
1330 dist.weibull = new std::weibull_distribution<float>;
1331 *dist.weibull = std::weibull_distribution<float>(dist_params[0], dist_params[1]);
1332 converted_distribution.dist = dist;
1333 converted_distribution.flag = 2;
1334 converted_distribution.repeat = (bool) repeat;
1335 } else {
1336 converted_distribution.flag = -1;
1337 }
1338 return true;
1339}
1340
1341
1342void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<vec2> &default_vec) {
1343 helios = xmldoc.child("helios");
1344 pugi::xml_node node;
1345 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1346 node = p.child(name.c_str());
1347 if (node.empty()) {
1348 std::cout << "WARNING: No value given for '" << name << "'.";
1349 } else {
1350 const char *node_str = node.child_value();
1351 vec2 default_value;
1352 if (!parse_vec2(node_str, default_value)) {
1353 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1354 }
1355 // else if( default_value.x<=0 || default_value.y<=0 ){
1356 // helios_runtime_error("ERROR: Value given for '" + name + "' must be greater than 0.");
1357 // }
1358 else {
1359 default_vec.push_back(default_value);
1360 }
1361 }
1362 }
1363}
1364
1365
1366void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<vec3> &default_vec) {
1367 helios = xmldoc.child("helios");
1368 pugi::xml_node node;
1369 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1370 node = p.child(name.c_str());
1371 if (node.empty()) {
1372 std::cout << "WARNING: No value given for '" << name << "'.";
1373 } else {
1374 const char *node_str = node.child_value();
1375 vec3 default_value;
1376 if (!parse_vec3(node_str, default_value)) {
1377 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1378 } else {
1379 default_vec.push_back(default_value);
1380 }
1381 }
1382 }
1383}
1384
1385
1386void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<std::string> &default_vec) {
1387 helios = xmldoc.child("helios");
1388 pugi::xml_node node;
1389 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1390 node = p.child(name.c_str());
1391 if (node.empty()) {
1392 std::cout << "WARNING: No value given for '" << name << "'.";
1393 } else {
1394 const char *node_str = node.child_value();
1395 std::string default_value = node_str;
1396 default_vec.push_back(default_value);
1397 }
1398 }
1399}
1400
1401
1402void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<float> &default_vec) {
1403 helios = xmldoc.child("helios");
1404 pugi::xml_node node;
1405 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1406 node = p.child(name.c_str());
1407 if (node.empty()) {
1408 std::cout << "WARNING: No value given for '" << name << "'.";
1409 } else {
1410 const char *node_str = node.child_value();
1411 float default_value;
1412 if (!parse_float(node_str, default_value)) {
1413 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1414 } else if (default_value < 0) {
1415 helios_runtime_error("ERROR: Value given for '" + name + "' must be greater than or equal to 0.");
1416 } else {
1417 default_vec.push_back(default_value);
1418 }
1419 }
1420 }
1421}
1422
1423
1424void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<int> &default_vec) {
1425 helios = xmldoc.child("helios");
1426 pugi::xml_node node;
1427 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1428 node = p.child(name.c_str());
1429 if (node.empty()) {
1430 std::cout << "WARNING: No value given for '" << name << "'.";
1431 } else {
1432 const char *node_str = node.child_value();
1433 int default_value;
1434 if (!parse_int(node_str, default_value)) {
1435 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1436 } else if (default_value < 0) {
1437 helios_runtime_error("ERROR: Value given for '" + name + "' must be greater than or equal to 0.");
1438 } else {
1439 default_vec.push_back(default_value);
1440 }
1441 }
1442 }
1443}
1444
1445
1446void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<int2> &default_vec) {
1447 helios = xmldoc.child("helios");
1448 pugi::xml_node node;
1449 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1450 node = p.child(name.c_str());
1451 if (node.empty()) {
1452 std::cout << "WARNING: No value given for '" << name << "'.";
1453 } else {
1454 const char *node_str = node.child_value();
1455 int2 default_value;
1456 if (!parse_int2(node_str, default_value)) {
1457 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1458 } else if (default_value.x <= 0 || default_value.y <= 0) {
1459 helios_runtime_error("ERROR: Value given for '" + name + "' must be greater than or equal to 0.");
1460 } else {
1461 default_vec.push_back(default_value);
1462 }
1463 }
1464 }
1465}
1466
1467
1468void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<helios::RGBcolor> &default_vec) {
1469 helios = xmldoc.child("helios");
1470 pugi::xml_node node;
1471 for (pugi::xml_node p = helios.child(parent.c_str()); p; p = p.next_sibling(parent.c_str())) {
1472 node = p.child(name.c_str());
1473 if (node.empty()) {
1474 std::cout << "WARNING: No value given for '" << name << "'.";
1475 } else {
1476 const char *node_str = node.child_value();
1477 helios::RGBcolor default_value;
1478 if (!parse_RGBcolor(node_str, default_value)) {
1479 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1480 } else {
1481 default_vec.push_back(default_value);
1482 }
1483 }
1484 }
1485}
1486
1487
1488void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<std::vector<vec3>> &default_vec) {
1489 helios = xmldoc.child("helios");
1490 pugi::xml_node p_;
1491 if (parent != "helios") {
1492 p_ = helios.child(parent.c_str());
1493 } else {
1494 p_ = helios;
1495 }
1496 for (pugi::xml_node p = p_; p; p = p.next_sibling(parent.c_str())) {
1497 std::vector<vec3> curr_vec = {};
1498 for (pugi::xml_node node = p.child(name.c_str()); node; node = node.next_sibling(name.c_str())) {
1499 const char *node_str = node.child_value();
1500 vec3 default_value;
1501 if (!parse_vec3(node_str, default_value)) {
1502 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1503 } else {
1504 curr_vec.push_back(default_value);
1505 }
1506 }
1507 default_vec.push_back(curr_vec);
1508 }
1509}
1510
1511
1512void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::vector<std::set<std::string>> &default_vec) {
1513 helios = xmldoc.child("helios");
1514 pugi::xml_node p_;
1515 if (parent != "helios") {
1516 p_ = helios.child(parent.c_str());
1517 } else {
1518 p_ = helios;
1519 }
1520 for (pugi::xml_node p = p_; p; p = p.next_sibling(parent.c_str())) {
1521 std::set<std::string> curr_vec = {};
1522 for (pugi::xml_node node = p.child(name.c_str()); node; node = node.next_sibling(name.c_str())) {
1523 const char *node_str = node.child_value();
1524 std::string default_value;
1525 if (node.empty()) {
1526 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1527 } else {
1528 default_value = node_str;
1529 curr_vec.insert(default_value);
1530 }
1531 }
1532 default_vec.push_back(curr_vec);
1533 }
1534}
1535
1536
1537void ProjectBuilder::xmlGetValues(const std::string &name, const std::string &parent, std::set<std::string> &default_set) {
1538 helios = xmldoc.child("helios");
1539 pugi::xml_node p_;
1540 if (parent != "helios") {
1541 p_ = helios.child(parent.c_str());
1542 } else {
1543 p_ = helios;
1544 }
1545 for (pugi::xml_node p = p_; p; p = p.next_sibling(parent.c_str())) {
1546 for (pugi::xml_node node = p.child(name.c_str()); node; node = node.next_sibling(name.c_str())) {
1547 const char *node_str = node.child_value();
1548 std::string default_value;
1549 if (node.empty()) {
1550 helios_runtime_error("ERROR: Value given for '" + name + "' could not be parsed.");
1551 } else {
1552 default_value = node_str;
1553 default_set.insert(default_value);
1554 }
1555 }
1556 }
1557}
1558
1559
1560void ProjectBuilder::setNodeLabels(const std::string &name, const std::string &parent, std::set<std::string> &labels_vec) {
1561 int i = 0;
1562 helios = xmldoc.child("helios");
1563
1564 std::set<pugi::xml_node> curr_nodes_set;
1565 for (pugi::xml_node node = helios.child(parent.c_str()); node; node = node.next_sibling(parent.c_str())) {
1566 curr_nodes_set.insert(node);
1567 }
1568 for (auto node: curr_nodes_set) {
1569 node.parent().remove_child(node);
1570 }
1571
1572 std::map<std::string, int> labels_dict = {};
1573 for (auto new_node_label: labels_vec) {
1574 pugi::xml_node new_node = helios.append_child(parent.c_str());
1575 pugi::xml_attribute node_label = new_node.attribute(name.c_str());
1576 node_label.set_value(new_node_label.c_str());
1577 new_node.append_attribute(name.c_str()).set_value(new_node_label.c_str());
1578 }
1579
1580 return;
1581}
1582
1583
1584void ProjectBuilder::xmlSetValue(const std::string &name, const std::string &parent, int &default_value) {
1585 helios = xmldoc.child("helios");
1586 pugi::xml_node p = helios;
1587 if (parent != "helios") {
1588 p = helios.child(parent.c_str());
1589 }
1590 pugi::xml_node node;
1591 node = p.child(name.c_str());
1592 if (!node) {
1593 node = p.append_child(name.c_str());
1594 }
1595 node.text().set(std::to_string(default_value).c_str());
1596}
1597
1598void ProjectBuilder::xmlSetValue(const std::string &name, const std::string &parent, float &default_value) {
1599 helios = xmldoc.child("helios");
1600 pugi::xml_node p = helios;
1601 if (parent != "helios") {
1602 p = helios.child(parent.c_str());
1603 }
1604 pugi::xml_node node;
1605 node = p.child(name.c_str());
1606 if (!node) {
1607 node = p.append_child(name.c_str());
1608 }
1609 node.text().set(std::to_string(default_value).c_str());
1610}
1611
1612void ProjectBuilder::xmlSetValue(const std::string &name, const std::string &parent, std::string &default_value) {
1613 helios = xmldoc.child("helios");
1614 pugi::xml_node p = helios;
1615 if (parent != "helios") {
1616 p = helios.child(parent.c_str());
1617 }
1618 pugi::xml_node node;
1619 node = p.child(name.c_str());
1620 if (!node) {
1621 node = p.append_child(name.c_str());
1622 }
1623 node.text().set(default_value.c_str());
1624}
1625
1626void ProjectBuilder::xmlRemoveField(const std::string &name, const std::string &parent) {
1627 helios = xmldoc.child("helios");
1628 pugi::xml_node p = helios;
1629 if (parent != "helios") {
1630 p = helios.child(parent.c_str());
1631 }
1632 pugi::xml_node node;
1633 node = p.child(name.c_str());
1634 if (node) {
1635 p.remove_child(name.c_str());
1636 }
1637}
1638
1639void ProjectBuilder::xmlSetValue(const std::string &name, const std::string &parent, int2 &default_value) {
1640 helios = xmldoc.child("helios");
1641 pugi::xml_node p = helios;
1642 if (parent != "helios") {
1643 p = helios.child(parent.c_str());
1644 }
1645 pugi::xml_node node;
1646 node = p.child(name.c_str());
1647 if (!node) {
1648 node = p.append_child(name.c_str());
1649 }
1650 node.text().set(vec_to_string(default_value).c_str());
1651}
1652
1653void ProjectBuilder::xmlSetValue(const std::string &name, const std::string &parent, vec2 &default_value) {
1654 helios = xmldoc.child("helios");
1655 pugi::xml_node p = helios;
1656 if (parent != "helios") {
1657 p = helios.child(parent.c_str());
1658 }
1659 pugi::xml_node node;
1660 node = p.child(name.c_str());
1661 if (!node) {
1662 node = p.append_child(name.c_str());
1663 }
1664 node.text().set(vec_to_string(default_value).c_str());
1665}
1666
1667void ProjectBuilder::xmlSetValue(const std::string &name, const std::string &parent, vec3 &default_value) {
1668 helios = xmldoc.child("helios");
1669 pugi::xml_node p = helios;
1670 if (parent != "helios") {
1671 p = helios.child(parent.c_str());
1672 }
1673 pugi::xml_node node;
1674 node = p.child(name.c_str());
1675 if (!node) {
1676 node = p.append_child(name.c_str());
1677 }
1678 node.text().set(vec_to_string(default_value).c_str());
1679}
1680
1681
1682void ProjectBuilder::xmlSetValues(const std::string &field_name, const std::string &node_name, std::vector<vec2> &values_vec, std::map<std::string, int> &node_map) {
1683 helios = xmldoc.child("helios");
1684
1685 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1686 pugi::xml_node node = p.child(field_name.c_str());
1687 if (!node) {
1688 node = p.append_child(field_name.c_str());
1689 }
1690 pugi::xml_attribute label = p.attribute("label");
1691 int idx = node_map[label.as_string()];
1692 node.text().set(vec_to_string(values_vec[idx]).c_str());
1693 }
1694}
1695
1696
1697void ProjectBuilder::xmlSetValues(const std::string &field_name, const std::string &node_name, std::vector<vec3> &values_vec, std::map<std::string, int> &node_map) {
1698 helios = xmldoc.child("helios");
1699
1700 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1701 pugi::xml_node node = p.child(field_name.c_str());
1702 if (!node) {
1703 node = p.append_child(field_name.c_str());
1704 }
1705 pugi::xml_attribute label = p.attribute("label");
1706 int idx = node_map[label.as_string()];
1707 node.text().set(vec_to_string(values_vec[idx]).c_str());
1708 }
1709}
1710
1711
1712void 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) {
1713 helios = xmldoc.child("helios");
1714
1715 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1716 pugi::xml_node node = p.child(field_name.c_str());
1717 if (!node) {
1718 node = p.append_child(field_name.c_str());
1719 }
1720 pugi::xml_attribute label = p.attribute("label");
1721 int idx = node_map[label.as_string()];
1722 helios::vec3 default_values_vec;
1723 default_values_vec.x = values_vec[idx].r;
1724 default_values_vec.y = values_vec[idx].g;
1725 default_values_vec.z = values_vec[idx].b;
1726 node.text().set(vec_to_string(default_values_vec).c_str());
1727 }
1728}
1729
1730
1731void ProjectBuilder::xmlSetValues(const std::string &field_name, const std::string &node_name, std::vector<int2> &values_vec, std::map<std::string, int> &node_map) {
1732 helios = xmldoc.child("helios");
1733
1734 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1735 pugi::xml_node node = p.child(field_name.c_str());
1736 if (!node) {
1737 node = p.append_child(field_name.c_str());
1738 }
1739 pugi::xml_attribute label = p.attribute("label");
1740 int idx = node_map[label.as_string()];
1741 node.text().set(vec_to_string(values_vec[idx]).c_str());
1742 }
1743}
1744
1745
1746void 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) {
1747 helios = xmldoc.child("helios");
1748
1749 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1750 pugi::xml_node node = p.child(field_name.c_str());
1751 if (!node) {
1752 node = p.append_child(field_name.c_str());
1753 }
1754 pugi::xml_attribute label = p.attribute("label");
1755 int idx = node_map[label.as_string()];
1756 node.text().set(values_vec[idx].c_str());
1757 }
1758}
1759
1760
1761void ProjectBuilder::xmlSetValues(const std::string &field_name, const std::string &node_name, std::vector<int> &values_vec, std::map<std::string, int> &node_map) {
1762 helios = xmldoc.child("helios");
1763
1764 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1765 pugi::xml_node node = p.child(field_name.c_str());
1766 if (!node) {
1767 node = p.append_child(field_name.c_str());
1768 }
1769 pugi::xml_attribute label = p.attribute("label");
1770 int idx = node_map[label.as_string()];
1771 node.text().set(std::to_string(values_vec[idx]).c_str());
1772 }
1773}
1774
1775
1776void ProjectBuilder::xmlSetValues(const std::string &field_name, const std::string &node_name, std::vector<float> &values_vec, std::map<std::string, int> &node_map) {
1777 helios = xmldoc.child("helios");
1778
1779 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1780 pugi::xml_node node = p.child(field_name.c_str());
1781 if (!node) {
1782 node = p.append_child(field_name.c_str());
1783 }
1784 pugi::xml_attribute label = p.attribute("label");
1785 int idx = node_map[label.as_string()];
1786 node.text().set(std::to_string(values_vec[idx]).c_str());
1787 }
1788}
1789
1790
1791void 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) {
1792 helios = xmldoc.child("helios");
1793
1794 for (pugi::xml_node p = helios.child(node_name.c_str()); p; p = p.next_sibling(node_name.c_str())) {
1795 std::vector<pugi::xml_node> remove = {};
1796 for (pugi::xml_node node = p.child(field_name.c_str()); node; node = node.next_sibling(field_name.c_str())) {
1797 remove.push_back(node);
1798 }
1799 for (pugi::xml_node &node: remove) {
1800 p.remove_child(node);
1801 }
1802 pugi::xml_attribute label = p.attribute("label");
1803 int idx = node_map[label.as_string()];
1804 for (int j = 0; j < values_vec[idx].size(); j++) {
1805 // p.append_child(name.c_str()).set_value(vec_to_string(default_vec[i][j]).c_str());
1806 pugi::xml_node new_node = p.append_child(field_name.c_str());
1807 new_node.text().set(vec_to_string(values_vec[idx][j]).c_str());
1808 }
1809 }
1810}
1811
1812
1813void 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) {
1814 helios = xmldoc.child("helios");
1815 int i = 0;
1816 pugi::xml_node p_;
1817 if (node_name != "helios") {
1818 p_ = helios.child(node_name.c_str());
1819 } else {
1820 p_ = helios;
1821 }
1822 for (pugi::xml_node p = p_; p; p = p.next_sibling(node_name.c_str())) {
1823 std::vector<pugi::xml_node> remove{};
1824 for (pugi::xml_node node = p.child(field_name.c_str()); node; node = node.next_sibling(field_name.c_str())) {
1825 remove.push_back(node);
1826 }
1827 for (pugi::xml_node &node: remove) {
1828 p.remove_child(node);
1829 }
1830 pugi::xml_attribute label = p.attribute("label");
1831 int idx = node_map[label.as_string()];
1832 for (std::string s: values_vec[idx]) {
1833 // p.append_child(name.c_str()).set_value(s.c_str());
1834 pugi::xml_node new_node = p.append_child(field_name.c_str());
1835 new_node.text().set(s.c_str());
1836 }
1837 }
1838} // TODO: test this function
1839
1840
1841void ProjectBuilder::xmlSetValues(const std::string &name, const std::string &parent, std::set<std::string> &default_set) {
1842 helios = xmldoc.child("helios");
1843 int i = 0;
1844 pugi::xml_node p_;
1845 if (parent != "helios") {
1846 p_ = helios.child(parent.c_str());
1847 } else {
1848 p_ = helios;
1849 }
1850 for (pugi::xml_node p = p_; p; p = p.next_sibling(parent.c_str())) {
1851 std::vector<pugi::xml_node> remove{};
1852 for (pugi::xml_node node = p.child(name.c_str()); node; node = node.next_sibling(name.c_str())) {
1853 remove.push_back(node);
1854 }
1855 for (pugi::xml_node &node: remove) {
1856 p.remove_child(node);
1857 }
1858 for (std::string s: default_set) {
1859 // p.append_child(name.c_str()).set_value(s.c_str());
1860 pugi::xml_node new_node = p.append_child(name.c_str());
1861 new_node.text().set(s.c_str());
1862 }
1863 i++;
1864 }
1865} // TODO: test this function
1866
1867
1869 if (!built) {
1870 std::cout << "Project must be built before running visualize." << std::endl;
1871 return;
1872 }
1873// if (enable_visualizer){
1874#ifdef ENABLE_HELIOS_VISUALIZER
1875 visualizer = new Visualizer(800);
1876 // #ifdef ENABLE_RADIATION_MODEL
1877 // radiation->enableCameraModelVisualization();
1878 // #endif //RADIATION_MODEL
1880
1881 // Uncomment below for interactive
1882 // visualizer.plotInteractive();
1883
1884 visualizer->addCoordinateAxes(helios::make_vec3(0, 0, 0.05), helios::make_vec3(1, 1, 1), "positive");
1886
1887 // Setup Dear ImGui context
1888 IMGUI_CHECKVERSION();
1889 ImGui::CreateContext();
1890 ImGuiIO &io = ImGui::GetIO();
1891 // ImFont* font_awesome = io.Fonts->AddFontFromFileTTF("plugins/visualizer/fonts/FontAwesome.ttf", 16.0f);
1892 ImFont *arial = io.Fonts->AddFontFromFileTTF("plugins/visualizer/fonts/Arial.ttf", 16.0f);
1893 io.Fonts->Build();
1894 // ImGui::PushFont(arial);
1895 io.FontDefault = arial;
1896 io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
1897
1898 // void* window;
1899
1900 // glfwShowWindow((GLFWwindow *) window);
1901
1902 // GLFWwindow* window = glfwCreateWindow(640, 480, "My Title", nullptr, nullptr);
1903 GLFWwindow *window = (GLFWwindow *) visualizer->getWindow();
1904
1905 glfwShowWindow(window);
1906
1907 bool show_demo_window = false;
1908 bool my_tool_active = true;
1909 // bool user_input = false;
1910
1911 // Setup Platform/Renderer backends
1912 ImGui_ImplGlfw_InitForOpenGL(window, true);
1913 ImGui_ImplOpenGL3_Init();
1914 // glfwSwapInterval(1); // enable V-Sync
1915
1916 ImVec2 current_position;
1917 ImVec2 last_position;
1918 bool currently_collapsed;
1919 bool previously_collapsed = false;
1920 std::string current_tab = "General";
1921 std::string previous_tab = "General";
1922
1923 // (Your code calls glfwPollEvents())
1924 // ...
1925 // Start the Dear ImGui frame
1926
1927 bool switch_visualization = false;
1928
1929 std::string current_cam_position = "0";
1930 while (glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS && glfwWindowShouldClose((GLFWwindow *) window) == 0) {
1931 glfwPollEvents();
1932 ImGui_ImplOpenGL3_NewFrame();
1933 ImGui_ImplGlfw_NewFrame();
1934 ImGui::NewFrame();
1935 // ImGui::ShowDemoWindow(&show_demo_window); // Show demo window! :)
1936
1937 // glfwSetKeyCallback(window, key_callback);
1938
1939 // Check for key press or mouse movement
1940 // if (glfwGetKey(window, GLFW_KEY_ESCAPE) == GLFW_PRESS ||
1941 // glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS) {
1942 // user_input = true;
1943 // }
1944
1945 // if (ImGui::IsKeyDown(ImGuiKey_Q)) {
1946 // user_input = true;
1947 // }
1948 //
1949 // if (user_input)
1950 // visualizer->plotUpdate();
1951
1952 user_input = false;
1953 ImGuiWindowFlags window_flags = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize;
1954 ImGuiWindowFlags window_flags2 = ImGuiWindowFlags_MenuBar | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_AlwaysAutoResize;
1955
1956 // ImGui::SetNextWindowSize(ImVec2(500, 400));
1957 // ImVec2 windowSize = ImGui::GetWindowSize();
1958 int windowSize_x = 0;
1959 int windowSize_y = 0;
1960 // visualizer->getWindowSize(windowSize_x, windowSize_y);
1961 glfwGetWindowSize((GLFWwindow *) window, &windowSize_x, &windowSize_y);
1962 int2 windowSize(windowSize_x, windowSize_y);
1963 // TEST
1964 glm::mat4 perspectiveTransformationMatrix = visualizer->getPerspectiveTransformationMatrix();
1965 glm::vec4 origin_position;
1966 std::string current_label;
1967 if (ImGui::IsMouseDown(ImGuiMouseButton_Left) && !ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow | ImGuiHoveredFlags_AllowWhenBlockedByActiveItem)) {
1968 currently_dragging = "";
1969 disable_dragging = true;
1970 }
1971 if (!ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
1972 if (!currently_dragging.empty()) {
1973 // ImVec2 mouse_pos = ImGui::GetMousePos();
1974 // float ndcX = (2.0f * mouse_pos.x / windowSize.x) - 1.0f;
1975 // float ndcY = 1.0f - (2.0f * mouse_pos.y / windowSize.y);
1976 // std::vector<vec3> camera_lookat_pos = visualizer->getCameraPosition();
1977 // vec3 camera_pos = camera_lookat_pos[0];
1978 // vec3 lookat_pos = camera_lookat_pos[1];
1979 // float depth = (camera_pos - lookat_pos).magnitude();
1980 // glm::vec4 clip_pos(ndcX, ndcY, depth, 1.0f);
1981 // glm::vec4 view_pos = glm::inverse(perspectiveTransformationMatrix) * clip_pos;
1982 // view_pos /= view_pos.w;
1983 // glm::mat4 viewMatrix = visualizer->getViewMatrix();
1984 // glm::vec4 world_pos = glm::inverse(viewMatrix) * view_pos;
1985 // glm::vec3 final_pos = glm::vec3(world_pos.x, world_pos.y, world_pos.z);
1986 ImVec2 mouse_pos = ImGui::GetMousePos();
1987 std::vector<vec3> camera_lookat_pos = visualizer->getCameraPosition();
1988 vec3 camera_pos = camera_lookat_pos[0];
1989 vec3 lookat_pos = camera_lookat_pos[1];
1990 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));
1991 ;
1992 float depth = (camera_pos - lookat_pos).magnitude();
1993 vec3 view_dir = (camera_pos - lookat_pos).normalize();
1994
1995 vec3 world_up = vec3(0, 1, 0);
1996
1997 vec3 right_dir = cross(world_up, view_dir);
1998 right_dir = right_dir.normalize();
1999
2000 vec3 up_dir = cross(view_dir, right_dir).normalize();
2001
2002 right_dir = cross(view_dir, world_up).normalize();
2003 float base_offset = 0.001f;
2004 float offset = base_offset * depth;
2005
2006 if (currently_dragging_type == "canopy") {
2007 canopy_dict[currently_dragging].origin += drag_distance * offset * (up_dir + right_dir);
2008 } else if (currently_dragging_type == "rig") {
2009 camera_positions[rig_dict[currently_dragging]] += drag_distance * offset * (up_dir + right_dir);
2010 }
2011 }
2012 currently_dragging = "";
2013 disable_dragging = false;
2014 dragging_start_position = int2(0, 0);
2015 }
2016 int object_window_count = 0;
2017 for (auto current_label: canopy_labels_set) {
2018 vec3 canopy_origin_ = canopy_dict[current_label].origin;
2019 origin_position = glm::vec4(canopy_origin_.x, canopy_origin_.y, canopy_origin_.z, 1.0);
2020 origin_position = perspectiveTransformationMatrix * origin_position;
2021 // ImGui::SetNextWindowSize(ImVec2(150, 10), ImGuiCond_Always);
2022 // ImGui::SetNextWindowSize(ImVec2(150, 10));
2023 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);
2024 // WINDOW MOUSE CLICK AND DRAG
2025 // TODO: re-enable this feature when it is improved
2026 // ImVec2 mouse_pos = ImGui::GetMousePos();
2027 // bool drag_window = (mouse_pos.x >= next_window_pos.x && mouse_pos.x <= next_window_pos.x + 150 &&
2028 // mouse_pos.y >= next_window_pos.y && mouse_pos.y <= next_window_pos.y + 10);
2029 // if (drag_window && ImGui::IsMouseDown(ImGuiMouseButton_Left) && currently_dragging.empty() && !disable_dragging){
2030 // currently_dragging = current_label;
2031 // currently_dragging_type = "canopy";
2032 // dragging_start_position = int2(mouse_pos.x, mouse_pos.y);
2033 // }
2034 // if (!disable_dragging && currently_dragging == current_label){
2035 // ImGui::SetNextWindowPos(mouse_pos);
2036 // } else{
2037 ImGui::SetNextWindowCollapsed(true, ImGuiCond_Once);
2038 ImGui::SetNextWindowPos(next_window_pos);
2039 // }
2040 ImGui::Begin((current_label + "###" + std::to_string(object_window_count)).c_str(), nullptr, //&my_tool_active,
2041 ImGui::IsWindowCollapsed() ? 0 : ImGuiWindowFlags_AlwaysAutoResize);
2042 if (ImGui::IsWindowCollapsed()) {
2043 ImGui::SetWindowSize(ImVec2(150, 10));
2044 }
2045 canopyTab(current_label, object_window_count);
2046 ImGui::End();
2047 object_window_count++;
2048 }
2049 for (auto current_label: rig_labels_set) {
2050 vec3 camera_position_ = camera_position_vec[rig_dict[current_label]][0];
2051 origin_position = glm::vec4(camera_position_.x, camera_position_.y, camera_position_.z, 1.0);
2052 origin_position = perspectiveTransformationMatrix * origin_position;
2053 // ImGui::SetNextWindowSize(ImVec2(150, 10), ImGuiCond_Always);
2054 // ImGui::SetNextWindowSize(ImVec2(150, 10));
2055 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);
2056 // WINDOW MOUSE CLICK AND DRAG
2057 // TODO: re-enable this feature when it is improved
2058 // ImVec2 mouse_pos = ImGui::GetMousePos();
2059 // bool drag_window = (mouse_pos.x >= next_window_pos.x && mouse_pos.x <= next_window_pos.x + 150 &&
2060 // mouse_pos.y >= next_window_pos.y && mouse_pos.y <= next_window_pos.y + 10);
2061 // if (drag_window && ImGui::IsMouseDown(ImGuiMouseButton_Left) && currently_dragging.empty() && !disable_dragging){
2062 // currently_dragging = current_label;
2063 // currently_dragging_type = "rig";
2064 // dragging_start_position = int2(mouse_pos.x, mouse_pos.y);
2065 // }
2066 // if (!disable_dragging && currently_dragging == current_label){
2067 // ImGui::SetNextWindowPos(mouse_pos);
2068 // } else{
2069 ImGui::SetNextWindowCollapsed(true, ImGuiCond_Once);
2070 ImGui::SetNextWindowPos(next_window_pos);
2071 // }
2072 ImGui::Begin((current_label + "###" + std::to_string(object_window_count)).c_str(), nullptr, // &my_tool_active,
2073 ImGui::IsWindowCollapsed() ? 0 : ImGuiWindowFlags_AlwaysAutoResize);
2074 if (ImGui::IsWindowCollapsed()) {
2075 ImGui::SetWindowSize(ImVec2(150, 10));
2076 }
2077 rigTab(current_label, object_window_count);
2078 ImGui::End();
2079 object_window_count++;
2080 }
2081 for (std::string obj_name: obj_names_set) {
2082 current_label = obj_name;
2083 vec3 obj_position_ = objects_dict[current_label].position;
2084 origin_position = glm::vec4(obj_position_.x, obj_position_.y, obj_position_.z, 1.0);
2085 origin_position = perspectiveTransformationMatrix * origin_position;
2086 // ImGui::SetNextWindowSize(ImVec2(150, 10), ImGuiCond_Always);
2087 // ImGui::SetNextWindowSize(ImVec2(150, 10));
2088 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);
2089 // WINDOW MOUSE CLICK AND DRAG
2090 // TODO: re-enable this feature when it is improved
2091 // ImVec2 mouse_pos = ImGui::GetMousePos();
2092 // bool drag_window = (mouse_pos.x >= next_window_pos.x && mouse_pos.x <= next_window_pos.x + 150 &&
2093 // mouse_pos.y >= next_window_pos.y && mouse_pos.y <= next_window_pos.y + 10);
2094 // if (drag_window && ImGui::IsMouseDown(ImGuiMouseButton_Left) && currently_dragging.empty() && !disable_dragging){
2095 // currently_dragging = current_label;
2096 // currently_dragging_type = "object";
2097 // dragging_start_position = int2(mouse_pos.x, mouse_pos.y);
2098 // }
2099 // if (!disable_dragging && currently_dragging == current_label){
2100 // ImGui::SetNextWindowPos(mouse_pos);
2101 // } else{
2102 ImGui::SetNextWindowCollapsed(true, ImGuiCond_Once);
2103 ImGui::SetNextWindowPos(next_window_pos);
2104 // }
2105 ImGui::Begin((current_label + "###" + std::to_string(object_window_count)).c_str(), nullptr, // &my_tool_active,
2106 ImGui::IsWindowCollapsed() ? 0 : ImGuiWindowFlags_AlwaysAutoResize);
2107 if (ImGui::IsWindowCollapsed()) {
2108 ImGui::SetWindowSize(ImVec2(150, 10));
2109 }
2110 objectTab(current_label, object_window_count);
2111 ImGui::End();
2112 object_window_count++;
2113 }
2114 //
2115 ImGui::SetNextWindowCollapsed(false, ImGuiCond_Once);
2116 ImGui::Begin("Editor", nullptr, window_flags2); // Begin editor window
2117 // ImGui::SetNextWindowPos(ImVec2(windowSize.x - 400.0f, 0), ImGuiCond_Always); // flag -> can't move window with mouse
2118 // ImGui::SetNextWindowPos(ImVec2(windowSize.x - 400.0f, 0), ImGuiCond_Always);
2119 current_position = ImGui::GetWindowPos();
2120 currently_collapsed = ImGui::IsWindowCollapsed();
2121
2122 if (current_tab != previous_tab || current_position.x != last_position.x || current_position.y != last_position.y || currently_collapsed != previously_collapsed) {
2123 user_input = true;
2124 previous_tab = current_tab;
2125 }
2126 if (ImGui::BeginMenuBar()) {
2127 if (ImGui::BeginMenu("File")) {
2128 if (ImGui::MenuItem("Open..", "Ctrl+O")) {
2129 std::string file_name = file_dialog();
2130 if (!file_name.empty()) {
2131 xmlGetValues(file_name);
2132 }
2133 }
2134 if (ImGui::MenuItem("Save XML", "Ctrl+S")) {
2135 xmlSetValues();
2136 }
2137 if (ImGui::MenuItem("Save As", "Ctrl+S")) {
2138 std::string new_xml_file = save_as_file_dialog(std::vector<std::string>{"XML"});
2139 if (!new_xml_file.empty()) {
2140 std::string file_extension = new_xml_file;
2141 size_t last_obj_file = file_extension.rfind('.');
2142 if (last_obj_file != std::string::npos) {
2143 file_extension = file_extension.substr(last_obj_file + 1);
2144 }
2145 if (file_extension == "xml") {
2146 if (!std::filesystem::exists(new_xml_file)) {
2147 // Create file
2148 std::filesystem::copy(xml_input_file, new_xml_file, std::filesystem::copy_options::overwrite_existing);
2149 }
2150 // Change XML input file
2151 std::string xml_input_file_ = xml_input_file;
2152 pugi::xml_node helios_ = helios;
2153 xml_input_file = new_xml_file;
2154 if (!open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
2155 helios_runtime_error(xml_error_string);
2156 }
2157 xmlSetValues();
2158 // Change XML input file back to original
2159 // xml_input_file = xml_input_file_;
2160 // helios = helios_;
2161 // if( !open_xml_file(xml_input_file, xmldoc, xml_error_string) ) {
2162 // helios_runtime_error(xml_error_string);
2163 // }
2164 } else {
2165 // Needs to be a obj or ply file
2166 std::cout << "Not a valid file type. Project must be saved to a XML file." << std::endl;
2167 }
2168 } else {
2169 // Not a valid file
2170 std::cout << "Not a valid file." << std::endl;
2171 }
2172 }
2173 if (ImGui::MenuItem("Close", "Ctrl+W")) {
2174 my_tool_active = false;
2175 }
2176 ImGui::EndMenu();
2177 }
2178 if (ImGui::BeginMenu("Visualization")) {
2179 // ImGui::PushFont(font_awesome);
2180 // io.FontDefault = font_awesome;
2181 if (ImGui::MenuItem("! REFRESH LIST !")) {
2182 refreshVisualizationTypes();
2183 }
2184 // ImGui::PopFont();
2185 // io.FontDefault = arial;
2186 if (ImGui::MenuItem("RGB (Default)") && visualization_type != "RGB") {
2187 visualization_type = "RGB";
2188 switch_visualization = true;
2189 }
2190 std::set<std::string> vis_types;
2191 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()));
2192 for (auto &type: vis_types) {
2193 if (ImGui::MenuItem(type.c_str()) && visualization_type != type) {
2194 visualization_type = type;
2195 switch_visualization = true;
2196 }
2197 }
2198 if (switch_visualization) {
2199 if (visualization_type != "RGB") {
2200 if (visualization_types_primitive.find(visualization_type) != visualization_types_primitive.end()) {
2201 visualizer->colorContextPrimitivesByData(visualization_type.c_str());
2202 } else {
2203 visualizer->colorContextPrimitivesByObjectData(visualization_type.c_str());
2204 }
2205 } else {
2207 }
2208 is_dirty = true;
2209 switch_visualization = false;
2210 }
2211 ImGui::EndMenu();
2212 }
2213 ImGui::EndMenuBar();
2214 }
2215 if (ImGui::Button("Reload")) {
2216 xmlSetValues();
2217 const char *font_name = "LCD";
2218 visualizer->addTextboxByCenter("LOADING...", vec3(.5, .5, 0), make_SphericalCoord(0, 0), RGB::red, 40, font_name, Visualizer::COORDINATES_WINDOW_NORMALIZED);
2221 delete context;
2222#ifdef ENABLE_PLANT_ARCHITECTURE
2223 delete plantarchitecture;
2224#endif // PLANT_ARCHITECTURE
2225#ifdef ENABLE_RADIATION_MODEL
2226 delete radiation;
2227#endif // RADIATION_MODEL
2228#ifdef ENABLE_SOLARPOSITION
2229 delete solarposition;
2230#endif // SOLARPOSITION
2231#ifdef ENABLE_ENERGYBALANCEMODEL
2232 delete energybalancemodel;
2233#endif // ENERGYBALANCEMODEL
2234#ifdef ENABLE_BOUNDARYLAYERCONDUCTANCEMODEL
2236#endif // BOUNDARYLAYERCONDUCTANCEMODEL
2237#ifdef ENABLE_RADIATION_MODEL
2238 delete cameraproperties;
2239#endif // RADIATION_MODEL
2240 buildFromXML();
2241// #ifdef ENABLE_RADIATION_MODEL
2242// radiation->enableCameraModelVisualization();
2243// #endif //RADIATION_MODEL
2244#ifdef ENABLE_PLANT_ARCHITECTURE
2246#endif // PLANT_ARCHITECTURE
2247 visualizer->addCoordinateAxes(helios::make_vec3(0, 0, 0.05), helios::make_vec3(1, 1, 1), "positive");
2249 }
2250 std::string image_dir = "./saved/";
2251 bool dir = std::filesystem::create_directories(image_dir);
2252 if (!dir && !std::filesystem::exists(image_dir)) {
2253 helios_runtime_error("Error: image output directory " + image_dir + " could not be created. Exiting...");
2254 }
2255// context.setPrimitiveData(UUIDs_bunny, "bunny", uint(0));
2256// plant segmentation bounding boxes
2257// plant ID bounding boxes (plant architecture->optional plant output data)
2258#ifdef ENABLE_RADIATION_MODEL
2259 ImGui::SameLine();
2260 if (ImGui::Button("Record")) {
2261 if (band_group_names.empty()) {
2262 std::cout << "At least 1 band group (a group of 1 or 3 bands) must be defined to record images." << std::endl;
2263 } else {
2264 // Update reflectivity, transmissivity, & emissivity for each band / primitive_type
2265 const char *font_name = "LCD";
2266 visualizer->addTextboxByCenter("LOADING...", vec3(.5, .5, 0), make_SphericalCoord(0, 0), RGB::red, 40, font_name, Visualizer::COORDINATES_WINDOW_NORMALIZED);
2268 updatePrimitiveTypes();
2269 updateSpectra();
2270 updateCameras(); // TODO: figure out why this causes an error
2271 record();
2275 }
2276 }
2277 recordPopup();
2278 ImGui::OpenPopupOnItemClick("repeat_record", ImGuiPopupFlags_MouseButtonRight);
2279#endif // RADIATION_MODEL
2280 // ####### RESULTS ####### //
2281 // ImGui::Text("Absorbed PAR: %f W/m^2", PAR_absorbed);
2282 // ImGui::Text("Absorbed NIR: %f W/m^2", NIR_absorbed);
2283 // ImGui::Text("Absorbed LW: %f W/m^2", LW_absorbed);
2284 ImGui::Text("Console:");
2285 outputConsole();
2286 if (ImGui::BeginTabBar("Settings#left_tabs_bar")) {
2287 if (ImGui::BeginTabItem("General")) {
2288 current_tab = "General";
2289 // ####### LOCATION ####### //
2290 ImGui::SetWindowFontScale(1.25f);
2291 ImGui::Text("Visualization:");
2292 ImGui::SetWindowFontScale(1.0f);
2293 // ####### COORDINATE AXES ####### //
2294 bool enable_coords_ = enable_coordinate_axes;
2295 toggle_button("##coordinate_axes", &enable_coordinate_axes);
2296 if (enable_coords_ != enable_coordinate_axes) {
2297 if (enable_coordinate_axes) {
2298 visualizer->addCoordinateAxes(helios::make_vec3(0, 0, 0.05), helios::make_vec3(1, 1, 1), "positive");
2299 is_dirty = true;
2300 } else {
2302 is_dirty = true;
2303 }
2304 }
2305 ImGui::SameLine();
2306 if (enable_coordinate_axes) {
2307 ImGui::Text("Coordinate Axes Enabled");
2308 } else {
2309 ImGui::Text("Coordinate Axes Disabled");
2310 }
2311 // ####### COLORBAR ####### //
2312 bool enable_colorbar_ = enable_colorbar;
2313 toggle_button("##colorbar", &enable_colorbar);
2314 if (enable_colorbar_ != enable_colorbar) {
2315 if (enable_colorbar) {
2317 is_dirty = true;
2318 } else {
2320 is_dirty = true;
2321 }
2322 }
2323 ImGui::SameLine();
2324 if (enable_colorbar) {
2325 ImGui::Text("Colorbar Enabled");
2326 } else {
2327 ImGui::Text("Colorbar Disabled");
2328 }
2329 // ####### LIGHTING MODEL ####### //
2330 std::string prev_lighting_model = lighting_model;
2331 ImGui::SetNextItemWidth(120);
2332 dropDown("Lighting Model", lighting_model, lighting_models);
2333 if (prev_lighting_model != lighting_model) {
2334 if (lighting_model == "None")
2336 if (lighting_model == "Phong")
2338 if (lighting_model == "Phong Shadowed")
2340 }
2341 ImGui::SetNextItemWidth(120);
2342 // ####### LIGHTING INTENSITY ####### //
2343 ImGui::InputFloat("Light Intensity Factor", &light_intensity);
2344 visualizer->setLightIntensityFactor(light_intensity);
2345 // ####### LIGHTING DIRECTION ####### //
2346 toggle_button("##light_coord_type", &light_coord_type);
2347 ImGui::SameLine();
2348 if (light_coord_type) {
2349 SphericalCoord light_dir_sphere_ = cart2sphere(light_direction);
2350 vec2 light_dir_sphere;
2351 light_dir_sphere.x = rad2deg(light_dir_sphere_.elevation);
2352 light_dir_sphere.y = rad2deg(light_dir_sphere_.azimuth);
2353 ImGui::Text("Elevation:");
2354 ImGui::SameLine();
2355 ImGui::SetNextItemWidth(80);
2356 ImGui::InputFloat("##light_elevation", &light_dir_sphere.x);
2357 ImGui::SameLine();
2358 ImGui::Text("Azimuth:");
2359 ImGui::SameLine();
2360 ImGui::SetNextItemWidth(80);
2361 ImGui::InputFloat("##light_azimuth", &light_dir_sphere.y);
2362 ImGui::SameLine();
2363 ImGui::Text("Light Direction (Spherical)");
2364 if (light_dir_sphere.x != light_dir_sphere_.elevation || light_dir_sphere.y != light_dir_sphere_.azimuth) {
2365 SphericalCoord light_dir = make_SphericalCoord(deg2rad(light_dir_sphere.x), deg2rad(light_dir_sphere.y));
2366 light_direction = sphere2cart(light_dir);
2367 }
2368 } else {
2369 float light_dir[3];
2370 light_dir[0] = light_direction.x;
2371 light_dir[1] = light_direction.y;
2372 light_dir[2] = light_direction.z;
2373 ImGui::InputFloat3("Light Direction (Cartesian)", light_dir);
2374 light_direction.x = light_dir[0];
2375 light_direction.y = light_dir[1];
2376 light_direction.z = light_dir[2];
2377 }
2378 visualizer->setLightDirection(light_direction);
2379 // ####### LOCATION ####### //
2380 ImGui::SetWindowFontScale(1.25f);
2381 ImGui::Text("Location:");
2382 ImGui::SetWindowFontScale(1.0f);
2383 if (ImGui::Button("Update Location")) {
2385 }
2386 // ####### LATITUDE ####### //
2387 ImGui::SetNextItemWidth(100);
2388 ImGui::InputFloat("Latitude", &latitude);
2389 randomizePopup("latitude", createTaggedPtr(&latitude));
2390 randomizerParams("latitude");
2391 ImGui::OpenPopupOnItemClick("randomize_latitude", ImGuiPopupFlags_MouseButtonRight);
2392 ImGui::SameLine();
2393 // ####### LONGITUDE ####### //
2394 ImGui::SetNextItemWidth(100);
2395 ImGui::InputFloat("Longitude", &longitude);
2396 randomizePopup("longitude", createTaggedPtr(&longitude));
2397 randomizerParams("longitude");
2398 ImGui::OpenPopupOnItemClick("randomize_longitude", ImGuiPopupFlags_MouseButtonRight);
2399 // ####### UTC OFFSET ####### //
2400 ImGui::SetNextItemWidth(100);
2401 ImGui::InputInt("UTC Offset", &UTC_offset);
2402 randomizePopup("UTC_offset", createTaggedPtr(&UTC_offset));
2403 randomizerParams("UTC_offset");
2404 ImGui::OpenPopupOnItemClick("randomize_UTC_offset", ImGuiPopupFlags_MouseButtonRight);
2405 // ####### Weather File ####### //
2406 ImGui::SetNextItemWidth(60);
2407 ImGui::RadioButton("CSV", is_weather_file_csv);
2408 if (ImGui::IsItemClicked())
2409 is_weather_file_csv = true;
2410 ImGui::SameLine();
2411 ImGui::RadioButton("CIMIS", !is_weather_file_csv);
2412 if (ImGui::IsItemClicked())
2413 is_weather_file_csv = false;
2414 std::string prev_weather_file;
2415 std::string *weather_file;
2416 if (is_weather_file_csv) {
2417 ImGui::Text("CSV");
2418 weather_file = &csv_weather_file;
2419 prev_weather_file = csv_weather_file;
2420 } else {
2421 ImGui::Text("CIMIS");
2422 weather_file = &cimis_weather_file;
2423 prev_weather_file = cimis_weather_file;
2424 }
2425 ImGui::SameLine();
2426 if (ImGui::Button("Weather File")) {
2427 std::string weather_file_ = file_dialog();
2428 if (!weather_file_.empty()) {
2429 *weather_file = weather_file_;
2430 try {
2431 if (is_weather_file_csv) {
2432 context->loadTabularTimeseriesData(*weather_file, {}, ",", "YYYYMMDD", 1);
2433 } else {
2434 context->loadTabularTimeseriesData(*weather_file, {"CIMIS"}, ",");
2435 }
2436 } catch (...) {
2437 std::cout << "Failed to load weather file: " << *weather_file << std::endl;
2438 *weather_file = prev_weather_file;
2439 }
2440 } else {
2441 *weather_file = prev_weather_file;
2442 }
2443 }
2444 ImGui::SameLine();
2445 std::string shorten_weather_file = *weather_file;
2446 for (char &c: shorten_weather_file) {
2447 if (c == '\\') {
2448 c = '/';
2449 }
2450 }
2451 size_t last_weather_file = shorten_weather_file.rfind('/');
2452 if (last_weather_file != std::string::npos) {
2453 shorten_weather_file = shorten_weather_file.substr(last_weather_file + 1);
2454 }
2455 ImGui::Text("%s", shorten_weather_file.c_str());
2456 // ####### GROUND ####### //
2457 ImGui::SetWindowFontScale(1.25f);
2458 ImGui::Text("Ground:");
2459 ImGui::SetWindowFontScale(1.0f);
2460 if (ImGui::Button("Update Ground")) {
2461 updateGround();
2462 updatePrimitiveTypes();
2463 updateSpectra();
2464 is_dirty = true;
2465 // refreshVisualization();
2466 }
2467 ImGui::SameLine();
2468 if (ImGui::Button("Delete Ground")) {
2469 deleteGround();
2470 updatePrimitiveTypes();
2471 updateSpectra();
2472 is_dirty = true;
2473 // refreshVisualization();
2474 }
2475 // ImGui::RadioButton("Manually Set Color", ground_flag == 0); if (ImGui::IsItemClicked()) ground_flag = 0;
2476 // ImGui::SameLine();
2477 ImGui::RadioButton("Use Texture File", ground_flag == 1);
2478 if (ImGui::IsItemClicked())
2479 ground_flag = 1;
2480 ImGui::SameLine();
2481 ImGui::RadioButton("Use Model File", ground_flag == 2);
2482 if (ImGui::IsItemClicked())
2483 ground_flag = 2;
2484 if (ground_flag == 0) {
2485 // ####### GROUND COLOR ####### //
2486 ImGui::ColorEdit3("##ground_color_edit", ground_color);
2487 } else if (ground_flag == 1) {
2488 // ####### GROUND TEXTURE File ####### //
2489 ImGui::SetNextItemWidth(60);
2490 if (ImGui::Button("Ground Texture File")) {
2491 std::string ground_texture_file_ = file_dialog();
2492 if (!ground_texture_file_.empty()) {
2493 ground_texture_file = ground_texture_file_;
2494 }
2495 }
2496 ImGui::SameLine();
2497 std::string shorten = ground_texture_file;
2498 for (char &c: shorten) {
2499 if (c == '\\') {
2500 c = '/';
2501 }
2502 }
2503 size_t last = shorten.rfind('/');
2504 if (last != std::string::npos) {
2505 shorten = shorten.substr(last + 1);
2506 }
2507 ImGui::Text("%s", shorten.c_str());
2508 } else if (ground_flag == 2) {
2509 // ####### GROUND Model File ####### //
2510 ImGui::SetNextItemWidth(60);
2511 if (ImGui::Button("Ground Model File")) {
2512 std::string ground_model_file_ = file_dialog();
2513 if (!ground_model_file_.empty()) {
2514 ground_model_file = ground_model_file_;
2515 }
2516 }
2517 ImGui::SameLine();
2518 ImGui::Text("%s", shortenPath(ground_model_file).c_str());
2519 }
2520 toggle_button("##use_ground_texture_color", &use_ground_texture);
2521 // ####### GROUND COLOR ####### //
2522 if (use_ground_texture) {
2523 ImGui::SameLine();
2524 ImGui::Text("Use Ground Texture Color");
2525 } else {
2526 ImGui::SameLine();
2527 ImGui::ColorEdit3("##ground_color_edit", ground_color);
2528 ImGui::SameLine();
2529 ImGui::Text("Manually Set Ground Color");
2530 }
2531 // ####### DOMAIN ORIGIN ####### //
2532 ImGui::SetNextItemWidth(60);
2533 ImGui::InputFloat("##domain_origin_x", &domain_origin.x);
2534 randomizePopup("domain_origin_x", createTaggedPtr(&domain_origin.x));
2535 randomizerParams("domain_origin_x");
2536 ImGui::OpenPopupOnItemClick("randomize_domain_origin_x", ImGuiPopupFlags_MouseButtonRight);
2537 ImGui::SameLine();
2538 ImGui::SetNextItemWidth(60);
2539 ImGui::InputFloat("##domain_origin_y", &domain_origin.y);
2540 randomizePopup("domain_origin_y", createTaggedPtr(&domain_origin.y));
2541 randomizerParams("domain_origin_y");
2542 ImGui::OpenPopupOnItemClick("randomize_domain_origin_y", ImGuiPopupFlags_MouseButtonRight);
2543 ImGui::SameLine();
2544 ImGui::SetNextItemWidth(60);
2545 ImGui::InputFloat("##domain_origin_z", &domain_origin.z);
2546 randomizePopup("domain_origin_z", createTaggedPtr(&domain_origin.z));
2547 randomizerParams("domain_origin_z");
2548 ImGui::OpenPopupOnItemClick("randomize_domain_origin_z", ImGuiPopupFlags_MouseButtonRight);
2549 ImGui::SameLine();
2550 ImGui::Text("Domain Origin");
2551 if (ground_flag == 1) {
2552 // ####### GROUND RESOLUTION ####### //
2553 ImGui::SetNextItemWidth(100);
2554 ImGui::InputInt("##ground_resolution_x", &ground_resolution.x);
2555 randomizePopup("ground_resolution_x", createTaggedPtr(&ground_resolution.x));
2556 randomizerParams("ground_resolution_x");
2557 ImGui::OpenPopupOnItemClick("randomize_ground_resolution_x", ImGuiPopupFlags_MouseButtonRight);
2558 ImGui::SameLine();
2559 ImGui::SetNextItemWidth(100);
2560 ImGui::InputInt("##ground_resolution_y", &ground_resolution.y);
2561 randomizePopup("ground_resolution_y", createTaggedPtr(&ground_resolution.y));
2562 randomizerParams("ground_resolution_y");
2563 ImGui::OpenPopupOnItemClick("randomize_ground_resolution_y", ImGuiPopupFlags_MouseButtonRight);
2564 ImGui::SameLine();
2565 ImGui::Text("Ground Resolution");
2566 // ####### DOMAIN EXTENT ####### //
2567 ImGui::SetNextItemWidth(50);
2568 ImGui::InputFloat("##domain_extent_x", &domain_extent.x);
2569 randomizePopup("domain_extent_x", createTaggedPtr(&domain_extent.x));
2570 randomizerParams("domain_extent_x");
2571 ImGui::OpenPopupOnItemClick("randomize_domain_extent_x", ImGuiPopupFlags_MouseButtonRight);
2572 ImGui::SameLine();
2573 ImGui::SetNextItemWidth(50);
2574 ImGui::InputFloat("##domain_extent_y", &domain_extent.y);
2575 randomizePopup("domain_extent_y", createTaggedPtr(&domain_extent.y));
2576 randomizerParams("domain_extent_y");
2577 ImGui::OpenPopupOnItemClick("randomize_domain_extent_y", ImGuiPopupFlags_MouseButtonRight);
2578 ImGui::SameLine();
2579 ImGui::Text("Domain Extent");
2580 // ####### NUMBER OF TILES ####### //
2581 ImGui::SetNextItemWidth(60);
2582 int temp[2];
2583 temp[0] = num_tiles.x;
2584 temp[1] = num_tiles.y;
2585 ImGui::InputInt2("Number of Tiles", temp);
2586 num_tiles.x = temp[0];
2587 num_tiles.y = temp[1];
2588 }
2589
2590 ImGui::EndTabItem();
2591 }
2592 // OBJECT TAB
2593 if (ImGui::BeginTabItem("Object")) {
2594 current_tab = "Object";
2595 if (ImGui::Button("Load Object File")) {
2596 std::string new_obj_file = file_dialog();
2597 if (!new_obj_file.empty() && std::filesystem::exists(new_obj_file)) {
2598 if (std::filesystem::path(new_obj_file).extension() != ".obj" && std::filesystem::path(new_obj_file).extension() != ".ply") {
2599 std::cout << "Object file must have .obj or .ply extension." << std::endl;
2600 } else {
2601 object new_obj;
2602 std::vector<uint> new_UUIDs;
2603 if (std::filesystem::path(new_obj_file).extension() == ".obj") {
2604 new_UUIDs = context->loadOBJ(new_obj_file.c_str());
2605 } else if (std::filesystem::path(new_obj_file).extension() == ".ply") {
2606 new_UUIDs = context->loadPLY(new_obj_file.c_str());
2607 }
2608 // check for MTL file
2609 std::filesystem::path mtl_path(new_obj_file);
2610 mtl_path.replace_extension("mtl");
2611 if (std::filesystem::exists(mtl_path)) {
2612 new_obj.use_texture_file = true;
2613 } else {
2614 new_obj.use_texture_file = false;
2615 }
2618 std::string default_object_label = "object";
2619 std::string new_obj_label = "object_0";
2620 int count = 0;
2621 while (objects_dict.find(new_obj_label) != objects_dict.end()) {
2622 count++;
2623 new_obj_label = default_object_label + "_" + std::to_string(count);
2624 }
2625 obj_names_set.insert(new_obj_label);
2626 new_obj.index = obj_idx;
2627 obj_idx++;
2628 new_obj.name = new_obj_label;
2629 new_obj.file = new_obj_file;
2630 new_obj.UUIDs = new_UUIDs;
2631 new_obj.position = vec3(0, 0, 0);
2632 new_obj.prev_position = vec3(0, 0, 0);
2633 new_obj.orientation = vec3(0, 0, 0);
2634 new_obj.prev_orientation = vec3(0, 0, 0);
2635 new_obj.scale = vec3(1, 1, 1);
2636 new_obj.prev_scale = vec3(1, 1, 1);
2637 new_obj.color = RGBcolor(0, 0, 1);
2638 new_obj.prev_color = RGBcolor(0, 0, 1);
2639 new_obj.data_group = "";
2640 new_obj.is_dirty = false;
2641 current_obj = new_obj_label;
2642 objects_dict[new_obj_label] = new_obj;
2643 }
2644 }
2645 }
2646 if (ImGui::BeginCombo("##obj_combo", current_obj.c_str())) {
2647 for (std::string obj_name: obj_names_set) {
2648 bool is_obj_selected = (current_obj == obj_name);
2649 if (ImGui::Selectable(obj_name.c_str(), is_obj_selected))
2650 current_obj = obj_name;
2651 if (is_obj_selected)
2652 ImGui::SetItemDefaultFocus();
2653 }
2654 ImGui::EndCombo();
2655 }
2656 ImGui::SameLine();
2657 ImGui::Text("Select Object");
2658 if (!current_obj.empty()) {
2659 // if (ImGui::Button("Update Object")){
2660 // updateObject(current_obj);
2661 // }
2662 // ImGui::SameLine();
2663 if (ImGui::Button("Delete Object")) {
2664 deleteObject(current_obj);
2665 }
2666 if (objects_dict[current_obj].is_dirty) {
2667 ImGui::SameLine();
2668 ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255)); // Red text
2669 ImGui::Text("update required");
2670 ImGui::PopStyleColor();
2671 }
2672 ImGui::SetNextItemWidth(100);
2673 std::string prev_obj_name = objects_dict[current_obj].name;
2674 ImGui::InputText("##obj_name", &objects_dict[current_obj].name);
2675 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()) {
2676 object temp_obj = objects_dict[prev_obj_name];
2677 current_obj = objects_dict[current_obj].name;
2678 std::map<std::string, object>::iterator delete_obj_iter = objects_dict.find(prev_obj_name);
2679 if (delete_obj_iter != objects_dict.end()) {
2680 objects_dict.erase(delete_obj_iter);
2681 }
2682 objects_dict[current_obj] = temp_obj;
2683 obj_names_set.erase(prev_obj_name);
2684 obj_names_set.insert(current_obj);
2685 } else {
2686 objects_dict[current_obj].name = prev_obj_name;
2687 }
2688 ImGui::SameLine();
2689 ImGui::Text("Object Name");
2690 if (!current_obj.empty()) {
2691 // ####### OBJECT DATA GROUP ####### //
2692 ImGui::SetNextItemWidth(100);
2693 std::string prev_obj_data_group = objects_dict[current_obj].data_group;
2694 ImGui::InputText("##obj_data_group", &objects_dict[current_obj].data_group);
2695 if (objects_dict[current_obj].data_group == "All" || objects_dict[current_obj].data_group.empty()) {
2696 objects_dict[current_obj].data_group = prev_obj_data_group;
2697 }
2698 if (!objects_dict[current_obj].data_group.empty() && prev_obj_data_group != objects_dict[current_obj].data_group) {
2699 std::string new_data_group = objects_dict[current_obj].data_group;
2700 context->setPrimitiveData(objects_dict[current_obj].UUIDs, "data_group", new_data_group);
2701 }
2702 ImGui::SameLine();
2703 ImGui::Text("Data Group");
2704 bool use_obj_texture = objects_dict[current_obj].use_texture_file;
2705 toggle_button("##use_texture_file", &use_obj_texture);
2706 if (use_obj_texture != objects_dict[current_obj].use_texture_file) {
2707 objects_dict[current_obj].use_texture_file = use_obj_texture;
2708 objects_dict[current_obj].is_dirty = true;
2709 updateObject(current_obj);
2710 is_dirty = true;
2711 }
2712 ImGui::SameLine();
2713 if (!use_obj_texture) {
2714 // ####### OBJECT COLOR ####### //
2715 float col[3];
2716 col[0] = objects_dict[current_obj].color.r;
2717 col[1] = objects_dict[current_obj].color.g;
2718 col[2] = objects_dict[current_obj].color.b;
2719 ImGui::ColorEdit3("##obj_color_edit", col);
2720 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]) {
2721 updateColor(current_obj, "obj", col);
2722 }
2723 ImGui::SameLine();
2724 ImGui::Text("Object Color");
2725 } else {
2726 // ####### OBJECT TEXTURE FILE ####### //
2727 ImGui::Text("Use Color from Texture File");
2728 }
2729 // ####### OBJECT SCALE ####### //
2730 ImGui::SetNextItemWidth(60);
2731 ImGui::InputFloat("##obj_scale_x", &objects_dict[current_obj].scale.x);
2732 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));
2733 randomizerParams("obj_scale_x_" + std::to_string(objects_dict[current_obj].index));
2734 ImGui::OpenPopupOnItemClick(("randomize_obj_scale_x_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2735 ImGui::SameLine();
2736 ImGui::SetNextItemWidth(60);
2737 ImGui::InputFloat("##obj_scale_y", &objects_dict[current_obj].scale.y);
2738 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));
2739 randomizerParams("obj_scale_y_" + std::to_string(objects_dict[current_obj].index));
2740 ImGui::OpenPopupOnItemClick(("randomize_obj_scale_y_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2741 ImGui::SameLine();
2742 ImGui::SetNextItemWidth(60);
2743 ImGui::InputFloat("##obj_scale_z", &objects_dict[current_obj].scale.z);
2744 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));
2745 randomizerParams("obj_scale_z_" + std::to_string(objects_dict[current_obj].index));
2746 ImGui::OpenPopupOnItemClick(("randomize_obj_scale_z_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2747 ImGui::SameLine();
2748 ImGui::Text("Object Scale");
2749 // ####### OBJECT POSITION ####### //
2750 ImGui::SetNextItemWidth(60);
2751 ImGui::InputFloat("##obj_position_x", &objects_dict[current_obj].position.x);
2752 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));
2753 randomizerParams("obj_position_x_" + std::to_string(objects_dict[current_obj].index));
2754 ImGui::OpenPopupOnItemClick(("randomize_obj_position_x_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2755 ImGui::SameLine();
2756 ImGui::SetNextItemWidth(60);
2757 ImGui::InputFloat("##obj_position_y", &objects_dict[current_obj].position.y);
2758 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));
2759 randomizerParams("obj_position_y_" + std::to_string(objects_dict[current_obj].index));
2760 ImGui::OpenPopupOnItemClick(("randomize_obj_position_y_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2761 ImGui::SameLine();
2762 ImGui::SetNextItemWidth(60);
2763 ImGui::InputFloat("##obj_position_z", &objects_dict[current_obj].position.z);
2764 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));
2765 randomizerParams("obj_position_z_" + std::to_string(objects_dict[current_obj].index));
2766 ImGui::OpenPopupOnItemClick(("randomize_obj_position_z_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2767 ImGui::SameLine();
2768 ImGui::Text("Object Position");
2769 // ####### OBJECT ORIENTATION ####### //
2770 ImGui::SetNextItemWidth(60);
2771 ImGui::InputFloat("##obj_orientation_x", &objects_dict[current_obj].orientation.x);
2772 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));
2773 randomizerParams("obj_orientation_x_" + std::to_string(objects_dict[current_obj].index));
2774 ImGui::OpenPopupOnItemClick(("randomize_obj_orientation_x_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2775 ImGui::SameLine();
2776 ImGui::SetNextItemWidth(60);
2777 ImGui::InputFloat("##obj_orientation_y", &objects_dict[current_obj].orientation.y);
2778 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));
2779 randomizerParams("obj_orientation_y_" + std::to_string(objects_dict[current_obj].index));
2780 ImGui::OpenPopupOnItemClick(("randomize_obj_orientation_y_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2781 ImGui::SameLine();
2782 ImGui::SetNextItemWidth(60);
2783 ImGui::InputFloat("##obj_orientation_z", &objects_dict[current_obj].orientation.z);
2784 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));
2785 randomizerParams("obj_orientation_z_" + std::to_string(objects_dict[current_obj].index));
2786 ImGui::OpenPopupOnItemClick(("randomize_obj_orientation_z_" + std::to_string(objects_dict[current_obj].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2787 ImGui::SameLine();
2788 ImGui::Text("Object Orientation");
2789 if (objects_dict[current_obj].position != objects_dict[current_obj].prev_position || objects_dict[current_obj].orientation != objects_dict[current_obj].prev_orientation ||
2790 objects_dict[current_obj].scale != objects_dict[current_obj].prev_scale || objects_dict[current_obj].color != objects_dict[current_obj].prev_color) {
2791 objects_dict[current_obj].is_dirty = true;
2792 }
2793 if (objects_dict[current_obj].is_dirty && !ImGui::IsAnyItemActive() && !ImGui::IsAnyItemFocused()) {
2794 updateObject(current_obj);
2795 }
2796 }
2797 }
2798 ImGui::EndTabItem();
2799 }
2800// if (enable_plantarchitecture){
2801#ifdef ENABLE_PLANT_ARCHITECTURE
2802 // CANOPY TAB
2803 if (ImGui::BeginTabItem("Canopy")) {
2804 current_tab = "Canopy";
2805 dropDown("##canopy_combo", current_canopy, canopy_labels_set);
2806 ImGui::SameLine();
2807 if (ImGui::Button("Add Canopy")) {
2808 addCanopy();
2809 }
2810 if (!current_canopy.empty()) {
2811 if (ImGui::Button("Update Canopy")) {
2812 updateCanopy(current_canopy);
2813 is_dirty = true;
2814 canopy_dict[current_canopy].is_dirty = false;
2815 }
2816 ImGui::SameLine();
2817 if (ImGui::Button("Delete Canopy")) {
2818 deleteCanopy(current_canopy);
2819 updatePrimitiveTypes();
2820 is_dirty = true;
2822 // refreshVisualization();
2823 }
2824 if (canopy_dict[current_canopy].is_dirty) {
2825 ImGui::SameLine();
2826 ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255)); // Red text
2827 ImGui::Text("update required");
2828 ImGui::PopStyleColor();
2829 }
2830 ImGui::SetNextItemWidth(100);
2831 std::string prev_canopy_name = canopy_dict[current_canopy].label;
2832 ImGui::InputText("##canopy_name", &canopy_dict[current_canopy].label);
2833 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()) {
2834 canopy temp = canopy_dict[current_canopy];
2835 current_canopy = canopy_dict[prev_canopy_name].label;
2836 std::map<std::string, canopy>::iterator current_canopy_iter = canopy_dict.find(prev_canopy_name);
2837 if (current_canopy_iter != canopy_dict.end()) {
2838 canopy_dict.erase(current_canopy_iter);
2839 }
2840 canopy_dict[current_canopy] = temp;
2841
2842 canopy_labels_set.erase(prev_canopy_name);
2843 canopy_labels_set.insert(current_canopy);
2844 } else {
2845 canopy_dict[current_canopy].label = prev_canopy_name;
2846 }
2847 ImGui::SameLine();
2848 ImGui::Text("Canopy Name");
2849 // ####### PLANT LIBRARY NAME ####### //
2850 ImGui::SetNextItemWidth(250);
2851 // ImGui::InputText("Plant Library", &plant_library_names[canopy_labels_dict[current_canopy]]);
2852 std::string prev_lib = canopy_dict[current_canopy].library_name_verbose;
2853 dropDown("Plant Library###dropdown", canopy_dict[current_canopy].library_name_verbose, plant_types_verbose);
2854 if (canopy_dict[current_canopy].library_name_verbose != prev_lib)
2855 canopy_dict[current_canopy].is_dirty = true;
2856 canopy_dict[current_canopy].library_name = plant_type_lookup[canopy_dict[current_canopy].library_name_verbose];
2857 // ######### CANOPY DATA GROUP ####### //
2858 ImGui::SetNextItemWidth(100);
2859 std::string prev_canopy_data_group = canopy_dict[current_canopy].data_group;
2860 ImGui::InputText("##canopy_data_group", &canopy_dict[current_canopy].data_group);
2861 if (canopy_dict[current_canopy].data_group == "All" || canopy_dict[current_canopy].data_group.empty()) {
2862 canopy_dict[current_canopy].data_group = prev_canopy_data_group;
2863 }
2864 if (!canopy_dict[current_canopy].data_group.empty() && prev_canopy_data_group != canopy_dict[current_canopy].data_group) {
2865 std::string new_data_group = canopy_dict[current_canopy].data_group;
2866 std::vector<uint> canopy_primID_vec;
2867 for (int i = 0; i < canopy_dict[current_canopy].IDs.size(); i++) {
2868 std::vector<uint> new_canopy_primIDs = plantarchitecture->getAllPlantUUIDs(canopy_dict[current_canopy].IDs[i]);
2869 canopy_primID_vec.insert(canopy_primID_vec.end(), new_canopy_primIDs.begin(), new_canopy_primIDs.end());
2870 }
2871 context->setPrimitiveData(canopy_primID_vec, "data_group", new_data_group);
2872 }
2873 ImGui::SameLine();
2874 ImGui::Text("Data Group");
2875 // ####### CANOPY ORIGIN ####### //
2876 vec3 prev_canopy_origin_ = vec3(canopy_dict[current_canopy].origin);
2877 ImGui::SetNextItemWidth(60);
2878 ImGui::InputFloat("##canopy_origin_x", &canopy_dict[current_canopy].origin.x);
2879 randomizePopup("canopy_origin_x_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].origin.x));
2880 randomizerParams("canopy_origin_x_" + std::to_string(canopy_dict[current_canopy].idx));
2881 ImGui::OpenPopupOnItemClick(("randomize_canopy_origin_x_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2882 ImGui::SameLine();
2883 ImGui::SetNextItemWidth(60);
2884 ImGui::InputFloat("##canopy_origin_y", &canopy_dict[current_canopy].origin.y);
2885 randomizePopup("canopy_origin_y_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].origin.y));
2886 randomizerParams("canopy_origin_y_" + std::to_string(canopy_dict[current_canopy].idx));
2887 ImGui::OpenPopupOnItemClick(("randomize_canopy_origin_y_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2888 ImGui::SameLine();
2889 ImGui::SetNextItemWidth(60);
2890 ImGui::InputFloat("##canopy_origin_z", &canopy_dict[current_canopy].origin.z);
2891 randomizePopup("canopy_origin_z_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].origin.z));
2892 randomizerParams("canopy_origin_z_" + std::to_string(canopy_dict[current_canopy].idx));
2893 ImGui::OpenPopupOnItemClick(("randomize_canopy_origin_z_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2894 ImGui::SameLine();
2895 ImGui::Text("Canopy Origin");
2896 if (prev_canopy_origin_ != canopy_dict[current_canopy].origin) {
2897 canopy_dict[current_canopy].is_dirty = true;
2898 }
2899 // ####### PLANT COUNT ####### //
2900 int2 prev_plant_count_ = int2(canopy_dict[current_canopy].plant_count);
2901 ImGui::SetNextItemWidth(100);
2902 ImGui::InputInt("##plant_count_x", &canopy_dict[current_canopy].plant_count.x);
2903 canopy_dict[current_canopy].plant_count.x = std::max(canopy_dict[current_canopy].plant_count.x, 1);
2904 randomizePopup("plant_count_x_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].plant_count.x));
2905 randomizerParams("plant_count_x_" + std::to_string(canopy_dict[current_canopy].idx));
2906 ImGui::OpenPopupOnItemClick(("randomize_plant_count_x_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2907 ImGui::SameLine();
2908 ImGui::SetNextItemWidth(100);
2909 ImGui::InputInt("##plant_count_y", &canopy_dict[current_canopy].plant_count.y);
2910 canopy_dict[current_canopy].plant_count.y = std::max(canopy_dict[current_canopy].plant_count.y, 1);
2911 randomizePopup("plant_count_y_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].plant_count.y));
2912 randomizerParams("plant_count_y_" + std::to_string(canopy_dict[current_canopy].idx));
2913 ImGui::OpenPopupOnItemClick(("randomize_plant_count_y_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2914 ImGui::SameLine();
2915 ImGui::Text("Plant Count");
2916 if (prev_plant_count_ != canopy_dict[current_canopy].plant_count) {
2917 canopy_dict[current_canopy].is_dirty = true;
2918 }
2919 // ####### PLANT SPACING ####### //
2920 vec2 prev_plant_spacing_ = vec2(canopy_dict[current_canopy].plant_spacing);
2921 ImGui::SetNextItemWidth(50);
2922 ImGui::InputFloat("##plant_spacing_x", &canopy_dict[current_canopy].plant_spacing.x);
2923 randomizePopup("plant_spacing_x_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].plant_spacing.x));
2924 randomizerParams("plant_spacing_x_" + std::to_string(canopy_dict[current_canopy].idx));
2925 ImGui::OpenPopupOnItemClick(("randomize_plant_spacing_x_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2926 ImGui::SameLine();
2927 ImGui::SetNextItemWidth(50);
2928 ImGui::InputFloat("##plant_spacing_y", &canopy_dict[current_canopy].plant_spacing.y);
2929 randomizePopup("plant_spacing_y_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].plant_spacing.y));
2930 randomizerParams("plant_spacing_y_" + std::to_string(canopy_dict[current_canopy].idx));
2931 ImGui::OpenPopupOnItemClick(("randomize_plant_spacing_y_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2932 ImGui::SameLine();
2933 ImGui::Text("Plant Spacing");
2934 if (prev_plant_spacing_ != canopy_dict[current_canopy].plant_spacing) {
2935 canopy_dict[current_canopy].is_dirty = true;
2936 }
2937 // ####### PLANT AGE ####### //
2938 float prev_age_ = canopy_dict[current_canopy].age;
2939 ImGui::SetNextItemWidth(80);
2940 ImGui::InputFloat("Plant Age", &canopy_dict[current_canopy].age);
2941 randomizePopup("plant_age_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].age));
2942 randomizerParams("plant_age_" + std::to_string(canopy_dict[current_canopy].idx));
2943 ImGui::OpenPopupOnItemClick(("randomize_plant_age_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2944 if (prev_age_ != canopy_dict[current_canopy].age) {
2945 canopy_dict[current_canopy].is_dirty = true;
2946 }
2947 // ####### GROUND CLIPPING HEIGHT ####### //
2948 float prev_ground_clipping_height_ = canopy_dict[current_canopy].ground_clipping_height;
2949 ImGui::SetNextItemWidth(80);
2950 ImGui::InputFloat("Ground Clipping Height", &canopy_dict[current_canopy].ground_clipping_height);
2951 randomizePopup("ground_clipping_height_" + std::to_string(canopy_dict[current_canopy].idx), createTaggedPtr(&canopy_dict[current_canopy].ground_clipping_height));
2952 randomizerParams("ground_clipping_height_" + std::to_string(canopy_dict[current_canopy].idx));
2953 ImGui::OpenPopupOnItemClick(("randomize_ground_clipping_height_" + std::to_string(canopy_dict[current_canopy].idx)).c_str(), ImGuiPopupFlags_MouseButtonRight);
2954 if (prev_ground_clipping_height_ != canopy_dict[current_canopy].ground_clipping_height) {
2955 canopy_dict[current_canopy].is_dirty = true;
2956 }
2957 if (ImGui::Button("Save Canopy to OBJ/PLY File")) {
2958 std::string new_obj_file = save_as_file_dialog(std::vector<std::string>{"OBJ", "PLY"});
2959 if (!new_obj_file.empty()) {
2960 std::string file_extension = new_obj_file;
2961 size_t last_obj_file = file_extension.rfind('.');
2962 if (last_obj_file != std::string::npos) {
2963 file_extension = file_extension.substr(last_obj_file + 1);
2964 }
2965 if (file_extension == "obj" || file_extension == "ply") {
2966 if (!std::filesystem::exists(new_obj_file)) {
2967 // Create file
2968 std::ofstream outFile(new_obj_file);
2969 }
2970 if (!save_plants_individually) {
2971 saveCanopy(new_obj_file, canopy_dict[current_canopy].IDs, canopy_dict[current_canopy].origin, file_extension);
2972 } else {
2973 saveCanopy(new_obj_file, canopy_dict[current_canopy].IDs, canopy_dict[current_canopy].individual_plant_locations, file_extension);
2974 }
2975 } else {
2976 // Needs to be a obj or ply file
2977 std::cout << "Not a valid file type. Object must be saved to .obj or .ply file." << std::endl;
2978 }
2979 } else {
2980 // Not a valid file
2981 std::cout << "Not a valid file." << std::endl;
2982 }
2983 }
2984 ImGui::SameLine();
2985 ImGui::Checkbox("Save plants individually", &save_plants_individually);
2986 }
2987 ImGui::EndTabItem();
2988 }
2989// } //PLANT_ARCHITECTURE
2990#endif // PLANT_ARCHITECTURE
2991#ifdef ENABLE_RADIATION_MODEL
2992 if (enable_radiation) {
2993 if (ImGui::BeginTabItem("Radiation")) {
2994 current_tab = "Radiation";
2995 // LOAD XML LIBRARY FILE
2996 ImGui::SetNextItemWidth(60);
2997 if (ImGui::Button("Load XML Library File")) {
2998 std::string new_xml_library_file = file_dialog();
2999 if (!new_xml_library_file.empty() && std::filesystem::exists(new_xml_library_file)) {
3000 if (xml_library_files.find(new_xml_library_file) == xml_library_files.end()) {
3001 xml_library_files.insert(new_xml_library_file);
3002 std::vector<std::string> current_spectra_file = get_xml_node_values(new_xml_library_file, "label", "globaldata_vec2");
3003 for (int i = 0; i < current_spectra_file.size(); i++) {
3004 possible_spectra.insert(current_spectra_file[i]);
3005 }
3006 }
3007 context->loadXML(new_xml_library_file.c_str());
3008 }
3009 }
3010 // ####### GLOBAL PROPERTIES ####### //
3011 ImGui::SetWindowFontScale(1.25f);
3012 ImGui::Text("Global Properties:");
3013 ImGui::SetWindowFontScale(1.0f);
3014 // ####### ENFORCE PERIODIC BOUNDARY CONDITION ####### //
3015 ImGui::Text("Enforce Periodic Boundary Condition:");
3016 ImGui::SameLine();
3017 bool prev_cond_x = enforce_periodic_boundary_x;
3018 ImGui::Checkbox("x###periodic_boundary_x", &enforce_periodic_boundary_x);
3019 ImGui::SameLine();
3020 bool prev_cond_y = enforce_periodic_boundary_y;
3021 ImGui::Checkbox("y###periodic_boundary_y", &enforce_periodic_boundary_y);
3022 if (prev_cond_x != enforce_periodic_boundary_x || prev_cond_y != enforce_periodic_boundary_y) {
3023 if (enforce_periodic_boundary_x && enforce_periodic_boundary_y)
3025 else if (enforce_periodic_boundary_x)
3027 else if (enforce_periodic_boundary_y)
3029 else
3031 }
3032 // ####### DIFFUSE EXTINCTION COEFFICIENT ####### //
3033 ImGui::SetNextItemWidth(60);
3034 float prev_value = diffuse_extinction_coeff;
3035 ImGui::InputFloat("Diffuse Extinction Coefficient", &diffuse_extinction_coeff);
3036 if (prev_value != diffuse_extinction_coeff) {
3037 context->setGlobalData("diffuse_extinction_coeff", diffuse_extinction_coeff);
3038 }
3039 randomizePopup("diffuse_extinction_coeff", createTaggedPtr(&diffuse_extinction_coeff));
3040 randomizerParams("diffuse_extinction_coeff");
3041 ImGui::OpenPopupOnItemClick("randomize_diffuse_extinction_coeff", ImGuiPopupFlags_MouseButtonRight);
3042 // ####### AIR TURBIDITY ####### //
3043 ImGui::SetNextItemWidth(60);
3044 prev_value = air_turbidity;
3045 ImGui::InputFloat("Air Turbidity", &air_turbidity);
3046 if (prev_value != air_turbidity) {
3047 if (air_turbidity > 0) {
3048 context->setGlobalData("air_turbidity", air_turbidity);
3049 } else if (air_turbidity < 0) { // try calibration
3050 if (context->doesTimeseriesVariableExist("net_radiation")) {
3051 air_turbidity = solarposition->calibrateTurbidityFromTimeseries("net_radiation");
3052 if (air_turbidity > 0 && air_turbidity < 1) {
3053 context->setGlobalData("air_turbidity", air_turbidity);
3054 }
3055 }
3056 }
3057 }
3058 randomizePopup("air_turbidity", createTaggedPtr(&air_turbidity));
3059 randomizerParams("air_turbidity");
3060 ImGui::OpenPopupOnItemClick("randomize_air_turbidity", ImGuiPopupFlags_MouseButtonRight);
3061 // ####### SOLAR DIRECT SPECTRUM ####### //
3062 ImGui::SetNextItemWidth(250);
3063 // ImGui::InputText("Solar Direct Spectrum", &solar_direct_spectrum);
3064 if (ImGui::BeginCombo("##combo_solar_direct_spectrum", solar_direct_spectrum.c_str())) {
3065 for (auto &spectra: possible_spectra) {
3066 bool is_solar_direct_spectrum_selected = (solar_direct_spectrum == spectra);
3067 if (ImGui::Selectable(spectra.c_str(), is_solar_direct_spectrum_selected))
3068 solar_direct_spectrum = spectra;
3069 if (is_solar_direct_spectrum_selected)
3070 ImGui::SetItemDefaultFocus();
3071 }
3072 ImGui::EndCombo();
3073 }
3074 ImGui::SameLine();
3075 ImGui::Text("Solar Direct Spectrum");
3076 // ####### BAND PROPERTIES ####### //
3077 ImGui::SetWindowFontScale(1.25f);
3078 ImGui::Text("Add Band:");
3079 ImGui::SetWindowFontScale(1.0f);
3080 // ####### ADD BAND ####### //
3081 toggle_button("##enable_wavelength", &enable_wavelength);
3082 ImGui::SameLine();
3083 if (enable_wavelength) {
3084 ImGui::Text("Wavelength Min:");
3085 ImGui::SameLine();
3086 ImGui::SetNextItemWidth(60);
3087 ImGui::InputFloat("##wavelength_min", &wavelength_min);
3088 ImGui::SameLine();
3089 ImGui::Text("Max:");
3090 ImGui::SameLine();
3091 ImGui::SetNextItemWidth(60);
3092 ImGui::InputFloat("##wavelength_max", &wavelength_max);
3093 } else {
3094 ImGui::Text("No Specified Wavelength");
3095 }
3096 //
3097 ImGui::Text("Label:");
3098 ImGui::SameLine();
3099 ImGui::SetNextItemWidth(100);
3100 ImGui::InputText("##new_band_label", &new_band_label);
3101 ImGui::SameLine();
3102 ImGui::Text("Emission:");
3103 ImGui::SameLine();
3104 ImGui::Checkbox("##enable_emission", &enable_emission);
3105 ImGui::SameLine();
3106 if (ImGui::Button("Add Band")) {
3107 if (enable_wavelength) {
3108 addBand(new_band_label, wavelength_min, wavelength_max, enable_emission);
3109 } else {
3110 addBand(new_band_label, enable_emission);
3111 bandlabels_set_wavelength.insert(new_band_label);
3112 }
3113 }
3114 // ####### BAND PROPERTIES ####### //
3115 ImGui::SetWindowFontScale(1.25f);
3116 ImGui::Text("Band Properties:");
3117 ImGui::SetWindowFontScale(1.0f);
3118 // ####### SELECT BAND ####### //
3119 if (ImGui::BeginCombo("##combo_current_band", current_band.c_str())) {
3120 for (std::string band: bandlabels_set) {
3121 bool is_current_band_selected = (current_band == band);
3122 if (ImGui::Selectable(band.c_str(), is_current_band_selected))
3123 current_band = band;
3124 if (is_current_band_selected)
3125 ImGui::SetItemDefaultFocus();
3126 }
3127 ImGui::EndCombo();
3128 }
3129 ImGui::SameLine();
3130 ImGui::Text("Select Band");
3131 // ####### DIRECT RAY COUNT ####### //
3132 int prev_direct_ray_count;
3133 ImGui::SetNextItemWidth(100);
3134 if (current_band == "All") {
3135 prev_direct_ray_count = direct_ray_count;
3136 ImGui::InputInt("Direct Ray Count", &direct_ray_count);
3137 randomizePopup("direct_ray_count", createTaggedPtr(&direct_ray_count));
3138 randomizerParams("direct_ray_count");
3139 ImGui::OpenPopupOnItemClick("randomize_direct_ray_count", ImGuiPopupFlags_MouseButtonRight);
3140 if (direct_ray_count != prev_direct_ray_count) {
3141 for (std::string band: bandlabels) {
3142 radiation->setDirectRayCount(band, direct_ray_count);
3143 direct_ray_count_dict[band] = direct_ray_count;
3144 }
3145 }
3146 } else {
3147 prev_direct_ray_count = direct_ray_count_dict[current_band];
3148 ImGui::InputInt("Direct Ray Count", &direct_ray_count_dict[current_band]);
3149 randomizePopup("direct_ray_count_" + current_band, createTaggedPtr(&direct_ray_count_dict[current_band]));
3150 randomizerParams("direct_ray_count_" + current_band);
3151 ImGui::OpenPopupOnItemClick(("randomize_direct_ray_count_" + current_band).c_str(), ImGuiPopupFlags_MouseButtonRight);
3152 if (direct_ray_count_dict[current_band] != prev_direct_ray_count) {
3153 radiation->setDirectRayCount(current_band, direct_ray_count_dict[current_band]);
3154 }
3155 }
3156 // ####### DIFFUSE RAY COUNT ####### //
3157 ImGui::SetNextItemWidth(100);
3158 int prev_diffuse_ray_count;
3159 if (current_band == "All") {
3160 prev_diffuse_ray_count = diffuse_ray_count;
3161 ImGui::InputInt("Diffuse Ray Count", &diffuse_ray_count);
3162 randomizePopup("diffuse_ray_count", createTaggedPtr(&diffuse_ray_count));
3163 randomizerParams("diffuse_ray_count");
3164 ImGui::OpenPopupOnItemClick("randomize_diffuse_ray_count", ImGuiPopupFlags_MouseButtonRight);
3165 if (diffuse_ray_count != prev_diffuse_ray_count) {
3166 for (std::string band: bandlabels) {
3167 radiation->setDiffuseRayCount(band, diffuse_ray_count);
3168 diffuse_ray_count_dict[band] = diffuse_ray_count;
3169 }
3170 }
3171 } else {
3172 prev_diffuse_ray_count = diffuse_ray_count_dict[current_band];
3173 ImGui::InputInt("Diffuse Ray Count", &diffuse_ray_count_dict[current_band]);
3174 randomizePopup("diffuse_ray_count_" + current_band, createTaggedPtr(&diffuse_ray_count_dict[current_band]));
3175 randomizerParams("diffuse_ray_count_" + current_band);
3176 ImGui::OpenPopupOnItemClick(("randomize_diffuse_ray_count_" + current_band).c_str(), ImGuiPopupFlags_MouseButtonRight);
3177 if (diffuse_ray_count_dict[current_band] != prev_diffuse_ray_count) {
3178 radiation->setDiffuseRayCount(current_band, diffuse_ray_count_dict[current_band]);
3179 }
3180 }
3181 // ####### SCATTERING DEPTH ####### //
3182 ImGui::SetNextItemWidth(100);
3183 int prev_scattering_depth;
3184 if (current_band == "All") {
3185 prev_scattering_depth = scattering_depth;
3186 ImGui::InputInt("Scattering Depth", &scattering_depth);
3187 randomizePopup("scattering_depth", createTaggedPtr(&scattering_depth));
3188 randomizerParams("scattering_depth");
3189 ImGui::OpenPopupOnItemClick("randomize_scattering_depth", ImGuiPopupFlags_MouseButtonRight);
3190 if (scattering_depth <= 0) {
3191 scattering_depth = prev_scattering_depth;
3192 }
3193 if (prev_scattering_depth != scattering_depth) {
3194 for (std::string band: bandlabels) {
3195 radiation->setScatteringDepth(band, scattering_depth);
3196 scattering_depth_dict[band] = scattering_depth;
3197 }
3198 }
3199 } else {
3200 prev_scattering_depth = scattering_depth_dict[current_band];
3201 ImGui::InputInt("Scattering Depth", &scattering_depth_dict[current_band]);
3202 randomizePopup("scattering_depth_" + current_band, createTaggedPtr(&scattering_depth_dict[current_band]));
3203 randomizerParams("scattering_depth_" + current_band);
3204 ImGui::OpenPopupOnItemClick(("randomize_scattering_depth_" + current_band).c_str(), ImGuiPopupFlags_MouseButtonRight);
3205 if (scattering_depth_dict[current_band] <= 0) { // scattering depth must be >0
3206 scattering_depth_dict[current_band] = prev_scattering_depth;
3207 }
3208 if (prev_scattering_depth != scattering_depth_dict[current_band]) {
3209 radiation->setScatteringDepth(current_band, scattering_depth_dict[current_band]);
3210 }
3211 }
3212 // ####### RADIATIVE PROPERTIES ####### //
3213 ImGui::SetWindowFontScale(1.25f);
3214 ImGui::Text("Radiative Properties:");
3215 ImGui::SetWindowFontScale(1.0f);
3216 ImGui::SetNextItemWidth(100);
3217 // ######### SELECT DATA GROUP ############//
3218 if (ImGui::Button("Refresh###data_groups_refresh")) {
3219 updatePrimitiveTypes();
3220 updateDataGroups();
3221 }
3222 ImGui::SameLine();
3223 ImGui::SetNextItemWidth(150);
3224 if (ImGui::BeginCombo("##data_group_primitive", current_data_group.c_str())) {
3225 for (std::string data_group: data_groups_set) {
3226 bool is_data_group_selected = (current_data_group == data_group);
3227 if (ImGui::Selectable(data_group.c_str(), is_data_group_selected))
3228 current_data_group = data_group;
3229 if (is_data_group_selected)
3230 ImGui::SetItemDefaultFocus();
3231 }
3232 ImGui::EndCombo();
3233 }
3234 ImGui::SameLine();
3235 ImGui::SetNextItemWidth(100);
3236 ImGui::Text("Select Data Group");
3237 // default primitive data group
3238 // ######### SELECT PRIMITIVE ############//
3239 if (ImGui::Button("Refresh")) {
3240 updatePrimitiveTypes();
3241 updateDataGroups();
3242 }
3243 ImGui::SameLine();
3244 ImGui::SetNextItemWidth(150);
3245 if (ImGui::BeginCombo("##combo_primitive", current_primitive.c_str())) {
3246 for (int m = 0; m < primitive_names.size(); m++) {
3247 bool is_primitive_selected = (current_primitive == primitive_names[m]);
3248 if (ImGui::Selectable(primitive_names[m].c_str(), is_primitive_selected))
3249 current_primitive = primitive_names[m];
3250 if (is_primitive_selected)
3251 ImGui::SetItemDefaultFocus();
3252 }
3253 ImGui::EndCombo();
3254 }
3255 ImGui::SameLine();
3256 ImGui::SetNextItemWidth(100);
3257 ImGui::Text("Select Primitive Type");
3258 if (current_data_group == "All") {
3259 // REFLECTIVITY
3260 ImGui::Text("Reflectivity:");
3261 std::string toggle_display_reflectivity = "Manual Entry";
3262 bool reflectivity_continuous = primitive_continuous[current_primitive][0];
3263 toggle_button("##reflectivity_toggle", &reflectivity_continuous);
3264 if (reflectivity_continuous != primitive_continuous[current_primitive][0]) {
3265 if (current_primitive == "All") {
3266 for (auto &prim_values: primitive_continuous) {
3267 primitive_continuous[prim_values.first][0] = reflectivity_continuous;
3268 }
3269 }
3270 primitive_continuous[current_primitive][0] = reflectivity_continuous;
3271 }
3272 if (primitive_continuous[current_primitive][0]) {
3273 toggle_display_reflectivity = "File Entry";
3274 }
3275 ImGui::SameLine();
3276 ImGui::SetNextItemWidth(250);
3277 if (!primitive_continuous[current_primitive][0]) {
3278 ImGui::Text("Select band:");
3279 ImGui::SameLine();
3280 ImGui::SetNextItemWidth(60);
3281 if (ImGui::BeginCombo("##combo_band_reflectivity", current_band_reflectivity.c_str())) {
3282 for (int n = 0; n < bandlabels.size(); n++) {
3283 bool is_band_selected = (current_band_reflectivity == bandlabels[n]);
3284 if (ImGui::Selectable(bandlabels[n].c_str(), is_band_selected))
3285 current_band_reflectivity = bandlabels[n];
3286 if (is_band_selected)
3287 ImGui::SetItemDefaultFocus();
3288 }
3289 ImGui::EndCombo();
3290 }
3291 ImGui::SameLine();
3292 ImGui::Text("Enter value:");
3293 ImGui::SameLine();
3294 ImGui::SetNextItemWidth(80);
3295 if (current_primitive == "All") {
3296 float prev_reflectivity = reflectivity;
3297 ImGui::InputFloat("##reflectivity_all", &reflectivity);
3298 if (reflectivity != prev_reflectivity) {
3299 for (auto &prim_values: primitive_values[current_band_reflectivity]) {
3300 primitive_values[current_band_reflectivity][prim_values.first][0] = reflectivity;
3301 }
3302 }
3303 } else {
3304 ImGui::InputFloat("##reflectivity", &primitive_values[current_band_reflectivity][current_primitive][0]);
3305 }
3306 } else {
3307 std::string reflectivity_prev = primitive_spectra[current_primitive][0];
3308 if (ImGui::BeginCombo("##reflectivity_combo_all", reflectivity_prev.c_str())) {
3309 for (auto &spectra: possible_spectra) {
3310 bool is_spectra_selected = (primitive_spectra[current_primitive][0] == spectra);
3311 if (ImGui::Selectable(spectra.c_str(), is_spectra_selected))
3312 primitive_spectra[current_primitive][0] = spectra;
3313 if (is_spectra_selected)
3314 ImGui::SetItemDefaultFocus();
3315 }
3316 ImGui::EndCombo();
3317 }
3318 if (current_primitive == "All" && reflectivity_prev != primitive_spectra[current_primitive][0]) {
3319 for (auto &prim_spectrum: primitive_spectra) {
3320 primitive_spectra[prim_spectrum.first][0] = primitive_spectra[current_primitive][0];
3321 }
3322 }
3323 }
3324 ImGui::SameLine();
3325 ImGui::Text("%s", toggle_display_reflectivity.c_str());
3326 // TRANSMISSIVITY
3327 ImGui::Text("Transmissivity:");
3328 std::string toggle_display_transmissivity = "Manual Entry";
3329 bool transmissivity_continuous = primitive_continuous[current_primitive][1];
3330 toggle_button("##transmissivity_toggle", &transmissivity_continuous);
3331 if (transmissivity_continuous != primitive_continuous[current_primitive][1]) {
3332 if (current_primitive == "All") {
3333 for (auto &prim_values: primitive_continuous) {
3334 primitive_continuous[prim_values.first][1] = transmissivity_continuous;
3335 }
3336 }
3337 primitive_continuous[current_primitive][1] = transmissivity_continuous;
3338 }
3339 if (primitive_continuous[current_primitive][1]) {
3340 toggle_display_transmissivity = "File Entry";
3341 }
3342 ImGui::SameLine();
3343 ImGui::SetNextItemWidth(250);
3344 if (!primitive_continuous[current_primitive][1]) {
3345 ImGui::Text("Select band:");
3346 ImGui::SameLine();
3347 ImGui::SetNextItemWidth(60);
3348 if (ImGui::BeginCombo("##combo_band_transmissivity", current_band_transmissivity.c_str())) {
3349 for (int n = 0; n < bandlabels.size(); n++) {
3350 bool is_band_selected = (current_band_transmissivity == bandlabels[n]);
3351 if (ImGui::Selectable(bandlabels[n].c_str(), is_band_selected))
3352 current_band_transmissivity = bandlabels[n];
3353 if (is_band_selected)
3354 ImGui::SetItemDefaultFocus();
3355 }
3356 ImGui::EndCombo();
3357 }
3358 ImGui::SameLine();
3359 ImGui::Text("Enter value:");
3360 ImGui::SameLine();
3361 ImGui::SetNextItemWidth(80);
3362 if (current_primitive == "All") {
3363 float prev_transmissivity = transmissivity;
3364 ImGui::InputFloat("##transmissivity_all", &transmissivity);
3365 if (transmissivity != prev_transmissivity) {
3366 for (auto &prim_values: primitive_values[current_band_transmissivity]) {
3367 primitive_values[current_band_transmissivity][prim_values.first][1] = transmissivity;
3368 }
3369 }
3370 } else {
3371 ImGui::InputFloat("##transmissivity", &primitive_values[current_band_transmissivity][current_primitive][1]);
3372 }
3373 } else {
3374 std::string transmissivity_prev = primitive_spectra[current_primitive][1];
3375 if (ImGui::BeginCombo("##transmissivity_combo", transmissivity_prev.c_str())) {
3376 for (auto &spectra: possible_spectra) {
3377 bool is_spectra_selected = (primitive_spectra[current_primitive][1] == spectra);
3378 if (ImGui::Selectable(spectra.c_str(), is_spectra_selected))
3379 primitive_spectra[current_primitive][1] = spectra;
3380 if (is_spectra_selected)
3381 ImGui::SetItemDefaultFocus();
3382 }
3383 ImGui::EndCombo();
3384 }
3385 if (current_primitive == "All" && transmissivity_prev != primitive_spectra[current_primitive][1]) {
3386 for (auto &prim_spectrum: primitive_spectra) {
3387 primitive_spectra[prim_spectrum.first][1] = primitive_spectra[current_primitive][1];
3388 }
3389 }
3390 }
3391 ImGui::SameLine();
3392 ImGui::Text("%s", toggle_display_transmissivity.c_str());
3393 // EMISSIVITY
3394 ImGui::Text("Emissivity:");
3395 // ImGui::SetNextItemWidth(250);
3396 // ImGui::Text("");
3397 ImGui::Dummy(ImVec2(35.f, 0.f));
3398 ImGui::SameLine();
3399 ImGui::Text("Select band:");
3400 ImGui::SameLine();
3401 ImGui::SetNextItemWidth(60);
3402 if (ImGui::BeginCombo("##combo_band_emissivity", current_band_emissivity.c_str())) {
3403 for (std::string band: bandlabels_set_emissivity) {
3404 bool is_band_selected = (current_band_emissivity == band);
3405 if (ImGui::Selectable(band.c_str(), is_band_selected))
3406 current_band_emissivity = band;
3407 if (is_band_selected)
3408 ImGui::SetItemDefaultFocus();
3409 }
3410 ImGui::EndCombo();
3411 }
3412 ImGui::SameLine();
3413 ImGui::Text("Enter value:");
3414 ImGui::SameLine();
3415 ImGui::SetNextItemWidth(80);
3416 if (current_primitive == "All") {
3417 float prev_emissivity = emissivity;
3418 ImGui::InputFloat("##emissivity_all", &emissivity);
3419 if (emissivity != prev_emissivity) {
3420 for (auto &prim_values: primitive_values[current_band_emissivity]) {
3421 primitive_values[current_band_emissivity][prim_values.first][2] = emissivity;
3422 }
3423 }
3424 } else {
3425 ImGui::InputFloat("##emissivity", &primitive_values[current_band_emissivity][current_primitive][2]);
3426 }
3427 ImGui::SameLine();
3428 ImGui::Text("Manual Entry");
3429 } else { // specific data group
3430 // REFLECTIVITY
3431 ImGui::Text("Reflectivity:");
3432 std::string toggle_display_reflectivity = "Manual Entry";
3433 bool reflectivity_continuous = primitive_continuous_dict[current_data_group][current_primitive][0];
3434 toggle_button("##reflectivity_toggle", &reflectivity_continuous);
3435 if (reflectivity_continuous != primitive_continuous_dict[current_data_group][current_primitive][0]) {
3436 if (current_primitive == "All") {
3437 for (auto &prim_values: primitive_continuous_dict[current_data_group]) {
3438 primitive_continuous_dict[current_data_group][prim_values.first][0] = reflectivity_continuous;
3439 }
3440 }
3441 primitive_continuous_dict[current_data_group][current_primitive][0] = reflectivity_continuous;
3442 }
3443 if (primitive_continuous_dict[current_data_group][current_primitive][0]) {
3444 toggle_display_reflectivity = "File Entry";
3445 }
3446 ImGui::SameLine();
3447 ImGui::SetNextItemWidth(250);
3448 if (!primitive_continuous_dict[current_data_group][current_primitive][0]) {
3449 ImGui::Text("Select band:");
3450 ImGui::SameLine();
3451 ImGui::SetNextItemWidth(60);
3452 if (ImGui::BeginCombo("##combo_band_reflectivity", current_band_reflectivity.c_str())) {
3453 for (int n = 0; n < bandlabels.size(); n++) {
3454 bool is_band_selected = (current_band_reflectivity == bandlabels[n]);
3455 if (ImGui::Selectable(bandlabels[n].c_str(), is_band_selected))
3456 current_band_reflectivity = bandlabels[n];
3457 if (is_band_selected)
3458 ImGui::SetItemDefaultFocus();
3459 }
3460 ImGui::EndCombo();
3461 }
3462 ImGui::SameLine();
3463 ImGui::Text("Enter value:");
3464 ImGui::SameLine();
3465 ImGui::SetNextItemWidth(80);
3466 if (current_primitive == "All") {
3467 float prev_reflectivity = reflectivity;
3468 ImGui::InputFloat("##reflectivity_all", &reflectivity);
3469 if (reflectivity != prev_reflectivity) {
3470 for (auto &prim_values: primitive_values_dict[current_data_group][current_band_reflectivity]) {
3471 primitive_values_dict[current_data_group][current_band_reflectivity][prim_values.first][0] = reflectivity;
3472 }
3473 }
3474 } else {
3475 ImGui::InputFloat("##reflectivity", &primitive_values_dict[current_data_group][current_band_reflectivity][current_primitive][0]);
3476 }
3477 } else {
3478 std::string reflectivity_prev = primitive_spectra_dict[current_data_group][current_primitive][0];
3479 if (ImGui::BeginCombo("##reflectivity_combo", reflectivity_prev.c_str())) {
3480 for (auto &spectra: possible_spectra) {
3481 bool is_spectra_selected = (primitive_spectra_dict[current_data_group][current_primitive][0] == spectra);
3482 if (ImGui::Selectable(spectra.c_str(), is_spectra_selected))
3483 primitive_spectra_dict[current_data_group][current_primitive][0] = spectra;
3484 if (is_spectra_selected)
3485 ImGui::SetItemDefaultFocus();
3486 }
3487 ImGui::EndCombo();
3488 }
3489 if (current_primitive == "All" && reflectivity_prev != primitive_spectra_dict[current_data_group][current_primitive][0]) {
3490 for (auto &prim_spectrum: primitive_spectra_dict[current_data_group]) {
3491 primitive_spectra_dict[current_data_group][prim_spectrum.first][0] = primitive_spectra_dict[current_data_group][current_primitive][0];
3492 }
3493 }
3494 }
3495 ImGui::SameLine();
3496 ImGui::TextUnformatted("%s", toggle_display_reflectivity.c_str());
3497 // TRANSMISSIVITY
3498 ImGui::Text("Transmissivity:");
3499 std::string toggle_display_transmissivity = "Manual Entry";
3500 bool transmissivity_continuous = primitive_continuous_dict[current_data_group][current_primitive][1];
3501 toggle_button("##transmissivity_toggle", &transmissivity_continuous);
3502 if (transmissivity_continuous != primitive_continuous_dict[current_data_group][current_primitive][1]) {
3503 if (current_primitive == "All") {
3504 for (auto &prim_values: primitive_continuous_dict[current_data_group]) {
3505 primitive_continuous_dict[current_data_group][prim_values.first][1] = transmissivity_continuous;
3506 }
3507 }
3508 primitive_continuous_dict[current_data_group][current_primitive][1] = transmissivity_continuous;
3509 }
3510 if (primitive_continuous_dict[current_data_group][current_primitive][1]) {
3511 toggle_display_transmissivity = "File Entry";
3512 }
3513 ImGui::SameLine();
3514 ImGui::SetNextItemWidth(250);
3515 if (!primitive_continuous_dict[current_data_group][current_primitive][1]) {
3516 ImGui::Text("Select band:");
3517 ImGui::SameLine();
3518 ImGui::SetNextItemWidth(60);
3519 if (ImGui::BeginCombo("##combo_band_transmissivity", current_band_transmissivity.c_str())) {
3520 for (int n = 0; n < bandlabels.size(); n++) {
3521 bool is_band_selected = (current_band_transmissivity == bandlabels[n]);
3522 if (ImGui::Selectable(bandlabels[n].c_str(), is_band_selected))
3523 current_band_transmissivity = bandlabels[n];
3524 if (is_band_selected)
3525 ImGui::SetItemDefaultFocus();
3526 }
3527 ImGui::EndCombo();
3528 }
3529 ImGui::SameLine();
3530 ImGui::Text("Enter value:");
3531 ImGui::SameLine();
3532 ImGui::SetNextItemWidth(80);
3533 if (current_primitive == "All") {
3534 float prev_transmissivity = transmissivity;
3535 ImGui::InputFloat("##transmissivity_all", &transmissivity);
3536 if (transmissivity != prev_transmissivity) {
3537 for (auto &prim_values: primitive_values_dict[current_data_group][current_band_transmissivity]) {
3538 primitive_values_dict[current_data_group][current_band_transmissivity][prim_values.first][1] = transmissivity;
3539 }
3540 }
3541 } else {
3542 ImGui::InputFloat("##transmissivity", &primitive_values_dict[current_data_group][current_band_transmissivity][current_primitive][1]);
3543 }
3544 } else {
3545 std::string transmissivity_prev = primitive_spectra_dict[current_data_group][current_primitive][1];
3546 if (ImGui::BeginCombo("##transmissivity_combo", transmissivity_prev.c_str())) {
3547 for (auto &spectra: possible_spectra) {
3548 bool is_spectra_selected = (primitive_spectra_dict[current_data_group][current_primitive][1] == spectra);
3549 if (ImGui::Selectable(spectra.c_str(), is_spectra_selected))
3550 primitive_spectra_dict[current_data_group][current_primitive][1] = spectra;
3551 if (is_spectra_selected)
3552 ImGui::SetItemDefaultFocus();
3553 }
3554 ImGui::EndCombo();
3555 }
3556 if (current_primitive == "All" && transmissivity_prev != primitive_spectra_dict[current_data_group][current_primitive][1]) {
3557 for (auto &prim_spectrum: primitive_spectra_dict[current_data_group]) {
3558 primitive_spectra_dict[current_data_group][prim_spectrum.first][1] = primitive_spectra_dict[current_data_group][current_primitive][1];
3559 }
3560 }
3561 }
3562 ImGui::SameLine();
3563 ImGui::TextUnformatted("%s", toggle_display_transmissivity.c_str());
3564 // EMISSIVITY
3565 ImGui::Text("Emissivity:");
3566 // ImGui::SetNextItemWidth(250);
3567 // ImGui::Text("");
3568 ImGui::Dummy(ImVec2(35.f, 0.f));
3569 ImGui::SameLine();
3570 ImGui::Text("Select band:");
3571 ImGui::SameLine();
3572 ImGui::SetNextItemWidth(60);
3573 if (ImGui::BeginCombo("##combo_band_emissivity", current_band_emissivity.c_str())) {
3574 for (std::string band: bandlabels_set_emissivity) {
3575 bool is_band_selected = (current_band_emissivity == band);
3576 if (ImGui::Selectable(band.c_str(), is_band_selected))
3577 current_band_emissivity = band;
3578 if (is_band_selected)
3579 ImGui::SetItemDefaultFocus();
3580 }
3581 ImGui::EndCombo();
3582 }
3583 ImGui::SameLine();
3584 ImGui::Text("Enter value:");
3585 ImGui::SameLine();
3586 ImGui::SetNextItemWidth(80);
3587 if (current_primitive == "All") {
3588 float prev_emissivity = emissivity;
3589 ImGui::InputFloat("##emissivity_all", &emissivity);
3590 if (emissivity != prev_emissivity) {
3591 for (auto &prim_values: primitive_values_dict[current_data_group][current_band_emissivity]) {
3592 primitive_values_dict[current_data_group][current_band_emissivity][prim_values.first][2] = emissivity;
3593 }
3594 }
3595 } else {
3596 ImGui::InputFloat("##emissivity", &primitive_values_dict[current_data_group][current_band_emissivity][current_primitive][2]);
3597 }
3598 ImGui::SameLine();
3599 ImGui::Text("Manual Entry");
3600 }
3601
3602 ImGui::EndTabItem();
3603 }
3604 } // RADIATION_MODEL
3605#endif // RADIATION_MODEL
3606 if (enable_radiation) {
3607 // RIG TAB
3608 if (ImGui::BeginTabItem("Rig")) {
3609 current_tab = "Rig";
3610 if (ImGui::BeginCombo("##rig_combo", current_rig.c_str())) {
3611 for (auto rig_label: rig_labels_set) {
3612 bool is_rig_selected = (current_rig == rig_label);
3613 if (ImGui::Selectable(rig_label.c_str(), is_rig_selected))
3614 current_rig = rig_label;
3615 current_cam_position = "0";
3616 if (is_rig_selected)
3617 ImGui::SetItemDefaultFocus();
3618 }
3619 ImGui::EndCombo();
3620 }
3621 ImGui::SameLine();
3622 if (ImGui::Button("Add Rig")) {
3623 std::string default_rig_label = "rig";
3624 std::string new_rig_label = "rig_0";
3625 int count = 0;
3626 while (rig_dict.find(new_rig_label) != rig_dict.end()) {
3627 count++;
3628 new_rig_label = default_rig_label + "_" + std::to_string(count);
3629 }
3630 rig_dict.insert({new_rig_label, scast<int>(rig_labels.size())});
3631 camera_positions.push_back(camera_position);
3632 camera_lookats.push_back(camera_lookat);
3633 camera_labels.push_back(camera_label);
3634 camera_position_vec.push_back(camera_position_vec[rig_dict[current_rig]]);
3635 camera_lookat_vec.push_back(camera_lookat_vec[rig_dict[current_rig]]);
3636 rig_labels.push_back(new_rig_label);
3637 rig_labels_set.insert(new_rig_label);
3638 rig_camera_labels.push_back(rig_camera_labels[rig_dict[current_rig]]);
3639 rig_light_labels.push_back(rig_light_labels[rig_dict[current_rig]]);
3640 keypoint_frames.push_back(keypoint_frames[rig_dict[current_rig]]);
3641 num_images_vec.push_back(num_images_vec[rig_dict[current_rig]]);
3642 rig_colors.push_back(rig_colors[rig_dict[current_rig]]);
3643 rig_position_noise.push_back(std::vector<distribution>{distribution{}, distribution{}, distribution{}});
3644 rig_lookat_noise.push_back(std::vector<distribution>{distribution{}, distribution{}, distribution{}});
3645 // current_rig = new_rig_label;
3646 std::string parent = "rig";
3647 pugi::xml_node rig_block = helios.child(parent.c_str());
3648 pugi::xml_node new_rig_node = helios.append_copy(rig_block);
3649 std::string name = "label";
3650 pugi::xml_attribute node_label = new_rig_node.attribute(name.c_str());
3651 node_label.set_value(new_rig_label.c_str());
3652 current_rig = new_rig_label;
3653 }
3654 if (!current_rig.empty()) {
3655 // ##### UPDATE RIG ######//
3656 // if (ImGui::Button("Update Rig")){
3657 // updateRigs();
3658 // }
3659 // ImGui::SameLine();
3660 if (ImGui::Button("Delete Rig")) {
3661 deleteRig(current_rig);
3662 }
3663 // ##### RIG NAME ######//
3664 ImGui::SetNextItemWidth(100);
3665 std::string prev_rig_name = rig_labels[rig_dict[current_rig]];
3666 ImGui::InputText("##rig_name", &rig_labels[rig_dict[current_rig]]);
3667 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()) {
3668 int temp = rig_dict[current_rig];
3669 current_rig = rig_labels[rig_dict[current_rig]];
3670 std::map<std::string, int>::iterator current_rig_iter = rig_dict.find(prev_rig_name);
3671 if (current_rig_iter != rig_dict.end()) {
3672 rig_dict.erase(current_rig_iter);
3673 }
3674 rig_dict[current_rig] = temp;
3675 rig_labels_set.erase(prev_rig_name);
3676 rig_labels_set.insert(rig_labels[rig_dict[current_rig]]);
3677 } else {
3678 rig_labels[rig_dict[current_rig]] = prev_rig_name;
3679 }
3680 ImGui::SameLine();
3681 ImGui::Text("Rig Name");
3682 // ####### WRITE DEPTH ####### //
3683 bool write_depth_ = write_depth[rig_dict[current_rig]];
3684 ImGui::Checkbox("Write Depth Images", &write_depth_);
3685 write_depth[rig_dict[current_rig]] = write_depth_;
3686 ImGui::SameLine();
3687 bool write_norm_depth_ = write_norm_depth[rig_dict[current_rig]];
3688 ImGui::Checkbox("Write Norm Depth Images", &write_norm_depth_);
3689 write_norm_depth[rig_dict[current_rig]] = write_norm_depth_;
3690 // ####### BOUNDING BOXES ####### //
3691 if (ImGui::BeginPopup("multi_select_popup")) {
3692 for (auto &box_pair: bounding_boxes) {
3693 ImGui::Selectable(box_pair.first.c_str(), &box_pair.second, ImGuiSelectableFlags_DontClosePopups);
3694 }
3695 ImGui::EndPopup();
3696 }
3697 if (ImGui::Button("Select Bounding Box Objects")) {
3698 ImGui::OpenPopup("multi_select_popup");
3699 }
3700 // ImGui::OpenPopupOnItemClick(("rig_position_noise_" + std::to_string(rig_dict[current_rig])).c_str(), ImGuiPopupFlags_MouseButtonLeft);
3701 // Display selected items
3702 ImGui::Text("Objects:");
3703 int idx = 0;
3704 for (auto &box_pair: bounding_boxes) {
3705 if (box_pair.second) {
3706 ImGui::SameLine(), ImGui::Text("%i. %s", idx, box_pair.first.c_str());
3707 idx++;
3708 }
3709 }
3710 // ####### RIG COLOR ####### //
3711 float col[3];
3712 col[0] = rig_colors[rig_dict[current_rig]].r;
3713 col[1] = rig_colors[rig_dict[current_rig]].g;
3714 col[2] = rig_colors[rig_dict[current_rig]].b;
3715 ImGui::ColorEdit3("##rig_color_edit", col);
3716 updateColor(current_rig, "rig", col);
3717 ImGui::SameLine();
3718 ImGui::Text("Rig Color");
3719 // ####### CAMERA LABEL ####### //
3720 /* SINGLE CAMERA VERSION
3721 ImGui::SetNextItemWidth(60);
3722 // ImGui::InputText("Camera Label", &camera_labels[rig_dict[(std::string) current_rig]]);
3723 if (ImGui::BeginCombo("##cam_label_combo", camera_labels[rig_dict[(std::string) current_rig]].c_str())){
3724 for (int n = 0; n < camera_names.size(); n++){
3725 bool is_cam_label_selected = (camera_labels[rig_dict[(std::string) current_rig]] == camera_names[n]); // You can store your selection however you want, outside or inside your objects
3726 if (ImGui::Selectable(camera_names[n].c_str(), is_cam_label_selected)){
3727 camera_labels[rig_dict[(std::string) current_rig]] = camera_names[n];
3728 }
3729 if (is_cam_label_selected)
3730 ImGui::SetItemDefaultFocus(); // You may set the initial focus when opening the combo (scrolling + for keyboard navigation support)
3731 }
3732 ImGui::EndCombo();
3733 }
3734 ImGui::SameLine();
3735 ImGui::Text("Camera Label");
3736 ImGui::EndTabItem();
3737 */
3738 // ####### CAMERA CHECKBOX ####### //
3739 ImGui::Text("Cameras:");
3740 for (int i = 0; i < camera_names.size(); i++) {
3741 std::string &camera_name = camera_names[i];
3742
3743 ImGui::SetNextItemWidth(60);
3744
3745 std::set curr_set = rig_camera_labels[rig_dict[current_rig]];
3746 // if (i % 3 != 0){
3747 // ImGui::SameLine();
3748 // }
3749 bool isCameraSelected = curr_set.find(camera_name) != curr_set.end();
3750 ImGui::PushID(i);
3751 if (ImGui::Checkbox(camera_name.c_str(), &isCameraSelected)) {
3752 if (isCameraSelected) {
3753 rig_camera_labels[rig_dict[current_rig]].insert(camera_name);
3754 } else {
3755 rig_camera_labels[rig_dict[current_rig]].erase(camera_name);
3756 }
3757 }
3758 ImGui::PopID();
3759 }
3760 // ####### LIGHT CHECKBOX ####### //
3761 ImGui::Text("Lights:");
3762 for (int i = 0; i < light_names.size(); i++) {
3763 std::string &light_name = light_names[i];
3764
3765 ImGui::SetNextItemWidth(60);
3766
3767 std::set curr_rig_light = rig_light_labels[rig_dict[current_rig]];
3768 bool isLightSelected = curr_rig_light.find(light_name) != curr_rig_light.end();
3769 ImGui::PushID(i);
3770 if (ImGui::Checkbox(light_name.c_str(), &isLightSelected)) {
3771 if (isLightSelected) {
3772 rig_light_labels[rig_dict[current_rig]].insert(light_name);
3773 } else {
3774 rig_light_labels[rig_dict[current_rig]].erase(light_name);
3775 }
3776 }
3777 ImGui::PopID();
3778 }
3779 // ####### ADD KEYPOINT ####### //
3780 std::stringstream cam_pos_value;
3781 cam_pos_value << current_cam_position.c_str();
3782 int current_cam_position_;
3783 cam_pos_value >> current_cam_position_;
3784 current_keypoint = std::to_string(keypoint_frames[rig_dict[current_rig]][current_cam_position_]);
3785 std::string modified_current_keypoint = std::to_string(keypoint_frames[rig_dict[current_rig]][current_cam_position_] + 1); // 1-indexed value
3786 if (ImGui::BeginCombo("##cam_combo", modified_current_keypoint.c_str())) {
3787 for (int n = 1; n <= camera_position_vec[rig_dict[current_rig]].size(); n++) {
3788 std::string select_cam_position = std::to_string(n - 1);
3789 std::string selected_keypoint = std::to_string(keypoint_frames[rig_dict[current_rig]][n - 1]);
3790 bool is_pos_selected = (current_cam_position == select_cam_position);
3791 std::string modified_selected_keypoint = std::to_string(keypoint_frames[rig_dict[current_rig]][n - 1] + 1); // 1-indexed value
3792 if (ImGui::Selectable(modified_selected_keypoint.c_str(), is_pos_selected)) {
3793 current_cam_position = std::to_string(n - 1);
3794 }
3795 if (is_pos_selected)
3796 ImGui::SetItemDefaultFocus();
3797 }
3798 ImGui::EndCombo();
3799 }
3800 cam_pos_value << current_cam_position.c_str();
3801 cam_pos_value >> current_cam_position_;
3802 ImGui::SameLine();
3803 if (ImGui::Button("Add Keypoint")) {
3804 camera_position_vec[rig_dict[current_rig]].push_back(camera_position_vec[rig_dict[current_rig]][current_cam_position_]);
3805 camera_lookat_vec[rig_dict[current_rig]].push_back(camera_lookat_vec[rig_dict[current_rig]][current_cam_position_]);
3806 keypoint_frames[rig_dict[current_rig]].push_back(keypoint_frames[rig_dict[current_rig]].back() + 1);
3807 is_dirty = true;
3808 }
3809 // ####### KEYPOINT FRAME ####### //
3810 ImGui::SetNextItemWidth(80);
3811 int modified_keypoint_frame = keypoint_frames[rig_dict[current_rig]][current_cam_position_] + 1; // 1-indexed value
3812 ImGui::InputInt("Keypoint Frame", &modified_keypoint_frame);
3813 if (modified_keypoint_frame != keypoint_frames[rig_dict[current_rig]][current_cam_position_] + 1) {
3814 keypoint_frames[rig_dict[current_rig]][current_cam_position_] = modified_keypoint_frame - 1;
3815 }
3816 // ####### CAMERA POSITION ####### //
3817 vec3 prev_rig_position_ = camera_position_vec[rig_dict[current_rig]][current_cam_position_];
3818 ImGui::SetNextItemWidth(60);
3819 ImGui::InputFloat("##camera_position_x", &camera_position_vec[rig_dict[current_rig]][current_cam_position_].x);
3820 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));
3821 randomizerParams("camera_position_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
3822 ImGui::OpenPopupOnItemClick(("randomize_camera_position_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3823 ImGui::SameLine();
3824 ImGui::SetNextItemWidth(60);
3825 ImGui::InputFloat("##camera_position_y", &camera_position_vec[rig_dict[current_rig]][current_cam_position_].y);
3826 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));
3827 randomizerParams("camera_position_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
3828 ImGui::OpenPopupOnItemClick(("randomize_camera_position_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3829 ImGui::SameLine();
3830 ImGui::SetNextItemWidth(60);
3831 ImGui::InputFloat("##camera_position_z", &camera_position_vec[rig_dict[current_rig]][current_cam_position_].z);
3832 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));
3833 randomizerParams("camera_position_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
3834 ImGui::OpenPopupOnItemClick(("randomize_camera_position_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3835 ImGui::SameLine();
3836 ImGui::Text("Rig Position");
3837 ImGui::SameLine();
3838 ImGui::Button("Add Noise###position");
3839 noisePopup("rig_position_noise_" + std::to_string(rig_dict[current_rig]), rig_lookat_noise[rig_dict[current_rig]]);
3840 ImGui::OpenPopupOnItemClick(("rig_position_noise_" + std::to_string(rig_dict[current_rig])).c_str(), ImGuiPopupFlags_MouseButtonLeft);
3841 // ####### CAMERA LOOKAT ####### //
3842 vec3 prev_rig_lookat_ = camera_lookat_vec[rig_dict[current_rig]][current_cam_position_];
3843 ImGui::SetNextItemWidth(60);
3844 ImGui::InputFloat("##camera_lookat_x", &camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].x);
3845 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));
3846 randomizerParams("camera_lookat_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
3847 ImGui::OpenPopupOnItemClick(("randomize_camera_lookat_x_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3848 ImGui::SameLine();
3849 ImGui::SetNextItemWidth(60);
3850 ImGui::InputFloat("##camera_lookat_y", &camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].y);
3851 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));
3852 randomizerParams("camera_lookat_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
3853 ImGui::OpenPopupOnItemClick(("randomize_camera_lookat_y_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3854 ImGui::SameLine();
3855 ImGui::SetNextItemWidth(60);
3856 ImGui::InputFloat("##camera_lookat_z", &camera_lookat_vec[rig_dict[current_rig]][current_cam_position_].z);
3857 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));
3858 randomizerParams("camera_lookat_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_));
3859 ImGui::OpenPopupOnItemClick(("randomize_camera_lookat_z_" + std::to_string(rig_dict[current_rig]) + std::to_string(current_cam_position_)).c_str(), ImGuiPopupFlags_MouseButtonRight);
3860 ImGui::SameLine();
3861 ImGui::Text("Rig Lookat");
3862 ImGui::SameLine();
3863 ImGui::Button("Add Noise###lookat");
3864 noisePopup("rig_lookat_noise_" + std::to_string(rig_dict[current_rig]), rig_lookat_noise[rig_dict[current_rig]]);
3865 ImGui::OpenPopupOnItemClick(("rig_lookat_noise_" + std::to_string(rig_dict[current_rig])).c_str(), ImGuiPopupFlags_MouseButtonLeft);
3866 // ####### NUMBER OF IMAGES ####### //
3867 ImGui::SetNextItemWidth(80);
3868 ImGui::InputInt("Total Number of Frames", &num_images_vec[rig_dict[current_rig]]);
3869 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);
3870
3871 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_]) {
3872 updateRigs();
3873 }
3874 }
3875 ImGui::EndTabItem();
3876 }
3877 // CAMERA TAB
3878 if (ImGui::BeginTabItem("Camera")) {
3879 current_tab = "Camera";
3880 // LOAD XML LIBRARY FILE
3881 ImGui::SetNextItemWidth(60);
3882 if (ImGui::Button("Load XML Library File")) {
3883 std::string new_xml_library_file = file_dialog();
3884 if (!new_xml_library_file.empty() && std::filesystem::exists(new_xml_library_file)) {
3885 if (camera_xml_library_files.find(new_xml_library_file) == camera_xml_library_files.end()) {
3886 camera_xml_library_files.insert(new_xml_library_file);
3887 std::vector<std::string> current_camera_file = get_xml_node_values(new_xml_library_file, "label", "globaldata_vec2");
3888 possible_camera_calibrations.insert(possible_camera_calibrations.end(), current_camera_file.begin(), current_camera_file.end());
3889 }
3890 context->loadXML(new_xml_library_file.c_str());
3891 }
3892 }
3893
3894 // ####### ADD BAND GROUP ####### //
3895 ImGui::SetWindowFontScale(1.25f);
3896 ImGui::Text("Band Groups:");
3897 ImGui::SetWindowFontScale(1.0f);
3898 dropDown("##band_group_combo", current_band_group, band_group_names);
3899 ImGui::SameLine();
3900 if (ImGui::Button("Add Band Group")) {
3901 std::string default_band_group_label = "band_group";
3902 std::string new_band_group_label = "band_group_0";
3903 int count = 0;
3904 while (band_group_lookup.find(new_band_group_label) != band_group_lookup.end()) {
3905 count++;
3906 new_band_group_label = default_band_group_label + "_" + std::to_string(count);
3907 }
3908 std::vector<std::string> new_band_group_vector;
3909 new_band_group_vector.push_back("red");
3910 new_band_group_vector.push_back("green");
3911 new_band_group_vector.push_back("blue");
3912 bandGroup new_band_group{new_band_group_vector, false, false};
3913 band_group_lookup[new_band_group_label] = new_band_group;
3914 band_group_names.insert(new_band_group_label);
3915 current_band_group = new_band_group_label;
3916 }
3917 if (!current_band_group.empty()) {
3918 ImGui::SetNextItemWidth(100);
3919 std::string prev_group_name = current_band_group;
3920 ImGui::InputText("Group Name", &current_band_group);
3921 if (current_band_group.empty() || band_group_lookup.find(current_band_group) != band_group_lookup.end()) {
3922 current_band_group = prev_group_name;
3923 }
3924 if (current_band_group != prev_group_name) {
3925 bandGroup temp = band_group_lookup[prev_group_name];
3926 std::map<std::string, bandGroup>::iterator current_band_group_iter = band_group_lookup.find(prev_group_name);
3927 if (current_band_group_iter != band_group_lookup.end()) {
3928 band_group_lookup.erase(current_band_group_iter);
3929 }
3930 band_group_lookup[current_band_group] = temp;
3931 band_group_names.erase(prev_group_name);
3932 band_group_names.insert(current_band_group);
3933 }
3934 ImGui::SameLine();
3935 if (ImGui::Button("Delete Group")) {
3936 band_group_names.erase(current_band_group);
3937 band_group_lookup.erase(current_band_group);
3938 current_band_group = "";
3939 }
3940 ImGui::Checkbox("Grayscale", &band_group_lookup[current_band_group].grayscale);
3941 ImGui::SameLine();
3942 ImGui::Checkbox("Norm", &band_group_lookup[current_band_group].norm);
3943 // Band 1
3944 ImGui::SetNextItemWidth(100);
3945 dropDown("##band_1_combo", band_group_lookup[current_band_group].bands[0], bandlabels);
3946 if (!band_group_lookup[current_band_group].grayscale) {
3947 // Band 2
3948 ImGui::SameLine();
3949 ImGui::SetNextItemWidth(100);
3950 dropDown("##band_2_combo", band_group_lookup[current_band_group].bands[1], bandlabels);
3951 // Band 3
3952 ImGui::SameLine();
3953 ImGui::SetNextItemWidth(100);
3954 dropDown("##band_3_combo", band_group_lookup[current_band_group].bands[2], bandlabels);
3955 ImGui::SameLine();
3956 ImGui::Text("Select Bands");
3957 } else {
3958 ImGui::SameLine();
3959 ImGui::Text("Select Band");
3960 }
3961 }
3962 ImGui::SetWindowFontScale(1.25f);
3963 ImGui::Text("Edit Camera:");
3964 ImGui::SetWindowFontScale(1.0f);
3965 if (ImGui::BeginCombo("##camera_combo", current_cam.c_str())) {
3966 for (int n = 0; n < camera_names.size(); n++) {
3967 bool is_cam_selected = (current_cam == camera_names[n]);
3968 if (ImGui::Selectable(camera_names[n].c_str(), is_cam_selected))
3969 current_cam = camera_names[n];
3970 if (is_cam_selected)
3971 ImGui::SetItemDefaultFocus();
3972 }
3973 ImGui::EndCombo();
3974 }
3975 ImGui::SameLine();
3976 if (ImGui::Button("Add New Camera")) {
3977 std::string default_cam_name = "camera";
3978 std::string new_cam_name = "camera_0";
3979 int count = 0;
3980 while (camera_dict.find(new_cam_name) != camera_dict.end()) {
3981 count++;
3982 new_cam_name = default_cam_name + "_" + std::to_string(count);
3983 }
3984 camera_dict.insert({new_cam_name, scast<int>(camera_names.size())});
3985 camera_resolutions.push_back(camera_resolution);
3986 camera_calibrations.push_back(camera_calibrations[camera_dict[current_cam]]);
3987 focal_plane_distances.push_back(focal_plane_distance);
3988 lens_diameters.push_back(lens_diameter);
3989 FOV_aspect_ratios.push_back(FOV_aspect_ratio);
3990 HFOVs.push_back(HFOV);
3991 camera_names.push_back(new_cam_name);
3992 std::string parent = "camera";
3993 pugi::xml_node camera_block = helios.child(parent.c_str());
3994 pugi::xml_node new_cam_node = helios.append_copy(camera_block);
3995 std::string name = "label";
3996 pugi::xml_attribute node_label = new_cam_node.attribute(name.c_str());
3997 node_label.set_value(new_cam_name.c_str());
3998 current_cam = new_cam_name;
3999 }
4000 ImGui::SetNextItemWidth(100);
4001 std::string prev_cam_name = camera_names[camera_dict[current_cam]];
4002 ImGui::InputText("##cam_name", &camera_names[camera_dict[current_cam]]);
4003 if (camera_names[camera_dict[current_cam]] != prev_cam_name) {
4004 int temp = camera_dict[current_cam];
4005 current_cam = camera_names[camera_dict[current_cam]];
4006 std::map<std::string, int>::iterator current_cam_iter = camera_dict.find(prev_cam_name);
4007 if (current_cam_iter != camera_dict.end()) {
4008 camera_dict.erase(current_cam_iter);
4009 }
4010 camera_dict[current_cam] = temp;
4011 }
4012 ImGui::SameLine();
4013 ImGui::Text("Camera Label");
4014 // ####### CAMERA CALIBRATION ####### //
4015 ImGui::SetNextItemWidth(100);
4016 dropDown("##camera_calibration_band", current_calibration_band, bandlabels);
4017 ImGui::SameLine();
4018 ImGui::Text("Band");
4019 ImGui::SetNextItemWidth(250);
4020 ImGui::SameLine();
4021 dropDown("##camera_band_group_combo", camera_calibrations[camera_dict[current_cam]][current_calibration_band], possible_camera_calibrations);
4022 ImGui::SameLine();
4023 ImGui::Text("Calibration");
4024 // ####### CAMERA CALIBRATION ####### //
4025 // std::string prev_cam_calibration = camera_calibrations[camera_dict[current_cam]];
4026 // if (ImGui::BeginCombo("##camera_calibration_combo", camera_calibrations[camera_dict[current_cam]].c_str())){
4027 // for (int n = 0; n < possible_camera_calibrations.size(); n++){
4028 // bool is_cam_calibration_selected = (camera_calibrations[camera_dict[current_cam]] == possible_camera_calibrations[n]);
4029 // if (ImGui::Selectable(possible_camera_calibrations[n].c_str(), is_cam_calibration_selected))
4030 // camera_calibrations[camera_dict[current_cam]] = possible_camera_calibrations[n];
4031 // if (is_cam_calibration_selected)
4032 // ImGui::SetItemDefaultFocus();
4033 // }
4034 // ImGui::EndCombo();
4035 // }
4036 // ImGui::SameLine();
4037 // ImGui::Text("Camera Calibration");
4038 // ####### CAMERA RESOLUTION ####### //
4039 ImGui::SetNextItemWidth(90);
4040 ImGui::InputInt("##camera_resolution_x", &camera_resolutions[camera_dict[current_cam]].x);
4041 randomizePopup("camera_resolution_x_" + std::to_string(camera_dict[current_cam]), createTaggedPtr(&camera_resolutions[camera_dict[current_cam]].x));
4042 randomizerParams("camera_resolution_x_" + std::to_string(camera_dict[current_cam]));
4043 ImGui::OpenPopupOnItemClick(("randomize_camera_resolution_x_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4044 ImGui::SameLine();
4045 ImGui::SetNextItemWidth(90);
4046 ImGui::InputInt("##camera_resolution_y", &camera_resolutions[camera_dict[current_cam]].y);
4047 randomizePopup("camera_resolution_y_" + std::to_string(camera_dict[current_cam]), createTaggedPtr(&camera_resolutions[camera_dict[current_cam]].y));
4048 randomizerParams("camera_resolution_y_" + std::to_string(camera_dict[current_cam]));
4049 ImGui::OpenPopupOnItemClick(("randomize_camera_resolution_y_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4050 ImGui::SameLine();
4051 ImGui::Text("Camera Resolution");
4052 // ####### FOCAL PLANE DISTANCE ####### //
4053 ImGui::SetNextItemWidth(50);
4054 ImGui::InputFloat("Focal Plane Distance", &focal_plane_distances[camera_dict[current_cam]]);
4055 randomizePopup("focal_plane_distance_" + std::to_string(camera_dict[current_cam]), createTaggedPtr(&focal_plane_distances[camera_dict[current_cam]]));
4056 randomizerParams("focal_plane_distance_" + std::to_string(camera_dict[current_cam]));
4057 ImGui::OpenPopupOnItemClick(("randomize_focal_plane_distance_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4058 // ####### LENS DIAMETER ####### //
4059 ImGui::SetNextItemWidth(50);
4060 ImGui::InputFloat("Lens Diameter", &lens_diameters[camera_dict[current_cam]]);
4061 randomizePopup("lens_diameter_" + std::to_string(camera_dict[current_cam]), createTaggedPtr(&lens_diameters[camera_dict[current_cam]]));
4062 randomizerParams("lens_diameter_" + std::to_string(camera_dict[current_cam]));
4063 ImGui::OpenPopupOnItemClick(("randomize_lens_diameter_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4064 // ####### FOV ASPECT RATIO ####### //
4065 ImGui::SetNextItemWidth(50);
4066 ImGui::InputFloat("FOV Aspect Ratio", &FOV_aspect_ratios[camera_dict[current_cam]]);
4067 randomizePopup("FOV_aspect_ratio_" + std::to_string(camera_dict[current_cam]), createTaggedPtr(&FOV_aspect_ratios[camera_dict[current_cam]]));
4068 randomizerParams("FOV_aspect_ratio_" + std::to_string(camera_dict[current_cam]));
4069 ImGui::OpenPopupOnItemClick(("randomize_FOV_aspect_ratio_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4070 // ####### HFOV ####### //
4071 ImGui::SetNextItemWidth(50);
4072 ImGui::InputFloat("HFOV", &HFOVs[camera_dict[current_cam]]);
4073 randomizePopup("HFOV_" + std::to_string(camera_dict[current_cam]), createTaggedPtr(&HFOVs[camera_dict[current_cam]]));
4074 randomizerParams("HFOV_" + std::to_string(camera_dict[current_cam]));
4075 ImGui::OpenPopupOnItemClick(("HFOV_" + std::to_string(camera_dict[current_cam])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4076 //
4077 ImGui::EndTabItem();
4078 }
4079 // LIGHT TAB
4080 if (ImGui::BeginTabItem("Light")) {
4081 current_tab = "Light";
4082 // LOAD XML LIBRARY FILE
4083 ImGui::SetNextItemWidth(60);
4084 if (ImGui::Button("Load XML Library File")) {
4085 std::string new_xml_library_file = file_dialog();
4086 if (!new_xml_library_file.empty() && std::filesystem::exists(new_xml_library_file)) {
4087 if (light_xml_library_files.find(new_xml_library_file) == light_xml_library_files.end()) {
4088 light_xml_library_files.insert(new_xml_library_file);
4089 std::vector<std::string> current_light_file = get_xml_node_values(new_xml_library_file, "label", "globaldata_vec2");
4090 possible_light_spectra.insert(possible_light_spectra.end(), current_light_file.begin(), current_light_file.end());
4091 }
4092 context->loadXML(new_xml_library_file.c_str());
4093 }
4094 }
4095 if (ImGui::BeginCombo("##light_combo", current_light.c_str())) {
4096 for (int n = 0; n < light_names.size(); n++) {
4097 bool is_light_selected = (current_light == light_names[n]);
4098 if (ImGui::Selectable(light_names[n].c_str(), is_light_selected))
4099 current_light = light_names[n];
4100 if (is_light_selected)
4101 ImGui::SetItemDefaultFocus();
4102 }
4103 ImGui::EndCombo();
4104 }
4105 ImGui::SameLine();
4106 if (ImGui::Button("Add Light")) {
4107 std::string default_light_name = "light";
4108 std::string new_light_name = "light_0";
4109 int count = 0;
4110 while (light_dict.find(new_light_name) != light_dict.end()) {
4111 count++;
4112 new_light_name = default_light_name + "_" + std::to_string(count);
4113 }
4114 light_dict.insert({new_light_name, scast<int>(light_names.size())});
4115 light_spectra.push_back(light_spectra[light_dict[current_light]]);
4116 light_types.push_back(light_types[light_dict[current_light]]);
4117 light_direction_vec.push_back(light_direction_vec[light_dict[current_light]]);
4118 light_direction_sph_vec.push_back(light_direction_sph_vec[light_dict[current_light]]);
4119 light_rotation_vec.push_back(light_rotation_vec[light_dict[current_light]]);
4120 light_size_vec.push_back(light_size_vec[light_dict[current_light]]);
4121 light_radius_vec.push_back(light_radius_vec[light_dict[current_light]]);
4122 light_names.push_back(new_light_name);
4123 light_flux_vec.push_back(light_flux_vec[light_dict[current_light]]);
4124 std::string parent = "light";
4125 pugi::xml_node light_block = helios.child(parent.c_str());
4126 pugi::xml_node new_light_node = helios.append_copy(light_block);
4127 std::string name = "label";
4128 pugi::xml_attribute node_label = new_light_node.attribute(name.c_str());
4129 node_label.set_value(new_light_name.c_str());
4130 current_light = new_light_name;
4131 }
4132 ImGui::SetNextItemWidth(100);
4133 std::string prev_light_name = light_names[light_dict[current_light]];
4134 ImGui::InputText("##light_name", &light_names[light_dict[current_light]]);
4135 if (light_names[light_dict[current_light]] != prev_light_name) {
4136 int temp = light_dict[current_light];
4137 current_light = light_names[light_dict[current_light]];
4138 std::map<std::string, int>::iterator current_light_iter = light_dict.find(prev_light_name);
4139 if (current_light_iter != light_dict.end()) {
4140 light_dict.erase(current_light_iter);
4141 }
4142 light_dict[current_light] = temp;
4143 }
4144 ImGui::SameLine();
4145 ImGui::Text("Light Label");
4146 // ####### LIGHT SPECTRA ####### //
4147 std::string prev_light_spectra = light_spectra[light_dict[current_light]];
4148 if (ImGui::BeginCombo("##light_spectra_combo", light_spectra[light_dict[current_light]].c_str())) {
4149 for (int n = 0; n < possible_light_spectra.size(); n++) {
4150 bool is_light_spectra_selected = (light_spectra[light_dict[current_light]] == possible_light_spectra[n]);
4151 if (ImGui::Selectable(possible_light_spectra[n].c_str(), is_light_spectra_selected))
4152 light_spectra[light_dict[current_light]] = possible_light_spectra[n];
4153 if (is_light_spectra_selected)
4154 ImGui::SetItemDefaultFocus();
4155 }
4156 ImGui::EndCombo();
4157 }
4158 ImGui::SameLine();
4159 ImGui::Text("Light Spectrum");
4160 // ####### LIGHT TYPE ############ //
4161 if (ImGui::BeginCombo("##light_type_combo", light_types[light_dict[current_light]].c_str())) {
4162 for (int n = 0; n < all_light_types.size(); n++) {
4163 bool is_type_selected = (light_types[light_dict[current_light]] == all_light_types[n]);
4164 if (ImGui::Selectable(all_light_types[n].c_str(), is_type_selected)) {
4165 light_types[light_dict[current_light]] = all_light_types[n];
4166 }
4167 if (is_type_selected)
4168 ImGui::SetItemDefaultFocus();
4169 }
4170 ImGui::EndCombo();
4171 }
4172 ImGui::SameLine();
4173 ImGui::Text("Light Type");
4174 // collimated -> direction
4175 // disk -> position, radius, rotation
4176 // sphere -> position, radius
4177 // sunsphere -> direction
4178 // rectangle -> position, size, rotation
4179 // ####### LIGHT DIRECTION ####### //
4180 if (light_types[light_dict[(std::string) current_light]] == "collimated" || light_types[light_dict[(std::string) current_light]] == "sunsphere") {
4181 ImGui::SetNextItemWidth(90);
4182 ImGui::InputFloat("##light_direction_x", &light_direction_vec[light_dict[current_light]].x);
4183 randomizePopup("light_direction_x_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_direction_vec[light_dict[current_light]].x));
4184 randomizerParams("light_direction_x_" + std::to_string(light_dict[current_light]));
4185 ImGui::OpenPopupOnItemClick(("light_direction_x_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4186 ImGui::SameLine();
4187 ImGui::SetNextItemWidth(90);
4188 ImGui::InputFloat("##light_direction_y", &light_direction_vec[light_dict[current_light]].y);
4189 randomizePopup("light_direction_y_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_direction_vec[light_dict[current_light]].y));
4190 randomizerParams("light_direction_y_" + std::to_string(light_dict[current_light]));
4191 ImGui::OpenPopupOnItemClick(("light_direction_y_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4192 ImGui::SameLine();
4193 ImGui::SetNextItemWidth(90);
4194 ImGui::InputFloat("##light_direction_z", &light_direction_vec[light_dict[current_light]].z);
4195 randomizePopup("light_direction_z_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_direction_vec[light_dict[current_light]].z));
4196 randomizerParams("light_direction_z_" + std::to_string(light_dict[current_light]));
4197 ImGui::OpenPopupOnItemClick(("light_direction_z_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4198 ImGui::SameLine();
4199 ImGui::Text("Light Direction");
4200 }
4201 // ####### LIGHT SOURCE FLUX ####### //
4202 ImGui::SetNextItemWidth(90);
4203 ImGui::InputFloat("##source_flux", &light_flux_vec[light_dict[current_light]]);
4204 randomizePopup("source_flux_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_flux_vec[light_dict[current_light]]));
4205 randomizerParams("source_flux_" + std::to_string(light_dict[current_light]));
4206 ImGui::OpenPopupOnItemClick(("source_flux_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4207 ImGui::SameLine();
4208 ImGui::Text("Source Flux");
4209 // radiation->setSourceFlux(light_UUID, band, flux_value);
4210 // ####### LIGHT ROTATION ####### //
4211 if (light_types[light_dict[current_light]] == "disk" || light_types[light_dict[current_light]] == "rectangle") {
4212 ImGui::SetNextItemWidth(90);
4213 ImGui::InputFloat("##light_rotation_x", &light_rotation_vec[light_dict[current_light]].x);
4214 randomizePopup("light_rotation_x_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_rotation_vec[light_dict[current_light]].x));
4215 randomizerParams("light_rotation_x_" + std::to_string(light_dict[current_light]));
4216 ImGui::OpenPopupOnItemClick(("light_rotation_x_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4217 ImGui::SameLine();
4218 ImGui::SetNextItemWidth(90);
4219 ImGui::InputFloat("##light_rotation_y", &light_rotation_vec[light_dict[current_light]].y);
4220 randomizePopup("light_rotation_y_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_rotation_vec[light_dict[current_light]].y));
4221 randomizerParams("light_rotation_y_" + std::to_string(light_dict[current_light]));
4222 ImGui::OpenPopupOnItemClick(("light_rotation_y_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4223 ImGui::SameLine();
4224 ImGui::SetNextItemWidth(90);
4225 ImGui::InputFloat("##light_rotation_z", &light_rotation_vec[light_dict[current_light]].z);
4226 randomizePopup("light_rotation_z_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_rotation_vec[light_dict[current_light]].z));
4227 randomizerParams("light_rotation_z_" + std::to_string(light_dict[current_light]));
4228 ImGui::OpenPopupOnItemClick(("light_rotation_z_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4229 ImGui::SameLine();
4230 ImGui::Text("Light Rotation");
4231 }
4232 // ####### LIGHT SIZE ####### //
4233 if (light_types[light_dict[current_light]] == "rectangle") {
4234 ImGui::SetNextItemWidth(90);
4235 ImGui::InputFloat("##light_size_x", &light_size_vec[light_dict[current_light]].x);
4236 randomizePopup("light_size_x_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_size_vec[light_dict[current_light]].x));
4237 randomizerParams("light_size_x_" + std::to_string(light_dict[current_light]));
4238 ImGui::OpenPopupOnItemClick(("light_size_x_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4239 ImGui::SameLine();
4240 ImGui::SetNextItemWidth(90);
4241 ImGui::InputFloat("##light_size_y", &light_size_vec[light_dict[current_light]].y);
4242 randomizePopup("light_size_y_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_size_vec[light_dict[current_light]].y));
4243 randomizerParams("light_size_y_" + std::to_string(light_dict[current_light]));
4244 ImGui::OpenPopupOnItemClick(("light_size_y_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4245 ImGui::SameLine();
4246 ImGui::Text("Light Size");
4247 }
4248 // ####### LIGHT RADIUS ####### //
4249 if (light_types[light_dict[current_light]] == "disk" || light_types[light_dict[current_light]] == "sphere") {
4250 ImGui::SetNextItemWidth(90);
4251 ImGui::InputFloat("##light_radius", &light_radius_vec[light_dict[current_light]]);
4252 randomizePopup("light_radius_" + std::to_string(light_dict[current_light]), createTaggedPtr(&light_radius_vec[light_dict[current_light]]));
4253 randomizerParams("light_radius_" + std::to_string(light_dict[current_light]));
4254 ImGui::OpenPopupOnItemClick(("light_radius_" + std::to_string(light_dict[current_light])).c_str(), ImGuiPopupFlags_MouseButtonRight);
4255 ImGui::SameLine();
4256 ImGui::Text("Light Radius");
4257 }
4258 // LIGHT END
4259 ImGui::EndTabItem();
4260 }
4261 }
4262 ImGui::EndTabBar();
4263 }
4264 // ImGui::Text("Hello, world %d", 123);
4265 // ImGui::Button("Save");
4266 // if (ImGui::Button("Save"))
4267 // std::cout << "here" << std::endl;
4268 last_position = current_position;
4269 previously_collapsed = currently_collapsed;
4270 ImGui::End();
4271
4272 if (is_dirty && !ImGui::IsMouseDragging(ImGuiMouseButton_Left) && !ImGui::IsMouseDown(ImGuiMouseButton_Left)) {
4274 // TODO: requery primitive types here
4275 // updatePrimitiveTypes();
4276 // refreshVisualizationTypes();
4278 is_dirty = false;
4279 }
4280
4281 // Rendering
4282 // (Your code clears your framebuffer, renders your other stuff etc.)
4283 // glClearColor(0.1f, 0.1f, 0.1f, 1.0f); // Set a background color (e.g., dark grey)
4284 // glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
4285 visualizer->plotOnce(!io.WantCaptureMouse);
4286 ImGui::Render();
4287 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
4288 glfwSwapBuffers(window);
4289 if (!io.WantCaptureMouse && !ImGui::IsAnyItemHovered()) {
4290 glfwWaitEvents();
4291 }
4292 // (Your code calls glfwSwapBuffers() etc.)
4293
4294 std::this_thread::sleep_for(std::chrono::milliseconds(100 / 6));
4295 }
4296
4297 ImGui_ImplOpenGL3_Shutdown();
4298 ImGui_ImplGlfw_Shutdown();
4299 ImGui::DestroyContext();
4300// }else{
4301#else
4302 std::cout << "Visualizer plugin is required for this function." << std::endl;
4303// } //HELIOS_VISUALIZER
4304#endif // HELIOS_VISUALIZER
4305}
4306
4307
4308void ProjectBuilder::buildAndVisualize(std::string xml_path) {
4309 buildFromXML(xml_path);
4310 visualize();
4311}
4312
4313
4318
4319
4321 // MAIN BLOCK
4322 // *** Latitude *** //
4323 xmlSetValue("latitude", "helios", latitude);
4324 xmlSetDistribution("latitude_dist", "helios", distributions[distribution_dict["latitude"]]);
4325 // *** Longitude *** //
4326 xmlSetValue("longitude", "helios", longitude);
4327 xmlSetDistribution("longitude_dist", "helios", distributions[distribution_dict["longitude"]]);
4328 // *** UTC Offset *** //
4329 xmlSetValue("UTC_offset", "helios", UTC_offset);
4330 xmlSetDistribution("UTC_offset_dist", "helios", distributions[distribution_dict["UTC_offset"]]);
4331 // *** CSV Weather File *** //
4332 xmlSetValue("csv_weather_file", "helios", csv_weather_file);
4333 // *** Domain Origin *** //
4334 xmlSetValue("domain_origin", "helios", domain_origin);
4335 xmlSetDistribution("domain_origin_x_dist", "helios", distributions[distribution_dict["domain_origin_x"]]);
4336 xmlSetDistribution("domain_origin_y_dist", "helios", distributions[distribution_dict["domain_origin_y"]]);
4337 xmlSetDistribution("domain_origin_z_dist", "helios", distributions[distribution_dict["domain_origin_z"]]);
4338 // *** Domain Extent *** //
4339 xmlSetValue("domain_extent", "helios", domain_extent);
4340 xmlSetDistribution("domain_extent_x_dist", "helios", distributions[distribution_dict["domain_extent_x"]]);
4341 xmlSetDistribution("domain_extent_y_dist", "helios", distributions[distribution_dict["domain_extent_y"]]);
4342 // *** Ground Resolution *** //
4343 xmlSetValue("ground_resolution", "helios", ground_resolution);
4344 xmlSetDistribution("ground_resolution_x_dist", "helios", distributions[distribution_dict["ground_resolution_x"]]);
4345 xmlSetDistribution("ground_resolution_y_dist", "helios", distributions[distribution_dict["ground_resolution_y"]]);
4346 // *** Ground Texture File *** //
4347 xmlSetValue("ground_texture_file", "helios", ground_texture_file);
4348 // *** Camera XML Library File *** //
4349 xmlSetValues("camera_xml_library_file", "helios", camera_xml_library_files);
4350 // *** Light XML Library File *** //
4351 xmlSetValues("light_xml_library_file", "helios", light_xml_library_files);
4352 // OBJECT BLOCK
4353 // Delete from XML doc
4354 helios = xmldoc.child("helios");
4355 pugi::xml_node node;
4356 node = helios.child("object");
4357 if (node) {
4358 node.parent().remove_child(node);
4359 }
4360 // Refresh lists
4361 obj_names.clear();
4362 obj_files.clear();
4363 obj_positions.clear();
4364 obj_orientations.clear();
4365 obj_scales.clear();
4366 obj_colors.clear();
4367 obj_data_groups.clear();
4368 for (std::string obj_name: obj_names_set) {
4369 object curr_obj = objects_dict[obj_name];
4370 obj_names.push_back(curr_obj.name);
4371 obj_files.push_back(curr_obj.file);
4372 obj_positions.push_back(curr_obj.position);
4373 obj_orientations.push_back(curr_obj.orientation);
4374 obj_scales.push_back(curr_obj.scale);
4375 obj_colors.push_back(curr_obj.color);
4376 obj_data_groups.push_back(curr_obj.data_group);
4377 }
4378 //
4379 setNodeLabels("label", "object", obj_names_set);
4380 xmlSetValues("file", "object", obj_files, obj_names_dict);
4381 xmlSetValues("position", "object", obj_positions, obj_names_dict);
4382 xmlSetValues("orientation", "object", obj_orientations, obj_names_dict);
4383 xmlSetValues("scale", "object", obj_scales, obj_names_dict);
4384 xmlSetValues("color", "object", obj_colors, obj_names_dict);
4385 xmlSetValues("data_group", "object", obj_data_groups, obj_names_dict);
4386// CANOPY BLOCK
4387#ifdef ENABLE_PLANT_ARCHITECTURE
4388 // Delete from XML doc
4389 helios = xmldoc.child("helios");
4390 node = helios.child("canopy");
4391 if (node) {
4392 node.parent().remove_child(node);
4393 }
4394 // Refresh lists
4395 plant_ages.clear();
4396 ground_clipping_heights.clear();
4397 canopy_labels.clear();
4398 plant_library_names.clear();
4399 plant_library_names_verbose.clear();
4400 canopy_IDs.clear();
4401 individual_plant_locations.clear();
4402 plant_spacings.clear();
4403 plant_counts.clear();
4404 canopy_origins.clear();
4405 canopy_data_groups.clear();
4406 for (std::string canopy_name: canopy_labels_set) {
4407 canopy curr_canopy = canopy_dict[canopy_name];
4408 plant_ages.push_back(curr_canopy.age);
4409 ground_clipping_heights.push_back(curr_canopy.ground_clipping_height);
4410 canopy_labels.push_back(curr_canopy.label);
4411 plant_library_names.push_back(curr_canopy.library_name);
4412 plant_library_names_verbose.push_back(curr_canopy.library_name_verbose);
4413 canopy_IDs.push_back(curr_canopy.IDs);
4414 individual_plant_locations.push_back(curr_canopy.individual_plant_locations);
4415 plant_spacings.push_back(curr_canopy.plant_spacing);
4416 plant_counts.push_back(curr_canopy.plant_count);
4417 canopy_origins.push_back(curr_canopy.origin);
4418 canopy_data_groups.push_back(curr_canopy.data_group);
4419 }
4420 //
4421 setNodeLabels("label", "canopy_block", canopy_labels_set);
4422 xmlSetValue("canopy_origin", "canopy_block", canopy_origin);
4423 xmlSetValue("plant_count", "canopy_block", plant_count);
4424 xmlSetValue("plant_spacing", "canopy_block", plant_spacing);
4425 xmlSetValue("plant_library_name", "canopy_block", plant_library_name);
4426 xmlSetValue("plant_age", "canopy_block", plant_age);
4427 xmlSetValue("ground_clipping_height", "canopy_block", ground_clipping_height);
4428 xmlSetValues("canopy_origin", "canopy_block", canopy_origins, canopy_labels_dict);
4429 xmlSetValues("plant_count", "canopy_block", plant_counts, canopy_labels_dict);
4430 xmlSetValues("plant_spacing", "canopy_block", plant_spacings, canopy_labels_dict);
4431 xmlSetValues("plant_library_name", "canopy_block", plant_library_names, canopy_labels_dict);
4432 xmlSetValues("plant_age", "canopy_block", plant_ages, canopy_labels_dict);
4433 xmlSetValues("ground_clipping_height", "canopy_block", ground_clipping_heights, canopy_labels_dict);
4434 xmlSetValues("data_group", "canopy_block", canopy_data_groups, canopy_labels_dict);
4435#endif
4436 // RIG BLOCK
4437 // Delete from XML doc
4438 helios = xmldoc.child("helios");
4439 node = helios.child("rig");
4440 if (node) {
4441 node.parent().remove_child(node);
4442 }
4443 setNodeLabels("label", "rig", rig_labels_set);
4444 xmlSetValues("color", "rig", rig_colors, rig_dict);
4445 // xmlSetValue("camera_position", "rig", camera_position);
4446 // xmlSetValue("camera_lookat", "rig", camera_lookat);
4447 xmlSetValue("camera_label", "rig", camera_label);
4448 // xmlSetValues("camera_position", "rig", camera_positions);
4449 xmlSetValues("camera_position", "rig", camera_position_vec, rig_dict);
4450 // xmlSetValues("camera_lookat", "rig", camera_lookats);
4451 xmlSetValues("camera_lookat", "rig", camera_lookat_vec, rig_dict);
4452 // xmlSetValues("camera_label", "rig", camera_labels);
4453 xmlSetValues("camera_label", "rig", rig_camera_labels, rig_dict);
4454 setKeypoints("keypoint", "camera_position", keypoint_frames);
4455 xmlSetValues("images", "rig", num_images_vec, rig_dict);
4456 std::vector<int> write_depth_{};
4457 std::vector<int> write_norm_depth_{};
4458 for (int i = 0; i < write_depth.size(); i++) {
4459 if (write_depth[i]) {
4460 write_depth_.push_back(1);
4461 } else {
4462 write_depth_.push_back(0);
4463 }
4464 if (write_norm_depth[i]) {
4465 write_norm_depth_.push_back(1);
4466 } else {
4467 write_norm_depth_.push_back(0);
4468 }
4469 }
4470 xmlSetValues("depth", "rig", write_depth_, rig_dict);
4471 xmlSetValues("normdepth", "rig", write_norm_depth_, rig_dict);
4472 // CAMERA BLOCK
4473 setNodeLabels("label", "camera", camera_names_set);
4474 xmlSetValue("camera_resolution", "camera", camera_resolution);
4475 xmlSetValue("focal_plane_distance", "camera", focal_plane_distance);
4476 xmlSetValue("lens_diameter", "camera", lens_diameter);
4477 xmlSetValue("FOV_aspect_ratio", "camera", FOV_aspect_ratio);
4478 xmlSetValue("HFOV", "camera", HFOV);
4479 xmlSetValues("camera_resolution", "camera", camera_resolutions, camera_dict);
4480 for (std::string &band: bandlabels) {
4481 for (std::string &camera: camera_names) {
4482 xmlSetValue("camera_calibration_" + band, "camera", camera_calibrations[camera_dict[camera]][band]);
4483 }
4484 }
4485 xmlSetValues("focal_plane_distance", "camera", focal_plane_distances, camera_dict);
4486 xmlSetValues("lens_diameter", "camera", lens_diameters, camera_dict);
4487 xmlSetValues("FOV_aspect_ratio", "camera", FOV_aspect_ratios, camera_dict);
4488 xmlSetValues("HFOV", "camera", HFOVs, camera_dict);
4489 // LIGHT BLOCK
4490 setNodeLabels("label", "light", light_names_set);
4491 xmlSetValues("light_type", "light", light_types, light_dict);
4492 xmlSetValues("light_spectra", "light", light_spectra, light_dict);
4493 xmlSetValues("light_direction", "light", light_direction_vec, light_dict);
4494 xmlSetValues("light_rotation", "light", light_rotation_vec, light_dict);
4495 xmlSetValues("light_size", "light", light_size_vec, light_dict);
4496 xmlSetValues("light_source_flux", "light", light_flux_vec, light_dict);
4497 xmlSetValues("light_radius", "light", light_radius_vec, light_dict);
4498 xmlSetValues("light_label", "rig", rig_light_labels, light_dict);
4499 // RADIATION BLOCK
4500 xmlSetValue("direct_ray_count", "radiation", direct_ray_count);
4501 xmlSetValue("diffuse_ray_count", "radiation", diffuse_ray_count);
4502 xmlSetValue("diffuse_extinction_coeff", "radiation", diffuse_extinction_coeff);
4503 xmlSetValue("scattering_depth", "radiation", scattering_depth);
4504 xmlSetValue("air_turbidity", "radiation", air_turbidity);
4505 xmlSetValues("load_xml_library_file", "radiation", xml_library_files);
4506 xmlSetValue("solar_direct_spectrum", "radiation", solar_direct_spectrum);
4507 xmlSetValue("leaf_reflectivity_spectrum", "radiation", leaf_reflectivity_spectrum);
4508 xmlSetValue("leaf_transmissivity_spectrum", "radiation", leaf_transmissivity_spectrum);
4509 xmlSetValue("leaf_emissivity", "radiation", leaf_emissivity);
4510 xmlSetValue("ground_reflectivity_spectrum", "radiation", ground_reflectivity_spectrum);
4511 for (std::string prim: primitive_names) {
4512 if (prim == "All")
4513 continue;
4514 // Reflectivity
4515 if (primitive_continuous[prim][0]) {
4516 xmlSetValue(prim + "_reflectivity_spectrum", "radiation", primitive_spectra[prim][0]);
4517 } else {
4518 xmlRemoveField(prim + "_reflectivity_spectrum", "radiation");
4519 }
4520 // Transmissivity
4521 if (primitive_continuous[prim][1]) {
4522 xmlSetValue(prim + "_transmissivity_spectrum", "radiation", primitive_spectra[prim][1]);
4523 } else {
4524 xmlRemoveField(prim + "_transmissivity_spectrum", "radiation");
4525 }
4526 for (std::string band: bandlabels) {
4527 if (band == "All")
4528 continue;
4529 xmlSetValue(prim + "_reflectivity", "radiation", primitive_values[band][prim][0]);
4530 xmlSetValue(prim + "_transmissivity", "radiation", primitive_values[band][prim][1]);
4531 xmlSetValue(prim + "_emissivity", "radiation", primitive_values[band][prim][2]);
4532 }
4533 }
4534 xmldoc.save_file(xml_input_file.c_str());
4535}
4536
4537
4538void ProjectBuilder::xmlSetValues(std::string xml_path) {
4539 xml_input_file = xml_path;
4540 if (!open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
4541 helios_runtime_error(xml_error_string);
4542 }
4543 xmlSetValues();
4544}
4545
4546
4548 distribution curr_distribution = distribution{};
4549 // MAIN BLOCK
4550 // *** Latitude *** //
4551 xmlGetValue("latitude", "helios", latitude);
4552 curr_distribution = distribution{};
4553 xmlGetDistribution("latitude_dist", "helios", curr_distribution);
4554 applyDistribution("latitude", curr_distribution, createTaggedPtr(&latitude));
4555 // *** Longitude *** //
4556 xmlGetValue("longitude", "helios", longitude);
4557 curr_distribution = distribution{};
4558 xmlGetDistribution("longitude_dist", "helios", curr_distribution);
4559 applyDistribution("longitude", curr_distribution, createTaggedPtr(&longitude));
4560 // *** UTC Offset *** //
4561 xmlGetValue("UTC_offset", "helios", UTC_offset);
4562 curr_distribution = distribution{};
4563 xmlGetDistribution("UTC_offset_dist", "helios", curr_distribution);
4564 applyDistribution("UTC_offset", curr_distribution, createTaggedPtr(&UTC_offset));
4565 // *** CSV Weather File *** //
4566 xmlGetValue("csv_weather_file", "helios", csv_weather_file);
4567 // *** Domain Origin *** //
4568 xmlGetValue("domain_origin", "helios", domain_origin);
4569 curr_distribution = distribution{};
4570 xmlGetDistribution("domain_origin_x_dist", "helios", curr_distribution);
4571 applyDistribution("domain_origin_x", curr_distribution, createTaggedPtr(&domain_origin.x));
4572 curr_distribution = distribution{};
4573 xmlGetDistribution("domain_origin_y_dist", "helios", curr_distribution);
4574 applyDistribution("domain_origin_y", curr_distribution, createTaggedPtr(&domain_origin.y));
4575 curr_distribution = distribution{};
4576 xmlGetDistribution("domain_origin_z_dist", "helios", curr_distribution);
4577 applyDistribution("domain_origin_z", curr_distribution, createTaggedPtr(&domain_origin.z));
4578 // *** Domain Extent *** //
4579 xmlGetValue("domain_extent", "helios", domain_extent);
4580 curr_distribution = distribution{};
4581 xmlGetDistribution("domain_extent_x_dist", "helios", curr_distribution);
4582 applyDistribution("domain_extent_x", curr_distribution, createTaggedPtr(&domain_extent.x));
4583 curr_distribution = distribution{};
4584 xmlGetDistribution("domain_extent_y_dist", "helios", curr_distribution);
4585 applyDistribution("domain_extent_y", curr_distribution, createTaggedPtr(&domain_extent.y));
4586 // *** Ground Resolution *** //
4587 xmlGetValue("ground_resolution", "helios", ground_resolution);
4588 curr_distribution = distribution{};
4589 xmlGetDistribution("ground_resolution_x_dist", "helios", curr_distribution);
4590 applyDistribution("ground_resolution_x", curr_distribution, createTaggedPtr(&ground_resolution.x));
4591 curr_distribution = distribution{};
4592 xmlGetDistribution("ground_resolution_y_dist", "helios", curr_distribution);
4593 applyDistribution("ground_resolution_y", curr_distribution, createTaggedPtr(&ground_resolution.y));
4594 // *** Ground Texture File *** //
4595 xmlGetValue("ground_texture_file", "helios", ground_texture_file);
4596 // *** Camera XML Library Files *** //
4597 xmlGetValues("camera_xml_library_file", "helios", camera_xml_library_files);
4598 possible_camera_calibrations.clear();
4599 for (auto &xml_library_file: camera_xml_library_files) {
4600 if (xml_library_file.empty() || !std::filesystem::exists(xml_library_file)) {
4601 continue;
4602 }
4603 std::vector<std::string> current_camera_file = get_xml_node_values(xml_library_file, "label", "globaldata_vec2");
4604 possible_camera_calibrations.insert(possible_camera_calibrations.end(), current_camera_file.begin(), current_camera_file.end());
4605 }
4606 // *** Light XML Library Files *** //
4607 xmlGetValues("light_xml_library_file", "helios", light_xml_library_files);
4608 possible_light_spectra.clear();
4609 for (auto &xml_library_file: light_xml_library_files) {
4610 if (xml_library_file.empty() || !std::filesystem::exists(xml_library_file)) {
4611 continue;
4612 }
4613 std::vector<std::string> current_light_file = get_xml_node_values(xml_library_file, "label", "globaldata_vec2");
4614 possible_light_spectra.insert(possible_light_spectra.end(), current_light_file.begin(), current_light_file.end());
4615 }
4616 // OBJECT BLOCK
4617 obj_names_dict.clear();
4618 obj_names_dict = getNodeLabels("label", "object", obj_names);
4619 obj_names_set = std::set<std::string>{obj_names.begin(), obj_names.end()};
4620 if (!obj_names.empty())
4621 current_obj = obj_names[0];
4622 xmlGetValues("file", "object", obj_files);
4623 xmlGetValues("position", "object", obj_positions);
4624 xmlGetValues("orientation", "object", obj_orientations);
4625 xmlGetValues("scale", "object", obj_scales);
4626 prev_obj_positions = obj_positions;
4627 prev_obj_orientations = obj_orientations;
4628 prev_obj_scales = obj_scales;
4629 obj_data_groups.clear();
4630 xmlGetValues("data_group", "object", obj_data_groups);
4631 obj_colors.clear();
4632 xmlGetValues("color", "object", obj_colors);
4633
4634 for (auto &obj: objects_dict) {
4635 deleteObject(obj.second.name);
4636 }
4637 objects_dict.clear();
4638 for (int i = 0; i < obj_files.size(); i++) {
4639 object new_object;
4640 std::vector<uint> new_UUIDs;
4641 std::string new_obj_file = obj_files[i];
4642 if (std::filesystem::path(new_obj_file).extension() == ".obj") {
4643 new_UUIDs = context->loadOBJ(new_obj_file.c_str());
4644 } else if (std::filesystem::path(new_obj_file).extension() == ".ply") {
4645 new_UUIDs = context->loadPLY(new_obj_file.c_str());
4646 } else {
4647 std::cout << "Failed to load object file " << new_obj_file << "." << std::endl;
4648 }
4649 // check for MTL file
4650 std::filesystem::path mtl_path(new_obj_file);
4651 mtl_path.replace_extension("mtl");
4652 if (std::filesystem::exists(mtl_path)) {
4653 new_object.use_texture_file = true;
4654 } else {
4655 new_object.use_texture_file = false;
4656 context->setPrimitiveColor(new_UUIDs, obj_colors[i]);
4657 }
4658 context->scalePrimitive(new_UUIDs, obj_scales[i]);
4659 context->rotatePrimitive(new_UUIDs, deg2rad(obj_orientations[i].x), "x");
4660 context->rotatePrimitive(new_UUIDs, deg2rad(obj_orientations[i].y), "y");
4661 context->rotatePrimitive(new_UUIDs, deg2rad(obj_orientations[i].z), "z");
4662 context->translatePrimitive(new_UUIDs, obj_positions[i]);
4663 obj_UUIDs.push_back(new_UUIDs);
4664 new_object.index = obj_idx;
4665 obj_idx++;
4666 new_object.name = obj_names[i];
4667 new_object.file = obj_files[i];
4668 new_object.data_group = obj_data_groups[i];
4669 new_object.UUIDs = new_UUIDs;
4670 new_object.position = obj_positions[i];
4671 new_object.prev_position = obj_positions[i];
4672 new_object.orientation = obj_orientations[i];
4673 new_object.prev_orientation = obj_orientations[i];
4674 new_object.scale = obj_scales[i];
4675 new_object.prev_scale = obj_scales[i];
4676 new_object.color = obj_colors[i];
4677 new_object.prev_color = obj_colors[i];
4678 new_object.is_dirty = false;
4679 objects_dict[new_object.name] = new_object;
4680 }
4681// CANOPY BLOCK
4682#ifdef ENABLE_PLANT_ARCHITECTURE
4683 canopy_labels.clear();
4684 canopy_labels_dict = getNodeLabels("label", "canopy_block", canopy_labels);
4685 for (auto canopy_label_: canopy_labels) {
4686 canopy_labels_set.insert(canopy_label_);
4687 }
4688 if (!canopy_labels.empty())
4689 current_canopy = canopy_labels[0];
4690 xmlGetValue("canopy_origin", "canopy_block", canopy_origin);
4691 xmlGetValue("plant_count", "canopy_block", plant_count);
4692 xmlGetValue("plant_spacing", "canopy_block", plant_spacing);
4693 xmlGetValue("plant_library_name", "canopy_block", plant_library_name);
4694 xmlGetValue("plant_age", "canopy_block", plant_age);
4695 xmlGetValue("ground_clipping_height", "canopy_block", ground_clipping_height);
4696 canopy_origins.clear();
4697 xmlGetValues("canopy_origin", "canopy_block", canopy_origins);
4698 plant_counts.clear();
4699 xmlGetValues("plant_count", "canopy_block", plant_counts);
4700 plant_spacings.clear();
4701 xmlGetValues("plant_spacing", "canopy_block", plant_spacings);
4702 plant_library_names.clear();
4703 xmlGetValues("plant_library_name", "canopy_block", plant_library_names);
4704 for (int i = 0; i < plant_library_names.size(); i++) {
4705 plant_library_names_verbose.push_back(plant_type_verbose_lookup[plant_library_names[i]]);
4706 }
4707 plant_ages.clear();
4708 xmlGetValues("plant_age", "canopy_block", plant_ages);
4709 ground_clipping_heights.clear();
4710 xmlGetValues("ground_clipping_height", "canopy_block", ground_clipping_heights);
4711 canopy_data_groups.clear();
4712 xmlGetValues("data_group", "canopy_block", canopy_data_groups);
4713
4714 canopy_dict.clear();
4715 for (int i = 0; i < canopy_labels.size(); i++) {
4716 canopy new_canopy;
4717 new_canopy.idx = canopy_idx;
4718 canopy_idx++;
4719 new_canopy.age = plant_ages[i];
4720 new_canopy.ground_clipping_height = ground_clipping_heights[i];
4721 new_canopy.label = canopy_labels[i];
4722 new_canopy.library_name = plant_library_names[i];
4723 new_canopy.library_name_verbose = plant_library_names_verbose[i];
4724 new_canopy.IDs = canopy_IDs[i];
4725 new_canopy.individual_plant_locations = individual_plant_locations[i];
4726 new_canopy.plant_spacing = plant_spacings[i];
4727 new_canopy.plant_count = plant_counts[i];
4728 new_canopy.origin = canopy_origins[i];
4729 new_canopy.data_group = canopy_data_groups[i];
4730 new_canopy.is_dirty = false;
4731 canopy_dict[new_canopy.label] = new_canopy;
4732 }
4733#endif
4734
4735// RIG BLOCK
4736#ifdef ENABLE_RADIATION_MODEL
4737 rig_labels.clear();
4738 rig_labels_set.clear();
4739 rig_dict = getNodeLabels("label", "rig", rig_labels);
4740 for (auto rig: rig_labels) {
4741 rig_labels_set.insert(rig);
4742 rig_position_noise.push_back(std::vector<distribution>{distribution{}, distribution{}, distribution{}});
4743 rig_lookat_noise.push_back(std::vector<distribution>{distribution{}, distribution{}, distribution{}});
4744 }
4745 current_rig = rig_labels[0];
4746 xmlGetValues("color", "rig", rig_colors);
4747 xmlGetValue("camera_position", "rig", camera_position);
4748 xmlGetValue("camera_lookat", "rig", camera_lookat);
4749 xmlGetValue("camera_label", "rig", camera_label);
4750 camera_positions.clear();
4751 xmlGetValues("camera_position", "rig", camera_positions);
4752 camera_position_vec.clear();
4753 xmlGetValues("camera_position", "rig", camera_position_vec);
4754 camera_lookats.clear();
4755 xmlGetValues("camera_lookat", "rig", camera_lookats);
4756 camera_lookat_vec.clear();
4757 xmlGetValues("camera_lookat", "rig", camera_lookat_vec);
4758 camera_labels.clear();
4759 xmlGetValues("camera_label", "rig", camera_labels);
4760 rig_camera_labels.clear();
4761 xmlGetValues("camera_label", "rig", rig_camera_labels);
4762 keypoint_frames.clear();
4763 getKeypoints("keypoint", "camera_position", keypoint_frames);
4764 current_keypoint = std::to_string(keypoint_frames[0][0]);
4765 num_images_vec.clear();
4766 xmlGetValues("images", "rig", num_images_vec);
4767 write_depth.clear();
4768 write_norm_depth.clear();
4769 std::vector<int> write_depth_{};
4770 std::vector<int> write_norm_depth_{};
4771 xmlGetValues("depth", "rig", write_depth_);
4772 xmlGetValues("depth", "rig", write_norm_depth_);
4773 for (int i = 0; i < write_depth_.size(); i++) {
4774 if (write_depth_[i] == 1) {
4775 write_depth.push_back(true);
4776 } else {
4777 write_depth.push_back(false);
4778 }
4779 if (write_norm_depth_[i] == 1) {
4780 write_norm_depth.push_back(true);
4781 } else {
4782 write_norm_depth.push_back(false);
4783 }
4784 }
4785 // CAMERA BLOCK
4786 camera_names.clear();
4787 camera_names_set.clear();
4788 camera_dict = getNodeLabels("label", "camera", camera_names);
4789 current_cam = camera_names[0];
4790 xmlGetValue("camera_resolution", "camera", camera_resolution);
4791 xmlGetValue("focal_plane_distance", "camera", focal_plane_distance);
4792 xmlGetValue("lens_diameter", "camera", lens_diameter);
4793 xmlGetValue("FOV_aspect_ratio", "camera", FOV_aspect_ratio);
4794 xmlGetValue("HFOV", "camera", HFOV);
4795 camera_resolutions.clear();
4796 xmlGetValues("camera_resolution", "camera", camera_resolutions);
4797 camera_calibrations.clear();
4798 for (std::string &camera: camera_names) {
4799 camera_calibrations.push_back(std::map<std::string, std::string>{});
4800 for (std::string &band: bandlabels) {
4801 xmlGetValue("camera_calibration_" + band, "camera", camera_calibrations[camera_dict[camera]][band]);
4802 }
4803 camera_names_set.insert(camera);
4804 }
4805 focal_plane_distances.clear();
4806 xmlGetValues("focal_plane_distance", "camera", focal_plane_distances);
4807 lens_diameters.clear();
4808 xmlGetValues("lens_diameter", "camera", lens_diameters);
4809 FOV_aspect_ratios.clear();
4810 xmlGetValues("FOV_aspect_ratio", "camera", FOV_aspect_ratios);
4811 HFOVs.clear();
4812 xmlGetValues("HFOV", "camera", HFOVs);
4813 // LIGHT BLOCK
4814 light_types.clear();
4815 xmlGetValues("light_type", "light", light_types);
4816 light_direction_vec.clear();
4817 xmlGetValues("light_direction", "light", light_direction_vec);
4818 light_direction_sph_vec.clear();
4819 for (vec3 vec: light_direction_vec) {
4820 light_direction_sph_vec.push_back(cart2sphere(vec));
4821 }
4822 light_rotation_vec.clear();
4823 xmlGetValues("light_rotation", "light", light_rotation_vec);
4824 light_size_vec.clear();
4825 xmlGetValues("light_size", "light", light_size_vec);
4826 light_flux_vec.clear();
4827 xmlGetValues("light_source_flux", "light", light_flux_vec);
4828 light_radius_vec.clear();
4829 xmlGetValues("light_radius", "light", light_radius_vec);
4830 light_spectra.clear();
4831 xmlGetValues("light_spectra", "light", light_spectra);
4832 light_names.clear();
4833 light_names_set.clear();
4834 light_dict = getNodeLabels("label", "light", light_names);
4835 for (auto &light: light_names) {
4836 light_names_set.insert(light);
4837 }
4838 current_light = light_names[0];
4839 rig_light_labels.clear();
4840 xmlGetValues("light_label", "rig", rig_light_labels);
4841 // RADIATION BLOCK
4842 xmlGetValue("direct_ray_count", "radiation", direct_ray_count);
4843 xmlGetValue("diffuse_ray_count", "radiation", diffuse_ray_count);
4844 xmlGetValue("diffuse_extinction_coeff", "radiation", diffuse_extinction_coeff);
4845 xmlGetValue("scattering_depth", "radiation", scattering_depth);
4846 xmlGetValue("air_turbidity", "radiation", air_turbidity);
4847 xmlGetValues("load_xml_library_file", "radiation", xml_library_files);
4848 possible_spectra.clear();
4849 for (auto &xml_library_file: xml_library_files) {
4850 if (xml_library_file.empty() || !std::filesystem::exists(xml_library_file)) {
4851 continue;
4852 }
4853 std::vector<std::string> current_spectra_file = get_xml_node_values(xml_library_file, "label", "globaldata_vec2");
4854 for (int i = 0; i < current_spectra_file.size(); i++) {
4855 possible_spectra.insert(current_spectra_file[i]);
4856 }
4857 }
4858 xmlGetValue("solar_direct_spectrum", "radiation", solar_direct_spectrum);
4859 xmlGetValue("leaf_reflectivity_spectrum", "radiation", leaf_reflectivity_spectrum);
4860 xmlGetValue("leaf_transmissivity_spectrum", "radiation", leaf_transmissivity_spectrum);
4861 xmlGetValue("leaf_emissivity", "radiation", leaf_emissivity);
4862 xmlGetValue("ground_reflectivity_spectrum", "radiation", ground_reflectivity_spectrum);
4863 primitive_values.clear();
4864 for (std::string band: bandlabels) {
4865 primitive_values[band];
4866 for (std::string prim: primitive_names) {
4867 primitive_values[band][prim] = {ground_reflectivity, ground_transmissivity, ground_emissivity};
4868 }
4869 }
4870 primitive_spectra.clear();
4871 primitive_spectra = {{"All", {reflectivity_spectrum, transmissivity_spectrum, emissivity_spectrum}},
4872 {"ground", {ground_reflectivity_spectrum, ground_transmissivity_spectrum, ground_emissivity_spectrum}},
4873 {"leaf", {leaf_reflectivity_spectrum, leaf_transmissivity_spectrum, leaf_emissivity_spectrum}},
4874 {"petiolule", {petiolule_reflectivity_spectrum, petiolule_transmissivity_spectrum, petiolule_emissivity_spectrum}},
4875 {"petiole", {petiole_reflectivity_spectrum, petiole_transmissivity_spectrum, petiole_emissivity_spectrum}},
4876 {"internode", {internode_reflectivity_spectrum, internode_transmissivity_spectrum, internode_emissivity_spectrum}},
4877 {"peduncle", {peduncle_reflectivity_spectrum, peduncle_transmissivity_spectrum, peduncle_emissivity_spectrum}},
4878 {"petal", {petal_reflectivity_spectrum, petal_transmissivity_spectrum, petal_emissivity_spectrum}},
4879 {"pedicel", {pedicel_reflectivity_spectrum, pedicel_transmissivity_spectrum, pedicel_emissivity_spectrum}},
4880 {"fruit", {fruit_reflectivity_spectrum, fruit_transmissivity_spectrum, fruit_emissivity_spectrum}}};
4881 for (std::string prim: primitive_names) {
4882 if (prim == "All")
4883 continue;
4884 std::string default_spectrum = "";
4885 // Reflectivity
4886 xmlGetValue(prim + "_reflectivity_spectrum", "radiation", default_spectrum);
4887 if (!default_spectrum.empty()) {
4888 primitive_spectra[prim][0] = default_spectrum;
4889 primitive_continuous[prim][0] = true;
4890 } else {
4891 primitive_continuous[prim][0] = false;
4892 }
4893 // Transmissivity
4894 default_spectrum = "";
4895 xmlGetValue(prim + "_transmissivity_spectrum", "radiation", default_spectrum);
4896 if (!default_spectrum.empty()) {
4897 primitive_spectra[prim][1] = default_spectrum;
4898 primitive_continuous[prim][1] = true;
4899 } else {
4900 primitive_continuous[prim][1] = false;
4901 }
4902 for (std::string band: bandlabels) {
4903 if (band == "All")
4904 continue;
4905 xmlGetValue(prim + "_reflectivity", "radiation", primitive_values[band][prim][0]);
4906 xmlGetValue(prim + "_transmissivity", "radiation", primitive_values[band][prim][1]);
4907 xmlGetValue(prim + "_emissivity", "radiation", primitive_values[band][prim][2]);
4908 }
4909 }
4910#endif
4911}
4912
4913void ProjectBuilder::xmlGetValues(std::string xml_path) {
4914 xml_input_file = xml_path;
4915 if (!open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
4916 helios_runtime_error(xml_error_string);
4917 }
4918 xmlGetValues();
4919}
4920
4921void ProjectBuilder::objectTab(std::string curr_obj_name, int id) {
4922#ifdef ENABLE_HELIOS_VISUALIZER
4923 if (ImGui::Button("Update Object")) {
4924 updateObject(curr_obj_name);
4925 refreshVisualization();
4926 }
4927 ImGui::SameLine();
4928 if (ImGui::Button("Delete Object")) {
4929 deleteObject(curr_obj_name);
4930 }
4931 ImGui::SetNextItemWidth(100);
4932 std::string prev_obj_name = objects_dict[curr_obj_name].name;
4933 ImGui::InputText(("##obj_name_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].name);
4934 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()) {
4935 object temp_obj = objects_dict[curr_obj_name];
4936 curr_obj_name = objects_dict[curr_obj_name].name;
4937 std::map<std::string, object>::iterator delete_obj_iter = objects_dict.find(prev_obj_name);
4938 if (delete_obj_iter != objects_dict.end()) {
4939 objects_dict.erase(delete_obj_iter);
4940 }
4941
4942 objects_dict[objects_dict[curr_obj_name].name] = temp_obj;
4943
4944 obj_names_set.erase(prev_obj_name);
4945 obj_names_set.insert(objects_dict[curr_obj_name].name);
4946 } else {
4947 objects_dict[curr_obj_name].name = prev_obj_name;
4948 }
4949 ImGui::SameLine();
4950 ImGui::Text("Object Name");
4951 // ####### OBJECT SCALE ####### //
4952 ImGui::SetNextItemWidth(60);
4953 ImGui::InputFloat(("##obj_scale_x_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].scale.x);
4954 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));
4955 randomizerParams("obj_scale_x_" + std::to_string(objects_dict[curr_obj_name].index));
4956 ImGui::OpenPopupOnItemClick(("randomize_obj_scale_x_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4957 ImGui::SameLine();
4958 ImGui::SetNextItemWidth(60);
4959 ImGui::InputFloat(("##obj_scale_y_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].scale.y);
4960 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));
4961 randomizerParams("obj_scale_y_" + std::to_string(objects_dict[curr_obj_name].index));
4962 ImGui::OpenPopupOnItemClick(("randomize_obj_scale_y_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4963 ImGui::SameLine();
4964 ImGui::SetNextItemWidth(60);
4965 ImGui::InputFloat(("##obj_scale_z_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].scale.z);
4966 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));
4967 randomizerParams("obj_scale_z_" + std::to_string(objects_dict[curr_obj_name].index));
4968 ImGui::OpenPopupOnItemClick(("randomize_obj_scale_z_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4969 ImGui::SameLine();
4970 ImGui::Text("Object Scale");
4971 // ####### OBJECT POSITION ####### //
4972 ImGui::SetNextItemWidth(60);
4973 ImGui::InputFloat(("##obj_position_x_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].position.x);
4974 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));
4975 randomizerParams("obj_position_x_" + std::to_string(objects_dict[curr_obj_name].index));
4976 ImGui::OpenPopupOnItemClick(("randomize_obj_position_x_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4977 ImGui::SameLine();
4978 ImGui::SetNextItemWidth(60);
4979 ImGui::InputFloat(("##obj_position_y_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].position.y);
4980 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));
4981 randomizerParams("obj_position_y_" + std::to_string(objects_dict[curr_obj_name].index));
4982 ImGui::OpenPopupOnItemClick(("randomize_obj_position_y_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4983 ImGui::SameLine();
4984 ImGui::SetNextItemWidth(60);
4985 ImGui::InputFloat(("##obj_position_z_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].position.z);
4986 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));
4987 randomizerParams("obj_position_z_" + std::to_string(objects_dict[curr_obj_name].index));
4988 ImGui::OpenPopupOnItemClick(("randomize_obj_position_z_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4989 ImGui::SameLine();
4990 ImGui::Text("Object Position");
4991 // ####### OBJECT ORIENTATION ####### //
4992 ImGui::SetNextItemWidth(60);
4993 ImGui::InputFloat(("##obj_orientation_x_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].orientation.x);
4994 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));
4995 randomizerParams("obj_orientation_x_" + std::to_string(objects_dict[curr_obj_name].index));
4996 ImGui::OpenPopupOnItemClick(("randomize_obj_orientation_x_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
4997 ImGui::SameLine();
4998 ImGui::SetNextItemWidth(60);
4999 ImGui::InputFloat(("##obj_orientation_y_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].orientation.y);
5000 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));
5001 randomizerParams("obj_orientation_y_" + std::to_string(objects_dict[curr_obj_name].index));
5002 ImGui::OpenPopupOnItemClick(("randomize_obj_orientation_y_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
5003 ImGui::SameLine();
5004 ImGui::SetNextItemWidth(60);
5005 ImGui::InputFloat(("##obj_orientation_z_" + std::to_string(id)).c_str(), &objects_dict[curr_obj_name].orientation.z);
5006 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));
5007 randomizerParams("obj_orientation_z_" + std::to_string(objects_dict[curr_obj_name].index));
5008 ImGui::OpenPopupOnItemClick(("randomize_obj_orientation_z_" + std::to_string(objects_dict[curr_obj_name].index)).c_str(), ImGuiPopupFlags_MouseButtonRight);
5009 ImGui::SameLine();
5010 ImGui::Text("Object Orientation");
5011}
5012
5013void ProjectBuilder::rigTab(std::string curr_rig_name, int id) {
5014 ImGui::SetNextItemWidth(100);
5015 std::string prev_rig_name = rig_labels[rig_dict[curr_rig_name]];
5016 ImGui::InputText("##rig_name", &rig_labels[rig_dict[curr_rig_name]]);
5017 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()) {
5018 rig_labels_set.erase(prev_rig_name);
5019 int temp = rig_dict[curr_rig_name];
5020 rig_labels_set.insert(rig_labels[temp]);
5021 curr_rig_name = rig_labels[rig_dict[curr_rig_name]];
5022 std::map<std::string, int>::iterator current_rig_iter = rig_dict.find(prev_rig_name);
5023 if (current_rig_iter != rig_dict.end()) {
5024 rig_dict.erase(current_rig_iter);
5025 }
5026 rig_dict[curr_rig_name] = temp;
5027
5028 rig_labels_set.erase(prev_rig_name);
5029 rig_labels_set.insert(rig_labels[rig_dict[curr_rig_name]]);
5030 } else {
5031 rig_labels[rig_dict[curr_rig_name]] = prev_rig_name;
5032 }
5033 ImGui::SameLine();
5034 ImGui::Text("Rig Name");
5035 int current_cam_position_ = 0; // TODO: make this dynamic
5036 // ####### CAMERA POSITION ####### //
5037 vec3 prev_rig_position = vec3(camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_]);
5038 ImGui::SetNextItemWidth(60);
5039 ImGui::InputFloat("##camera_position_x", &camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_].x);
5040 ImGui::SameLine();
5041 ImGui::SetNextItemWidth(60);
5042 ImGui::InputFloat("##camera_position_y", &camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_].y);
5043 ImGui::SameLine();
5044 ImGui::SetNextItemWidth(60);
5045 ImGui::InputFloat("##camera_position_z", &camera_position_vec[rig_dict[curr_rig_name]][current_cam_position_].z);
5046 ImGui::SameLine();
5047 ImGui::Text("Rig Position");
5048 // ####### CAMERA LOOKAT ####### //
5049 vec3 prev_rig_lookat = vec3(camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_]);
5050 ImGui::SetNextItemWidth(60);
5051 ImGui::InputFloat("##camera_lookat_x", &camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_].x);
5052 ImGui::SameLine();
5053 ImGui::SetNextItemWidth(60);
5054 ImGui::InputFloat("##camera_lookat_y", &camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_].y);
5055 ImGui::SameLine();
5056 ImGui::SetNextItemWidth(60);
5057 ImGui::InputFloat("##camera_lookat_z", &camera_lookat_vec[rig_dict[curr_rig_name]][current_cam_position_].z);
5058 ImGui::SameLine();
5059 ImGui::Text("Rig Lookat");
5060
5061 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_]) {
5062 updateRigs();
5063 }
5064#endif
5065}
5066
5067void ProjectBuilder::canopyTab(std::string curr_canopy_name, int id) {
5068#ifdef ENABLE_PLANT_ARCHITECTURE
5069 if (ImGui::Button("Update Canopy")) {
5070 updateCanopy(curr_canopy_name);
5071 is_dirty = true;
5072 canopy_dict[current_canopy].is_dirty = false;
5073 }
5074 ImGui::SameLine();
5075 if (ImGui::Button("Delete Canopy")) {
5076 deleteCanopy(curr_canopy_name);
5077 is_dirty = true;
5078 canopy_dict[current_canopy].is_dirty = false;
5079 // refreshVisualization();
5080 }
5081 if (canopy_dict[curr_canopy_name].is_dirty) {
5082 ImGui::SameLine();
5083 ImGui::PushStyleColor(ImGuiCol_Text, IM_COL32(255, 0, 0, 255)); // Red text
5084 ImGui::Text("update required");
5085 ImGui::PopStyleColor();
5086 }
5087 ImGui::SetNextItemWidth(100);
5088 std::string prev_canopy_name = canopy_dict[curr_canopy_name].label;
5089 ImGui::InputText("##canopy_name", &canopy_dict[curr_canopy_name].label);
5090 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()) {
5091 canopy temp = canopy_dict[curr_canopy_name];
5092 curr_canopy_name = canopy_dict[curr_canopy_name].label;
5093 std::map<std::string, canopy>::iterator current_canopy_iter = canopy_dict.find(prev_canopy_name);
5094 if (current_canopy_iter != canopy_dict.end()) {
5095 canopy_dict.erase(current_canopy_iter);
5096 }
5097 canopy_dict[curr_canopy_name] = temp;
5098
5099 canopy_labels_set.erase(prev_canopy_name);
5100 canopy_labels_set.insert(canopy_dict[curr_canopy_name].label);
5101 } else {
5102 canopy_dict[curr_canopy_name].label = prev_canopy_name;
5103 }
5104 vec3 prev_canopy_origin_ = vec3(canopy_dict[curr_canopy_name].origin);
5105 ImGui::SetNextItemWidth(60);
5106 ImGui::InputFloat("##canopy_origin_x", &canopy_dict[curr_canopy_name].origin.x);
5107 ImGui::SameLine();
5108 ImGui::SetNextItemWidth(60);
5109 ImGui::InputFloat("##canopy_origin_y", &canopy_dict[curr_canopy_name].origin.y);
5110 ImGui::SameLine();
5111 ImGui::SetNextItemWidth(60);
5112 ImGui::InputFloat("##canopy_origin_z", &canopy_dict[curr_canopy_name].origin.z);
5113 ImGui::SameLine();
5114 ImGui::Text("Canopy Origin");
5115 // ####### PLANT COUNT ####### //
5116 int2 prev_plant_count_ = int2(canopy_dict[curr_canopy_name].plant_count);
5117 ImGui::SetNextItemWidth(100);
5118 ImGui::InputInt("##plant_count_x", &canopy_dict[curr_canopy_name].plant_count.x);
5119 ImGui::SameLine();
5120 ImGui::SetNextItemWidth(100);
5121 ImGui::InputInt("##plant_count_y", &canopy_dict[curr_canopy_name].plant_count.y);
5122 ImGui::SameLine();
5123 ImGui::Text("Plant Count");
5124 // ####### PLANT SPACING ####### //
5125 vec2 prev_plant_spacing_ = vec2(canopy_dict[curr_canopy_name].plant_spacing);
5126 ImGui::SetNextItemWidth(50);
5127 ImGui::InputFloat("##plant_spacing_x", &canopy_dict[curr_canopy_name].plant_spacing.x);
5128 ImGui::SameLine();
5129 ImGui::SetNextItemWidth(50);
5130 ImGui::InputFloat("##plant_spacing_y", &canopy_dict[curr_canopy_name].plant_spacing.y);
5131 ImGui::SameLine();
5132 ImGui::Text("Plant Spacing");
5133 // ####### PLANT LIBRARY NAME ####### //
5134 std::string prev_plant_library_ = canopy_dict[curr_canopy_name].library_name;
5135 ImGui::SetNextItemWidth(250);
5136 dropDown("Plant Library###dropdown", canopy_dict[curr_canopy_name].library_name_verbose, plant_types_verbose);
5137 canopy_dict[curr_canopy_name].library_name = plant_type_lookup[canopy_dict[curr_canopy_name].library_name_verbose];
5138 // ####### PLANT AGE ####### //
5139 float prev_plant_age_ = canopy_dict[curr_canopy_name].age;
5140 ImGui::SetNextItemWidth(80);
5141 ImGui::InputFloat("Plant Age", &canopy_dict[curr_canopy_name].age);
5142 // ####### GROUND CLIPPING HEIGHT ####### //
5143 float prev_ground_clipping_height_ = canopy_dict[curr_canopy_name].ground_clipping_height;
5144 ImGui::SetNextItemWidth(80);
5145 ImGui::InputFloat("Ground Clipping Height", &canopy_dict[curr_canopy_name].ground_clipping_height);
5146 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 ||
5147 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) {
5148 canopy_dict[curr_canopy_name].is_dirty = true;
5149 }
5150#endif // PLANT_ARCHITECTURE
5151}
5152
5153void ProjectBuilder::saveCanopy(std::string file_name, std::vector<uint> canopy_ID_vec, vec3 position, std::string file_extension) const {
5154#ifdef ENABLE_PLANT_ARCHITECTURE
5155 std::vector<std::string> primitive_data_vec = {"object_label"};
5156 std::vector<uint> canopy_primID_vec;
5157 std::vector<uint> canopy_objID_vec;
5158 // plantarchitecture->getAllPlantObjectIDs(plantID)
5159 for (int i = 0; i < canopy_ID_vec.size(); i++) {
5160 std::vector<uint> canopy_prim_UUIDs = plantarchitecture->getAllPlantUUIDs(canopy_ID_vec[i]);
5161 std::vector<uint> canopy_obj_UUIDs = plantarchitecture->getAllPlantObjectIDs(canopy_ID_vec[i]);
5162 canopy_primID_vec.insert(canopy_primID_vec.end(), canopy_prim_UUIDs.begin(), canopy_prim_UUIDs.end());
5163 canopy_objID_vec.insert(canopy_objID_vec.end(), canopy_obj_UUIDs.begin(), canopy_obj_UUIDs.end());
5164 }
5165 for (uint objID: canopy_objID_vec) {
5166 context->translateObject(objID, -position);
5167 }
5168 if (file_extension == "obj") {
5169 context->writeOBJ(file_name, canopy_primID_vec, primitive_data_vec, true);
5170 } else if (file_extension == "ply") {
5171 // context->writePLY(file_name, obj_UUID_vec, primitive_data_vec);
5172 }
5173 for (uint objID: canopy_objID_vec) {
5174 context->translateObject(objID, position);
5175 }
5176#endif
5177}
5178
5179void ProjectBuilder::saveCanopy(std::string file_name_base, std::vector<uint> canopy_ID_vec, std::vector<helios::vec3> positions, std::string file_extension) const {
5180#ifdef ENABLE_PLANT_ARCHITECTURE
5181 std::vector<std::string> primitive_data_vec = {"object_label"};
5182 std::vector<std::vector<uint>> canopy_primID_vec;
5183 std::vector<std::vector<uint>> canopy_objID_vec;
5184 // plantarchitecture->getAllPlantObjectIDs(plantID)
5185 for (int i = 0; i < canopy_ID_vec.size(); i++) {
5186 std::vector<uint> canopy_prim_UUIDs = plantarchitecture->getAllPlantUUIDs(canopy_ID_vec[i]);
5187 std::vector<uint> canopy_obj_UUIDs = plantarchitecture->getAllPlantObjectIDs(canopy_ID_vec[i]);
5188 canopy_primID_vec.push_back(canopy_prim_UUIDs);
5189 canopy_objID_vec.push_back(canopy_obj_UUIDs);
5190 }
5191 for (int i = 0; i < canopy_objID_vec.size(); i++) {
5192 for (uint objID: canopy_objID_vec[i]) {
5193 context->translateObject(objID, -positions[i]);
5194 }
5195 }
5196 std::filesystem::path file_path(file_name_base);
5197 std::string ext = file_path.extension().string();
5198 file_path.replace_extension("");
5199 std::string file_name = file_path.string();
5200 if (file_extension == "obj") {
5201 for (int i = 0; i < canopy_primID_vec.size(); i++) {
5202 context->writeOBJ(file_name + "_" + std::to_string(i) + ext, canopy_primID_vec[i], primitive_data_vec, true);
5203 }
5204 } else if (file_extension == "ply") {
5205 // context->writePLY(file_name, obj_UUID_vec, primitive_data_vec);
5206 }
5207 for (int i = 0; i < canopy_objID_vec.size(); i++) {
5208 for (uint objID: canopy_objID_vec[i]) {
5209 context->translateObject(objID, positions[i]);
5210 }
5211 }
5212#endif
5213}
5214
5215void ProjectBuilder::addBand(std::string label, float wavelength_min, float wavelength_max, bool enable_emission) {
5216#ifdef ENABLE_RADIATION_MODEL
5217 if (label.empty()) {
5218 std::cout << "Failed to add band. Please specify a band label." << std::endl;
5219 return;
5220 }
5221 if (bandlabels_set.find(label) != bandlabels_set.end()) {
5222 std::cout << "Failed to add band. Band with the specified name already exists." << std::endl;
5223 return;
5224 }
5225 if (wavelength_min > wavelength_max) {
5226 std::cout << "Failed to add band. Invalid wavelength minimum and maximum." << std::endl;
5227 return;
5228 }
5229 bandlabels.push_back(label);
5230 bandlabels_set.insert(label);
5231 primitive_values[label] = {{"All", {reflectivity, transmissivity, emissivity}},
5232 {"ground", {ground_reflectivity, ground_transmissivity, ground_emissivity}},
5233 {"leaf", {leaf_reflectivity, leaf_transmissivity, leaf_emissivity}},
5234 {"petiolule", {petiolule_reflectivity, petiolule_transmissivity, petiolule_emissivity}},
5235 {"petiole", {petiole_reflectivity, petiole_transmissivity, petiole_emissivity}},
5236 {"internode", {internode_reflectivity, internode_transmissivity, internode_emissivity}},
5237 {"peduncle", {peduncle_reflectivity, peduncle_transmissivity, peduncle_emissivity}},
5238 {"petal", {petal_reflectivity, petal_transmissivity, petal_emissivity}},
5239 {"pedicel", {pedicel_reflectivity, pedicel_transmissivity, pedicel_emissivity}},
5240 {"fruit", {fruit_reflectivity, fruit_transmissivity, fruit_emissivity}}};
5241 for (auto &primitive_values_pair: primitive_values_dict) {
5242 primitive_values_dict[primitive_values_pair.first][label] = {{"All", {reflectivity, transmissivity, emissivity}},
5243 {"ground", {ground_reflectivity, ground_transmissivity, ground_emissivity}},
5244 {"leaf", {leaf_reflectivity, leaf_transmissivity, leaf_emissivity}},
5245 {"petiolule", {petiolule_reflectivity, petiolule_transmissivity, petiolule_emissivity}},
5246 {"petiole", {petiole_reflectivity, petiole_transmissivity, petiole_emissivity}},
5247 {"internode", {internode_reflectivity, internode_transmissivity, internode_emissivity}},
5248 {"peduncle", {peduncle_reflectivity, peduncle_transmissivity, peduncle_emissivity}},
5249 {"petal", {petal_reflectivity, petal_transmissivity, petal_emissivity}},
5250 {"pedicel", {pedicel_reflectivity, pedicel_transmissivity, pedicel_emissivity}},
5251 {"fruit", {fruit_reflectivity, fruit_transmissivity, fruit_emissivity}}};
5252 }
5253 radiation->addRadiationBand(label, wavelength_min, wavelength_max);
5254 // radiation->addRadiationBand(label);
5255 if (!enable_emission) {
5256 radiation->disableEmission(label);
5257 } else {
5258 bandlabels_set_emissivity.insert(label);
5259 }
5260 radiation->setDirectRayCount(label, direct_ray_count);
5261 direct_ray_count_dict.insert({label, direct_ray_count});
5262 radiation->setDiffuseRayCount(label, diffuse_ray_count);
5263 diffuse_ray_count_dict.insert({label, diffuse_ray_count});
5264 radiation->setScatteringDepth(label, scattering_depth);
5265 scattering_depth_dict.insert({label, scattering_depth});
5266#endif
5267}
5268
5269void ProjectBuilder::addBand(std::string label, bool enable_emission) {
5270#ifdef ENABLE_RADIATION_MODEL
5271 if (label.empty()) {
5272 std::cout << "Failed to add band. Please specify a band label." << std::endl;
5273 return;
5274 }
5275 if (bandlabels_set.find(label) != bandlabels_set.end()) {
5276 std::cout << "Failed to add band. Band with the specified name already exists." << std::endl;
5277 return;
5278 }
5279 bandlabels.push_back(label);
5280 bandlabels_set.insert(label);
5281 primitive_values[label] = {{"All", {reflectivity, transmissivity, emissivity}},
5282 {"ground", {ground_reflectivity, ground_transmissivity, ground_emissivity}},
5283 {"leaf", {leaf_reflectivity, leaf_transmissivity, leaf_emissivity}},
5284 {"petiolule", {petiolule_reflectivity, petiolule_transmissivity, petiolule_emissivity}},
5285 {"petiole", {petiole_reflectivity, petiole_transmissivity, petiole_emissivity}},
5286 {"internode", {internode_reflectivity, internode_transmissivity, internode_emissivity}},
5287 {"peduncle", {peduncle_reflectivity, peduncle_transmissivity, peduncle_emissivity}},
5288 {"petal", {petal_reflectivity, petal_transmissivity, petal_emissivity}},
5289 {"pedicel", {pedicel_reflectivity, pedicel_transmissivity, pedicel_emissivity}},
5290 {"fruit", {fruit_reflectivity, fruit_transmissivity, fruit_emissivity}}};
5291 for (auto &primitive_values_pair: primitive_values_dict) {
5292 primitive_values_dict[primitive_values_pair.first][label] = {{"All", {reflectivity, transmissivity, emissivity}},
5293 {"ground", {ground_reflectivity, ground_transmissivity, ground_emissivity}},
5294 {"leaf", {leaf_reflectivity, leaf_transmissivity, leaf_emissivity}},
5295 {"petiolule", {petiolule_reflectivity, petiolule_transmissivity, petiolule_emissivity}},
5296 {"petiole", {petiole_reflectivity, petiole_transmissivity, petiole_emissivity}},
5297 {"internode", {internode_reflectivity, internode_transmissivity, internode_emissivity}},
5298 {"peduncle", {peduncle_reflectivity, peduncle_transmissivity, peduncle_emissivity}},
5299 {"petal", {petal_reflectivity, petal_transmissivity, petal_emissivity}},
5300 {"pedicel", {pedicel_reflectivity, pedicel_transmissivity, pedicel_emissivity}},
5301 {"fruit", {fruit_reflectivity, fruit_transmissivity, fruit_emissivity}}};
5302 }
5304 // radiation->addRadiationBand(label);
5305 if (!enable_emission) {
5306 radiation->disableEmission(label);
5307 } else {
5308 bandlabels_set_emissivity.insert(label);
5309 }
5310 radiation->setDirectRayCount(label, direct_ray_count);
5311 direct_ray_count_dict.insert({label, direct_ray_count});
5312 radiation->setDiffuseRayCount(label, diffuse_ray_count);
5313 diffuse_ray_count_dict.insert({label, diffuse_ray_count});
5314 radiation->setScatteringDepth(label, scattering_depth);
5315 scattering_depth_dict.insert({label, scattering_depth});
5316#endif
5317}
5318
5319
5320#ifdef ENABLE_HELIOS_VISUALIZER
5321void ProjectBuilder::randomizePopup(std::string popup_name, taggedPtr ptr) {
5322 std::string popup = "randomize_" + popup_name;
5323 if (ImGui::BeginPopup(popup.c_str())) {
5324 ImGui::Text("Random Distribution");
5325 ImGui::SetNextItemWidth(150);
5326 if (ImGui::BeginCombo("##combo_distribution", current_distribution.c_str())) {
5327 for (int n = 0; n < distribution_names.size(); n++) {
5328 bool is_dist_selected = (current_distribution == distribution_names[n]);
5329 if (ImGui::Selectable(distribution_names[n].c_str(), is_dist_selected))
5330 current_distribution = distribution_names[n];
5331 if (is_dist_selected)
5332 ImGui::SetItemDefaultFocus();
5333 }
5334 ImGui::EndCombo();
5335 }
5336 if (current_distribution == "Normal (Gaussian)") {
5337 ImGui::SetNextItemWidth(150);
5338 ImGui::InputFloat("Mean", &curr_distribution_params[0]);
5339 ImGui::SetNextItemWidth(150);
5340 ImGui::InputFloat("Variance", &curr_distribution_params[1]);
5341 }
5342 if (current_distribution == "Uniform") {
5343 ImGui::SetNextItemWidth(150);
5344 ImGui::InputFloat("Lower Bound", &curr_distribution_params[0]);
5345 ImGui::SetNextItemWidth(150);
5346 ImGui::InputFloat("Upper Bound", &curr_distribution_params[1]);
5347 }
5348 if (current_distribution == "Weibull") {
5349 ImGui::SetNextItemWidth(150);
5350 ImGui::InputFloat("Shape (k)", &curr_distribution_params[0]);
5351 ImGui::SetNextItemWidth(150);
5352 ImGui::InputFloat(u8"Scale (\u03bb)", &curr_distribution_params[1]);
5353 }
5354 if (current_distribution != "N/A") {
5355 ImGui::Checkbox("Randomize for Every Image", &randomize_repeatedly);
5356 }
5357 if (ImGui::Button("Apply")) {
5358 applyDistribution(popup_name, ptr);
5359 ImGui::CloseCurrentPopup();
5360 }
5361 ImGui::EndPopup();
5362 }
5363}
5364#else
5365void ProjectBuilder::randomizePopup(std::string popup_name, taggedPtr ptr) {
5366 // Visualizer plugin is required for GUI functionality
5367}
5368#endif // ENABLE_HELIOS_VISUALIZER
5369
5370
5371#ifdef ENABLE_HELIOS_VISUALIZER
5372void ProjectBuilder::noisePopup(std::string popup_name, std::vector<distribution> &dist_vec) {
5373 std::string popup = popup_name;
5374 if (ImGui::BeginPopup(popup.c_str())) {
5375 ImGui::Text("Add Random Noise Along Path");
5376 ImGui::SetNextItemWidth(100);
5377 if (ImGui::BeginCombo("##axis_combo", current_axis.c_str())) {
5378 for (auto axis: possible_axes) {
5379 bool is_axis_selected = (current_axis == axis);
5380 if (ImGui::Selectable(axis.c_str(), is_axis_selected))
5381 current_axis = axis;
5382 if (is_axis_selected)
5383 ImGui::SetItemDefaultFocus();
5384 }
5385 ImGui::EndCombo();
5386 }
5387 ImGui::SameLine();
5388 ImGui::Text("Axis");
5389 ImGui::SetNextItemWidth(150);
5390 if (ImGui::BeginCombo("##combo_distribution", current_distribution.c_str())) {
5391 for (int n = 0; n < distribution_names.size(); n++) {
5392 bool is_dist_selected = (current_distribution == distribution_names[n]);
5393 if (ImGui::Selectable(distribution_names[n].c_str(), is_dist_selected))
5394 current_distribution = distribution_names[n];
5395 if (is_dist_selected)
5396 ImGui::SetItemDefaultFocus();
5397 }
5398 ImGui::EndCombo();
5399 }
5400 ImGui::SameLine();
5401 ImGui::Text("Distribution");
5402 if (current_distribution == "Normal (Gaussian)") {
5403 ImGui::SetNextItemWidth(150);
5404 ImGui::InputFloat("Mean", &curr_distribution_params[0]);
5405 ImGui::SetNextItemWidth(150);
5406 ImGui::InputFloat("Variance", &curr_distribution_params[1]);
5407 }
5408 if (current_distribution == "Uniform") {
5409 ImGui::SetNextItemWidth(150);
5410 ImGui::InputFloat("Lower Bound", &curr_distribution_params[0]);
5411 ImGui::SetNextItemWidth(150);
5412 ImGui::InputFloat("Upper Bound", &curr_distribution_params[1]);
5413 }
5414 if (current_distribution == "Weibull") {
5415 ImGui::SetNextItemWidth(150);
5416 ImGui::InputFloat("Shape (k)", &curr_distribution_params[0]);
5417 ImGui::SetNextItemWidth(150);
5418 ImGui::InputFloat(u8"Scale (\u03bb)", &curr_distribution_params[1]);
5419 }
5420 int idx;
5421 if (current_axis == "X") {
5422 idx = 0;
5423 } else if (current_axis == "Y") {
5424 idx = 1;
5425 } else {
5426 idx = 2;
5427 }
5428 if (ImGui::Button("Apply")) {
5429 distUnion dist_union{};
5430 if (current_distribution == "Normal (Gaussian)") {
5431 dist_union.normal = new std::normal_distribution<float>;
5432 *dist_union.normal = std::normal_distribution<float>(curr_distribution_params[0], curr_distribution_params[1]);
5433 dist_vec[idx].dist = dist_union;
5434 dist_vec[idx].flag = 0;
5435 dist_vec[idx].repeat = 0;
5436 }
5437 if (current_distribution == "Uniform") {
5438 dist_union.uniform = new std::uniform_real_distribution<float>;
5439 *dist_union.uniform = std::uniform_real_distribution<float>(curr_distribution_params[0], curr_distribution_params[1]);
5440 dist_vec[idx].dist = dist_union;
5441 dist_vec[idx].flag = 1;
5442 dist_vec[idx].repeat = 0;
5443 }
5444 if (current_distribution == "Weibull") {
5445 dist_union.weibull = new std::weibull_distribution<float>;
5446 *dist_union.weibull = std::weibull_distribution<float>(curr_distribution_params[0], curr_distribution_params[1]);
5447 dist_vec[idx].dist = dist_union;
5448 dist_vec[idx].flag = 2;
5449 dist_vec[idx].repeat = 0;
5450 }
5451 if (current_distribution == "N/A") {
5452 dist_vec[idx].flag = -1;
5453 dist_vec[idx].repeat = 0;
5454 }
5455
5456 ImGui::CloseCurrentPopup();
5457 }
5458 ImGui::EndPopup();
5459 }
5460}
5461#else
5462void ProjectBuilder::noisePopup(std::string popup_name, std::vector<distribution> &dist_vec) {
5463 // Visualizer plugin is required for GUI functionality
5464}
5465#endif // ENABLE_HELIOS_VISUALIZER
5466
5467
5468void ProjectBuilder::applyDistribution(std::string var_name, taggedPtr ptr) {
5469 if (current_distribution == "N/A") {
5470 distribution_types[var_name] = "N/A";
5471 }
5472 if (current_distribution == "Normal (Gaussian)") {
5473 std::normal_distribution<float> curr_dist_normal(curr_distribution_params[0], curr_distribution_params[1]);
5474 distribution_dict[var_name] = distributions.size();
5475 distributions.push_back(createDistribution(curr_dist_normal, randomize_repeatedly));
5476 distribution_types[var_name] = "Normal (Gaussian)";
5477 }
5478 if (current_distribution == "Uniform") {
5479 std::uniform_real_distribution<float> curr_dist_uniform(curr_distribution_params[0], curr_distribution_params[1]);
5480 distribution_dict[var_name] = distributions.size();
5481 distributions.push_back(createDistribution(curr_dist_uniform, randomize_repeatedly));
5482 distribution_types[var_name] = "Uniform";
5483 }
5484 if (current_distribution == "Weibull") {
5485 std::weibull_distribution<float> curr_dist_weibull(curr_distribution_params[0], curr_distribution_params[1]);
5486 distribution_dict[var_name] = distributions.size();
5487 distributions.push_back(createDistribution(curr_dist_weibull, randomize_repeatedly));
5488 distribution_types[var_name] = "Weibull";
5489 }
5490 distribution_params[var_name] = curr_distribution_params;
5491 randomized_variable_lookup[var_name] = ptr;
5492 sample(var_name);
5493}
5494
5495
5496void ProjectBuilder::applyDistribution(std::string var_name, distribution dist, taggedPtr ptr) {
5497 if (dist.flag == -1) {
5498 distribution_dict[var_name] = distributions.size();
5499 distributions.push_back(dist);
5500 distribution_types[var_name] = "N/A";
5501 distribution_params[var_name] = std::vector<float>{0.0, 0.0};
5502 }
5503 if (dist.flag == 0) {
5504 distribution_dict[var_name] = distributions.size();
5505 distributions.push_back(dist);
5506 distribution_types[var_name] = "Normal (Gaussian)";
5507 distribution_params[var_name] = std::vector<float>{dist.dist.normal->mean(), dist.dist.normal->stddev()};
5508 }
5509 if (current_distribution == "Uniform") {
5510 distribution_dict[var_name] = distributions.size();
5511 distributions.push_back(dist);
5512 distribution_types[var_name] = "Uniform";
5513 distribution_params[var_name] = std::vector<float>{dist.dist.uniform->a(), dist.dist.uniform->b()};
5514 }
5515 if (current_distribution == "Weibull") {
5516 distribution_dict[var_name] = distributions.size();
5517 distributions.push_back(dist);
5518 distribution_types[var_name] = "Weibull";
5519 distribution_params[var_name] = std::vector<float>{dist.dist.weibull->a(), dist.dist.weibull->b()};
5520 }
5521 randomized_variable_lookup[var_name] = ptr;
5522 sample(var_name);
5523}
5524
5525
5526void ProjectBuilder::randomize(bool randomize_all) {
5527 for (std::pair<std::string, int> dist_pair: distribution_dict) {
5528 std::string var_name = dist_pair.first;
5529 distribution dist = distributions[dist_pair.second];
5530 if (randomize_all || dist.repeat) {
5531 sample(var_name);
5532 }
5533 }
5534}
5535
5536
5538 digitPtr p;
5539 p.f = ptr;
5540 taggedPtr t{p, false};
5541 return t;
5542}
5543
5544
5546 digitPtr p;
5547 p.i = ptr;
5548 taggedPtr t{p, true};
5549 return t;
5550}
5551
5552
5553taggedPtr createTaggedPtr(float *ptr, bool *dirty) {
5554 digitPtr p;
5555 p.f = ptr;
5556 taggedPtr t{p, false, dirty};
5557 return t;
5558}
5559
5560
5561taggedPtr createTaggedPtr(int *ptr, bool *dirty) {
5562 digitPtr p;
5563 p.i = ptr;
5564 taggedPtr t{p, true, dirty};
5565 return t;
5566}
5567
5568
5569distribution createDistribution(const std::normal_distribution<float> &dist, bool randomize_repeat) {
5570 distUnion u;
5571 u.normal = new std::normal_distribution<float>;
5572 *u.normal = dist;
5573 distribution d{u, 0, randomize_repeat};
5574 return d;
5575}
5576
5577distribution createDistribution(const std::uniform_real_distribution<float> &dist, bool randomize_repeat) {
5578 distUnion u;
5579 u.uniform = new std::uniform_real_distribution<float>;
5580 *u.uniform = dist;
5581 distribution d{u, 1, randomize_repeat};
5582 return d;
5583}
5584
5585distribution createDistribution(const std::weibull_distribution<float> &dist, bool randomize_repeat) {
5586 distUnion u;
5587 u.weibull = new std::weibull_distribution<float>;
5588 *u.weibull = dist;
5589 distribution d{u, 2, randomize_repeat};
5590 return d;
5591}
5592
5593#ifdef ENABLE_HELIOS_VISUALIZER
5594void ProjectBuilder::randomizerParams(std::string var_name) {
5595 if (ImGui::IsItemClicked(ImGuiMouseButton_Right)) {
5596 if (distribution_params.find(var_name) != distribution_params.end()) {
5597 curr_distribution_params = distribution_params[var_name];
5598 } else {
5599 curr_distribution_params = std::vector<float>{0, 0};
5600 }
5601 if (distribution_types.find(var_name) != distribution_types.end()) {
5602 current_distribution = distribution_types[var_name];
5603 } else {
5604 current_distribution = "N/A";
5605 }
5606 if (current_distribution != "N/A") {
5607 randomize_repeatedly = distributions[distribution_dict[var_name]].repeat;
5608 }
5609 }
5610}
5611#else
5612void ProjectBuilder::randomizerParams(std::string var_name) {
5613 // Visualizer plugin is required for GUI functionality
5614}
5615#endif // ENABLE_HELIOS_VISUALIZER
5616
5617void ProjectBuilder::sample(std::string var_name) {
5618 if (distribution_types.find(var_name) == distribution_types.end() || distribution_types[var_name] == "N/A") {
5619 return;
5620 }
5621 distribution d = distributions[distribution_dict[var_name]];
5622 taggedPtr t = randomized_variable_lookup[var_name];
5623 float sampled_value;
5624 if (d.flag == 0) {
5625 std::normal_distribution<float> normal = *d.dist.normal;
5626 sampled_value = normal(generator);
5627 if (t.isInt) {
5628 *t.ptr.i = (int) sampled_value;
5629 } else {
5630 *t.ptr.f = sampled_value;
5631 }
5632 } else if (d.flag == 1) {
5633 std::uniform_real_distribution<float> uniform = *d.dist.uniform;
5634 sampled_value = uniform(generator);
5635 if (t.isInt) {
5636 *t.ptr.i = (int) sampled_value;
5637 } else {
5638 *t.ptr.f = sampled_value;
5639 }
5640 } else if (d.flag == 2) {
5641 std::weibull_distribution<float> weibull = *d.dist.weibull;
5642 sampled_value = weibull(generator);
5643 if (t.isInt) {
5644 *t.ptr.i = (int) sampled_value;
5645 } else {
5646 *t.ptr.f = sampled_value;
5647 }
5648 }
5649 // if (t.object.idx != -1){
5650 // if (t.object.isCanopy){
5651 // dirty_canopies.insert(t.object.idx);
5652 // } else{
5653 // dirty_objects.insert(t.object.idx);
5654 // }
5655 // }
5656}
5657
5658
5660 for (int canopy_idx: dirty_canopies) {
5661 // updateCanopy(canopy_idx);
5662 }
5663 for (int object_idx: dirty_objects) {
5664 updateObject(obj_names[object_idx]);
5665 }
5666 dirty_canopies.clear();
5667 dirty_objects.clear();
5668}
5669
5670
5672 for (std::pair<std::string, std::string> var_pair: distribution_types) {
5673 sample(var_pair.first);
5674 }
5675}
5676
5677#ifdef ENABLE_HELIOS_VISUALIZER
5678void ProjectBuilder::outputConsole() {
5679 // Temporarily restore std::cout so ImGui can print to the console without
5680 // altering the member pointer used by the destructor to restore the
5681 // original buffer at program exit.
5682 std::streambuf *prev_buf = std::cout.rdbuf();
5683 std::string buffer = captured_cout.str();
5684 std::size_t buffer_size = buffer.size();
5685 if (ImGui::BeginChild("##console", ImVec2(-FLT_MIN, ImGui::GetTextLineHeight() * 5), ImGuiChildFlags_None, ImGuiWindowFlags_HorizontalScrollbar)) {
5686 ImGui::TextUnformatted(buffer.c_str());
5687 if (buffer_size != last_console_size) {
5688 ImGui::SetScrollHereY(1.0f);
5689 }
5690 ImGui::EndChild();
5691 }
5692 last_console_size = buffer_size;
5693 std::cout.rdbuf(prev_buf);
5694}
5695#else
5696void ProjectBuilder::outputConsole() {
5697 // Visualizer plugin is required for GUI functionality
5698}
5699#endif // ENABLE_HELIOS_VISUALIZER
5700
5701void ProjectBuilder::updateColor(std::string curr_obj, std::string obj_type, float *new_color) {
5702 RGBcolor *curr_color = nullptr;
5703 if (obj_type == "obj") {
5704 curr_color = &objects_dict[curr_obj].color;
5705 }
5706 if (obj_type == "rig" || obj_type == "arrow" || obj_type == "camera") {
5707 curr_color = &rig_colors[rig_dict[curr_obj]];
5708 }
5709 // if (curr_color->r == new_color[0] && curr_color->g == new_color[1] && curr_color->b == new_color[2]){
5710 // return;
5711 // }
5712 if (curr_color->r != new_color[0] || curr_color->g != new_color[1] || curr_color->b != new_color[2]) {
5713 is_dirty = true;
5714 }
5715 curr_color->r = new_color[0];
5716 curr_color->g = new_color[1];
5717 curr_color->b = new_color[2];
5718 if (obj_type == "obj") {
5719 context->setPrimitiveColor(objects_dict[curr_obj].UUIDs, *curr_color);
5720 }
5721 if (obj_type == "rig") {
5722 if (arrow_dict.find(curr_obj) != arrow_dict.end()) {
5723 for (std::vector<uint> &arrow: arrow_dict.at(curr_obj)) {
5724 context->setPrimitiveColor(arrow, *curr_color);
5725 }
5726 }
5727 if (camera_models_dict.find(curr_obj) != camera_models_dict.end()) {
5728 context->setPrimitiveColor(camera_models_dict.at(curr_obj), *curr_color);
5729 }
5730 }
5731 if (obj_type == "arrow") {
5732 if (arrow_dict.find(curr_obj) != arrow_dict.end()) {
5733 for (std::vector<uint> &arrow: arrow_dict.at(curr_obj)) {
5734 context->setPrimitiveColor(arrow, *curr_color);
5735 }
5736 }
5737 }
5738 if (obj_type == "camera") {
5739 if (camera_models_dict.find(curr_obj) != camera_models_dict.end()) {
5740 context->setPrimitiveColor(camera_models_dict.at(curr_obj), *curr_color);
5741 }
5742 }
5743}
5744
5745
5746void ProjectBuilder::updateObject(std::string curr_obj) {
5747 // Scale, rotate, and translate object
5748 if (objects_dict[curr_obj].use_texture_file && objects_dict[curr_obj].is_dirty) {
5749 context->deletePrimitive(objects_dict[curr_obj].UUIDs);
5750 if (std::filesystem::path(objects_dict[curr_obj].file).extension() == ".obj") {
5751 objects_dict[curr_obj].UUIDs = context->loadOBJ(objects_dict[curr_obj].file.c_str());
5752 } else if (std::filesystem::path(objects_dict[curr_obj].file).extension() == ".ply") {
5753 objects_dict[curr_obj].UUIDs = context->loadPLY(objects_dict[curr_obj].file.c_str());
5754 }
5755 context->scalePrimitive(objects_dict[curr_obj].UUIDs, objects_dict[curr_obj].scale);
5756 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, deg2rad(objects_dict[curr_obj].orientation.x), "x");
5757 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, deg2rad(objects_dict[curr_obj].orientation.y), "y");
5758 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, deg2rad(objects_dict[curr_obj].orientation.z), "z");
5759 context->translatePrimitive(objects_dict[curr_obj].UUIDs, objects_dict[curr_obj].position);
5760
5761 objects_dict[curr_obj].prev_scale = objects_dict[curr_obj].scale;
5762 objects_dict[curr_obj].prev_orientation = objects_dict[curr_obj].orientation;
5763 objects_dict[curr_obj].prev_position = objects_dict[curr_obj].position;
5764 }
5765 if (objects_dict[curr_obj].scale != objects_dict[curr_obj].prev_scale) {
5766 vec3 obj_scale_;
5767 obj_scale_.x = objects_dict[curr_obj].scale.x / objects_dict[curr_obj].prev_scale.x;
5768 obj_scale_.y = objects_dict[curr_obj].scale.y / objects_dict[curr_obj].prev_scale.y;
5769 obj_scale_.z = objects_dict[curr_obj].scale.z / objects_dict[curr_obj].prev_scale.z;
5770 // context->scalePrimitiveAboutPoint();
5771 context->translatePrimitive(objects_dict[curr_obj].UUIDs, -objects_dict[curr_obj].prev_position); // translate back to origin
5772 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, -deg2rad(objects_dict[curr_obj].prev_orientation.x), "x");
5773 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, -deg2rad(objects_dict[curr_obj].prev_orientation.y), "y");
5774 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, -deg2rad(objects_dict[curr_obj].prev_orientation.z), "z");
5775
5776 context->scalePrimitive(objects_dict[curr_obj].UUIDs, obj_scale_);
5777 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, deg2rad(objects_dict[curr_obj].prev_orientation.x), "x");
5778 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, deg2rad(objects_dict[curr_obj].prev_orientation.y), "y");
5779 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, deg2rad(objects_dict[curr_obj].prev_orientation.z), "z");
5780 context->translatePrimitive(objects_dict[curr_obj].UUIDs, objects_dict[curr_obj].prev_position); // restore translation
5781 objects_dict[curr_obj].prev_scale = objects_dict[curr_obj].scale;
5782 }
5783 if (objects_dict[curr_obj].orientation != objects_dict[curr_obj].prev_orientation) {
5784 // context->rotatePrimitive(origin = prev_position, axis = (1,0,0));
5785 // rotate about x
5786 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, 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));
5787 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, 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));
5788 context->rotatePrimitive(objects_dict[curr_obj].UUIDs, 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));
5789 objects_dict[curr_obj].prev_orientation = objects_dict[curr_obj].orientation;
5790 }
5791 if (objects_dict[curr_obj].position != objects_dict[curr_obj].prev_position) {
5792 context->translatePrimitive(objects_dict[curr_obj].UUIDs, objects_dict[curr_obj].position - objects_dict[curr_obj].prev_position);
5793 objects_dict[curr_obj].prev_position = objects_dict[curr_obj].position;
5794 }
5795 objects_dict[curr_obj].prev_color = objects_dict[curr_obj].color;
5796 objects_dict[curr_obj].is_dirty = false;
5797
5798 is_dirty = true;
5799}
5800
5801
5803 deleteArrows();
5804 arrow_dict.clear();
5805 updateArrows();
5806 deleteCameraModels();
5807 camera_models_dict.clear();
5808 updateCameraModels();
5809 // Update visualizer
5810 // refreshVisualization();
5811 is_dirty = true;
5812}
5813
5814
5815void ProjectBuilder::deleteRig(std::string curr_rig) {
5816 int delete_idx = rig_dict[curr_rig];
5817 rig_dict.erase(rig_dict.find(curr_rig));
5818 rig_labels_set.erase(curr_rig);
5819 updateRigs();
5820 if (!rig_labels_set.empty() && current_rig == curr_rig) {
5821 current_rig = *rig_labels_set.begin();
5822 } else {
5823 current_rig = "";
5824 }
5825}
5826
5827
5828#ifdef ENABLE_HELIOS_VISUALIZER
5829void ProjectBuilder::dropDown(std::string widget_name, std::string &selected, std::vector<std::string> choices) {
5830 if (ImGui::BeginCombo(widget_name.c_str(), selected.c_str())) {
5831 for (int n = 0; n < choices.size(); n++) {
5832 bool is_selected = (selected == choices[n]);
5833 if (ImGui::Selectable(choices[n].c_str(), is_selected))
5834 selected = choices[n];
5835 if (is_selected)
5836 ImGui::SetItemDefaultFocus();
5837 }
5838 ImGui::EndCombo();
5839 }
5840}
5841
5842
5843void ProjectBuilder::dropDown(std::string widget_name, std::string &selected, std::set<std::string> choices) {
5844 if (ImGui::BeginCombo(widget_name.c_str(), selected.c_str())) {
5845 for (std::string choice: choices) {
5846 bool is_selected = (selected == choice);
5847 if (ImGui::Selectable(choice.c_str(), is_selected))
5848 selected = choice;
5849 if (is_selected)
5850 ImGui::SetItemDefaultFocus();
5851 }
5852 ImGui::EndCombo();
5853 }
5854}
5855#else
5856void ProjectBuilder::dropDown(std::string widget_name, std::string &selected, std::vector<std::string> choices) {
5857 // Visualizer plugin is required for GUI functionality
5858}
5859
5860void ProjectBuilder::dropDown(std::string widget_name, std::string &selected, std::set<std::string> choices) {
5861 // Visualizer plugin is required for GUI functionality
5862}
5863#endif // ENABLE_HELIOS_VISUALIZER
5864
5865void ProjectBuilder::deleteCanopy(const std::string &canopy) {
5866#ifdef ENABLE_PLANT_ARCHITECTURE
5867 for (auto plant_instance: canopy_dict[canopy].IDs) {
5868 plantarchitecture->deletePlantInstance(plant_instance);
5869 }
5870 canopy_dict.erase(canopy);
5871 canopy_labels_set.erase(canopy);
5872 if (!canopy_labels_set.empty() && current_canopy == canopy) {
5873 current_canopy = *canopy_labels_set.begin();
5874 } else {
5875 current_canopy = "";
5876 }
5877
5878 is_dirty = true;
5879#endif
5880}
5881
5882
5883void ProjectBuilder::deleteObject(const std::string &obj) {
5884 context->deletePrimitive(objects_dict[obj].UUIDs);
5885 // refreshVisualization();
5886 objects_dict.erase(obj);
5887 obj_names_set.erase(obj);
5888 if (!obj_names_set.empty()) {
5889 current_obj = *obj_names_set.begin();
5890 } else {
5891 current_obj = "";
5892 }
5893
5894 is_dirty = true;
5895}
5896
5897
5898void ProjectBuilder::updateCanopy(const std::string &canopy) {
5899#ifdef ENABLE_PLANT_ARCHITECTURE
5900 for (auto plant_instance: canopy_dict[canopy].IDs) {
5901 plantarchitecture->deletePlantInstance(plant_instance);
5902 }
5903 plantarchitecture->loadPlantModelFromLibrary(canopy_dict[canopy].library_name);
5904 plantarchitecture->enableGroundClipping(canopy_dict[canopy].ground_clipping_height);
5905
5906 std::vector<uint> new_canopy_IDs = plantarchitecture->buildPlantCanopyFromLibrary(canopy_dict[canopy].origin, canopy_dict[canopy].plant_spacing, canopy_dict[canopy].plant_count, canopy_dict[canopy].age);
5907 std::vector<vec3> curr_plant_locations = plantarchitecture->getPlantBasePosition(new_canopy_IDs);
5908 canopy_dict[canopy].individual_plant_locations = curr_plant_locations;
5909
5910 leaf_UUIDs = plantarchitecture->getAllLeafUUIDs();
5911 primitive_UUIDs["leaf"] = leaf_UUIDs;
5912 internode_UUIDs = plantarchitecture->getAllInternodeUUIDs();
5913 primitive_UUIDs["internode"] = internode_UUIDs;
5914 petiole_UUIDs = plantarchitecture->getAllPetioleUUIDs();
5915 primitive_UUIDs["petiole"] = petiole_UUIDs;
5916 peduncle_UUIDs = plantarchitecture->getAllPeduncleUUIDs();
5917 primitive_UUIDs["peduncle"] = peduncle_UUIDs;
5918 std::vector<uint> flower_UUIDs = plantarchitecture->getAllFlowerUUIDs();
5919 petal_UUIDs = context->filterPrimitivesByData(flower_UUIDs, "object_label", "petal");
5920 sepal_UUIDs = context->filterPrimitivesByData(flower_UUIDs, "object_label", "sepal");
5921 if (petal_UUIDs.empty() && sepal_UUIDs.empty()) {
5922 petal_UUIDs = flower_UUIDs;
5923 sepal_UUIDs.clear();
5924 }
5925 fruit_UUIDs = plantarchitecture->getAllFruitUUIDs();
5926 primitive_UUIDs["petal"] = petal_UUIDs;
5927 primitive_UUIDs["sepal"] = sepal_UUIDs;
5928 primitive_UUIDs["flower"] = flower_UUIDs;
5929
5930 canopy_dict[canopy].IDs = new_canopy_IDs;
5931#endif
5932}
5933
5934
5935void ProjectBuilder::addCanopy() {
5936 std::string default_canopy_label = "canopy";
5937 std::string new_canopy_label = "canopy_0";
5938 int count = 0;
5939 while (canopy_dict.find(new_canopy_label) != canopy_dict.end()) {
5940 count++;
5941 new_canopy_label = default_canopy_label + "_" + std::to_string(count);
5942 }
5943 canopy new_canopy;
5944 new_canopy.idx = canopy_idx;
5945 canopy_labels_set.insert(new_canopy_label);
5946 canopy_idx++;
5947 new_canopy.age = plant_age;
5948 new_canopy.ground_clipping_height = ground_clipping_height;
5949 new_canopy.label = new_canopy_label;
5950 new_canopy.library_name = plant_library_name;
5951 new_canopy.library_name_verbose = plant_library_name_verbose;
5952 new_canopy.IDs = std::vector<unsigned int>{};
5953 new_canopy.individual_plant_locations = std::vector<vec3>{};
5954 new_canopy.plant_spacing = plant_spacing;
5955 new_canopy.plant_count = plant_count;
5956 new_canopy.origin = canopy_origin;
5957 new_canopy.data_group = "";
5958 canopy_dict[new_canopy.label] = new_canopy;
5959
5960 current_canopy = new_canopy_label;
5961}
5962
5963
5964#ifdef ENABLE_HELIOS_VISUALIZER
5965void ProjectBuilder::refreshVisualization() {
5966 const char *font_name = "LCD";
5967 visualizer->addTextboxByCenter("LOADING...", vec3(.5, .5, 0), make_SphericalCoord(0, 0), RGB::red, 40, font_name, Visualizer::COORDINATES_WINDOW_NORMALIZED);
5971 if (enable_coordinate_axes) {
5972 visualizer->addCoordinateAxes(helios::make_vec3(0, 0, 0.05), helios::make_vec3(1, 1, 1), "positive");
5973 }
5975}
5976#else
5977void ProjectBuilder::refreshVisualization() {
5978 // Visualizer plugin is required for GUI functionality
5979}
5980#endif // ENABLE_HELIOS_VISUALIZER
5981
5982
5983#ifdef ENABLE_HELIOS_VISUALIZER
5984void ProjectBuilder::recordPopup() {
5985 if (ImGui::BeginPopup("repeat_record")) {
5986 ImGui::SetNextItemWidth(100);
5987 ImGui::InputInt("Number of Recordings", &num_recordings);
5988 ImGui::EndPopup();
5989 }
5990}
5991#else
5992void ProjectBuilder::recordPopup() {
5993 // Visualizer plugin is required for GUI functionality
5994}
5995#endif // ENABLE_HELIOS_VISUALIZER
5996
5997
5999 Location location;
6000 location.latitude_deg = latitude;
6001 location.longitude_deg = longitude;
6002 location.UTC_offset = static_cast<float>(UTC_offset);
6003 context->setLocation(location);
6004}
6005
6006
6008 context->deletePrimitive(ground_UUIDs);
6009 if (context->doesObjectExist(ground_objID))
6010 context->deleteObject(ground_objID);
6011 ground_UUIDs.clear();
6012 primitive_UUIDs["ground"].clear();
6013
6014 // uint ground_objID = context->addTileObject( domain_origin, domain_extent, nullptr, ground_resolution, ground_texture_file.c_str() );
6015 if (!ground_model_file.empty() && ground_flag == 2 && use_ground_texture) {
6016 ground_UUIDs = context->loadOBJ(ground_model_file.c_str());
6017 context->translatePrimitive(ground_UUIDs, domain_origin);
6018 ground_objID = context->addPolymeshObject(ground_UUIDs);
6019 } else if (!ground_texture_file.empty() && ground_flag == 1 && use_ground_texture) {
6020 if (num_tiles.x > 1 || num_tiles.y > 1 || ground_resolution.x > 1 || ground_resolution.y > 1) {
6021 buildTiledGround(domain_origin, domain_extent, num_tiles, ground_resolution, ground_texture_file.c_str(), 0.f);
6022
6023 return;
6024 } else {
6025 ground_objID = context->addTileObject(domain_origin, domain_extent, nullrotation, ground_resolution, ground_texture_file.c_str());
6026 ground_UUIDs = context->getObjectPrimitiveUUIDs(ground_objID);
6027 }
6028 } else if (ground_flag == 1 && !use_ground_texture) {
6029 RGBcolor ground_color_;
6030 ground_color_.r = ground_color[0];
6031 ground_color_.g = ground_color[1];
6032 ground_color_.b = ground_color[2];
6033
6034 if (num_tiles.x > 1 || num_tiles.y > 1 || ground_resolution.x > 1 || ground_resolution.y > 1) {
6035 buildTiledGround(domain_origin, domain_extent, num_tiles, ground_resolution, ground_color_, 0.f);
6036 context->setPrimitiveColor(ground_UUIDs, ground_color_);
6037
6038 return;
6039 } else {
6040 ground_objID = context->addTileObject(domain_origin, domain_extent, nullrotation, ground_resolution, ground_color_);
6041 ground_UUIDs = context->getObjectPrimitiveUUIDs(ground_objID);
6042 }
6043 } else if (ground_flag == 2 && !use_ground_texture) {
6044 RGBcolor ground_color_;
6045 ground_color_.r = ground_color[0];
6046 ground_color_.g = ground_color[1];
6047 ground_color_.b = ground_color[2];
6048 ground_UUIDs = context->loadOBJ(ground_model_file.c_str());
6049 ground_objID = context->addPolymeshObject(ground_UUIDs);
6050 context->setObjectColor(ground_objID, ground_color_);
6051 }
6052 // else {
6053 // ground_objID = context->addTileObject(domain_origin, domain_extent, nullrotation, ground_resolution);
6054 // ground_UUIDs = context->getObjectPrimitiveUUIDs(ground_objID);
6055 // }
6056 ground_UUIDs.clear();
6057 ground_UUIDs = context->getObjectPrimitiveUUIDs(ground_objID);
6058 context->cleanDeletedUUIDs(ground_UUIDs);
6059 context->setGlobalData("ground_UUIDs", ground_UUIDs);
6060 context->setPrimitiveData(ground_UUIDs, "twosided_flag", uint(0));
6061 context->setPrimitiveData(ground_UUIDs, "object_label", "ground");
6062 primitive_UUIDs["ground"] = ground_UUIDs;
6063}
6064
6065
6067 context->deletePrimitive(ground_UUIDs);
6068 if (context->doesObjectExist(ground_objID))
6069 context->deleteObject(ground_objID);
6070 ground_UUIDs.clear();
6071 primitive_UUIDs["ground"].clear();
6072}
6073
6074#ifdef ENABLE_HELIOS_VISUALIZER
6075void ProjectBuilder::refreshVisualizationTypes() {
6076 // primitive
6077 visualization_types_primitive.clear();
6078 std::vector<uint> allUUIDs = context->getAllUUIDs();
6079 for (auto &UUID: allUUIDs) {
6080 std::vector<std::string> primitiveData = context->listPrimitiveData(UUID);
6081 for (auto &data: primitiveData) {
6082 visualization_types_primitive.insert(data);
6083 primitive_data_types[data] = context->getPrimitiveDataType(data.c_str());
6084 }
6085 }
6086
6087 // object
6088 visualization_types_object.clear();
6089 std::vector<uint> allobjIDs = context->getAllObjectIDs();
6090 for (auto &objID: allobjIDs) {
6091 std::vector<std::string> objData = context->listObjectData(objID);
6092 for (auto &data: objData) {
6093 visualization_types_object.insert(data);
6094 object_data_types[data] = context->getObjectDataType(data.c_str());
6095 }
6096 }
6097}
6098#else
6099void ProjectBuilder::refreshVisualizationTypes() {
6100 // Visualizer plugin is required for GUI functionality
6101}
6102#endif // ENABLE_HELIOS_VISUALIZER
6103
6104
6105std::string ProjectBuilder::shortenPath(std::string path_name) {
6106 std::string shorten_path = path_name;
6107 for (char &c: shorten_path) {
6108 if (c == '\\') {
6109 c = '/';
6110 }
6111 }
6112 size_t last_file = shorten_path.rfind('/');
6113 if (last_file != std::string::npos) {
6114 shorten_path = shorten_path.substr(last_file + 1);
6115 }
6116 return shorten_path;
6117}
6118
6119
6121 bounding_boxes_map.clear();
6122 int idx = 0;
6123 for (auto &box_pair: bounding_boxes) {
6124 if (box_pair.second) {
6125 bounding_boxes_map[box_pair.first] = idx;
6126 idx++;
6127 }
6128 }
6129 // std::vector<uint> all_UUIDs = context->getAllUUIDs();
6130 // context->clearPrimitiveData(all_UUIDs, "object_number");
6131 // for (auto &UUID : all_UUIDs){
6132 // if (!context->doesPrimitiveDataExist(UUID, "object_label")) continue;
6133 // std::string obj_label;
6134 // context->getPrimitiveData(UUID, "object_label", obj_label);
6135 // if (bounding_boxes_map.find(obj_label) != bounding_boxes_map.end()){
6136 // context->setPrimitiveData(UUID, "object_number", HELIOS_TYPE_UINT, 1, &bounding_boxes_map[obj_label]);
6137 // }
6138 // }
6139}
6140
6141
6142void ProjectBuilder::buildTiledGround(const vec3 &ground_origin, const vec2 &ground_extent, const int2 &texture_subtiles, const int2 &texture_subpatches, const char *ground_texture_file, float ground_rotation) {
6143 context->deletePrimitive(ground_UUIDs);
6144 if (context->doesObjectExist(ground_objID))
6145 context->deleteObject(ground_objID);
6146 ground_UUIDs.clear();
6147 primitive_UUIDs["ground"].clear();
6148
6149 vec2 dx_tile(ground_extent.x / float(texture_subtiles.x), ground_extent.y / float(texture_subtiles.y));
6150
6151 vec2 dx_subpatch(dx_tile.x / float(texture_subpatches.x), dx_tile.y / float(texture_subpatches.y));
6152
6153 std::vector<uint> UUIDs;
6154 for (int j = 0; j < texture_subtiles.y; j++) {
6155 for (int i = 0; i < texture_subtiles.x; i++) {
6156
6157 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);
6158
6159 if (ground_rotation != 0) {
6160 center = rotatePointAboutLine(center, ground_origin, make_vec3(0, 0, 1), ground_rotation);
6161 }
6162
6163 UUIDs = context->addTile(center, dx_tile, make_SphericalCoord(0, -ground_rotation), texture_subpatches, ground_texture_file);
6164
6165 ground_UUIDs.insert(ground_UUIDs.begin(), UUIDs.begin(), UUIDs.end());
6166 }
6167 }
6168 context->cleanDeletedUUIDs(ground_UUIDs);
6169
6170 context->setPrimitiveData(ground_UUIDs, "twosided_flag", uint(0));
6171 context->setGlobalData("ground_UUIDs", ground_UUIDs);
6172 context->setPrimitiveData(ground_UUIDs, "object_label", "ground");
6173 primitive_UUIDs["ground"] = ground_UUIDs;
6174}
6175
6176
6177void ProjectBuilder::buildTiledGround(const vec3 &ground_origin, const vec2 &ground_extent, const int2 &texture_subtiles, const int2 &texture_subpatches, RGBcolor ground_color, float ground_rotation) {
6178 context->deletePrimitive(ground_UUIDs);
6179 if (context->doesObjectExist(ground_objID))
6180 context->deleteObject(ground_objID);
6181 ground_UUIDs.clear();
6182 primitive_UUIDs["ground"].clear();
6183
6184 vec2 dx_tile(ground_extent.x / float(texture_subtiles.x), ground_extent.y / float(texture_subtiles.y));
6185
6186 vec2 dx_subpatch(dx_tile.x / float(texture_subpatches.x), dx_tile.y / float(texture_subpatches.y));
6187
6188 std::vector<uint> UUIDs;
6189 for (int j = 0; j < texture_subtiles.y; j++) {
6190 for (int i = 0; i < texture_subtiles.x; i++) {
6191
6192 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);
6193
6194 if (ground_rotation != 0) {
6195 center = rotatePointAboutLine(center, ground_origin, make_vec3(0, 0, 1), ground_rotation);
6196 }
6197
6198 UUIDs = context->addTile(center, dx_tile, make_SphericalCoord(0, -ground_rotation), texture_subpatches, ground_color);
6199
6200 ground_UUIDs.insert(ground_UUIDs.begin(), UUIDs.begin(), UUIDs.end());
6201 }
6202 }
6203 context->cleanDeletedUUIDs(ground_UUIDs);
6204
6205 context->setPrimitiveData(ground_UUIDs, "twosided_flag", uint(0));
6206 context->setGlobalData("ground_UUIDs", ground_UUIDs);
6207 context->setPrimitiveData(ground_UUIDs, "object_label", "ground");
6208 primitive_UUIDs["ground"] = ground_UUIDs;
6209}