28extern int m_DialogStyle;
33CursorData::CursorData(wxWindow *window,
GRIBUICtrlBar &parent)
37 wxWindowListNode *node = this->GetChildren().GetFirst();
39 wxWindow *win = node->GetData();
40 if (
dynamic_cast<wxCheckBox *
>(win)) {
41 int winId =
dynamic_cast<wxCheckBox *
>(win)->GetId() - ID_CB_WIND;
42 if (m_gparent.InDataPlot(winId)) {
43 dynamic_cast<wxCheckBox *
>(win)->SetId(winId);
44 dynamic_cast<wxCheckBox *
>(win)->SetValue(m_gparent.m_bDataPlot[winId]);
47 node = node->GetNext();
52 m_tCursorTrackTimer.Connect(
53 wxEVT_TIMER, wxTimerEventHandler(CursorData::OnCursorTrackTimer),
nullptr,
59void CursorData::OnCBAny(wxCommandEvent &event) {
60 int id =
event.GetId();
61 wxWindow *win = this->FindWindow(
id);
62 if (m_gparent.InDataPlot(
id))
63 m_gparent.m_bDataPlot[id] = ((wxCheckBox *)win)->IsChecked();
64 ResolveDisplayConflicts(
id);
67void CursorData::ResolveDisplayConflicts(
int Id) {
69 for (
int i = 0; i < GribOverlaySettings::GEO_ALTITUDE; i++) {
70 if (i != Id && m_gparent.m_bDataPlot[i]) {
83 m_gparent.m_bDataPlot[i] =
false;
84 wxWindow *win = FindWindow(i);
85 ((wxCheckBox *)win)->SetValue(
false);
89 m_gparent.SetFactoryOptions();
92void CursorData::AddTrackingControl(wxControl *ctrl1, wxControl *ctrl2,
93 wxControl *ctrl3, wxControl *ctrl4,
94 bool show,
bool vertical,
int wctrl2,
97 m_fgTrackingControls->Add(ctrl1, 0, wxALL, 1);
100 m_fgTrackingControls->Add(ctrl2, 0, wxALL, 0);
101 ctrl2->SetMinSize(wxSize(wctrl2, -1));
104 m_fgTrackingControls->Add(0, 0, 1, wxALL, 1);
107 long flag1 = wxALIGN_CENTER;
108 long flag = vertical ? flag1 : wxALL;
109 m_fgTrackingControls->Add(ctrl3, 0, flag, 0);
110 ctrl3->SetMinSize(wxSize(wctrl3_4, -1));
112 }
else if (!vertical)
113 m_fgTrackingControls->Add(0, 0, 1, wxALL, 1);
116 m_fgTrackingControls->Add(ctrl4, 0, wxALL, 0);
117 ctrl4->SetMinSize(wxSize(vertical ? wctrl2 : wctrl3_4, -1));
119 }
else if (!vertical)
120 m_fgTrackingControls->Add(0, 0, 1, wxALL, 1);
123 if (ctrl1) ctrl1->Hide();
124 if (ctrl2) ctrl2->Hide();
125 if (ctrl3) ctrl3->Hide();
126 if (ctrl4) ctrl4->Hide();
130void CursorData::PopulateTrackingControls(
bool vertical) {
131 m_fgTrackingControls->Clear();
133 auto *ps = (wxFlexGridSizer *)(m_gparent.GetSizer());
134 if (ps && (ps->GetCols() == 1))
135 m_fgTrackingControls->SetCols(4);
137 m_fgTrackingControls->SetCols(12);
139 m_fgTrackingControls->SetCols(2);
145 GetTextExtent(
"abcdefghihjk", &wn,
nullptr,
nullptr,
nullptr,
147 GetTextExtent(
"abcdef", &ws,
nullptr,
nullptr,
nullptr,
150 "abcdefghijklmopq", &wd,
nullptr,
nullptr,
nullptr,
153 "abcdefghijklm", &wl,
nullptr,
nullptr,
nullptr,
157 auto *dummy =
new wxTextCtrl(
this, wxID_ANY, wxEmptyString, wxDefaultPosition,
158 wxDefaultSize, wxTE_READONLY | wxNO_BORDER);
162 GribOverlaySettings::BFS;
163 wd = vertical ? wn : bf ? wn : wd;
164 wl = vertical ? wn : wl;
166 AddTrackingControl(m_cbWind, m_tcWindSpeed, m_tcWindSpeedBf,
167 m_tcWindDirection,
false, vertical, 0,
170 m_cbWind, m_tcWindSpeed,
171 vertical ? (bf ? dummy : m_tcWindSpeedBf) : m_tcWindDirection,
172 vertical ? m_tcWindDirection : nullptr,
173 m_gparent.m_pTimelineSet &&
174 m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(
Idx_WIND_VX) !=
176 m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(
Idx_WIND_VY) !=
179 AddTrackingControl(m_cbWindGust, m_tcWindGust,
nullptr,
nullptr,
185 AddTrackingControl(m_cbPressure, m_tcPressure,
nullptr,
nullptr,
193 AddTrackingControl(m_cbWave, m_tcWaveHeight, m_tcWavePeriode,
194 m_tcWaveDirection,
false, vertical, 0,
201 AddTrackingControl(m_cbWave, m_tcWaveHeight,
202 vertical ? m_tcWavePeriode : m_tcWaveDirection,
203 vertical ? m_tcWaveDirection : nullptr,
204 m_Altitude == 0, vertical, wl, ws);
206 AddTrackingControl(m_cbWave, m_tcWaveHeight,
nullptr,
nullptr,
207 m_Altitude == 0, vertical, wn);
212 AddTrackingControl(m_cbWave, m_tcWaveDirection,
nullptr,
nullptr,
213 m_Altitude == 0, vertical, wn);
216 AddTrackingControl(m_cbCurrent, m_tcCurrentVelocity, m_tcCurrentDirection,
217 nullptr,
false, vertical, 0,
219 AddTrackingControl(m_cbCurrent, m_tcCurrentVelocity,
220 vertical ? dummy : m_tcCurrentDirection,
221 vertical ? m_tcCurrentDirection : nullptr,
222 m_gparent.m_pTimelineSet &&
223 m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(
225 m_gparent.m_bGRIBActiveFile->m_GribIdxArray.Index(
229 AddTrackingControl(m_cbPrecipitation, m_tcPrecipitation,
nullptr,
nullptr,
235 AddTrackingControl(m_cbCloud, m_tcCloud,
nullptr,
nullptr,
241 AddTrackingControl(m_cbAirTemperature, m_tcAirTemperature,
nullptr,
nullptr,
247 AddTrackingControl(m_cbSeaTemperature, m_tcSeaTemperature,
nullptr,
nullptr,
253 AddTrackingControl(m_cbCAPE, m_tcCAPE,
nullptr,
nullptr,
259 AddTrackingControl(m_cbReflC, m_tcReflC,
nullptr,
nullptr,
267 AddTrackingControl(m_cbAltitude, m_tcAltitude,
nullptr,
nullptr,
273 AddTrackingControl(m_cbTemp, m_tcTemp,
nullptr,
nullptr,
279 AddTrackingControl(m_cbRelHumid, m_tcRelHumid,
nullptr,
nullptr,
286 m_stTrackingText->SetLabel(_(
"Data at cursor position"));
292 GribOverlaySettings::GEO_ALTITUDE,
295 .GetAltitudeFromIndex(
298 .Settings[GribOverlaySettings::PRESSURE]
302 GribOverlaySettings::PRESSURE))
303 : wxString::Format(
"%1.*f ", lev == (int)lev ? 0 : 1, lev)
304 .Append(m_gparent.m_OverlaySettings.GetUnitSymbol(
308 pre.Append(_(
"at Geopotential Height"));
310 m_tcAltitude->SetToolTip(_(
"Altitude") + t);
311 m_tcTemp->SetToolTip(_(
"Temperature") + t);
312 m_tcRelHumid->SetToolTip(_(
"Relative Humidity") + t);
319 m_tcWindSpeed->SetToolTip(_(
"Wind Speed") + t);
320 m_tcWindSpeedBf->SetToolTip(_(
"Wind Speed in Bf") + t);
321 m_tcWindDirection->SetToolTip(_(
"Wind Direction") + t);
324 GribOverlaySettings::GEO_ALTITUDE),
325 lev == (
int)lev ? 0 : 1, lev);
326 m_tcWindGust->SetToolTip(_(
"Wind Gust at") + t);
329 wxString s[] = {
" ", _(
"Air Temperature at"), _(
"surface level"),
330 _(
"Sea Surface Temperature")};
333 GribOverlaySettings::GEO_ALTITUDE,
336 1000 + NORWAY_METNO) != wxNOT_FOUND
338 :
" %1.*f " + m_gparent.m_OverlaySettings.GetUnitSymbol(
340 lev == (int)lev ? 0 : 1, lev);
341 m_tcAirTemperature->SetToolTip(s[1] + t);
343 m_tcSeaTemperature->SetToolTip(
352void CursorData::UpdateTrackingControls() {
360 RecordArray[
Idx_WIND_VY + m_Altitude], m_cursor_lon, m_cursor_lat)) {
362 GribOverlaySettings::WIND, vkn);
364 m_tcWindSpeed->SetValue(
366 GribOverlaySettings::WIND),
372 .m_Units != GribOverlaySettings::BFS) {
374 if (m_DialogStyle == SEPARATED_VERTICAL)
375 m_tcWindSpeedBf->SetValue(wxString::Format(
"%2d bf", (
int)round(vk)));
377 m_tcWindSpeed->SetValue(m_tcWindSpeed->GetValue().Append(
" - ").Append(
378 wxString::Format(
"%2d bf", (
int)round(vk))));
381 m_tcWindDirection->SetValue(wxString::Format(
"%03d%c", (
int)(ang), 0x00B0));
383 m_tcWindSpeed->SetValue(_(
"N/A"));
384 m_tcWindSpeedBf->SetValue(_(
"N/A"));
385 m_tcWindDirection->SetValue(_(
"N/A"));
391 m_cursor_lon, m_cursor_lat,
true);
393 if (vkn_ != GRIB_NOTDEF) {
395 GribOverlaySettings::WIND_GUST, vkn_);
396 m_tcWindGust->SetValue(
398 GribOverlaySettings::WIND_GUST),
401 m_tcWindGust->SetValue(_(
"N/A"));
407 m_cursor_lon, m_cursor_lat,
true);
409 if (press != GRIB_NOTDEF) {
411 GribOverlaySettings::PRESSURE, press);
417 m_tcPressure->SetValue(
419 GribOverlaySettings::PRESSURE),
422 m_tcPressure->SetValue(_(
"N/A"));
428 m_cursor_lon, m_cursor_lat,
true);
430 if (height != GRIB_NOTDEF) {
432 GribOverlaySettings::WAVE, height);
435 GribOverlaySettings::WAVE),
439 m_cursor_lon, m_cursor_lat,
true);
440 if (period != GRIB_NOTDEF) {
441 if (m_DialogStyle == SEPARATED_VERTICAL)
442 m_tcWavePeriode->SetValue(
443 wxString::Format(
"%01ds", (
int)round(period)));
445 w.Append(wxString::Format(
" - %01ds", (
int)round(period)));
447 m_tcWavePeriode->SetValue(_(
"N/A"));
449 m_tcWavePeriode->SetValue(_(
"N/A"));
451 m_tcWaveHeight->SetValue(w);
453 m_tcWaveHeight->SetValue(_(
"N/A"));
459 m_cursor_lon, m_cursor_lat,
true,
true);
460 if (direction != GRIB_NOTDEF)
461 m_tcWaveDirection->SetValue(
462 wxString::Format(
"%03d%c", (
int)direction, 0x00B0));
464 m_tcWaveDirection->SetValue(_(
"N/A"));
475 if (ang >= 360) ang -= 360;
476 if (ang < 0) ang += 360;
479 GribOverlaySettings::CURRENT, vkn);
481 m_tcCurrentVelocity->SetValue(
483 GribOverlaySettings::CURRENT),
486 m_tcCurrentDirection->SetValue(
487 wxString::Format(
"%03d%c", (
int)(ang), 0x00B0));
489 m_tcCurrentVelocity->SetValue(_(
"N/A"));
490 m_tcCurrentDirection->SetValue(_(
"N/A"));
496 m_cursor_lon, m_cursor_lat,
true);
498 if (precip != GRIB_NOTDEF) {
500 GribOverlaySettings::PRECIPITATION, precip);
501 int p = precip < 10. ? 2 : precip < 100. ? 1 : 0;
503 .Settings[GribOverlaySettings::PRECIPITATION]
507 m_tcPrecipitation->SetValue(
509 GribOverlaySettings::PRECIPITATION),
512 m_tcPrecipitation->SetValue(_(
"N/A"));
518 m_cursor_lon, m_cursor_lat,
true);
520 if (cloud != GRIB_NOTDEF) {
522 GribOverlaySettings::CLOUD, cloud);
523 wxString val(wxString::Format(
"%5.0f ", cloud));
525 GribOverlaySettings::CLOUD));
527 m_tcCloud->SetValue(_(
"N/A"));
533 m_cursor_lon, m_cursor_lat,
true);
535 if (temp != GRIB_NOTDEF) {
537 GribOverlaySettings::AIR_TEMPERATURE, temp);
538 m_tcAirTemperature->SetValue(
540 GribOverlaySettings::AIR_TEMPERATURE),
543 m_tcAirTemperature->SetValue(_(
"N/A"));
549 m_cursor_lon, m_cursor_lat,
true);
551 if (temp != GRIB_NOTDEF) {
553 GribOverlaySettings::SEA_TEMPERATURE, temp);
554 m_tcSeaTemperature->SetValue(
556 GribOverlaySettings::SEA_TEMPERATURE),
559 m_tcSeaTemperature->SetValue(_(
"N/A"));
565 m_cursor_lon, m_cursor_lat,
true);
567 if (cape != GRIB_NOTDEF) {
569 GribOverlaySettings::CAPE, cape);
572 GribOverlaySettings::CAPE),
575 m_tcCAPE->SetValue(_(
"N/A"));
579 m_cursor_lon, m_cursor_lat,
true);
581 if (c_refl != GRIB_NOTDEF) {
583 GribOverlaySettings::COMP_REFL, c_refl);
586 GribOverlaySettings::COMP_REFL),
589 m_tcReflC->SetValue(_(
"N/A"));
595 m_cursor_lon, m_cursor_lat,
true);
597 if (geop != GRIB_NOTDEF) {
599 GribOverlaySettings::GEO_ALTITUDE, geop);
600 m_tcAltitude->SetValue(wxString::Format(
"%5.0f ", geop) +
602 GribOverlaySettings::GEO_ALTITUDE));
604 m_tcAltitude->SetValue(_(
"N/A"));
610 m_cursor_lon, m_cursor_lat,
true);
612 if (temp != GRIB_NOTDEF) {
614 GribOverlaySettings::AIR_TEMPERATURE, temp);
615 m_tcTemp->SetValue(wxString::Format(
"%5.1f ", temp) +
617 GribOverlaySettings::AIR_TEMPERATURE));
619 m_tcTemp->SetValue(_(
"N/A"));
624 m_cursor_lon, m_cursor_lat,
true);
626 if (humi != GRIB_NOTDEF) {
628 GribOverlaySettings::REL_HUMIDITY, humi);
629 m_tcRelHumid->SetValue(wxString::Format(
"%5.0f ", humi) +
631 GribOverlaySettings::REL_HUMIDITY));
633 m_tcRelHumid->SetValue(_(
"N/A"));
637void CursorData::OnMenuCallBack(wxMouseEvent &event) {
639 auto *menu =
new wxMenu();
640 int id =
event.GetId();
642 case GribOverlaySettings::WIND:
643 MenuAppend(menu, B_ARROWS, _(
"Barbed Arrows"),
id);
644 MenuAppend(menu, ISO_LINE, _(
"Display Isotachs"),
id);
645 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
646 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
647 MenuAppend(menu, PARTICLES, _(
"Particle Map"),
id);
649 case GribOverlaySettings::WIND_GUST:
650 MenuAppend(menu, ISO_LINE, _(
"Display Isotachs"),
id);
651 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
652 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
654 case GribOverlaySettings::PRESSURE:
655 MenuAppend(menu, ISO_LINE, _(
"Display Isobars"),
id);
656 MenuAppend(menu, ISO_ABBR, _(
"Abbreviated Isobars Numbers"),
id);
657 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
659 case GribOverlaySettings::AIR_TEMPERATURE:
660 case GribOverlaySettings::SEA_TEMPERATURE:
661 MenuAppend(menu, ISO_LINE, _(
"Display Isotherms"),
id);
663 case GribOverlaySettings::CLOUD:
664 case GribOverlaySettings::PRECIPITATION:
665 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
666 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
668 case GribOverlaySettings::CAPE:
669 MenuAppend(menu, ISO_LINE, _(
"Display Iso CAPE"),
id);
670 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
671 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
673 case GribOverlaySettings::COMP_REFL:
674 MenuAppend(menu, ISO_LINE, _(
"Display Iso Reflectivity"),
id);
675 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
676 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
678 case GribOverlaySettings::WAVE:
679 MenuAppend(menu, D_ARROWS, _(
"Direction Arrows"),
id);
680 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
681 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
683 case GribOverlaySettings::CURRENT:
684 MenuAppend(menu, D_ARROWS, _(
"Direction Arrows"),
id);
685 MenuAppend(menu, OVERLAY, _(
"OverlayMap"),
id);
686 MenuAppend(menu, NUMBERS, _(
"Numbers"),
id);
687 MenuAppend(menu, PARTICLES, _(
"Particle Map"),
id);
693 wxwxMenuItemListNode *node = menu->GetMenuItems().GetFirst();
695 wxMenuItem *it = node->GetData();
696 switch (it->GetId()) {
722 assert(
false &&
"Illegal menu item");
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,
const wxString &label,
739 auto *item =
new wxMenuItem(menu,
id, label,
"", wxITEM_CHECK);
743 item->SetFont(*qFont);
751 else if (
id == ISO_LINE)
753 else if (
id == ISO_ABBR)
756 else if (
id == D_ARROWS)
758 else if (
id == OVERLAY)
760 else if (
id == NUMBERS)
762 else if (
id == PARTICLES)
769void CursorData::OnMouseEvent(wxMouseEvent &event) {
770 if (event.RightDown()) {
771 if (m_DialogStyle >> 1 == ATTACHED) {
772 wxMouseEvent evt(event);
773 m_gparent.DoOnMouseEvent(evt);
778 static wxPoint s_gspt;
781 event.GetPosition(&x, &y);
782 wxPoint spt = wxPoint(x, y);
783 if (event.GetId() != 1000)
784 spt = ClientToScreen(spt);
786 spt = GetParent()->ClientToScreen(spt);
789 if (!m_bLeftDown && event.LeftIsDown()) {
792 if (!HasCapture()) CaptureMouse();
793 }
else if (m_bLeftDown && !event.LeftIsDown()) {
796 if (HasCapture()) ReleaseMouse();
800 if (event.LeftDown()) {
802 if (!HasCapture()) CaptureMouse();
805 if (event.LeftUp()) {
807 if (HasCapture()) ReleaseMouse();
811 if (event.Dragging()) {
812 wxPoint par_pos_old = GetParent()->GetPosition();
814 wxPoint par_pos = par_pos_old;
815 par_pos.x += spt.x - s_gspt.x;
816 par_pos.y += spt.y - s_gspt.y;
819 wxPoint pos_in_parent_old =
823 if (pos_in_parent.x < pos_in_parent_old.x) {
824 if (pos_in_parent.x < 10) {
827 }
else if (pos_in_parent.x > pos_in_parent_old.x) {
830 if (pos_in_parent.x > (max_right - 10)) {
831 pos_in_parent.x = max_right;
836 if (pos_in_parent.y < pos_in_parent_old.y) {
837 if (pos_in_parent.y < 10) {
840 }
else if (pos_in_parent.y > pos_in_parent_old.y) {
843 if (pos_in_parent.y > (max_down - 10)) {
844 pos_in_parent.y = max_down;
850 GetParent()->Move(final_pos);
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.
A meteorological data grid from a GRIB (Gridded Binary) file.
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.
double GetInterpolatedValue(double px, double py, bool numericalInterpolation=true, bool dir=false) const
Get spatially interpolated value at exact lat/lon position.
GRIB Weather Data Plugin for OpenCPN.
@ 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)
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.