24 #include <Wt/WComboBox> 25 #include <Wt/WContainerWidget> 26 #include <Wt/WGroupBox> 27 #include <Wt/WLineEdit> 28 #include <Wt/WPushButton> 30 #include <goby/util/as.h> 32 #include "liaison_geodesy.h" 36 goby::common::LiaisonGeodesy::LiaisonGeodesy(
const protobuf::LiaisonConfig& cfg,
37 Wt::WContainerWidget* parent)
38 : LiaisonContainer(parent), geodesy_config_(cfg.GetExtension(protobuf::geodesy_config)),
39 mode_(DECIMAL_DEGREES), last_lat_(
std::numeric_limits<
double>::quiet_NaN()),
40 last_lon_(
std::numeric_limits<
double>::quiet_NaN()),
41 last_x_(
std::numeric_limits<
double>::quiet_NaN()),
42 last_y_(
std::numeric_limits<
double>::quiet_NaN())
44 latlon_format_ =
new Wt::WComboBox(
this);
45 latlon_format_->addItem(
"Decimal Degrees");
46 latlon_format_->addItem(
"Degrees, Decimal Minutes");
47 latlon_format_->addItem(
"Degrees, Minutes, Seconds");
49 latlon_format_->changed().connect(
this, &LiaisonGeodesy::change_mode);
51 WGroupBox* datum_box =
new Wt::WGroupBox(
"Datum",
this);
52 new WText(
"Latitude: ", datum_box);
53 datum_lat_ =
new WText(datum_box);
54 new WBreak(datum_box);
55 new WText(
"Longitude: ", datum_box);
56 datum_lon_ =
new WText(datum_box);
58 geodesy_.Initialise(geodesy_config_.lat_origin(), geodesy_config_.lon_origin());
60 WGroupBox* local_to_geo_box =
new Wt::WGroupBox(
"Local UTM to Latitude/Longitude",
this);
62 new WText(
"X (m): ", local_to_geo_box);
63 local_to_geo_x_ =
new WLineEdit(local_to_geo_box);
65 new WBreak(local_to_geo_box);
66 new WText(
"Y (m): ", local_to_geo_box);
67 local_to_geo_y_ =
new WLineEdit(local_to_geo_box);
68 new WBreak(local_to_geo_box);
69 local_to_geo_button_ =
new WPushButton(
"Convert", local_to_geo_box);
70 local_to_geo_button_->clicked().connect(
this, &LiaisonGeodesy::convert_local_to_geo);
71 local_to_geo_x_->changed().connect(
this, &LiaisonGeodesy::convert_local_to_geo);
72 local_to_geo_y_->changed().connect(
this, &LiaisonGeodesy::convert_local_to_geo);
74 new WBreak(local_to_geo_box);
76 new WText(
"Latitude: ", local_to_geo_box);
77 local_to_geo_lat_ =
new WText(local_to_geo_box);
78 new WBreak(local_to_geo_box);
79 new WText(
"Longitude: ", local_to_geo_box);
80 local_to_geo_lon_ =
new WText(local_to_geo_box);
82 WGroupBox* geo_to_local_box =
new Wt::WGroupBox(
"Latitude/Longitude to Local UTM",
this);
84 WContainerWidget* lat_box =
new WContainerWidget(geo_to_local_box);
85 new WText(
"Latitude: ", lat_box);
86 lat_box->resize(WLength(20, Wt::WLength::FontEm), WLength());
88 geo_to_local_lat_deg_ =
new WLineEdit(geo_to_local_box);
89 new WText(std::wstring(1,
wchar_t(0x00B0)), geo_to_local_box);
90 geo_to_local_lat_deg_->resize(WLength(5, Wt::WLength::FontEm), WLength());
91 lat_min_box_ =
new WContainerWidget(geo_to_local_box);
92 lat_min_box_->setInline(
true);
93 geo_to_local_lat_min_ =
new WLineEdit(lat_min_box_);
94 new WText(
"'", lat_min_box_);
95 geo_to_local_lat_min_->resize(WLength(5, Wt::WLength::FontEm), WLength());
96 lat_sec_box_ =
new WContainerWidget(geo_to_local_box);
97 lat_sec_box_->setInline(
true);
98 geo_to_local_lat_sec_ =
new WLineEdit(lat_sec_box_);
99 new WText(
"\"", lat_sec_box_);
100 geo_to_local_lat_sec_->resize(WLength(5, Wt::WLength::FontEm), WLength());
101 lat_hemi_box_ =
new WContainerWidget(geo_to_local_box);
102 lat_hemi_box_->setInline(
true);
103 geo_to_local_lat_hemi_ =
new Wt::WComboBox(lat_hemi_box_);
104 geo_to_local_lat_hemi_->addItem(
"N");
105 geo_to_local_lat_hemi_->addItem(
"S");
107 new WBreak(geo_to_local_box);
109 WContainerWidget* lon_box =
new WContainerWidget(geo_to_local_box);
110 new WText(
"Longitude: ", lon_box);
111 lon_box->resize(WLength(20, Wt::WLength::FontEm), WLength());
113 geo_to_local_lon_deg_ =
new WLineEdit(geo_to_local_box);
114 geo_to_local_lon_deg_->resize(WLength(5, Wt::WLength::FontEm), WLength());
115 new WText(std::wstring(1,
wchar_t(0x00B0)), geo_to_local_box);
116 lon_min_box_ =
new WContainerWidget(geo_to_local_box);
117 lon_min_box_->setInline(
true);
118 geo_to_local_lon_min_ =
new WLineEdit(lon_min_box_);
119 new WText(
"'", lon_min_box_);
120 geo_to_local_lon_min_->resize(WLength(5, Wt::WLength::FontEm), WLength());
121 lon_sec_box_ =
new WContainerWidget(geo_to_local_box);
122 lon_sec_box_->setInline(
true);
123 geo_to_local_lon_sec_ =
new WLineEdit(lon_sec_box_);
124 new WText(
"'", lon_sec_box_);
125 geo_to_local_lon_sec_->resize(WLength(5, Wt::WLength::FontEm), WLength());
126 lon_hemi_box_ =
new WContainerWidget(geo_to_local_box);
127 lon_hemi_box_->setInline(
true);
128 geo_to_local_lon_hemi_ =
new Wt::WComboBox(lon_hemi_box_);
129 geo_to_local_lon_hemi_->addItem(
"E");
130 geo_to_local_lon_hemi_->addItem(
"W");
132 new WBreak(geo_to_local_box);
134 geo_to_local_button_ =
new WPushButton(
"Convert", geo_to_local_box);
135 new WBreak(geo_to_local_box);
137 new WText(
"X (m): ", geo_to_local_box);
138 geo_to_local_x_ =
new WText(geo_to_local_box);
139 new WBreak(geo_to_local_box);
140 new WText(
"Y (m): ", geo_to_local_box);
141 geo_to_local_y_ =
new WText(geo_to_local_box);
143 geo_to_local_button_->clicked().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
144 geo_to_local_lat_deg_->changed().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
145 geo_to_local_lat_min_->changed().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
146 geo_to_local_lat_sec_->changed().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
147 geo_to_local_lat_hemi_->changed().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
148 geo_to_local_lon_deg_->changed().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
149 geo_to_local_lon_min_->changed().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
150 geo_to_local_lon_sec_->changed().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
151 geo_to_local_lon_hemi_->changed().connect(
this, &LiaisonGeodesy::convert_geo_to_local);
155 set_name(
"MOOSGeodesy");
158 void goby::common::LiaisonGeodesy::loop() {}
160 void goby::common::LiaisonGeodesy::convert_local_to_geo()
162 geodesy_.UTM2LatLong(goby::util::as<double>(boost::trim_copy(local_to_geo_x_->text().narrow())),
163 goby::util::as<double>(boost::trim_copy(local_to_geo_y_->text().narrow())),
164 last_lat_, last_lon_);
168 void goby::common::LiaisonGeodesy::convert_geo_to_local()
171 goby::util::as<double>(boost::trim_copy(geo_to_local_lat_deg_->text().narrow())),
173 goby::util::as<double>(boost::trim_copy(geo_to_local_lat_min_->text().narrow())),
175 goby::util::as<double>(boost::trim_copy(geo_to_local_lat_sec_->text().narrow()));
178 goby::util::as<double>(boost::trim_copy(geo_to_local_lon_deg_->text().narrow())),
180 goby::util::as<double>(boost::trim_copy(geo_to_local_lon_min_->text().narrow())),
182 goby::util::as<double>(boost::trim_copy(geo_to_local_lon_sec_->text().narrow()));
184 double lat = lat_deg;
185 double lon = lon_deg;
188 case DEGREES_MINUTES_SECONDS:
189 lat += lat > 0 ? lat_sec / 3600 : -lat_sec / 3600;
190 lon += lon > 0 ? lon_sec / 3600 : -lon_sec / 3600;
192 case DEGREES_MINUTES:
193 lat += lat > 0 ? lat_min / 60 : -lat_min / 60;
194 if (geo_to_local_lat_hemi_->currentIndex() == 1)
196 lon += lon > 0 ? lon_min / 60 : -lon_min / 60;
197 if (geo_to_local_lon_hemi_->currentIndex() == 1)
201 case DECIMAL_DEGREES:
break;
204 geodesy_.LatLong2LocalUTM(lat, lon, last_y_, last_x_);
206 if (!(boost::math::isnan)(last_x_) && !(boost::math::isnan)(last_y_))
208 std::stringstream x_ss, y_ss;
209 x_ss << std::fixed << std::setprecision(2) << last_x_;
210 y_ss << std::fixed << std::setprecision(2) << last_y_;
212 geo_to_local_x_->setText(x_ss.str());
213 geo_to_local_y_->setText(y_ss.str());
217 geo_to_local_x_->setText(
"---");
218 geo_to_local_y_->setText(
"---");
222 void goby::common::LiaisonGeodesy::change_mode()
224 int mode = latlon_format_->currentIndex();
225 mode_ =
static_cast<LatLonMode
>(mode);
231 case DECIMAL_DEGREES:
233 geo_to_local_lat_deg_->resize(WLength(20, Wt::WLength::FontEm), WLength());
235 geo_to_local_lon_deg_->resize(WLength(20, Wt::WLength::FontEm), WLength());
237 lat_min_box_->hide();
238 lat_hemi_box_->hide();
239 lon_min_box_->hide();
240 lon_hemi_box_->hide();
241 lon_sec_box_->hide();
242 lat_sec_box_->hide();
245 case DEGREES_MINUTES:
247 geo_to_local_lat_deg_->resize(WLength(5, Wt::WLength::FontEm), WLength());
249 geo_to_local_lon_deg_->resize(WLength(5, Wt::WLength::FontEm), WLength());
250 geo_to_local_lat_min_->resize(WLength(15, Wt::WLength::FontEm), WLength());
252 geo_to_local_lon_min_->resize(WLength(15, Wt::WLength::FontEm), WLength());
254 lat_sec_box_->hide();
255 lon_sec_box_->hide();
256 lat_min_box_->show();
257 lat_hemi_box_->show();
258 lon_min_box_->show();
259 lon_hemi_box_->show();
262 case DEGREES_MINUTES_SECONDS:
264 geo_to_local_lat_deg_->resize(WLength(5, Wt::WLength::FontEm), WLength());
266 geo_to_local_lon_deg_->resize(WLength(5, Wt::WLength::FontEm), WLength());
267 geo_to_local_lat_min_->resize(WLength(5, Wt::WLength::FontEm), WLength());
269 geo_to_local_lon_min_->resize(WLength(5, Wt::WLength::FontEm), WLength());
271 lat_sec_box_->show();
272 lon_sec_box_->show();
273 lat_min_box_->show();
274 lat_hemi_box_->show();
275 lon_min_box_->show();
276 lon_hemi_box_->show();
280 convert_geo_to_local();
283 void goby::common::LiaisonGeodesy::reformat()
285 datum_lat_->setText(format(geodesy_config_.lat_origin(), mode_, LAT));
286 datum_lon_->setText(format(geodesy_config_.lon_origin(), mode_, LON));
288 if (!(boost::math::isnan)(last_lat_))
289 local_to_geo_lat_->setText(format(last_lat_, mode_, LAT));
291 local_to_geo_lat_->setText(
"---");
293 if (!(boost::math::isnan)(last_lon_))
294 local_to_geo_lon_->setText(format(last_lon_, mode_, LON));
296 local_to_geo_lon_->setText(
"---");
299 std::wstring goby::common::LiaisonGeodesy::format(
double angle, LatLonMode mode, LatLon type)
301 char pos = (type == LAT) ?
'N' :
'E';
302 char neg = (type == LAT) ?
'S' :
'W';
307 case DECIMAL_DEGREES:
309 std::wstringstream ss;
310 ss << std::fixed << std::setprecision(7) << angle << wchar_t(0x00B0);
314 case DEGREES_MINUTES:
316 int deg = std::abs(angle);
317 double min = (std::abs(angle) - deg) * 60;
318 std::wstringstream ss;
319 ss << deg << wchar_t(0x00B0) <<
" " << std::setprecision(7) << min <<
"' " 320 << ((angle > 0) ? pos : neg);
323 case DEGREES_MINUTES_SECONDS:
325 int deg = std::abs(angle);
326 int min = (std::abs(angle) - deg) * 60;
327 double sec = (std::abs(angle) - deg - min / 60.0) * 3600;
328 std::wstringstream ss;
329 ss << deg << wchar_t(0x00B0) <<
" " << min <<
"' " << sec <<
"\" " 330 << ((angle > 0) ? pos : neg);