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(
"abcdefghihjk", &wn,
nullptr, 0, 0,
149 GetTextExtent(
"abcdef", &ws,
nullptr, 0, 0,
152 "abcdefghijklmopq", &wd,
nullptr, 0, 0,
155 "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,
297 .GetAltitudeFromIndex(
300 .Settings[GribOverlaySettings::PRESSURE]
304 GribOverlaySettings::PRESSURE))
305 : wxString::Format(
"%1.*f ", lev == (int)lev ? 0 : 1, lev)
306 .Append(m_gparent.m_OverlaySettings.GetUnitSymbol(
310 pre.Append(_(
"at Geopotential Height"));
312 m_tcAltitude->SetToolTip(_(
"Altitude") + t);
313 m_tcTemp->SetToolTip(_(
"Temperature") + t);
314 m_tcRelHumid->SetToolTip(_(
"Relative Humidity") + t);
321 m_tcWindSpeed->SetToolTip(_(
"Wind Speed") + t);
322 m_tcWindSpeedBf->SetToolTip(_(
"Wind Speed in Bf") + t);
323 m_tcWindDirection->SetToolTip(_(
"Wind Direction") + t);
326 GribOverlaySettings::GEO_ALTITUDE),
327 lev == (
int)lev ? 0 : 1, lev);
328 m_tcWindGust->SetToolTip(_(
"Wind Gust at") + t);
331 wxString s[] = {
" ", _(
"Air Temperature at"), _(
"surface level"),
332 _(
"Sea Surface Temperature")};
335 GribOverlaySettings::GEO_ALTITUDE,
338 1000 + NORWAY_METNO) != wxNOT_FOUND
340 :
" %1.*f " + m_gparent.m_OverlaySettings.GetUnitSymbol(
342 lev == (int)lev ? 0 : 1, lev);
343 m_tcAirTemperature->SetToolTip(s[1] + t);
345 m_tcSeaTemperature->SetToolTip(
354void CursorData::UpdateTrackingControls(
void) {
362 RecordArray[
Idx_WIND_VY + m_Altitude], m_cursor_lon, m_cursor_lat)) {
364 GribOverlaySettings::WIND, vkn);
366 m_tcWindSpeed->SetValue(
368 GribOverlaySettings::WIND),
374 .m_Units != GribOverlaySettings::BFS) {
376 if (m_DialogStyle == SEPARATED_VERTICAL)
377 m_tcWindSpeedBf->SetValue(wxString::Format(
"%2d bf", (
int)round(vk)));
379 m_tcWindSpeed->SetValue(m_tcWindSpeed->GetValue().Append(
" - ").Append(
380 wxString::Format(
"%2d bf", (
int)round(vk))));
383 m_tcWindDirection->SetValue(wxString::Format(
"%03d%c", (
int)(ang), 0x00B0));
385 m_tcWindSpeed->SetValue(_(
"N/A"));
386 m_tcWindSpeedBf->SetValue(_(
"N/A"));
387 m_tcWindDirection->SetValue(_(
"N/A"));
393 m_cursor_lon, m_cursor_lat,
true);
395 if (vkn != GRIB_NOTDEF) {
397 GribOverlaySettings::WIND_GUST, vkn);
398 m_tcWindGust->SetValue(
400 GribOverlaySettings::WIND_GUST),
403 m_tcWindGust->SetValue(_(
"N/A"));
409 m_cursor_lon, m_cursor_lat,
true);
411 if (press != GRIB_NOTDEF) {
413 GribOverlaySettings::PRESSURE, press);
419 m_tcPressure->SetValue(
421 GribOverlaySettings::PRESSURE),
424 m_tcPressure->SetValue(_(
"N/A"));
430 m_cursor_lon, m_cursor_lat,
true);
432 if (height != GRIB_NOTDEF) {
434 GribOverlaySettings::WAVE, height);
437 GribOverlaySettings::WAVE),
441 m_cursor_lon, m_cursor_lat,
true);
442 if (period != GRIB_NOTDEF) {
443 if (m_DialogStyle == SEPARATED_VERTICAL)
444 m_tcWavePeriode->SetValue(
445 wxString::Format(
"%01ds", (
int)round(period)));
447 w.Append(wxString::Format(
" - %01ds", (
int)round(period)));
449 m_tcWavePeriode->SetValue(_(
"N/A"));
451 m_tcWavePeriode->SetValue(_(
"N/A"));
453 m_tcWaveHeight->SetValue(w);
455 m_tcWaveHeight->SetValue(_(
"N/A"));
461 m_cursor_lon, m_cursor_lat,
true,
true);
462 if (direction != GRIB_NOTDEF)
463 m_tcWaveDirection->SetValue(
464 wxString::Format(
"%03d%c", (
int)direction, 0x00B0));
466 m_tcWaveDirection->SetValue(_(
"N/A"));
477 if (ang >= 360) ang -= 360;
478 if (ang < 0) ang += 360;
481 GribOverlaySettings::CURRENT, vkn);
483 m_tcCurrentVelocity->SetValue(
485 GribOverlaySettings::CURRENT),
488 m_tcCurrentDirection->SetValue(
489 wxString::Format(
"%03d%c", (
int)(ang), 0x00B0));
491 m_tcCurrentVelocity->SetValue(_(
"N/A"));
492 m_tcCurrentDirection->SetValue(_(
"N/A"));
498 m_cursor_lon, m_cursor_lat,
true);
500 if (precip != GRIB_NOTDEF) {
502 GribOverlaySettings::PRECIPITATION, precip);
503 int p = precip < 10. ? 2 : precip < 100. ? 1 : 0;
505 .Settings[GribOverlaySettings::PRECIPITATION]
509 m_tcPrecipitation->SetValue(
511 GribOverlaySettings::PRECIPITATION),
514 m_tcPrecipitation->SetValue(_(
"N/A"));
520 m_cursor_lon, m_cursor_lat,
true);
522 if (cloud != GRIB_NOTDEF) {
524 GribOverlaySettings::CLOUD, cloud);
525 wxString val(wxString::Format(
"%5.0f ", cloud));
527 GribOverlaySettings::CLOUD));
529 m_tcCloud->SetValue(_(
"N/A"));
535 m_cursor_lon, m_cursor_lat,
true);
537 if (temp != GRIB_NOTDEF) {
539 GribOverlaySettings::AIR_TEMPERATURE, temp);
540 m_tcAirTemperature->SetValue(
542 GribOverlaySettings::AIR_TEMPERATURE),
545 m_tcAirTemperature->SetValue(_(
"N/A"));
551 m_cursor_lon, m_cursor_lat,
true);
553 if (temp != GRIB_NOTDEF) {
555 GribOverlaySettings::SEA_TEMPERATURE, temp);
556 m_tcSeaTemperature->SetValue(
558 GribOverlaySettings::SEA_TEMPERATURE),
561 m_tcSeaTemperature->SetValue(_(
"N/A"));
567 m_cursor_lon, m_cursor_lat,
true);
569 if (cape != GRIB_NOTDEF) {
571 GribOverlaySettings::CAPE, cape);
574 GribOverlaySettings::CAPE),
577 m_tcCAPE->SetValue(_(
"N/A"));
581 m_cursor_lon, m_cursor_lat,
true);
583 if (c_refl != GRIB_NOTDEF) {
585 GribOverlaySettings::COMP_REFL, c_refl);
588 GribOverlaySettings::COMP_REFL),
591 m_tcReflC->SetValue(_(
"N/A"));
597 m_cursor_lon, m_cursor_lat,
true);
599 if (geop != GRIB_NOTDEF) {
601 GribOverlaySettings::GEO_ALTITUDE, geop);
602 m_tcAltitude->SetValue(wxString::Format(
"%5.0f ", geop) +
604 GribOverlaySettings::GEO_ALTITUDE));
606 m_tcAltitude->SetValue(_(
"N/A"));
612 m_cursor_lon, m_cursor_lat,
true);
614 if (temp != GRIB_NOTDEF) {
616 GribOverlaySettings::AIR_TEMPERATURE, temp);
617 m_tcTemp->SetValue(wxString::Format(
"%5.1f ", temp) +
619 GribOverlaySettings::AIR_TEMPERATURE));
621 m_tcTemp->SetValue(_(
"N/A"));
626 m_cursor_lon, m_cursor_lat,
true);
628 if (humi != GRIB_NOTDEF) {
630 GribOverlaySettings::REL_HUMIDITY, humi);
631 m_tcRelHumid->SetValue(wxString::Format(
"%5.0f ", humi) +
633 GribOverlaySettings::REL_HUMIDITY));
635 m_tcRelHumid->SetValue(_(
"N/A"));
639void CursorData::OnMenuCallBack(wxMouseEvent &event) {
641 wxMenu *menu =
new wxMenu();
642 int id =
event.GetId();
644 case GribOverlaySettings::WIND:
645 MenuAppend(menu, B_ARROWS, _(
"Barbed Arrows"),
id);
646 MenuAppend(menu, ISO_LINE, _(
"Display Isotachs"),
id);
647 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
648 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
649 MenuAppend(menu, PARTICLES, _(
"Particle Map"),
id);
651 case GribOverlaySettings::WIND_GUST:
652 MenuAppend(menu, ISO_LINE, _(
"Display Isotachs"),
id);
653 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
654 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
656 case GribOverlaySettings::PRESSURE:
657 MenuAppend(menu, ISO_LINE, _(
"Display Isobars"),
id);
658 MenuAppend(menu, ISO_ABBR, _(
"Abbreviated Isobars Numbers"),
id);
659 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
661 case GribOverlaySettings::AIR_TEMPERATURE:
662 case GribOverlaySettings::SEA_TEMPERATURE:
663 MenuAppend(menu, ISO_LINE, _(
"Display Isotherms"),
id);
665 case GribOverlaySettings::CLOUD:
666 case GribOverlaySettings::PRECIPITATION:
667 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
668 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
670 case GribOverlaySettings::CAPE:
671 MenuAppend(menu, ISO_LINE, _(
"Display Iso CAPE"),
id);
672 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
673 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
675 case GribOverlaySettings::COMP_REFL:
676 MenuAppend(menu, ISO_LINE, _(
"Display Iso Reflectivity"),
id);
677 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
678 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
680 case GribOverlaySettings::WAVE:
681 MenuAppend(menu, D_ARROWS, _(
"Direction Arrows"),
id);
682 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
683 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
685 case GribOverlaySettings::CURRENT:
686 MenuAppend(menu, D_ARROWS, _(
"Direction Arrows"),
id);
687 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
688 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
689 MenuAppend(menu, PARTICLES, _(
"Particle Map"),
id);
695 wxwxMenuItemListNode *node = menu->GetMenuItems().GetFirst();
697 wxMenuItem *it = node->GetData();
698 switch (it->GetId()) {
724 node = node->GetNext();
728 if (m_gparent.InDataPlot(
id) && m_gparent.m_bDataPlot[
id])
729 ResolveDisplayConflicts(
id);
737void CursorData::MenuAppend(wxMenu *menu,
int id, wxString label,
int setting) {
738 wxMenuItem *item =
new wxMenuItem(menu,
id, label,
"", wxITEM_CHECK);
742 item->SetFont(*qFont);
750 else if (
id == ISO_LINE)
752 else if (
id == ISO_ABBR)
754 else if (
id == D_ARROWS)
756 else if (
id == OVERLAY)
758 else if (
id == NUMBERS)
760 else if (
id == PARTICLES)
767void CursorData::OnMouseEvent(wxMouseEvent &event) {
768 if (event.RightDown()) {
769 if (m_DialogStyle >> 1 == ATTACHED) {
770 wxMouseEvent evt(event);
771 m_gparent.OnMouseEvent(evt);
776 static wxPoint s_gspt;
779 event.GetPosition(&x, &y);
780 wxPoint spt = wxPoint(x, y);
781 if (event.GetId() != 1000)
782 spt = ClientToScreen(spt);
784 spt = GetParent()->ClientToScreen(spt);
787 if (!m_bLeftDown && event.LeftIsDown()) {
790 if (!HasCapture()) CaptureMouse();
791 }
else if (m_bLeftDown && !event.LeftIsDown()) {
794 if (HasCapture()) ReleaseMouse();
798 if (event.LeftDown()) {
800 if (!HasCapture()) CaptureMouse();
803 if (event.LeftUp()) {
805 if (HasCapture()) ReleaseMouse();
809 if (event.Dragging()) {
810 wxPoint par_pos_old = GetParent()->GetPosition();
812 wxPoint par_pos = par_pos_old;
813 par_pos.x += spt.x - s_gspt.x;
814 par_pos.y += spt.y - s_gspt.y;
817 wxPoint pos_in_parent_old =
821 if (pos_in_parent.x < pos_in_parent_old.x) {
822 if (pos_in_parent.x < 10) {
825 }
else if (pos_in_parent.x > pos_in_parent_old.x) {
828 if (pos_in_parent.x > (max_right - 10)) {
829 pos_in_parent.x = max_right;
834 if (pos_in_parent.y < pos_in_parent_old.y) {
835 if (pos_in_parent.y < 10) {
838 }
else if (pos_in_parent.y > pos_in_parent_old.y) {
841 if (pos_in_parent.y > (max_down - 10)) {
842 pos_in_parent.y = max_down;
848 GetParent()->Move(final_pos);
@ Idx_COMP_REFL
Composite radar reflectivity in dBZ (decibel relative to Z)
@ Idx_PRECIP_TOT
Precipitation data in millimeters per hour.
@ Idx_AIR_TEMP
Air temperature at 2m in Kelvin (K)
@ Idx_PRESSURE
Surface pressure in Pascal (Pa)
@ Idx_WVDIR
Wave direction.
@ Idx_CLOUD_TOT
Total cloud cover in % (percent, range 0-100%)
@ Idx_WIND_GUST
Wind gust speed at surface in m/s.
@ Idx_WIND_VX
Surface wind velocity X component in m/s.
@ Idx_HTSIGW
Significant wave height in meters.
@ Idx_HUMID_RE
Surface relative humidity in % (percent, range 0-100%)
@ Idx_SEACURRENT_VY
Sea current velocity Y component in m/s.
@ Idx_GEOP_HGT
Surface geopotential height in gpm (geopotential meters)
@ Idx_SEA_TEMP
Sea surface temperature in Kelvin (K)
@ Idx_WIND_VY
Surface wind velocity Y component in m/s.
@ Idx_SEACURRENT_VX
Sea current velocity X component in m/s.
@ Idx_CAPE
Convective Available Potential Energy in J/kg (Joules per kilogram)
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.
wxWindow * GetOCPNCanvasWindow()
Gets OpenCPN's main canvas window.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
void DimeWindow(wxWindow *win)
Applies system color scheme to window.
OpenGL Platform Abstraction Layer.