0.4.1
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages Concepts
PositionInput.cpp
Go to the documentation of this file.
1// This file is part of INSTINCT, the INS Toolkit for Integrated
2// Navigation Concepts and Training by the Institute of Navigation of
3// the University of Stuttgart, Germany.
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9/// @file PositionInput.hpp
10/// @brief Position Input GUI widgets
11/// @author T. Topp (topp@ins.uni-stuttgart.de)
12/// @date 2023-08-14
13
14#include "PositionInput.hpp"
15
16#include <imgui.h>
17#include <fmt/core.h>
18
21
22namespace NAV
23{
24
26{
27 switch (refFrame)
28 {
30 return "ECEF";
32 return "LLA";
34 break;
35 }
36 return "";
37}
38
39namespace gui::widgets
40{
41namespace
42{
43/// @brief Shows a ComboBox to select the position input reference frame
44/// @param[in] label Label to show beside the combo box. This has to be a unique id for ImGui.
45/// @param[in] refFrame Reference to the frame to select
46bool ComboPositionInputReferenceFrame(const char* label, PositionWithFrame::ReferenceFrame& refFrame)
47{
48 return gui::widgets::EnumCombo(label, refFrame);
49}
50} // namespace
51} // namespace gui::widgets
52
53} // namespace NAV
54
55bool NAV::gui::widgets::PositionInput(const char* str, PositionWithFrame& position, PositionInputLayout layout, float itemWidth)
56{
57 bool changes = false;
58 bool edited = false;
59
60 ImGui::BeginGroup();
61
63 {
64 std::string txt = str;
65 txt = txt.substr(0, txt.find_first_of('#'));
66 ImGui::TextUnformatted(txt.c_str());
67 ImGui::SameLine();
68 }
69
70 if (layout == PositionInputLayout::SINGLE_ROW) { ImGui::SetNextItemWidth(80.0F); }
71 else { ImGui::SetNextItemWidth(itemWidth); }
72 if (ComboPositionInputReferenceFrame(fmt::format("{}##ComboPositionInputReferenceFrame {}", layout != PositionInputLayout::SINGLE_ROW ? str : "", str).c_str(), position.frame))
73 {
74 changes = true;
75 }
76 if (layout == PositionInputLayout::SINGLE_ROW) { ImGui::SameLine(); }
77
79 {
80 ImGui::SetNextItemWidth(itemWidth);
81 if (ImGui::InputDouble(fmt::format("{}##X {}", layout != PositionInputLayout::TWO_ROWS ? "X" : "", str).c_str(), &position.e_position(0), 0.0, 0.0, "%.4fm")) { changes = true; }
82
83 if (layout == PositionInputLayout::SINGLE_ROW || layout == PositionInputLayout::TWO_ROWS) { ImGui::SameLine(); }
84 ImGui::SetNextItemWidth(itemWidth);
85 if (ImGui::InputDouble(fmt::format("{}##Y {}", layout != PositionInputLayout::TWO_ROWS ? "Y" : "", str).c_str(), &position.e_position(1), 0.0, 0.0, "%.4fm")) { changes = true; }
86
87 if (layout == PositionInputLayout::SINGLE_ROW || layout == PositionInputLayout::TWO_ROWS) { ImGui::SameLine(); }
88 ImGui::SetNextItemWidth(itemWidth);
89 if (ImGui::InputDouble(fmt::format("{}##Z {}", layout != PositionInputLayout::TWO_ROWS ? "Z" : "", str).c_str(), &position.e_position(2), 0.0, 0.0, "%.4fm")) { changes = true; }
90
92 {
93 ImGui::SameLine();
94 ImGui::SetCursorPosX(ImGui::GetCursorPosX() - ImGui::GetStyle().ItemSpacing.x + ImGui::GetStyle().ItemInnerSpacing.x);
95 ImGui::TextUnformatted("XYZ");
96 }
97 }
99 {
100 auto lla_position = trafo::ecef2lla_WGS84(position.e_position);
101 lla_position(0) = rad2deg(lla_position(0));
102 lla_position(1) = rad2deg(lla_position(1));
103 if (lla_position.hasNaN())
104 {
105 lla_position = Eigen::Vector3d(0, 0, 0);
106 position.e_position = trafo::lla2ecef_WGS84(lla_position);
107 }
108
109 ImGui::SetNextItemWidth(itemWidth);
110 if (ImGui::InputDoubleL(fmt::format("{}##Lat {}", layout != PositionInputLayout::TWO_ROWS ? "Latitude" : "", str).c_str(), &lla_position(0), -90.0, 90.0, 0.0, 0.0, "%.9f°")) { edited = true; }
111 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
112
113 if (layout == PositionInputLayout::SINGLE_ROW || layout == PositionInputLayout::TWO_ROWS) { ImGui::SameLine(); }
114 ImGui::SetNextItemWidth(itemWidth);
115 if (ImGui::InputDoubleL(fmt::format("{}##Lon {}", layout != PositionInputLayout::TWO_ROWS ? "Longitude" : "", str).c_str(), &lla_position(1), -180.0, 180.0, 0.0, 0.0, "%.9f°")) { edited = true; }
116 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
117
118 if (layout == PositionInputLayout::SINGLE_ROW || layout == PositionInputLayout::TWO_ROWS) { ImGui::SameLine(); }
119 ImGui::SetNextItemWidth(itemWidth);
120 if (ImGui::InputDouble(fmt::format("{}##Alt {}", layout != PositionInputLayout::TWO_ROWS ? "Altitude" : "", str).c_str(), &lla_position(2), 0.0, 0.0, "%.4fm")) { edited = true; }
121 if (ImGui::IsItemDeactivatedAfterEdit()) { changes = true; }
122
123 if (layout == PositionInputLayout::TWO_ROWS)
124 {
125 ImGui::SameLine();
126 ImGui::SetCursorPosX(ImGui::GetCursorPosX() - ImGui::GetStyle().ItemSpacing.x + ImGui::GetStyle().ItemInnerSpacing.x);
127 ImGui::TextUnformatted("Lat, Lon, Alt");
128 }
129
130 if (changes || edited)
131 {
132 lla_position(0) = deg2rad(lla_position(0));
133 lla_position(1) = deg2rad(lla_position(1));
134 if (!lla_position.hasNaN())
135 {
136 position.e_position = trafo::lla2ecef_WGS84(lla_position);
137 }
138 }
139 }
140
141 ImGui::EndGroup();
142
143 return changes;
144}
145
147{
148 j = to_string(refFrame);
149}
150
152{
153 auto text = j.get<std::string>();
154 if (text == "ECEF") { refFrame = PositionWithFrame::ReferenceFrame::ECEF; }
155 else if (text == "LLA") { refFrame = PositionWithFrame::ReferenceFrame::LLA; }
156}
158{
159 j["frame"] = position.frame;
161 {
162 j["position"] = position.e_position;
163 }
165 {
166 auto lla = trafo::ecef2lla_WGS84(position.e_position);
167 j["position"] = Eigen::Vector3d(rad2deg(lla(0)), rad2deg(lla(1)), lla(2));
168 }
169}
170
172{
173 if (j.contains("frame"))
174 {
175 j.at("frame").get_to(position.frame);
176 }
177 if (j.contains("position"))
178 {
180 {
181 j.at("position").get_to(position.e_position);
182 }
184 {
185 auto lla = j.at("position").get<Eigen::Vector3d>();
186 position.e_position = trafo::lla2ecef_WGS84(Eigen::Vector3d(deg2rad(lla(0)), deg2rad(lla(1)), lla(2)));
187 }
188 }
189}
Combo representing an enumeration.
nlohmann::json json
json namespace
Position Input GUI widgets.
ImGui extensions.
bool InputDoubleL(const char *label, double *v, double v_min, double v_max, double step, double step_fast, const char *format, ImGuiInputTextFlags flags)
Shows a value limited InputText GUI element for 'double'.
Definition imgui_ex.cpp:294
bool EnumCombo(const char *label, T &enumeration, size_t startIdx=0)
Combo representing an enumeration.
Definition EnumCombo.hpp:30
void from_json(const json &j, DynamicInputPins &obj, Node *node)
Converts the provided json object into a node object.
bool PositionInput(const char *str, PositionWithFrame &position, PositionInputLayout layout=PositionInputLayout::SINGLE_COLUMN, float itemWidth=140.0F)
Inputs to edit an Position object.
void to_json(json &j, const DynamicInputPins &obj)
Converts the provided object into json.
PositionInputLayout
Layout options for the Position input.
@ SINGLE_ROW
All elements in a single row.
Eigen::Vector3< typename Derived::Scalar > ecef2lla_WGS84(const Eigen::MatrixBase< Derived > &e_position)
Converts Earth-centered-Earth-fixed coordinates into latitude, longitude and altitude using WGS84.
Eigen::Vector3< typename Derived::Scalar > lla2ecef_WGS84(const Eigen::MatrixBase< Derived > &lla_position)
Converts latitude, longitude and altitude into Earth-centered-Earth-fixed coordinates using WGS84.
const char * to_string(gui::widgets::PositionWithFrame::ReferenceFrame refFrame)
Converts the enum to a string.
constexpr auto deg2rad(const T &deg)
Convert Degree to Radians.
Definition Units.hpp:21
constexpr auto rad2deg(const T &rad)
Convert Radians to Degree.
Definition Units.hpp:39
Position with Reference frame, used for GUI input.
Eigen::Vector3d e_position
Position in ECEF coordinates in [m].
ReferenceFrame frame
Reference frame used for the input, not for the storage of values.