29extern double m_cursor_lat, m_cursor_lon;
30extern int m_DialogStyle;
35CursorData::CursorData(wxWindow *window,
GRIBUICtrlBar &parent)
39 wxWindowListNode *node = this->GetChildren().GetFirst();
41 wxWindow *win = node->GetData();
42 if (
dynamic_cast<wxCheckBox *
>(win)) {
43 int winId =
dynamic_cast<wxCheckBox *
>(win)->GetId() - ID_CB_WIND;
44 if (m_gparent.InDataPlot(winId)) {
45 dynamic_cast<wxCheckBox *
>(win)->SetId(winId);
46 dynamic_cast<wxCheckBox *
>(win)->SetValue(m_gparent.m_bDataPlot[winId]);
49 node = node->GetNext();
54 m_tCursorTrackTimer.Connect(
55 wxEVT_TIMER, wxTimerEventHandler(CursorData::OnCursorTrackTimer),
nullptr,
61void CursorData::OnCBAny(wxCommandEvent &event) {
62 int id =
event.GetId();
63 wxWindow *win = this->FindWindow(
id);
64 if (m_gparent.InDataPlot(
id))
65 m_gparent.m_bDataPlot[id] = ((wxCheckBox *)win)->IsChecked();
66 ResolveDisplayConflicts(
id);
69void CursorData::ResolveDisplayConflicts(
int Id) {
71 for (
int i = 0; i < GribOverlaySettings::GEO_ALTITUDE; i++) {
72 if (i != Id && m_gparent.m_bDataPlot[i]) {
85 m_gparent.m_bDataPlot[i] =
false;
86 wxWindow *win = FindWindow(i);
87 ((wxCheckBox *)win)->SetValue(
false);
91 m_gparent.SetFactoryOptions();
94void CursorData::AddTrackingControl(wxControl *ctrl1, wxControl *ctrl2,
95 wxControl *ctrl3, wxControl *ctrl4,
96 bool show,
bool vertical,
int wctrl2,
99 m_fgTrackingControls->Add(ctrl1, 0, wxALL, 1);
102 m_fgTrackingControls->Add(ctrl2, 0, wxALL, 0);
103 ctrl2->SetMinSize(wxSize(wctrl2, -1));
106 m_fgTrackingControls->Add(0, 0, 1, wxALL, 1);
109 long flag1 = wxALIGN_CENTER;
110 long flag = vertical ? flag1 : wxALL;
111 m_fgTrackingControls->Add(ctrl3, 0, flag, 0);
112 ctrl3->SetMinSize(wxSize(wctrl3_4, -1));
114 }
else if (!vertical)
115 m_fgTrackingControls->Add(0, 0, 1, wxALL, 1);
118 m_fgTrackingControls->Add(ctrl4, 0, wxALL, 0);
119 ctrl4->SetMinSize(wxSize(vertical ? wctrl2 : wctrl3_4, -1));
121 }
else if (!vertical)
122 m_fgTrackingControls->Add(0, 0, 1, wxALL, 1);
125 if (ctrl1) ctrl1->Hide();
126 if (ctrl2) ctrl2->Hide();
127 if (ctrl3) ctrl3->Hide();
128 if (ctrl4) ctrl4->Hide();
132void CursorData::PopulateTrackingControls(
bool vertical) {
133 m_fgTrackingControls->Clear();
135 wxFlexGridSizer *ps = (wxFlexGridSizer *)(m_gparent.GetSizer());
136 if (ps && (ps->GetCols() == 1))
137 m_fgTrackingControls->SetCols(4);
139 m_fgTrackingControls->SetCols(12);
141 m_fgTrackingControls->SetCols(2);
147 GetTextExtent(_T(
"abcdefghihjk"), &wn,
nullptr, 0, 0,
149 GetTextExtent(_T(
"abcdef"), &ws,
nullptr, 0, 0,
152 _T(
"abcdefghijklmopq"), &wd,
nullptr, 0, 0,
155 _T(
"abcdefghijklm"), &wl,
nullptr, 0, 0,
160 new wxTextCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
161 wxDefaultSize, wxTE_READONLY | wxNO_BORDER);
165 GribOverlaySettings::BFS;
166 wd = vertical ? wn : bf ? wn : wd;
167 wl = vertical ? wn : wl;
169 AddTrackingControl(m_cbWind, m_tcWindSpeed, m_tcWindSpeedBf,
170 m_tcWindDirection,
false, vertical, 0,
173 m_cbWind, m_tcWindSpeed,
174 vertical ? (bf ? dummy : m_tcWindSpeedBf) : m_tcWindDirection,
175 vertical ? m_tcWindDirection : 0,
176 m_gparent.m_pTimelineSet &&
177 m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(
Idx_WIND_VX) !=
179 m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(
Idx_WIND_VY) !=
182 AddTrackingControl(m_cbWindGust, m_tcWindGust, 0, 0,
188 AddTrackingControl(m_cbPressure, m_tcPressure, 0, 0,
196 AddTrackingControl(m_cbWave, m_tcWaveHeight, m_tcWavePeriode,
197 m_tcWaveDirection,
false, vertical, 0,
204 AddTrackingControl(m_cbWave, m_tcWaveHeight,
205 vertical ? m_tcWavePeriode : m_tcWaveDirection,
206 vertical ? m_tcWaveDirection : 0, m_Altitude == 0,
209 AddTrackingControl(m_cbWave, m_tcWaveHeight, 0, 0, m_Altitude == 0,
215 AddTrackingControl(m_cbWave, m_tcWaveDirection, 0, 0, m_Altitude == 0,
219 AddTrackingControl(m_cbCurrent, m_tcCurrentVelocity, m_tcCurrentDirection, 0,
220 false, vertical, 0, 0);
221 AddTrackingControl(m_cbCurrent, m_tcCurrentVelocity,
222 vertical ? dummy : m_tcCurrentDirection,
223 vertical ? m_tcCurrentDirection : 0,
224 m_gparent.m_pTimelineSet &&
225 m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(
227 m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(
231 AddTrackingControl(m_cbPrecipitation, m_tcPrecipitation, 0, 0,
237 AddTrackingControl(m_cbCloud, m_tcCloud, 0, 0,
243 AddTrackingControl(m_cbAirTemperature, m_tcAirTemperature, 0, 0,
249 AddTrackingControl(m_cbSeaTemperature, m_tcSeaTemperature, 0, 0,
255 AddTrackingControl(m_cbCAPE, m_tcCAPE, 0, 0,
261 AddTrackingControl(m_cbReflC, m_tcReflC, 0, 0,
269 AddTrackingControl(m_cbAltitude, m_tcAltitude, 0, 0,
275 AddTrackingControl(m_cbTemp, m_tcTemp, 0, 0,
281 AddTrackingControl(m_cbRelHumid, m_tcRelHumid, 0, 0,
288 m_stTrackingText->SetLabel(_(
"Data at cursor position"));
294 GribOverlaySettings::GEO_ALTITUDE,
299 .GetAltitudeFromIndex(
301 .Settings[GribOverlaySettings::PRESSURE]
305 GribOverlaySettings::PRESSURE))
306 : wxString::Format(_T(
"%1.*f "), lev == (int)lev ? 0 : 1, lev)
307 .Append(m_gparent.m_OverlaySettings.GetUnitSymbol(
309 wxString pre = _T(
" ");
311 pre.Append(_(
"at Geopotential Height"));
313 m_tcAltitude->SetToolTip(_(
"Altitude") + t);
314 m_tcTemp->SetToolTip(_(
"Temperature") + t);
315 m_tcRelHumid->SetToolTip(_(
"Relative Humidity") + t);
322 m_tcWindSpeed->SetToolTip(_(
"Wind Speed") + t);
323 m_tcWindSpeedBf->SetToolTip(_(
"Wind Speed in Bf") + t);
324 m_tcWindDirection->SetToolTip(_(
"Wind Direction") + t);
327 GribOverlaySettings::GEO_ALTITUDE),
328 lev == (
int)lev ? 0 : 1, lev);
329 m_tcWindGust->SetToolTip(_(
"Wind Gust at") + t);
332 wxString s[] = {_T(
" "), _(
"Air Temperature at"), _(
"surface level"),
333 _(
"Sea Surface Temperature")};
336 GribOverlaySettings::GEO_ALTITUDE,
339 1000 + NORWAY_METNO) != wxNOT_FOUND
341 : _T(
" %1.*f ") + m_gparent.m_OverlaySettings.GetUnitSymbol(
343 lev == (int)lev ? 0 : 1, lev);
344 m_tcAirTemperature->SetToolTip(s[1] + t);
346 m_tcSeaTemperature->SetToolTip(
355void CursorData::UpdateTrackingControls(
void) {
363 RecordArray[
Idx_WIND_VY + m_Altitude], m_cursor_lon, m_cursor_lat)) {
365 GribOverlaySettings::WIND, vkn);
367 m_tcWindSpeed->SetValue(
369 GribOverlaySettings::WIND),
375 .m_Units != GribOverlaySettings::BFS) {
377 if (m_DialogStyle == SEPARATED_VERTICAL)
378 m_tcWindSpeedBf->SetValue(
379 wxString::Format(_T(
"%2d bf"), (
int)round(vk)));
381 m_tcWindSpeed->SetValue(
382 m_tcWindSpeed->GetValue().Append(_T(
" - ")).Append(
383 wxString::Format(_T(
"%2d bf"), (
int)round(vk))));
386 m_tcWindDirection->SetValue(
387 wxString::Format(_T(
"%03d%c"), (
int)(ang), 0x00B0));
389 m_tcWindSpeed->SetValue(_(
"N/A"));
390 m_tcWindSpeedBf->SetValue(_(
"N/A"));
391 m_tcWindDirection->SetValue(_(
"N/A"));
397 m_cursor_lon, m_cursor_lat,
true);
399 if (vkn != GRIB_NOTDEF) {
401 GribOverlaySettings::WIND_GUST, vkn);
402 m_tcWindGust->SetValue(wxString::Format(
404 GribOverlaySettings::WIND_GUST),
407 m_tcWindGust->SetValue(_(
"N/A"));
413 m_cursor_lon, m_cursor_lat,
true);
415 if (press != GRIB_NOTDEF) {
417 GribOverlaySettings::PRESSURE, press);
423 m_tcPressure->SetValue(wxString::Format(
425 GribOverlaySettings::PRESSURE),
428 m_tcPressure->SetValue(_(
"N/A"));
434 m_cursor_lon, m_cursor_lat,
true);
436 if (height != GRIB_NOTDEF) {
438 GribOverlaySettings::WAVE, height);
439 wxString w(wxString::Format(
441 GribOverlaySettings::WAVE),
445 m_cursor_lon, m_cursor_lat,
true);
446 if (period != GRIB_NOTDEF) {
447 if (m_DialogStyle == SEPARATED_VERTICAL)
448 m_tcWavePeriode->SetValue(
449 wxString::Format(_T(
"%01ds"), (
int)round(period)));
451 w.Append(wxString::Format(_T(
" - %01ds"), (
int)round(period)));
453 m_tcWavePeriode->SetValue(_(
"N/A"));
455 m_tcWavePeriode->SetValue(_(
"N/A"));
457 m_tcWaveHeight->SetValue(w);
459 m_tcWaveHeight->SetValue(_(
"N/A"));
465 m_cursor_lon, m_cursor_lat,
true,
true);
466 if (direction != GRIB_NOTDEF)
467 m_tcWaveDirection->SetValue(
468 wxString::Format(_T(
"%03d%c"), (
int)direction, 0x00B0));
470 m_tcWaveDirection->SetValue(_(
"N/A"));
481 if (ang >= 360) ang -= 360;
482 if (ang < 0) ang += 360;
485 GribOverlaySettings::CURRENT, vkn);
487 m_tcCurrentVelocity->SetValue(wxString::Format(
489 GribOverlaySettings::CURRENT),
492 m_tcCurrentDirection->SetValue(
493 wxString::Format(_T(
"%03d%c"), (
int)(ang), 0x00B0));
495 m_tcCurrentVelocity->SetValue(_(
"N/A"));
496 m_tcCurrentDirection->SetValue(_(
"N/A"));
502 m_cursor_lon, m_cursor_lat,
true);
504 if (precip != GRIB_NOTDEF) {
506 GribOverlaySettings::PRECIPITATION, precip);
507 int p = precip < 10. ? 2 : precip < 100. ? 1 : 0;
509 .Settings[GribOverlaySettings::PRECIPITATION]
513 m_tcPrecipitation->SetValue(wxString::Format(
515 GribOverlaySettings::PRECIPITATION),
518 m_tcPrecipitation->SetValue(_(
"N/A"));
524 m_cursor_lon, m_cursor_lat,
true);
526 if (cloud != GRIB_NOTDEF) {
528 GribOverlaySettings::CLOUD, cloud);
529 wxString val(wxString::Format(_T(
"%5.0f "), cloud));
531 GribOverlaySettings::CLOUD));
533 m_tcCloud->SetValue(_(
"N/A"));
539 m_cursor_lon, m_cursor_lat,
true);
541 if (temp != GRIB_NOTDEF) {
543 GribOverlaySettings::AIR_TEMPERATURE, temp);
544 m_tcAirTemperature->SetValue(wxString::Format(
546 GribOverlaySettings::AIR_TEMPERATURE),
549 m_tcAirTemperature->SetValue(_(
"N/A"));
555 m_cursor_lon, m_cursor_lat,
true);
557 if (temp != GRIB_NOTDEF) {
559 GribOverlaySettings::SEA_TEMPERATURE, temp);
560 m_tcSeaTemperature->SetValue(wxString::Format(
562 GribOverlaySettings::SEA_TEMPERATURE),
565 m_tcSeaTemperature->SetValue(_(
"N/A"));
571 m_cursor_lon, m_cursor_lat,
true);
573 if (cape != GRIB_NOTDEF) {
575 GribOverlaySettings::CAPE, cape);
576 m_tcCAPE->SetValue(wxString::Format(
578 GribOverlaySettings::CAPE),
581 m_tcCAPE->SetValue(_(
"N/A"));
585 m_cursor_lon, m_cursor_lat,
true);
587 if (c_refl != GRIB_NOTDEF) {
589 GribOverlaySettings::COMP_REFL, c_refl);
590 m_tcReflC->SetValue(wxString::Format(
592 GribOverlaySettings::COMP_REFL),
595 m_tcReflC->SetValue(_(
"N/A"));
601 m_cursor_lon, m_cursor_lat,
true);
603 if (geop != GRIB_NOTDEF) {
605 GribOverlaySettings::GEO_ALTITUDE, geop);
606 m_tcAltitude->SetValue(wxString::Format(_T(
"%5.0f "), geop) +
608 GribOverlaySettings::GEO_ALTITUDE));
610 m_tcAltitude->SetValue(_(
"N/A"));
616 m_cursor_lon, m_cursor_lat,
true);
618 if (temp != GRIB_NOTDEF) {
620 GribOverlaySettings::AIR_TEMPERATURE, temp);
621 m_tcTemp->SetValue(wxString::Format(_T(
"%5.1f "), temp) +
623 GribOverlaySettings::AIR_TEMPERATURE));
625 m_tcTemp->SetValue(_(
"N/A"));
630 m_cursor_lon, m_cursor_lat,
true);
632 if (humi != GRIB_NOTDEF) {
634 GribOverlaySettings::REL_HUMIDITY, humi);
635 m_tcRelHumid->SetValue(wxString::Format(_T(
"%5.0f "), humi) +
637 GribOverlaySettings::REL_HUMIDITY));
639 m_tcRelHumid->SetValue(_(
"N/A"));
643void CursorData::OnMenuCallBack(wxMouseEvent &event) {
645 wxMenu *menu =
new wxMenu();
646 int id =
event.GetId();
648 case GribOverlaySettings::WIND:
649 MenuAppend(menu, B_ARROWS, _(
"Barbed Arrows"),
id);
650 MenuAppend(menu, ISO_LINE, _(
"Display Isotachs"),
id);
651 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
652 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
653 MenuAppend(menu, PARTICLES, _(
"Particle Map"),
id);
655 case GribOverlaySettings::WIND_GUST:
656 MenuAppend(menu, ISO_LINE, _(
"Display Isotachs"),
id);
657 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
658 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
660 case GribOverlaySettings::PRESSURE:
661 MenuAppend(menu, ISO_LINE, _(
"Display Isobars"),
id);
662 MenuAppend(menu, ISO_ABBR, _(
"Abbreviated Isobars Numbers"),
id);
663 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
665 case GribOverlaySettings::AIR_TEMPERATURE:
666 case GribOverlaySettings::SEA_TEMPERATURE:
667 MenuAppend(menu, ISO_LINE, _(
"Display Isotherms"),
id);
669 case GribOverlaySettings::CLOUD:
670 case GribOverlaySettings::PRECIPITATION:
671 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
672 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
674 case GribOverlaySettings::CAPE:
675 MenuAppend(menu, ISO_LINE, _(
"Display Iso CAPE"),
id);
676 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
677 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
679 case GribOverlaySettings::COMP_REFL:
680 MenuAppend(menu, ISO_LINE, _(
"Display Iso Reflectivity"),
id);
681 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
682 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
684 case GribOverlaySettings::WAVE:
685 MenuAppend(menu, D_ARROWS, _(
"Direction Arrows"),
id);
686 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
687 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
689 case GribOverlaySettings::CURRENT:
690 MenuAppend(menu, D_ARROWS, _(
"Direction Arrows"),
id);
691 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
692 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
693 MenuAppend(menu, PARTICLES, _(
"Particle Map"),
id);
699 wxwxMenuItemListNode *node = menu->GetMenuItems().GetFirst();
701 wxMenuItem *it = node->GetData();
702 switch (it->GetId()) {
728 node = node->GetNext();
732 if (m_gparent.InDataPlot(
id) && m_gparent.m_bDataPlot[
id])
733 ResolveDisplayConflicts(
id);
741void CursorData::MenuAppend(wxMenu *menu,
int id, wxString label,
int setting) {
742 wxMenuItem *item =
new wxMenuItem(menu,
id, label, _T(
""), wxITEM_CHECK);
746 item->SetFont(*qFont);
754 else if (
id == ISO_LINE)
756 else if (
id == ISO_ABBR)
758 else if (
id == D_ARROWS)
760 else if (
id == OVERLAY)
762 else if (
id == NUMBERS)
764 else if (
id == PARTICLES)
771void CursorData::OnMouseEvent(wxMouseEvent &event) {
772 if (event.RightDown()) {
773 if (m_DialogStyle >> 1 == ATTACHED) {
774 wxMouseEvent evt(event);
775 m_gparent.OnMouseEvent(evt);
780 static wxPoint s_gspt;
783 event.GetPosition(&x, &y);
784 wxPoint spt = wxPoint(x, y);
785 if (event.GetId() != 1000)
786 spt = ClientToScreen(spt);
788 spt = GetParent()->ClientToScreen(spt);
791 if (!m_bLeftDown && event.LeftIsDown()) {
794 if (!HasCapture()) CaptureMouse();
795 }
else if (m_bLeftDown && !event.LeftIsDown()) {
798 if (HasCapture()) ReleaseMouse();
802 if (event.LeftDown()) {
804 if (!HasCapture()) CaptureMouse();
807 if (event.LeftUp()) {
809 if (HasCapture()) ReleaseMouse();
813 if (event.Dragging()) {
814 wxPoint par_pos_old = GetParent()->GetPosition();
816 wxPoint par_pos = par_pos_old;
817 par_pos.x += spt.x - s_gspt.x;
818 par_pos.y += spt.y - s_gspt.y;
820 wxPoint pos_in_parent = GetOCPNCanvasWindow()->ScreenToClient(par_pos);
821 wxPoint pos_in_parent_old =
822 GetOCPNCanvasWindow()->ScreenToClient(par_pos_old);
825 if (pos_in_parent.x < pos_in_parent_old.x) {
826 if (pos_in_parent.x < 10) {
829 }
else if (pos_in_parent.x > pos_in_parent_old.x) {
831 GetOCPNCanvasWindow()->GetClientSize().x - GetParent()->GetSize().x;
832 if (pos_in_parent.x > (max_right - 10)) {
833 pos_in_parent.x = max_right;
838 if (pos_in_parent.y < pos_in_parent_old.y) {
839 if (pos_in_parent.y < 10) {
842 }
else if (pos_in_parent.y > pos_in_parent_old.y) {
844 GetOCPNCanvasWindow()->GetClientSize().y - GetParent()->GetSize().y;
845 if (pos_in_parent.y > (max_down - 10)) {
846 pos_in_parent.y = max_down;
850 wxPoint final_pos = GetOCPNCanvasWindow()->ClientToScreen(pos_in_parent);
852 GetParent()->Move(final_pos);
@ Idx_COMP_REFL
Composite radar reflectivity.
@ Idx_PRECIP_TOT
Total precipitation.
@ Idx_AIR_TEMP
Air temperature at 2m.
@ Idx_PRESSURE
Surface pressure.
@ Idx_WVDIR
Wave direction.
@ Idx_CLOUD_TOT
Total cloud cover.
@ Idx_WIND_GUST
Wind gust speed at surface.
@ Idx_WIND_VX
Surface wind velocity X component.
@ Idx_HTSIGW
Significant wave height.
@ Idx_HUMID_RE
Surface relative humidity.
@ Idx_SEACURRENT_VY
Sea current velocity Y component.
@ Idx_GEOP_HGT
Surface geopotential height.
@ Idx_SEA_TEMP
Sea surface temperature.
@ Idx_WIND_VY
Surface wind velocity Y component.
@ Idx_SEACURRENT_VX
Sea current velocity X component.
@ Idx_CAPE
Convective Available Potential Energy.
GribOverlaySettings m_OverlaySettings
Settings that control how GRIB data is displayed and overlaid.
GRIBFile * m_bGRIBActiveFile
Currently active GRIB file being displayed.
GribTimelineRecordSet * m_pTimelineSet
Current set of GRIB records for timeline playback.
GribRecord * m_GribRecordPtrArray[Idx_COUNT]
Array of pointers to GRIB records representing different meteorological parameters.
Represents a meteorological data grid from a GRIB (Gridded Binary) file.
double getInterpolatedValue(double px, double py, bool numericalInterpolation=true, bool dir=false) const
Get spatially interpolated value at exact lat/lon position.
static bool getInterpolatedValues(double &M, double &A, const GribRecord *GRX, const GribRecord *GRY, double px, double py, bool numericalInterpolation=true)
Gets spatially interpolated wind or current vector values at a specific latitude/longitude point.
GRIB Weather Data Plugin for OpenCPN.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
OpenGL Platform Abstraction Layer.