25#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
37#include <wx/wfstream.h>
40#include <unordered_map>
46enum { SAILDOCS, ZYGRIB };
47enum { GFS, COAMPS, RTOFS, HRRR, ICON, ECMWF };
49wxString toMailFormat(
int NEflag,
52 char c = NEflag == 1 ? a < 0 ?
'S' :
'N' : a < 0 ?
'W' :
'E';
54 s.Printf(_T (
"%01d%c" ), abs(a), c);
69 m_boundingBoxCanvasIndex = -1;
72#if defined(__WXOSX__) || defined(__WXGTK3__)
74 m_displayScale = GetContentScaleFactor();
79 m_downloading =
false;
80 m_bTransferSuccess =
true;
83 auto bg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOW)
84 .GetAsString(wxC2S_HTML_SYNTAX);
85 auto fg = wxSystemSettings::GetColour(wxSYS_COLOUR_WINDOWTEXT)
86 .GetAsString(wxC2S_HTML_SYNTAX);
87 m_htmlWinWorld->SetBorders(10);
88 m_htmlWinWorld->SetPage(
89 "<html><body bgcolor="
98 _(
"<h1>OpenCPN ECMWF forecast</h1>"
99 "<p>Free service based on ECMWF Open Data published under the terms of "
100 "Creative Commons CC-4.0-BY license</p>"
101 "<p>The IFS model GRIB files include information about surface "
103 "atmospheric pressure, wind strength, wind direction, wave height and "
104 "direction for the whole world on a 0.25 degree resolution "
106 "step in the first 144 hours and 6 hour step up to 10 days.</p>"
107 "The AIFS model contains data for wind, pressure and temperature on a "
108 "0.25 degree grid with 6 hour step for up to 15 days"
109 "<p>The data is updated twice a day as soon as the 00z and 12z model "
110 "runs finish and the "
111 "results are published by ECMWF, which usually means new forecast data "
112 "is available shortly after 8AM and 8PM UTC.</p>"
113 "<p>The grib downloaded covers the area of the primary chart "
115 "<p>The service is provided on best effort basis and comes with no "
116 "guarantees. The server is hosted by a volunteer and the service is "
117 "provided free of charge and without accepting any liability "
118 "whatsoever for its continuous availability, or for any loss or damage "
119 "arising from its use. If you find the service useful, please "
120 "consider making a donation to the OpenCPN project.</p>"
121 "<p>This service is based on data and products of the European Centre "
122 "for Medium-Range Weather Forecasts (ECMWF).</p>"
123 "<p>Source: www.ecmwf.int</p>"
124 "<p>Disclaimer: ECMWF does not accept any liability whatsoever for any "
125 "error or omission in the data, their availability, or for any loss or "
126 "damage arising from their use.</p>"
127 "</font></body></html>"));
128 m_htmlInfoWin->SetBorders(10);
129 m_htmlInfoWin->SetPage(
130 "<html><body bgcolor="
139 _(
"<h1>Grib weather forecasts</h1>"
140 "<p>Collection of local weather models from various sources available "
141 "for download over the internet.</p>"
142 "</font></body></html>"));
144 m_bLocal_source_selected =
false;
145 EnableDownloadButtons();
147 m_selectedAtmModelIndex = 0;
148 m_selectedWaveModelIndex = 0;
149 InitializeXygribDialog();
152GribRequestSetting::~GribRequestSetting() {
158 wxEVT_DOWNLOAD_EVENT,
159 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
168void GribRequestSetting::SaveConfig() {
171 pConf->SetPath(_T(
"/PlugIns/GRIB" ));
173 pConf->Write(_T (
"MailRequestConfig" ), m_RequestConfigBase);
174 pConf->Write(_T(
"MailSenderAddress" ), m_pSenderAddress->GetValue());
175 pConf->Write(_T(
"MailRequestAddresses" ), m_MailToAddresses);
176 pConf->Write(_T(
"ZyGribLogin" ), m_pLogin->GetValue());
177 pConf->Write(_T(
"ZyGribCode" ), m_pCode->GetValue());
178 pConf->Write(_T(
"SendMailMethod" ), m_SendMethod);
179 pConf->Write(_T(
"MovingGribSpeed" ), m_sMovingSpeed->GetValue());
180 pConf->Write(_T(
"MovingGribCourse" ), m_sMovingCourse->GetValue());
185 pConf->Write(_T(
"ManualRequestZoneSizingMode" ),
m_ZoneSelMode);
188 pConf->Write(_T(
"RequestZoneMaxLat" ),
m_spMaxLat->GetValue());
189 pConf->Write(_T(
"RequestZoneMinLat" ),
m_spMinLat->GetValue());
190 pConf->Write(_T(
"RequestZoneMaxLon" ),
m_spMaxLon->GetValue());
191 pConf->Write(_T(
"RequestZoneMinLon" ),
m_spMinLon->GetValue());
195void GribRequestSetting::InitRequestConfig() {
199 pConf->SetPath(_T(
"/PlugIns/GRIB" ));
202 pConf->Read(_T(
"MailRequestConfig" ), &m_RequestConfigBase,
203 _T(
"000220XX........0" ));
204 pConf->Read(_T(
"MailSenderAddress" ), &l,
"");
205 m_pSenderAddress->ChangeValue(l);
206 pConf->Read(_T(
"MailRequestAddresses" ), &m_MailToAddresses,
207 "query@saildocs.com;gribauto@zygrib.org");
208 pConf->Read(_T(
"ZyGribLogin" ), &l,
"");
209 m_pLogin->ChangeValue(l);
210 pConf->Read(_T(
"ZyGribCode" ), &l,
"");
211 m_pCode->ChangeValue(l);
212 pConf->Read(_T(
"SendMailMethod" ), &m_SendMethod, 0);
213 pConf->Read(_T(
"MovingGribSpeed" ), &m, 0);
214 m_sMovingSpeed->SetValue(m);
215 pConf->Read(_T(
"MovingGribCourse" ), &m, 0);
216 m_sMovingCourse->SetValue(m);
217 pConf->Read(_T(
"ManualRequestZoneSizingMode" ), &m, 0);
219 pConf->Read(_T(
"ManualRequestZoneSizing" ), &m, 0);
226 UpdateAreaSelectionState();
227 pConf->Read(_T(
"RequestZoneMaxLat" ), &m, 0);
229 pConf->Read(_T(
"RequestZoneMinLat" ), &m, 0);
231 pConf->Read(_T(
"RequestZoneMaxLon" ), &m, 0);
233 pConf->Read(_T(
"RequestZoneMinLon" ), &m, 0);
236 SetCoordinatesText();
239 if (m_RequestConfigBase.Len() !=
240 wxString(_T(
"000220XX.............." )).Len())
241 m_RequestConfigBase = _T(
"000220XX.............." );
244 wxString s1[] = {
"GFS",
"COAMPS",
"RTOFS",
"HRRR",
"ICON",
"ECMWF"};
245 for (
unsigned int i = 0; i < (
sizeof(s1) /
sizeof(wxString)); i++)
246 m_pModel->Append(s1[i]);
247 wxString s2[] = {
"Saildocs",
"zyGrib"};
248 for (
unsigned int i = 0; i < (
sizeof(s2) /
sizeof(wxString)); i++)
249 m_pMailTo->Append(s2[i]);
250 wxString s3[] = {
"WW3-GLOBAL",
"WW3-MEDIT"};
251 for (
unsigned int i = 0; i < (
sizeof(s3) /
sizeof(wxString)); i++)
252 m_pWModel->Append(s3[i]);
255 m_tResUnit->SetLabel(wxString::Format(
"\u00B0"));
256 m_sCourseUnit->SetLabel(wxString::Format(
"\u00B0"));
260 GetTextExtent(
"-360", &w, &h, 0, 0,
264 m_sMovingSpeed->SetMinSize(wxSize(w, h));
265 m_sMovingCourse->SetMinSize(wxSize(w, h));
272 m_pSenderAddress->SetToolTip(
273 _(
"Address used to send request eMail. (Mandatory for LINUX)"));
274 m_pLogin->SetToolTip(_(
"This is your zyGrib's forum access Login"));
276 _(
"Get this Code in zyGrib's forum ( This is not your password! )"));
277 m_sMovingSpeed->SetToolTip(_(
"Enter your forescasted Speed (in Knots)"));
278 m_sMovingCourse->SetToolTip(_(
"Enter your forecasted Course"));
281 ((wxString)m_RequestConfigBase.GetChar(0)).ToLong(&i);
282 m_pMailTo->SetSelection(i);
283 ((wxString)m_RequestConfigBase.GetChar(1)).ToLong(&i);
284 m_pModel->SetSelection(i);
285 m_cMovingGribEnabled->SetValue(m_RequestConfigBase.GetChar(16) ==
287 ((wxString)m_RequestConfigBase.GetChar(2)).ToLong(&i);
288 ((wxString)m_RequestConfigBase.GetChar(3)).ToLong(&j);
289 ((wxString)m_RequestConfigBase.GetChar(4)).ToLong(&k, 16);
293 m_pSenderSizer->ShowItems(
false);
295 if (m_SendMethod == 0)
296 m_pSenderSizer->ShowItems(
false);
298 m_pSenderSizer->ShowItems(
302 m_tMouseEventTimer.Connect(
303 wxEVT_TIMER, wxTimerEventHandler(GribRequestSetting::OnMouseEventTimer),
308 ApplyRequestConfig(i, j, k);
310 ((wxString)m_RequestConfigBase.GetChar(5)).ToLong(&j);
311 m_pWModel->SetSelection(j);
313 m_pWind->Enable(
false);
314 m_pPress->Enable(
false);
319 m_MailImage->SetValue(WriteMail());
322wxWindow *GetGRIBCanvas();
323void GribRequestSetting::OnClose(wxCloseEvent &event) {
326 m_downloading =
false;
327 m_download_handle = 0;
331 wxEVT_DOWNLOAD_EVENT,
332 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
341 m_parent.m_highlight_latmax = 0;
342 m_parent.m_highlight_lonmax = 0;
343 m_parent.m_highlight_latmin = 0;
344 m_parent.m_highlight_lonmin = 0;
348void GribRequestSetting::SetRequestDialogSize() {
351 GetTextExtent(
"abc",
nullptr, &y, 0, 0,
OCPNGetFont(_(
"Dialog")));
352 m_MailImage->SetMinSize(
353 wxSize(-1, ((y * m_MailImage->GetNumberOfLines()) + 10)));
357 m_fgScrollSizer->Fit(m_sScrolledDialog);
360 SetMinSize(wxSize(0, 0));
363 wxWindow *frame = wxTheApp->GetTopWindow();
365 int w = frame->GetClientSize().x;
366 int h = frame->GetClientSize().y;
372 m_sScrolledDialog->SetMinSize(
373 wxSize(wxMin(w, scroll.x),
374 wxMin(h, scroll.y)));
379 wxSize sd = GetSize();
380 if (sd.y == GetClientSize().y) sd.y += 30;
381 SetSize(wxSize(sd.x, sd.y));
382 SetMinSize(wxSize(sd.x, sd.y));
390 if ((fabs(vp->
lat_max) < 90.) && (fabs(lonmax) < 360.)) {
391 if (lonmax < -180.) lonmax += 360.;
392 if (lonmax > 180.) lonmax -= 360.;
394 if ((fabs(vp->
lat_min) < 90.) && (fabs(lonmin) < 360.)) {
395 if (lonmin < -180.) lonmin += 360.;
396 if (lonmin > 180.) lonmin -= 360.;
399 bool bnew_val =
false;
401 if (
m_spMinLon->GetValue() != (
int)floor(lonmin)) bnew_val =
true;
403 if (
m_spMaxLon->GetValue() != (
int)ceil(lonmax)) bnew_val =
true;
411 SetCoordinatesText();
412 m_MailImage->SetValue(WriteMail());
417 if (!(event.ShiftDown() || m_bpManualSelection->GetValue())) {
422 if (event.LeftDown() && !event.Dragging()) {
437 int xm =
event.GetX() * m_displayScale;
438 int ym =
event.GetY() * m_displayScale;
440 if (event.LeftDown() && !event.Dragging()) {
441 m_parent.pParent->SetFocus();
454 SetCoordinatesText();
455 UpdateAreaSelectionState();
456 m_MailImage->SetValue(WriteMail());
459 UpdateGribSizeEstimate();
460 m_boundingBoxCanvasIndex = -1;
461 }
else if (event.Dragging()) {
476 if (!m_tMouseEventTimer.IsRunning())
477 m_tMouseEventTimer.Start(20, wxTIMER_ONE_SHOT);
482void GribRequestSetting::OnMouseEventTimer(wxTimerEvent &event) {
504void GribRequestSetting::SetCoordinatesText() {
505 m_stMaxLatNS->SetLabel(
m_spMaxLat->GetValue() < 0 ? _(
"S") : _(
"N"));
506 m_stMinLonEW->SetLabel(
m_spMinLon->GetValue() < 0 ? _(
"W") : _(
"E"));
507 m_stMaxLonEW->SetLabel(
m_spMaxLon->GetValue() < 0 ? _(
"W") : _(
"E"));
508 m_stMinLatNS->SetLabel(
m_spMinLat->GetValue() < 0 ? _(
"S") : _(
"N"));
511size_t LengthSelToHours(
int sel) {
523std::string GribRequestSetting::FormatPerLocale(T value) {
524 std::stringstream ss;
526 ss.imbue(std::locale(
""));
531wxString GribRequestSetting::GetDownloadProgressText(
long transferredBytes,
533 if (totalBytes > 0) {
534 return wxString::Format(_(
"Downloading... %s kB / %s kB (%li%%)"),
535 FormatPerLocale(transferredBytes / 1024).c_str(),
536 FormatPerLocale(totalBytes / 1024).c_str(),
537 (
int)((
double)transferredBytes / totalBytes * 100));
539 return wxString::Format(_(
"Downloading... %s kB / ???"),
540 FormatPerLocale(transferredBytes / 1024).c_str());
547 switch (ev.getDLEventCondition()) {
551 Disconnect(wxEVT_DOWNLOAD_EVENT,
555 m_downloading =
false;
556 m_download_handle = 0;
561 switch (m_downloadType) {
563 m_staticTextInfo->SetLabelText(
564 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
568 m_stLocalDownloadInfo->SetLabelText(
569 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
574 m_xygribPanel->m_progress_gauge->SetValue(
575 100 * ev.getTransferred() / ev.getTotal());
578 m_xygribPanel->m_status_text->SetLabel(
579 GetDownloadProgressText(ev.getTransferred(), ev.getTotal()));
591void GribRequestSetting::OnWorldDownload(wxCommandEvent &event) {
594 m_downloading =
false;
595 m_download_handle = 0;
597 wxEVT_DOWNLOAD_EVENT,
598 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
600 m_btnDownloadWorld->SetLabelText(_(
"Download"));
601 m_staticTextInfo->SetLabelText(_(
"Download canceled"));
604 EnableDownloadButtons();
605 wxTheApp->ProcessPendingEvents();
610 m_downloading =
true;
612 EnableDownloadButtons();
613 m_btnDownloadWorld->SetLabelText(_(
"Cancel"));
614 m_staticTextInfo->SetLabelText(_(
"Preparing data on server..."));
617 switch (m_chECMWFResolution->GetSelection()) {
622 model =
"ecmwfaifs0p25";
628 std::ostringstream oss;
629 oss <<
"https://grib.bosun.io/grib?";
630 oss <<
"model=" << model;
635 oss <<
"&length=" << LengthSelToHours(m_chForecastLength->GetSelection());
637 wxString::Format(
"ocpn_%s_%li_%s.grb2", model.c_str(),
638 LengthSelToHours(m_chForecastLength->GetSelection()),
639 wxDateTime::Now().Format(
"%F-%H-%M"));
640 wxString path = m_parent.GetGribDir();
641 path.Append(wxFileName::GetPathSeparator());
642 path.Append(filename);
646 wxEVT_DOWNLOAD_EVENT,
647 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
651 while (m_downloading) {
652 wxTheApp->ProcessPendingEvents();
656 if (m_bTransferSuccess) {
657 m_staticTextInfo->SetLabelText(
658 wxString::Format(_(
"Download complete: %s"), path.c_str()));
665 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
667 m_parent.SetDialogsStyleSizePosition(
true);
671 m_staticTextInfo->SetLabelText(_(
"Download failed"));
674 m_btnDownloadWorld->SetLabelText(_(
"Download"));
676 EnableDownloadButtons();
679enum LocalSourceItem { SOURCE, AREA, GRIB };
681enum LocalGribDownloadType { DIRECT, MANIFEST, WEBPAGE };
684 GribCatalogInfo(LocalSourceItem type, wxString name, wxString description,
685 wxString url, wxString filename,
686 LocalGribDownloadType download_type,
double latmin,
687 double lonmin,
double latmax,
double lonmax)
690 description(description),
693 download_type(download_type),
698 LocalSourceItem type;
700 wxString description;
703 LocalGribDownloadType download_type;
710void GribRequestSetting::FillTreeCtrl(
wxJSONValue &data) {
711 m_SourcesTreeCtrl1->DeleteAllItems();
713 m_SourcesTreeCtrl1->AddRoot(_(
"Local high resolution forecasts"));
714 if (data.HasMember(
"sources") && data[
"sources"].IsArray()) {
715 for (
int i = 0; i < data[
"sources"].Size(); i++) {
718 LocalSourceItem::SOURCE, source[
"source"].AsString(),
719 source[
"description"].AsString(), source[
"url"].AsString(),
720 wxEmptyString, LocalGribDownloadType::WEBPAGE, 0, 0, 0, 0);
721 wxTreeItemId src_id = m_SourcesTreeCtrl1->AppendItem(
722 root, source[
"source"].AsString(), -1, -1, info);
723 if (source.
HasMember(
"areas") && source[
"areas"].IsArray()) {
724 for (
int j = 0; j < source[
"areas"].
Size(); j++) {
727 LocalSourceItem::AREA, area[
"name"].AsString(),
728 source[
"description"].AsString(), source[
"url"].AsString(),
729 wxEmptyString, LocalGribDownloadType::WEBPAGE,
730 area[
"boundary"][
"lat_min"].AsDouble(),
731 area[
"boundary"][
"lon_min"].AsDouble(),
732 area[
"boundary"][
"lat_max"].AsDouble(),
733 area[
"boundary"][
"lon_max"].AsDouble());
734 m_SourcesTreeCtrl1->AppendItem(src_id, area[
"name"].AsString(), -1,
736 if (area.
HasMember(
"gribs") && area[
"gribs"].IsArray()) {
737 for (
int k = 0; k < area[
"gribs"].
Size(); k++) {
740 LocalSourceItem::GRIB, grib[
"name"].AsString(),
741 source[
"description"].AsString(),
742 grib.
HasMember(
"url") ? grib[
"url"].AsString()
743 : grib[
"cat_url"].AsString(),
744 grib.HasMember(
"filename") ? grib[
"filename"].AsString() :
"",
745 grib.HasMember(
"url") ? LocalGribDownloadType::DIRECT
746 : LocalGribDownloadType::MANIFEST,
747 area[
"boundary"][
"lat_min"].AsDouble(),
748 area[
"boundary"][
"lon_min"].AsDouble(),
749 area[
"boundary"][
"lat_max"].AsDouble(),
750 area[
"boundary"][
"lon_max"].AsDouble());
751 m_SourcesTreeCtrl1->AppendItem(
752 m_SourcesTreeCtrl1->GetLastChild(src_id),
753 grib[
"name"].AsString(), -1, -1, info);
758 m_SourcesTreeCtrl1->CollapseAllChildren(src_id);
761 m_SourcesTreeCtrl1->Expand(root);
764void GribRequestSetting::ReadLocalCatalog() {
766 wxFileInputStream str(m_parent.
pPlugIn->m_local_sources_catalog);
768 reader.
Parse(str, &root);
772void GribRequestSetting::HighlightArea(
double latmax,
double lonmax,
773 double latmin,
double lonmin) {
774 m_parent.m_highlight_latmax = latmax;
775 m_parent.m_highlight_lonmax = lonmax;
776 m_parent.m_highlight_latmin = latmin;
777 m_parent.m_highlight_lonmin = lonmin;
780void GribRequestSetting::OnLocalTreeSelChanged(wxTreeEvent &event) {
781 wxTreeItemId item = m_SourcesTreeCtrl1->GetSelection();
784 if (src->type == LocalSourceItem::GRIB) {
785 m_stLocalDownloadInfo->SetLabelText(_(
"Download grib..."));
786 m_bLocal_source_selected =
true;
787 HighlightArea(src->latmax, src->lonmax, src->latmin, src->lonmin);
789 m_stLocalDownloadInfo->SetLabelText(_(
"Select grib..."));
790 m_bLocal_source_selected =
false;
791 HighlightArea(src->latmax, src->lonmax, src->latmin, src->lonmin);
794 EnableDownloadButtons();
797void GribRequestSetting::OnUpdateLocalCatalog(wxCommandEvent &event) {
800 m_downloading =
false;
801 m_download_handle = 0;
803 wxEVT_DOWNLOAD_EVENT,
804 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
806 m_btnDownloadLocal->SetLabelText(_(
"Download"));
807 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
810 EnableDownloadButtons();
811 wxTheApp->ProcessPendingEvents();
816 m_downloading =
true;
818 EnableDownloadButtons();
819 m_btnDownloadLocal->SetLabelText(_(
"Cancel"));
820 m_staticTextInfo->SetLabelText(_(
"Downloading catalog update..."));
825 wxEVT_DOWNLOAD_EVENT,
826 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
829 CATALOG_URL, m_parent.
pPlugIn->m_local_sources_catalog +
"new",
this,
831 while (m_downloading) {
832 wxTheApp->ProcessPendingEvents();
836 if (m_bTransferSuccess) {
837 wxRenameFile(m_parent.
pPlugIn->m_local_sources_catalog +
"new",
838 m_parent.
pPlugIn->m_local_sources_catalog,
true);
840 m_stLocalDownloadInfo->SetLabelText(_(
"Catalog update complete."));
842 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
845 m_btnDownloadLocal->SetLabelText(_(
"Download"));
847 EnableDownloadButtons();
850void GribRequestSetting::OnDownloadLocal(wxCommandEvent &event) {
853 m_downloading =
false;
854 m_download_handle = 0;
856 wxEVT_DOWNLOAD_EVENT,
857 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
859 m_btnDownloadLocal->SetLabelText(_(
"Download"));
860 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
863 EnableDownloadButtons();
864 wxTheApp->ProcessPendingEvents();
869 m_downloading =
true;
871 EnableDownloadButtons();
872 m_btnDownloadLocal->SetLabelText(_(
"Cancel"));
873 m_staticTextInfo->SetLabelText(_(
"Downloading grib..."));
876 m_SourcesTreeCtrl1->GetSelection()));
877 if (!src || src->type != LocalSourceItem::GRIB || src->url.IsEmpty()) {
878 m_downloading =
false;
879 m_stLocalDownloadInfo->SetLabelText(_(
"Download can't be started."));
880 m_btnDownloadWorld->SetLabelText(_(
"Download"));
882 EnableDownloadButtons();
888 wxEVT_DOWNLOAD_EVENT,
889 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
891 wxString url = src->url;
894 if (src->download_type == LocalGribDownloadType::MANIFEST) {
895 wxString path = m_parent.GetGribDir();
896 path.Append(wxFileName::GetPathSeparator());
897 path.Append(
"grib_manifest.json");
899 while (m_downloading) {
900 wxTheApp->ProcessPendingEvents();
905 if (!m_bTransferSuccess) {
907 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
911 m_stLocalDownloadInfo->SetLabelText(_(
"Download canceled"));
915 wxFileInputStream str(path);
917 reader.
Parse(str, &root);
919 wxString parsed = root[
"url"].
AsString();
920 if (parsed.StartsWith(
"http")) {
923 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
930 m_downloading =
false;
931 m_download_handle = 0;
932 Disconnect(wxEVT_DOWNLOAD_EVENT,
936 m_btnDownloadLocal->SetLabelText(_(
"Download"));
937 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
940 EnableDownloadButtons();
941 wxTheApp->ProcessPendingEvents();
947 m_downloading =
true;
952 wxEVT_DOWNLOAD_EVENT,
953 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
956 if (!src->filename.IsEmpty()) {
957 filename = src->filename;
962 filename.Replace(
"?",
"_");
963 filename.Replace(
"&",
"_");
964 if (!(filename.Contains(
".grb2") || filename.Contains(
".grib2") ||
965 filename.Contains(
".grb") || filename.Contains(
".grib"))) {
966 filename.Append(
".grb");
970 wxString path = m_parent.GetGribDir();
971 path.Append(wxFileName::GetPathSeparator());
972 path.Append(filename);
974 while (m_downloading) {
975 wxTheApp->ProcessPendingEvents();
979 if (m_bTransferSuccess) {
980 m_stLocalDownloadInfo->SetLabelText(_(
"Grib download complete."));
981 m_stLocalDownloadInfo->SetLabelText(
982 wxString::Format(_(
"Download complete: %s"), path.c_str()));
990 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
992 m_parent.SetDialogsStyleSizePosition(
true);
996 m_stLocalDownloadInfo->SetLabelText(_(
"Download failed"));
999 m_btnDownloadWorld->SetLabelText(_(
"Download"));
1001 EnableDownloadButtons();
1004void GribRequestSetting::EnableDownloadButtons() {
1005 switch (m_downloadType) {
1007 m_btnDownloadWorld->Enable(
true);
1008 m_btnDownloadLocal->Enable(
false);
1009 m_buttonUpdateCatalog->Enable(
false);
1013 m_btnDownloadWorld->Enable(
false);
1014 m_btnDownloadLocal->Enable(m_bLocal_source_selected || m_downloading);
1015 m_buttonUpdateCatalog->Enable(
false);
1018 m_xygribPanel->m_download_button->Enable(
true);
1021 m_btnDownloadWorld->Enable(
true);
1022 m_btnDownloadLocal->Enable(m_bLocal_source_selected || m_downloading);
1023 m_buttonUpdateCatalog->Enable(
true);
1024 m_xygribPanel->m_download_button->Enable(
true);
1029void GribRequestSetting::StopGraphicalZoneSelection() {
1049 if (!m_AllowSend)
return;
1055 UpdateGribSizeEstimate();
1058void GribRequestSetting::ApplyRequestConfig(
unsigned rs,
unsigned it,
1061 const wxString res[][RESOLUTIONS] = {
1062 {
"0.25",
"0.5",
"1.0",
"2.0"},
1063 {
"0.2",
"0.8",
"1.6", wxEmptyString},
1064 {
"0.08",
"0.24",
"1.0", wxEmptyString},
1065 {
"0.03",
"0.24",
"1.0", wxEmptyString},
1066 {
"0.0625",
"0.125", wxEmptyString, wxEmptyString},
1067 {
"0.4",
"1.0",
"2.0", wxEmptyString}
1070 IsZYGRIB = m_pMailTo->GetCurrentSelection() == ZYGRIB;
1072 m_pModel->SetSelection(GFS);
1073 IsGFS = m_pModel->GetCurrentSelection() == GFS;
1074 bool IsRTOFS = m_pModel->GetCurrentSelection() == RTOFS;
1075 bool IsHRRR = m_pModel->GetCurrentSelection() == HRRR;
1076 bool IsICON = m_pModel->GetCurrentSelection() == ICON;
1077 bool IsECMWF = m_pModel->GetCurrentSelection() == ECMWF;
1080 m_pResolution->Clear();
1081 if (m_pModel->GetCurrentSelection() >= 0) {
1082 for (
int i = 0; i < RESOLUTIONS; i++) {
1083 if (res[m_pModel->GetCurrentSelection()][i] != wxEmptyString) {
1084 wxString s = res[m_pModel->GetCurrentSelection()][i];
1085 m_pResolution->Append(s);
1089 m_pResolution->SetSelection(rs);
1093 l = (IsGFS || IsRTOFS || IsICON || IsECMWF) ? 3 : IsHRRR ? 1 : 6;
1096 m = IsHRRR ? 2 : 25;
1098 m_pInterval->Clear();
1099 for (
unsigned i = l; i < m; i *= 2)
1100 m_pInterval->Append(wxString::Format(
"%d", i));
1101 m_pInterval->SetSelection(wxMin(it, m_pInterval->GetCount() - 1));
1111 m_pTimeRange->Clear();
1112 for (
unsigned i = 2; i < l + 1; i++)
1113 m_pTimeRange->Append(wxString::Format(
"%d", i));
1114 m_pTimeRange->SetSelection(wxMin(l - 2, tr));
1116 m_pModel->Enable(!IsZYGRIB);
1117 m_pWind->SetValue(!IsRTOFS);
1118 m_pPress->SetValue(!IsRTOFS);
1119 m_pWaves->SetValue(m_RequestConfigBase.GetChar(8) ==
'X' && IsGFS);
1120 m_pWaves->Enable(IsECMWF ||
1121 (IsGFS && m_pTimeRange->GetCurrentSelection() < 7));
1123 m_pRainfall->SetValue(m_RequestConfigBase.GetChar(9) ==
'X' &&
1125 m_pRainfall->Enable(IsGFS || IsHRRR);
1126 m_pCloudCover->SetValue(m_RequestConfigBase.GetChar(10) ==
'X' && IsGFS);
1127 m_pCloudCover->Enable(IsGFS);
1128 m_pAirTemp->SetValue(m_RequestConfigBase.GetChar(11) ==
'X' &&
1129 (IsGFS || IsHRRR || IsICON || IsECMWF));
1130 m_pAirTemp->Enable(IsGFS || IsHRRR || IsICON || IsECMWF);
1131 m_pSeaTemp->SetValue(m_RequestConfigBase.GetChar(12) ==
'X' &&
1132 ((!IsZYGRIB && IsGFS) || IsRTOFS || IsHRRR || IsICON));
1133 m_pSeaTemp->Enable(!IsZYGRIB && (IsGFS || IsHRRR || IsICON));
1134 m_pWindGust->SetValue(m_RequestConfigBase.GetChar(14) ==
'X' &&
1135 (IsGFS || IsHRRR || IsICON));
1136 m_pWindGust->Enable(IsGFS || IsHRRR || IsICON);
1137 m_pCAPE->SetValue(m_RequestConfigBase.GetChar(15) ==
'X' &&
1139 m_pCAPE->Enable(IsGFS || IsHRRR);
1140 m_pReflectivity->Enable(IsGFS || IsHRRR);
1142 m_pAltitudeData->SetValue(
1143 (IsGFS || IsICON || IsECMWF)
1144 ? m_RequestConfigBase.GetChar(17) ==
'X'
1146 m_pAltitudeData->Enable(IsGFS || IsICON || IsECMWF);
1147 m_p850hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(18) ==
'X'
1149 m_p850hpa->Enable(IsZYGRIB);
1150 m_p700hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(19) ==
'X'
1152 m_p700hpa->Enable(IsZYGRIB);
1153 m_p500hpa->SetValue((IsGFS || IsICON || IsECMWF)
1154 ? m_RequestConfigBase.GetChar(20) ==
'X'
1156 m_p500hpa->Enable(IsGFS || IsICON || IsECMWF);
1157 m_p300hpa->SetValue(IsZYGRIB ? m_RequestConfigBase.GetChar(21) ==
'X'
1159 m_p300hpa->Enable(IsZYGRIB);
1161 m_pCurrent->SetValue(IsRTOFS);
1162 m_pCurrent->Enable(
false);
1165 m_cMovingGribEnabled->Show(!IsZYGRIB);
1166 m_fgMovingParams->ShowItems(m_cMovingGribEnabled->IsChecked() &&
1167 m_cMovingGribEnabled->IsShown());
1169 m_fgLog->ShowItems(IsZYGRIB);
1171 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1173 m_fgAltitudeData->ShowItems(
1174 m_pAltitudeData->IsChecked());
1177void GribRequestSetting::OnTopChange(wxCommandEvent &event) {
1179 if (m_pMailTo->GetCurrentSelection() == ZYGRIB) {
1180 m_pMailTo->SetSelection(0);
1183 _(
"Sorry...\nZyGrib momentary stopped providing this service...\nOnly "
1184 "Saildocs option is available"),
1185 _(
"Warning"), wxOK);
1187 ApplyRequestConfig(m_pResolution->GetCurrentSelection(),
1188 m_pInterval->GetCurrentSelection(),
1189 m_pTimeRange->GetCurrentSelection());
1191 m_cMovingGribEnabled->Show(m_pMailTo->GetCurrentSelection() == SAILDOCS);
1193 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1195 SetRequestDialogSize();
1198void GribRequestSetting::UpdateAreaSelectionState() {
1207void GribRequestSetting::OnZoneSelectionModeChange(wxCommandEvent &event) {
1208 StopGraphicalZoneSelection();
1217 }
else if (event.GetId() ==
MANSELECT) {
1223 m_cUseSavedZone->SetValue(
false);
1224 }
else if (event.GetId() ==
SAVEDZONE) {
1232 UpdateAreaSelectionState();
1233 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1235 SetRequestDialogSize();
1249 center.x = x + (zw / 2);
1250 center.y = y + (zh / 2);
1256 wxColour pen_color, back_color;
1257 GetGlobalColor(_T (
"DASHR" ), &pen_color);
1258 GetGlobalColor(_T (
"YELO1" ), &back_color);
1260 int label_offsetx = 5, label_offsety = 1;
1263 EstimateFileSize(&size);
1265 wxString label(_(
"Coord. "));
1266 label.Append(toMailFormat(1,
m_spMaxLat->GetValue()) +
" ");
1267 label.Append(toMailFormat(0,
m_spMinLon->GetValue()) +
" ");
1268 label.Append(toMailFormat(1,
m_spMinLat->GetValue()) +
" ");
1269 label.Append(toMailFormat(0,
m_spMaxLon->GetValue()) +
"\n");
1270 label.Append(
"Estim. Size ")
1271 .Append((wxString::Format(_T(
"%1.2f " ), size) + _(
"MB")));
1274 wxPen pen(pen_color);
1277 m_pdc->SetBrush(*wxTRANSPARENT_BRUSH);
1278 m_pdc->DrawRectangle(x, y, zw, zh);
1283 sdc.GetMultiLineTextExtent(label, &w, &h, &sl, font);
1285 m_pdc->GetMultiLineTextExtent(label, &w, &h, &sl, font);
1289 w += 2 * label_offsetx, h += 2 * label_offsety;
1290 x = center.x - (w / 2);
1291 y = center.y - (h / 2);
1293 h *= m_displayScale;
1294 w *= m_displayScale;
1301 mdc.SetBrush(back_color);
1302 mdc.SetPen(*wxTRANSPARENT_PEN);
1303 mdc.SetTextForeground(wxColor(0, 0, 0));
1304 mdc.DrawRectangle(0, 0, w, h);
1305 mdc.DrawLabel(label, wxRect(label_offsetx, label_offsety, w, h));
1307 wxImage im = bm.ConvertToImage();
1309 w = im.GetWidth(), h = im.GetHeight();
1310 for (
int j = 0; j < h; j++)
1311 for (
int i = 0; i < w; i++) im.SetAlpha(i, j, 155);
1313 m_pdc->DrawBitmap(im, x, y,
true);
1317#ifndef USE_ANDROID_GLES2
1324 m_oDC->SetPen(wxPen(pen_color, 3));
1327 outline[0] = wxPoint(x, y);
1328 outline[1] = wxPoint(x + zw, y);
1329 outline[2] = wxPoint(x + zw, y + zh);
1330 outline[3] = wxPoint(x, y + zh);
1331 outline[4] = wxPoint(x, y);
1332 m_oDC->DrawLines(5, outline);
1334 m_oDC->SetFont(*font);
1336 m_oDC->GetTextExtent(label, &w, &h);
1337 h *= m_displayScale;
1338 w *= m_displayScale;
1340 m_oDC->GetTextExtent(
"W", &ww, &hw);
1342 int label_offsetx = ww, label_offsety = 1;
1343 int x = center.x - w / 2;
1344 int y = center.y - h / 2;
1346 w += 2 * label_offsetx, h += 2 * label_offsety;
1348 m_oDC->SetBrush(wxBrush(back_color));
1349 m_oDC->DrawRoundedRectangle(x, y, w, h, 0);
1352 m_oDC->SetPen(wxPen(wxColour(0, 0, 0), 1));
1354 outline[0] = wxPoint(x, y);
1355 outline[1] = wxPoint(x + w, y);
1356 outline[2] = wxPoint(x + w, y + h);
1357 outline[3] = wxPoint(x, y + h);
1358 outline[4] = wxPoint(x, y);
1359 m_oDC->DrawLines(5, outline);
1361 m_oDC->DrawText(label, x + label_offsetx, y + label_offsety);
1381void GribRequestSetting::OnMovingClick(wxCommandEvent &event) {
1382 m_fgMovingParams->ShowItems(m_cMovingGribEnabled->IsChecked() &&
1383 m_cMovingGribEnabled->IsShown());
1385 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1386 SetRequestDialogSize();
1391void GribRequestSetting::OnCoordinatesChange(wxSpinEvent &event) {
1392 SetCoordinatesText();
1394 StopGraphicalZoneSelection();
1396 if (!m_AllowSend)
return;
1398 m_MailImage->SetValue(WriteMail());
1401void GribRequestSetting::OnAnyChange(wxCommandEvent &event) {
1402 m_fgAltitudeData->ShowItems(m_pAltitudeData->IsChecked());
1404 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1406 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1408 SetRequestDialogSize();
1411void GribRequestSetting::OnTimeRangeChange(wxCommandEvent &event) {
1412 m_pWModel->Show(IsZYGRIB && m_pWaves->IsChecked());
1414 if (m_pModel->GetCurrentSelection() == 0) {
1415 if (m_pTimeRange->GetCurrentSelection() >
1417 m_pWaves->SetValue(0);
1418 m_pWaves->Enable(
false);
1421 _(
"You request a forecast for more than 8 days horizon.\nThis is "
1422 "conflicting with Wave data which will be removed from your "
1423 "request.\nDon't forget that beyond the first 8 days, the "
1424 "resolution will be only 2.5\u00B0x2.5\u00B0\nand the time "
1425 "intervall 12 hours."),
1428 m_pWaves->Enable(
true);
1431 if (m_AllowSend) m_MailImage->SetValue(WriteMail());
1433 SetRequestDialogSize();
1436void GribRequestSetting::OnOK(wxCommandEvent &event) {
1437 bool IsCOAMPS = m_pModel->GetCurrentSelection() == COAMPS;
1438 bool IsRTOFS = m_pModel->GetCurrentSelection() == RTOFS;
1439 bool IsICON = m_pModel->GetCurrentSelection() == ICON;
1440 bool IsECMWF = m_pModel->GetCurrentSelection() == ECMWF;
1441 m_RequestConfigBase.SetChar(
1442 0, (
char)(m_pMailTo->GetCurrentSelection() +
'0'));
1443 m_cMovingGribEnabled->IsChecked()
1444 ? m_RequestConfigBase.SetChar(16,
'X')
1445 : m_RequestConfigBase.SetChar(16,
'.');
1448 m_RequestConfigBase.SetChar(
1449 1, (
char)(m_pModel->GetCurrentSelection() +
'0'));
1451 m_RequestConfigBase.SetChar(
1452 2, (
char)(m_pResolution->GetCurrentSelection() +
'0'));
1454 m_RequestConfigBase.SetChar(3,
1455 (
char)(m_pInterval->GetCurrentSelection() +
'0'));
1458 range.Printf(
"%x", m_pTimeRange->GetCurrentSelection() +
1460 m_RequestConfigBase.SetChar(4, range.GetChar(0));
1462 if (IsZYGRIB && m_pWModel->IsShown())
1463 m_RequestConfigBase.SetChar(
1464 5, (
char)(m_pWModel->GetCurrentSelection() +
'0'));
1466 m_RequestConfigBase.SetChar(
1468 m_RequestConfigBase.SetChar(
1471 if (!IsCOAMPS && !IsRTOFS) {
1472 m_pWindGust->IsChecked() ? m_RequestConfigBase.SetChar(14,
'X')
1473 : m_RequestConfigBase.SetChar(14,
'.');
1474 m_pWaves->IsChecked() ? m_RequestConfigBase.SetChar(8,
'X')
1475 : m_RequestConfigBase.SetChar(8,
'.');
1476 m_pRainfall->IsChecked() ? m_RequestConfigBase.SetChar(9,
'X')
1477 : m_RequestConfigBase.SetChar(9,
'.');
1478 m_pCloudCover->IsChecked() ? m_RequestConfigBase.SetChar(10,
'X')
1479 : m_RequestConfigBase.SetChar(10,
'.');
1480 m_pAirTemp->IsChecked() ? m_RequestConfigBase.SetChar(11,
'X')
1481 : m_RequestConfigBase.SetChar(11,
'.');
1482 m_pSeaTemp->IsChecked() ? m_RequestConfigBase.SetChar(12,
'X')
1483 : m_RequestConfigBase.SetChar(12,
'.');
1484 m_pCAPE->IsChecked() ? m_RequestConfigBase.SetChar(15,
'X')
1485 : m_RequestConfigBase.SetChar(15,
'.');
1488 m_pCurrent->IsChecked() ? m_RequestConfigBase.SetChar(13,
'X')
1489 : m_RequestConfigBase.SetChar(13,
'.');
1491 if (IsGFS || IsICON || IsECMWF) {
1492 m_pAltitudeData->IsChecked()
1493 ? m_RequestConfigBase.SetChar(17,
'X')
1494 : m_RequestConfigBase.SetChar(17,
'.');
1495 m_p500hpa->IsChecked() ? m_RequestConfigBase.SetChar(20,
'X')
1496 : m_RequestConfigBase.SetChar(20,
'.');
1499 m_p850hpa->IsChecked() ? m_RequestConfigBase.SetChar(18,
'X')
1500 : m_RequestConfigBase.SetChar(18,
'.');
1501 m_p700hpa->IsChecked() ? m_RequestConfigBase.SetChar(19,
'X')
1502 : m_RequestConfigBase.SetChar(19,
'.');
1503 m_p300hpa->IsChecked() ? m_RequestConfigBase.SetChar(21,
'X')
1504 : m_RequestConfigBase.SetChar(21,
'.');
1511wxString GribRequestSetting::WriteMail() {
1513 int limit = IsZYGRIB ? 2 : 0;
1517 const wxString s[] = {
",",
" "};
1518 const wxString p[][11] = {
1520 {
"APCP",
"TCDC",
"AIRTMP",
"HTSGW,WVPER,WVDIR",
"SEATMP",
"GUST",
"CAPE",
1521 wxEmptyString, wxEmptyString,
"WIND500,HGT500", wxEmptyString},
1526 {
"",
"",
"AIRTMP",
"",
"SFCTMP",
"GUST",
"",
"",
"",
"WIND500,HGT500",
1529 {
"",
"",
"TEMP",
"WAVES",
"",
"",
"",
"",
"",
"WIND500,HGT500",
""},
1531 {
"PRECIP",
"CLOUD",
"TEMP",
"WVSIG WVWIND", wxEmptyString,
"GUST",
"CAPE",
1532 "A850",
"A700",
"A500",
"A300"}};
1534 wxString r_topmess, r_parameters, r_zone;
1536 switch (m_pMailTo->GetCurrentSelection()) {
1538 r_zone = toMailFormat(1,
m_spMaxLat->GetValue()) +
"," +
1539 toMailFormat(1,
m_spMinLat->GetValue()) +
"," +
1540 toMailFormat(2,
m_spMinLon->GetValue()) +
"," +
1542 r_topmess =
"send ";
1543 r_topmess.Append(m_pModel->GetStringSelection() +
":");
1544 r_topmess.Append(r_zone +
"|");
1545 r_topmess.Append(m_pResolution->GetStringSelection())
1547 .Append(m_pResolution->GetStringSelection())
1550 m_pInterval->GetStringSelection().ToDouble(&v);
1551 r_topmess.Append(wxString::Format(
"0,%d,%d", (
int)v, (
int)v * 2));
1552 m_pTimeRange->GetStringSelection().ToDouble(&v);
1553 r_topmess.Append(wxString::Format(
"..%d", (
int)v * 24) +
"|=\n");
1560 r_zone = toMailFormat(1,
m_spMinLat->GetValue()) +
1561 toMailFormat(2,
m_spMinLon->GetValue()) +
" " +
1563 toMailFormat(2, maxlon);
1564 r_topmess =
"login : ";
1565 r_topmess.Append(m_pLogin->GetValue() +
"\n");
1566 r_topmess.Append(
"code :");
1567 r_topmess.Append(m_pCode->GetValue() +
"\n");
1568 r_topmess.Append(
"area : ");
1569 r_topmess.append(r_zone +
"\n");
1570 r_topmess.Append(
"resol : ");
1571 r_topmess.append(m_pResolution->GetStringSelection() +
"\n");
1572 r_topmess.Append(
"days : ");
1573 r_topmess.append(m_pTimeRange->GetStringSelection() +
"\n");
1574 r_topmess.Append(
"hours : ");
1575 r_topmess.append(m_pInterval->GetStringSelection() +
"\n");
1576 if (m_pWaves->IsChecked()) {
1577 r_topmess.Append(
"waves : ");
1578 r_topmess.append(m_pWModel->GetStringSelection() +
"\n");
1580 r_topmess.Append(
"meteo : ");
1581 r_topmess.append(m_pModel->GetStringSelection() +
"\n");
1582 if (m_pLogin->GetValue().IsEmpty() || m_pCode->GetValue().IsEmpty())
1587 int GFSZ = IsZYGRIB ? 6 : 0;
1588 switch (m_pModel->GetCurrentSelection()) {
1590 r_parameters =
"WIND" + s[m_pMailTo->GetCurrentSelection()] +
1592 if (m_pRainfall->IsChecked())
1593 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1595 if (m_pCloudCover->IsChecked())
1596 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1598 if (m_pAirTemp->IsChecked())
1599 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1601 if (m_pWaves->IsChecked())
1602 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1604 if (m_pSeaTemp->IsChecked())
1605 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1607 if (m_pWindGust->IsChecked())
1608 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1610 if (m_pCAPE->IsChecked())
1611 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1613 if (m_pAltitudeData->IsChecked()) {
1614 if (m_p850hpa->IsChecked())
1615 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1617 if (m_p700hpa->IsChecked())
1618 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1620 if (m_p500hpa->IsChecked())
1621 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1623 if (m_p300hpa->IsChecked())
1624 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1629 r_parameters =
"WIND,PRMSL";
1633 r_parameters =
"CUR,WTMP";
1636 r_parameters =
"WIND,PRMSL";
1638 if (m_pRainfall->IsChecked())
1639 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][0]);
1640 if (m_pAirTemp->IsChecked())
1641 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][2]);
1642 if (m_pSeaTemp->IsChecked())
1643 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][4]);
1644 if (m_pWindGust->IsChecked())
1645 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][5]);
1646 if (m_pCAPE->IsChecked())
1647 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[GFS][6]);
1650 r_parameters =
"WIND,PRMSL";
1652 if (m_pAirTemp->IsChecked())
1653 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][2]);
1654 if (m_pSeaTemp->IsChecked())
1655 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][4]);
1656 if (m_pWindGust->IsChecked())
1657 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][5]);
1658 if (m_pAltitudeData->IsChecked()) {
1659 if (m_p500hpa->IsChecked())
1660 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ICON][9]);
1664 r_parameters =
"WIND,MSLP";
1666 if (m_pAirTemp->IsChecked())
1667 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ECMWF][2]);
1668 if (m_pAltitudeData->IsChecked()) {
1669 if (m_p500hpa->IsChecked())
1670 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] +
1673 if (m_pWaves->IsChecked())
1674 r_parameters.Append(s[m_pMailTo->GetCurrentSelection()] + p[ECMWF][3]);
1677 if (!IsZYGRIB && m_cMovingGribEnabled->IsChecked())
1678 r_parameters.Append(wxString::Format(
"|%d,%d", m_sMovingSpeed->GetValue(),
1679 m_sMovingCourse->GetValue()));
1683 char c = m_pMailTo->GetCurrentSelection() == SAILDOCS ?
',' :
' ';
1684 for (
size_t i = 0; i < r_parameters.Len(); i++) {
1685 if (r_parameters.GetChar(i) ==
'|')
1687 if (r_parameters.GetChar(i) == c) j++;
1689 r_parameters.insert(
1690 i + 1, m_pMailTo->GetCurrentSelection() == SAILDOCS ?
"=\n" :
"\n");
1696 m_MailError_Nb += EstimateFileSize(&size);
1698 m_tFileSize->SetLabel(wxString::Format(_T(
"%1.2f " ), size) + _(
"MB"));
1701 m_tLimit->SetLabel(wxString(
"( ") + _(
"Max") +
1702 wxString::Format(
" %d ", limit) + _(
"MB") +
" )");
1703 if (size > limit) m_MailError_Nb += 2;
1705 m_tLimit->SetLabel(wxEmptyString);
1707 return wxString(r_topmess + r_parameters);
1710int GribRequestSetting::EstimateFileSize(
double *size) {
1711 if (!size)
return 0;
1715 double reso, time, inter;
1716 m_pResolution->GetStringSelection().ToDouble(&reso);
1717 m_pTimeRange->GetStringSelection().ToDouble(&time);
1718 m_pInterval->GetStringSelection().ToDouble(&inter);
1722 if (maxlat - minlat < 0)
return 3;
1723 double wlon = (maxlon > minlon ? 0 : 360) + maxlon - minlon;
1724 if (wlon > 180 || (maxlat - minlat > 180))
return 4;
1726 if (fabs(wlon) < 2 * reso || maxlat - minlat < 2 * reso)
1729 int npts = (int)(ceil(((
double)(maxlat - minlat) / reso)) *
1730 ceil(((
double)(wlon) / reso)));
1732 if (m_pModel->GetCurrentSelection() == COAMPS)
1733 npts = wxMin(npts, (
int)(ceil(40.0 / reso) * ceil(40.0 / reso)));
1736 int nbrec = (int)(time * 24 / inter) + 1;
1737 int nbPress = (m_pPress->IsChecked()) ? nbrec : 0;
1738 int nbWind = (m_pWind->IsChecked()) ? 2 * nbrec : 0;
1739 int nbwave = (m_pWaves->IsChecked()) ? 2 * nbrec : 0;
1740 int nbRain = (m_pRainfall->IsChecked()) ? nbrec - 1 : 0;
1741 int nbCloud = (m_pCloudCover->IsChecked()) ? nbrec - 1 : 0;
1742 int nbTemp = (m_pAirTemp->IsChecked()) ? nbrec : 0;
1743 int nbSTemp = (m_pSeaTemp->IsChecked()) ? nbrec : 0;
1744 int nbGUSTsfc = (m_pWindGust->IsChecked()) ? nbrec : 0;
1745 int nbCurrent = (m_pCurrent->IsChecked()) ? nbrec : 0;
1746 int nbCape = (m_pCAPE->IsChecked()) ? nbrec : 0;
1748 IsZYGRIB ? 5 * nbrec : 3 * nbrec;
1752 double estime = 0.0;
1756 estime += nbWind * (head + (nbits * npts) / 8 + 2);
1757 estime += nbCurrent * (head + (nbits * npts) / 8 + 2);
1760 estime += nbTemp * (head + (nbits * npts) / 8 + 2);
1761 estime += nbSTemp * (head + (nbits * npts) / 8 + 2);
1764 estime += nbRain * (head + (nbits * npts) / 8 + 2);
1767 estime += nbPress * (head + (nbits * npts) / 8 + 2);
1770 estime += nbCloud * (head + (nbits * npts) / 8 + 2);
1773 estime += nbGUSTsfc * (head + (nbits * npts) / 8 + 2);
1776 estime += nbCape * (head + (nbits * npts) / 8 + 2);
1779 estime += nbwave * (head + (nbits * npts) / 8 + 2);
1781 if (m_pAltitudeData->IsChecked()) {
1783 if (m_p850hpa->IsChecked()) nbalt++;
1784 if (m_p700hpa->IsChecked()) nbalt++;
1785 if (m_p500hpa->IsChecked()) nbalt++;
1786 if (m_p300hpa->IsChecked()) nbalt++;
1789 estime += nbAltitude * nbalt * (head + (nbits * npts) / 8 + 2);
1792 *size = estime / (1024. * 1024.);
1797const wxString EncodeURL(
const wxString &uri) {
1798 static std::unordered_map<int, wxString> sEncodeMap = {
1799 {(int)
'!',
"%21"}, {(int)
'#',
"%23"}, {(int)
'$',
"%24"},
1800 {(int)
'&',
"%26"}, {(int)
'\'',
"%27"}, {(int)
'(',
"%28"},
1801 {(int)
')',
"%29"}, {(int)
'*',
"%2A"}, {(int)
'+',
"%2B"},
1802 {(int)
',',
"%2C"}, {(int)
';',
"%3B"}, {(int)
'=',
"%3D"},
1803 {(int)
'?',
"%3F"}, {(int)
'@',
"%40"}, {(int)
'[',
"%5B"},
1804 {(int)
']',
"%5D"}, {(int)
' ',
"%20"}, {(int)
'|',
"%7C"},
1805 {(int)
':',
"%3A"}, {(int)
'\n',
"%0A"}};
1808 for (
size_t i = 0; i < uri.length(); ++i) {
1810 std::unordered_map<int, wxString>::iterator iter = sEncodeMap.find((
int)ch);
1811 if (iter != sEncodeMap.end()) {
1812 encoded << iter->second;
1820void GribRequestSetting::OnSendMaiL(wxCommandEvent &event) {
1821 StopGraphicalZoneSelection();
1828 m_MailImage->SetForegroundColour(
1832 m_MailImage->SetValue(WriteMail());
1833 SetRequestDialogSize();
1838 const wxString error[] = {
1840 _(
"Before sending an email to Zygrib you have to enter your Login and "
1841 "Code.\nPlease visit www.zygrib.org/ and follow instructions..."),
1842 _(
"Too big file! zyGrib limit is 2Mb!"),
1843 _(
"Error! Max Lat lower than Min Lat or Max Lon lower than Min Lon!"),
1844 _(
"Too large area! Each side must be less than 180\u00B0!"),
1845 _(
"Too small area for this resolution!")};
1847 ::wxBeginBusyCursor();
1849 m_MailImage->SetForegroundColour(wxColor(255, 0, 0));
1850 m_AllowSend =
false;
1852 if (m_MailError_Nb) {
1853 if (m_MailError_Nb > 7) {
1854 m_MailImage->SetValue(error[1] + error[0] + error[m_MailError_Nb - 6]);
1856 if (m_MailError_Nb == 6) m_MailError_Nb = 1;
1857 m_MailImage->SetValue(error[m_MailError_Nb]);
1861 SetRequestDialogSize();
1863 ::wxEndBusyCursor();
1868 std::string mailto =
1869 (m_pMailTo->GetCurrentSelection() == SAILDOCS
1870 ? m_MailToAddresses.BeforeFirst(_T(
';'))
1871 : m_MailToAddresses.AfterFirst(_T(
';')).BeforeFirst(_T(
';')))
1873 std::string mailfrom = m_pSenderAddress->GetValue().ToStdString();
1875 std::regex mailregex(
"^([a-z0-9+_\\.-]+)@([\\da-z\\.-]+)\\.([a-z\\.]{2,6})$");
1877 if ((!mailto.empty() && !std::regex_match(mailto, mailregex)) ||
1878 (!mailfrom.empty() && !std::regex_match(mailfrom, mailregex))) {
1881 _(
"Sender or recipient e-mail address seems invalid.\nPlease correct "
1882 "it in the configuration file."),
1883 _(
"Error"), wxOK | wxICON_ERROR);
1893 new wxMailMessage((m_pMailTo->GetCurrentSelection() == SAILDOCS)
1897 EncodeURL(WriteMail()),
1901 new wxMailMessage((m_pMailTo->GetCurrentSelection() == SAILDOCS)
1910 if (mail.Send(*message, m_SendMethod)) {
1912 m_MailImage->SetValue(
1913 _(
"Your request is ready. An email is prepared in your email "
1914 "environment. \nYou have just to verify and send it...\nSave or "
1915 "Cancel to finish...or Continue..."));
1917 if (m_SendMethod == 0) {
1918 m_MailImage->SetValue(
1919 _(
"Your request is ready. An email is prepared in your email "
1920 "environment. \nYou have just to verify and send it...\nSave or "
1921 "Cancel to finish...or Continue..."));
1923 m_MailImage->SetValue(
1924 _(
"Your request was sent \n(if your system has an MTA configured and "
1925 "is able to send email).\nSave or Cancel to finish...or "
1930 m_MailImage->SetValue(
1931 _(
"Request can't be sent. Please verify your email systeme "
1932 "parameters.\nYou should also have a look at your log file.\nSave or "
1933 "Cancel to finish..."));
1937 SetRequestDialogSize();
1939 ::wxEndBusyCursor();
1944wxString GribRequestSetting::BuildXyGribUrl() {
1947 wxString::Format(
"http://grbsrv.opengribs.org/getmygribs2.php?");
1949 urlStr << wxString::Format(
"la1=%.0f", floor(
GetMinLat()));
1950 urlStr << wxString::Format(
"&la2=%.0f", ceil(
GetMaxLat()));
1951 urlStr << wxString::Format(
"&lo1=%.0f", floor(
GetMinLon()));
1952 urlStr << wxString::Format(
"&lo2=%.0f", ceil(
GetMaxLon()));
1955 urlStr << wxString::Format(
1957 xygribAtmModelList[m_selectedAtmModelIndex]
1958 ->reqName[m_xygribPanel->m_resolution_choice->GetSelection()]);
1960 urlStr << wxString::Format(
1962 xygribAtmModelList[m_selectedAtmModelIndex]
1963 ->interval[m_xygribPanel->m_interval_choice->GetSelection()]);
1965 urlStr << wxString::Format(
1966 "&days=%d", m_xygribPanel->m_duration_choice->GetSelection() + 1);
1970 wxString selStr = m_xygribPanel->m_run_choice->GetStringSelection();
1971 if (selStr.IsSameAs(
"18h",
false)) {
1972 urlStr <<
"&cyc=18";
1973 }
else if (selStr.IsSameAs(
"12h",
false)) {
1974 urlStr <<
"&cyc=12";
1975 }
else if (selStr.IsSameAs(
"6h",
false)) {
1976 urlStr <<
"&cyc=06";
1977 }
else if (selStr.IsSameAs(
"0h",
false)) {
1978 urlStr <<
"&cyc=00";
1980 urlStr <<
"&cyc=last";
1985 if (m_xygribPanel->m_wind_cbox->IsEnabled() &&
1986 m_xygribPanel->m_wind_cbox->IsChecked())
1988 if (m_xygribPanel->m_pressure_cbox->IsEnabled() &&
1989 m_xygribPanel->m_pressure_cbox->IsChecked()) {
1990 if (xygribAtmModelList[m_selectedAtmModelIndex]->altPressure) {
1996 if (m_xygribPanel->m_precipitation_cbox->IsEnabled() &&
1997 m_xygribPanel->m_precipitation_cbox->IsChecked())
1999 if (m_xygribPanel->m_cloudcover_cbox->IsEnabled() &&
2000 m_xygribPanel->m_cloudcover_cbox->IsChecked())
2002 if (m_xygribPanel->m_temperature_cbox->IsEnabled() &&
2003 m_xygribPanel->m_temperature_cbox->IsChecked())
2005 if (m_xygribPanel->m_cape_cbox->IsEnabled() &&
2006 m_xygribPanel->m_cape_cbox->IsChecked())
2008 if (m_xygribPanel->m_reflectivity_cbox->IsEnabled() &&
2009 m_xygribPanel->m_reflectivity_cbox->IsChecked())
2011 if (m_xygribPanel->m_gust_cbox->IsEnabled() &&
2012 m_xygribPanel->m_gust_cbox->IsChecked())
2016 if ((m_selectedWaveModelIndex >= 0) &&
2017 (xygribWaveModelList[m_selectedWaveModelIndex] !=
nullptr)) {
2018 wxString modelStr = wxString::Format(
2019 "&wmdl=%s", xygribWaveModelList[m_selectedWaveModelIndex]->reqName);
2020 wxString wParams =
"";
2021 if (m_xygribPanel->m_waveheight_cbox->IsChecked()) {
2024 if (m_xygribPanel->m_windwave_cbox->IsChecked()) {
2025 wParams <<
"h;d;p;";
2027 if (wParams.length() > 0) {
2028 urlStr << wxString::Format(
"%s&wpar=%s", modelStr.c_str(),
2031 urlStr <<
"&wmdl=none";
2034 urlStr <<
"&wmdl=none";
2042wxString GribRequestSetting::BuildGribFileName() {
2043 wxString selStr = m_xygribPanel->m_resolution_choice->GetStringSelection();
2044 selStr.Replace(
".",
"P");
2047 if (m_selectedWaveModelIndex < 0) {
2048 fileName = wxString::Format(
2049 "XyGrib_%s_%s_%s.grb2", wxDateTime::Now().Format(
"%F-%H-%M"),
2050 m_xygribPanel->m_atmmodel_choice->GetStringSelection(), selStr);
2052 fileName = wxString::Format(
2053 "XyGrib_%s_%s_%s_%s.grb2", wxDateTime::Now().Format(
"%F-%H-%M"),
2054 m_xygribPanel->m_atmmodel_choice->GetStringSelection(), selStr,
2055 m_xygribPanel->m_wavemodel_choice->GetStringSelection());
2067void GribRequestSetting::OnXyGribDownloadButton(wxCommandEvent &event) {
2069 if (m_downloading) {
2073 m_downloading =
false;
2074 m_download_handle = 0;
2076 wxEVT_DOWNLOAD_EVENT,
2077 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2078 m_connected =
false;
2079 m_xygribPanel->m_progress_gauge->SetValue(0);
2080 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2081 m_xygribPanel->m_status_text->SetLabelText(_(
"Download cancelled"));
2084 EnableDownloadButtons();
2085 wxTheApp->ProcessPendingEvents();
2090 if (m_gribSizeEstimate > XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB * 1024 * 1024) {
2091 m_xygribPanel->m_status_text->SetLabelText(
2092 wxString::Format(_(
"Can't download GRIB file bigger than %d MB"),
2093 (
int)XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB));
2099 MemorizeXyGribConfiguration();
2101 m_downloading =
true;
2103 EnableDownloadButtons();
2105 m_xygribPanel->m_download_button->SetLabelText(_(
"Cancel"));
2106 m_xygribPanel->m_status_text->SetLabelText(
2107 _(
"Preparing GRIB file on server..."));
2111 wxString requestUrl = BuildXyGribUrl();
2116 wxString filename = wxString::Format(
"ocpn_xygrib_%s.xml",
2117 wxDateTime::Now().Format(
"%F-%H-%M"));
2118 wxString path = m_parent.GetGribDir();
2119 path << wxFileName::GetPathSeparator();
2124 wxEVT_DOWNLOAD_EVENT,
2125 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2128 &m_download_handle);
2133 while (m_downloading) {
2134 wxTheApp->ProcessPendingEvents();
2138 if ((m_canceled) || (!m_bTransferSuccess)) {
2140 m_xygribPanel->m_status_text->SetLabelText(_(
"Grib request failed"));
2141 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2143 EnableDownloadButtons();
2151 bool readOk = xmlFile.Open(path);
2153 readOk &= xmlFile.ReadAll(&strXml);
2161 if (readOk && (((
int)strXml.find(
"\"status\":true") == wxNOT_FOUND))) {
2164 int errPos = strXml.find(
"\"message\":\"");
2165 int errEnd = strXml.find(
"\"}");
2166 if ((errPos != wxNOT_FOUND) && (errEnd != wxNOT_FOUND)) {
2168 errorStr = strXml.Mid(errPos, errEnd - errPos);
2170 errorStr =
"Unknown server error";
2173 m_xygribPanel->m_status_text->SetLabelText(
2174 wxString::Format(
"%s (%s)", _(
"Server Error"), errorStr));
2175 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2177 EnableDownloadButtons();
2182 int urlPos = strXml.find(
"\"url\":\"http:");
2183 int urlEnd = strXml.find(
".grb2\"");
2184 if ((urlPos != wxNOT_FOUND) && (urlEnd != wxNOT_FOUND)) {
2187 url = strXml.Mid(urlPos, urlEnd - urlPos);
2188 url.Replace(
"\\/",
"/");
2199 m_xygribPanel->m_status_text->SetLabelText(
2200 _(
"Error parsing XML file from server"));
2201 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2203 EnableDownloadButtons();
2207 m_xygribPanel->m_status_text->SetLabelText(_(
"Downloading GRIB file"));
2210 path = m_parent.GetGribDir();
2211 path << wxFileName::GetPathSeparator();
2212 path << BuildGribFileName();
2216 m_downloading =
true;
2220 wxEVT_DOWNLOAD_EVENT,
2221 (wxObjectEventFunction)(wxEventFunction)&GribRequestSetting::onDLEvent);
2227 while (m_downloading) {
2228 wxTheApp->ProcessPendingEvents();
2233 m_xygribPanel->m_download_button->SetLabelText(_(
"Download"));
2236 if (m_bTransferSuccess) {
2238 m_xygribPanel->m_status_text->SetLabelText(_(
"Download complete"));
2239 wxFileName fn(path);
2243 m_parent.OpenFile();
2245 if (m_parent.
pPlugIn->m_bZoomToCenterAtInit) m_parent.DoZoomToCenter();
2247 m_parent.SetDialogsStyleSizePosition(
true);
2252 m_xygribPanel->m_status_text->SetLabelText(_(
"Download failed"));
2256 EnableDownloadButtons();
2262void GribRequestSetting::OnXyGribAtmModelChoice(wxCommandEvent &event) {
2266 wxString atmModel = m_xygribPanel->m_atmmodel_choice->GetStringSelection();
2268 while ((selectedAtmModel = xygribAtmModelList[modelIndex]) !=
nullptr) {
2269 if (selectedAtmModel->name.IsSameAs(atmModel,
true)) {
2276 if (selectedAtmModel ==
nullptr) {
2277 selectedAtmModel = xygribAtmModelList[0];
2282 if (selectedAtmModel->wind)
2283 m_xygribPanel->m_wind_cbox->Enable();
2285 m_xygribPanel->m_wind_cbox->Disable();
2287 if (selectedAtmModel->gust)
2288 m_xygribPanel->m_gust_cbox->Enable();
2290 m_xygribPanel->m_gust_cbox->Disable();
2292 if (selectedAtmModel->pressure)
2293 m_xygribPanel->m_pressure_cbox->Enable();
2295 m_xygribPanel->m_pressure_cbox->Disable();
2297 if (selectedAtmModel->temperature)
2298 m_xygribPanel->m_temperature_cbox->Enable();
2300 m_xygribPanel->m_temperature_cbox->Disable();
2302 if (selectedAtmModel->cape)
2303 m_xygribPanel->m_cape_cbox->Enable();
2305 m_xygribPanel->m_cape_cbox->Disable();
2307 if (selectedAtmModel->reflectivity)
2308 m_xygribPanel->m_reflectivity_cbox->Enable();
2310 m_xygribPanel->m_reflectivity_cbox->Disable();
2312 if (selectedAtmModel->cloudCover)
2313 m_xygribPanel->m_cloudcover_cbox->Enable();
2315 m_xygribPanel->m_cloudcover_cbox->Disable();
2317 if (selectedAtmModel->precipitation)
2318 m_xygribPanel->m_precipitation_cbox->Enable();
2320 m_xygribPanel->m_precipitation_cbox->Disable();
2323 m_xygribPanel->m_resolution_choice->Clear();
2324 for (
int i = 0; i < selectedAtmModel->nbRes; i++) {
2325 m_xygribPanel->m_resolution_choice->Insert(selectedAtmModel->resolution[i],
2330 m_xygribPanel->m_duration_choice->Clear();
2331 for (
int i = 0; i < selectedAtmModel->duration; i++) {
2332 m_xygribPanel->m_duration_choice->Insert(wxString::Format(
"%d", i + 1), i);
2336 m_xygribPanel->m_interval_choice->Clear();
2337 for (
int i = 0; i < selectedAtmModel->nbInterval; i++) {
2338 m_xygribPanel->m_interval_choice->Insert(
2339 wxString::Format(
"%dh", selectedAtmModel->interval[i]), i);
2343 m_xygribPanel->m_run_choice->Clear();
2344 if (selectedAtmModel->runMask == XYGRIB_RUN_0_12) {
2345 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2346 m_xygribPanel->m_run_choice->Insert(
"12h", 1);
2347 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 2);
2349 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2350 m_xygribPanel->m_run_choice->Insert(
"6h", 1);
2351 m_xygribPanel->m_run_choice->Insert(
"12h", 2);
2352 m_xygribPanel->m_run_choice->Insert(
"18h", 3);
2353 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 4);
2356 if (modelIndex == m_parent.xyGribConfig.atmModelIndex) {
2357 ApplyXyGribConfiguration();
2359 m_selectedAtmModelIndex = modelIndex;
2360 m_xygribPanel->m_resolution_choice->SetSelection(0);
2361 m_xygribPanel->m_duration_choice->SetSelection(
2362 m_xygribPanel->m_duration_choice->GetCount() - 1);
2363 m_xygribPanel->m_interval_choice->SetSelection(0);
2364 m_xygribPanel->m_run_choice->SetSelection(
2365 m_xygribPanel->m_run_choice->GetCount() - 1);
2367 MemorizeXyGribConfiguration();
2373void GribRequestSetting::OnXyGribWaveModelChoice(wxCommandEvent &event) {
2377 wxString waveModel = m_xygribPanel->m_wavemodel_choice->GetStringSelection();
2379 while ((selectedModel = xygribWaveModelList[modelIndex]) !=
nullptr) {
2380 if (selectedModel->name.IsSameAs(waveModel,
true)) {
2387 if (selectedModel ==
nullptr) {
2389 m_selectedWaveModelIndex = -1;
2390 m_xygribPanel->m_waveheight_cbox->Disable();
2391 m_xygribPanel->m_windwave_cbox->Disable();
2392 MemorizeXyGribConfiguration();
2396 m_selectedWaveModelIndex = modelIndex;
2399 if (selectedModel->significantHeight) {
2400 m_xygribPanel->m_waveheight_cbox->Enable();
2402 m_xygribPanel->m_waveheight_cbox->Disable();
2405 if (selectedModel->windWaves) {
2406 m_xygribPanel->m_windwave_cbox->Enable();
2408 m_xygribPanel->m_windwave_cbox->Disable();
2410 MemorizeXyGribConfiguration();
2416void GribRequestSetting::OnXyGribConfigChange(wxCommandEvent &event) {
2417 MemorizeXyGribConfiguration();
2421void GribRequestSetting::InitializeXygribDialog() {
2426 m_xygribPanel->m_atmmodel_choice->Clear();
2428 while ((selectedAtmModel = xygribAtmModelList[modelIndex]) !=
nullptr) {
2429 m_xygribPanel->m_atmmodel_choice->Insert(selectedAtmModel->name,
2434 m_selectedAtmModelIndex = m_parent.xyGribConfig.atmModelIndex;
2435 selectedAtmModel = xygribAtmModelList[m_selectedAtmModelIndex];
2438 m_xygribPanel->m_wavemodel_choice->Clear();
2440 while ((selectedWaveModel = xygribWaveModelList[modelIndex]) !=
nullptr) {
2441 m_xygribPanel->m_wavemodel_choice->Insert(selectedWaveModel->name,
2446 m_xygribPanel->m_wavemodel_choice->Insert(
"None", modelIndex);
2447 m_selectedWaveModelIndex = m_parent.xyGribConfig.waveModelIndex;
2448 selectedWaveModel = xygribWaveModelList[m_selectedWaveModelIndex];
2449 if (selectedWaveModel ==
nullptr) {
2450 m_selectedWaveModelIndex = -1;
2454 m_xygribPanel->m_resolution_choice->Clear();
2455 for (
int i = 0; i < selectedAtmModel->nbRes; i++) {
2456 m_xygribPanel->m_resolution_choice->Insert(selectedAtmModel->resolution[i],
2461 m_xygribPanel->m_duration_choice->Clear();
2462 for (
int i = 0; i < selectedAtmModel->duration; i++) {
2463 m_xygribPanel->m_duration_choice->Insert(wxString::Format(
"%d", i + 1), i);
2467 m_xygribPanel->m_interval_choice->Clear();
2468 for (
int i = 0; i < selectedAtmModel->nbInterval; i++) {
2469 m_xygribPanel->m_interval_choice->Insert(
2470 wxString::Format(
"%dh", selectedAtmModel->interval[i]), i);
2474 m_xygribPanel->m_run_choice->Clear();
2475 if (selectedAtmModel->runMask == XYGRIB_RUN_0_12) {
2476 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2477 m_xygribPanel->m_run_choice->Insert(
"12h", 1);
2478 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 2);
2480 m_xygribPanel->m_run_choice->Insert(
"0h", 0);
2481 m_xygribPanel->m_run_choice->Insert(
"6h", 1);
2482 m_xygribPanel->m_run_choice->Insert(
"12h", 2);
2483 m_xygribPanel->m_run_choice->Insert(
"18h", 3);
2484 m_xygribPanel->m_run_choice->Insert(_(
"Latest"), 4);
2487 if (selectedAtmModel->wind)
2488 m_xygribPanel->m_wind_cbox->Enable();
2490 m_xygribPanel->m_wind_cbox->Disable();
2492 if (selectedAtmModel->gust)
2493 m_xygribPanel->m_gust_cbox->Enable();
2495 m_xygribPanel->m_gust_cbox->Disable();
2497 if (selectedAtmModel->pressure)
2498 m_xygribPanel->m_pressure_cbox->Enable();
2500 m_xygribPanel->m_pressure_cbox->Disable();
2502 if (selectedAtmModel->temperature)
2503 m_xygribPanel->m_temperature_cbox->Enable();
2505 m_xygribPanel->m_temperature_cbox->Disable();
2507 if (selectedAtmModel->cape)
2508 m_xygribPanel->m_cape_cbox->Enable();
2510 m_xygribPanel->m_cape_cbox->Disable();
2512 if (selectedAtmModel->reflectivity)
2513 m_xygribPanel->m_reflectivity_cbox->Enable();
2515 m_xygribPanel->m_reflectivity_cbox->Disable();
2517 if (selectedAtmModel->cloudCover)
2518 m_xygribPanel->m_cloudcover_cbox->Enable();
2520 m_xygribPanel->m_cloudcover_cbox->Disable();
2522 if (selectedAtmModel->precipitation)
2523 m_xygribPanel->m_precipitation_cbox->Enable();
2525 m_xygribPanel->m_precipitation_cbox->Disable();
2527 if ((selectedWaveModel !=
nullptr) && (selectedWaveModel->significantHeight))
2528 m_xygribPanel->m_waveheight_cbox->Enable();
2530 m_xygribPanel->m_waveheight_cbox->Disable();
2532 if ((selectedWaveModel !=
nullptr) && (selectedWaveModel->windWaves))
2533 m_xygribPanel->m_windwave_cbox->Enable();
2535 m_xygribPanel->m_windwave_cbox->Disable();
2537 ApplyXyGribConfiguration();
2544void GribRequestSetting::ApplyXyGribConfiguration() {
2545 m_xygribPanel->m_atmmodel_choice->SetSelection(
2546 m_parent.xyGribConfig.atmModelIndex);
2547 m_xygribPanel->m_wavemodel_choice->SetSelection(
2548 m_parent.xyGribConfig.waveModelIndex);
2550 m_xygribPanel->m_wind_cbox->SetValue(m_parent.xyGribConfig.wind);
2551 m_xygribPanel->m_gust_cbox->SetValue(m_parent.xyGribConfig.gust);
2552 m_xygribPanel->m_pressure_cbox->SetValue(m_parent.xyGribConfig.pressure);
2553 m_xygribPanel->m_temperature_cbox->SetValue(
2554 m_parent.xyGribConfig.temperature);
2555 m_xygribPanel->m_cape_cbox->SetValue(m_parent.xyGribConfig.cape);
2556 m_xygribPanel->m_reflectivity_cbox->SetValue(
2557 m_parent.xyGribConfig.reflectivity);
2558 m_xygribPanel->m_cloudcover_cbox->SetValue(m_parent.xyGribConfig.cloudCover);
2559 m_xygribPanel->m_precipitation_cbox->SetValue(
2560 m_parent.xyGribConfig.precipitation);
2561 m_xygribPanel->m_waveheight_cbox->SetValue(m_parent.xyGribConfig.waveHeight);
2562 m_xygribPanel->m_windwave_cbox->SetValue(m_parent.xyGribConfig.windWaves);
2563 m_xygribPanel->m_resolution_choice->SetSelection(
2564 m_parent.xyGribConfig.resolutionIndex);
2565 m_xygribPanel->m_duration_choice->SetSelection(
2566 m_parent.xyGribConfig.durationIndex);
2567 m_xygribPanel->m_interval_choice->SetSelection(
2568 m_parent.xyGribConfig.intervalIndex);
2569 m_xygribPanel->m_run_choice->SetSelection(m_parent.xyGribConfig.runIndex);
2571 UpdateGribSizeEstimate();
2578void GribRequestSetting::MemorizeXyGribConfiguration() {
2579 m_parent.xyGribConfig.atmModelIndex =
2580 m_xygribPanel->m_atmmodel_choice->GetSelection();
2581 m_parent.xyGribConfig.waveModelIndex =
2582 m_xygribPanel->m_wavemodel_choice->GetSelection();
2584 m_parent.xyGribConfig.wind = m_xygribPanel->m_wind_cbox->IsChecked();
2585 m_parent.xyGribConfig.gust = m_xygribPanel->m_gust_cbox->IsChecked();
2586 m_parent.xyGribConfig.pressure = m_xygribPanel->m_pressure_cbox->IsChecked();
2587 m_parent.xyGribConfig.temperature =
2588 m_xygribPanel->m_temperature_cbox->IsChecked();
2589 m_parent.xyGribConfig.cape = m_xygribPanel->m_cape_cbox->IsChecked();
2590 m_parent.xyGribConfig.reflectivity =
2591 m_xygribPanel->m_reflectivity_cbox->IsChecked();
2592 m_parent.xyGribConfig.cloudCover =
2593 m_xygribPanel->m_cloudcover_cbox->IsChecked();
2594 m_parent.xyGribConfig.precipitation =
2595 m_xygribPanel->m_precipitation_cbox->IsChecked();
2596 m_parent.xyGribConfig.waveHeight =
2597 m_xygribPanel->m_waveheight_cbox->IsChecked();
2598 m_parent.xyGribConfig.windWaves = m_xygribPanel->m_windwave_cbox->IsChecked();
2600 m_parent.xyGribConfig.resolutionIndex =
2601 m_xygribPanel->m_resolution_choice->GetSelection();
2602 m_parent.xyGribConfig.durationIndex =
2603 m_xygribPanel->m_duration_choice->GetSelection();
2604 m_parent.xyGribConfig.intervalIndex =
2605 m_xygribPanel->m_interval_choice->GetSelection();
2606 m_parent.xyGribConfig.runIndex = m_xygribPanel->m_run_choice->GetSelection();
2608 UpdateGribSizeEstimate();
2614void GribRequestSetting::UpdateGribSizeEstimate() {
2619 if (!m_xygribPanel->m_resolution_choice->GetStringSelection().ToCDouble(
2621 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2624 if (!m_xygribPanel->m_duration_choice->GetStringSelection().ToCLong(&days)) {
2625 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2628 wxString intvStr = m_xygribPanel->m_interval_choice->GetStringSelection();
2629 intvStr.Replace(
"h",
"");
2630 if (!intvStr.ToCLong(&interval)) {
2631 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2636 m_xygribPanel->m_sizeestimate_text->SetLabel(
"Unknown");
2645 int npts = (int)(ceil(fabs(xmax - xmin) / resolution) *
2646 ceil(fabs(ymax - ymin) / resolution));
2649 int nbrec = (int)days * 24 / interval + 1;
2651 int nbPress = (m_xygribPanel->m_pressure_cbox->IsChecked() &&
2652 m_xygribPanel->m_pressure_cbox->IsEnabled())
2655 int nbWind = (m_xygribPanel->m_wind_cbox->IsChecked() &&
2656 m_xygribPanel->m_wind_cbox->IsEnabled())
2659 int nbRain = (m_xygribPanel->m_precipitation_cbox->IsChecked() &&
2660 m_xygribPanel->m_precipitation_cbox->IsEnabled())
2663 int nbCloud = (m_xygribPanel->m_cloudcover_cbox->IsChecked() &&
2664 m_xygribPanel->m_cloudcover_cbox->IsEnabled())
2667 int nbTemp = (m_xygribPanel->m_temperature_cbox->IsChecked() &&
2668 m_xygribPanel->m_temperature_cbox->IsEnabled())
2672 int nbCAPEsfc = (m_xygribPanel->m_cape_cbox->IsChecked() &&
2673 m_xygribPanel->m_cape_cbox->IsEnabled())
2676 int nbReflectivity = (m_xygribPanel->m_reflectivity_cbox->IsChecked() &&
2677 m_xygribPanel->m_reflectivity_cbox->IsEnabled())
2680 int nbGUSTsfc = (m_xygribPanel->m_gust_cbox->IsChecked() &&
2681 m_xygribPanel->m_gust_cbox->IsEnabled())
2691 estimate += nbWind * (head + (nbits * npts) / 8 + 2);
2694 estimate += nbTemp * (head + (nbits * npts) / 8 + 2);
2700 estimate += nbRain * (head + 24 + (nbits * npts) / 8 + 2);
2703 estimate += nbPress * (head + (nbits * npts) / 8 + 2);
2706 estimate += nbCloud * (head + 24 + (nbits * npts) / 8 + 2);
2709 estimate += nbReflectivity * (head + (nbits * npts) / 8 + 2);
2712 estimate += nbCAPEsfc * (head + (nbits * npts) / 8 + 2);
2715 estimate += nbGUSTsfc * (head + (nbits * npts) / 8 + 2);
2719 int atmEstimate = estimate;
2723 if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2726 npts = (int)(ceil(fabs(xmax - xmin) / 0.5) * ceil(fabs(ymax - ymin) / 0.5));
2727 nbrec = (int)fmin(8, days) * 24 / interval + 1;
2728 }
else if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2732 (int)(ceil(fabs(xmax - xmin) / 0.25) * ceil(fabs(ymax - ymin) / 0.25));
2733 nbrec = (int)fmin(8, days) * 24 / interval + 1;
2734 }
else if (m_xygribPanel->m_wavemodel_choice->GetStringSelection().IsSameAs(
2738 (int)(ceil(fabs(xmax - xmin) / 0.05) * ceil(fabs(ymax - ymin) / 0.1));
2739 nbrec = (int)fmin(4, days) * 24 / interval + 1;
2745 if (m_xygribPanel->m_waveheight_cbox->IsChecked()) {
2747 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2750 if (m_xygribPanel->m_windwave_cbox->IsChecked()) {
2752 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2754 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2756 estimate += nbrec * (head + (nbits * npts) / 8 + 2);
2759 int wavEstimate = estimate - atmEstimate;
2761 wavEstimate = wavEstimate * 0.6;
2763 estimate = atmEstimate + wavEstimate;
2766 estimate = estimate * 0.65;
2768 wxString warningStr =
"";
2769 if (estimate / (1024 * 1024) > XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB) {
2770 warningStr = wxString::Format(
"(Warning GRIB exceeds %d MB limit)",
2771 XYGRIB_MAX_DOWNLOADABLE_GRIB_SIZE_MB);
2774 m_xygribPanel->m_sizeestimate_text->SetLabel(
2775 wxString::Format(
"%d kB %s", estimate / 1024, warningStr));
2777 m_gribSizeEstimate = estimate;
GRIB Data Visualization and Rendering Factory.
int m_SavedZoneSelMode
Persisted version of the GRIB area selection mode.
int m_ZoneSelMode
Tracks the current state of GRIB area selection for zone coordinates.
GRIB Weather Data Request and Download Management.
@ WORLD
Global forecast downloads (e.g., GFS)
@ XYGRIB
Downloads from XyGrib service.
@ NONE
No download source selected.
@ LOCAL_CATALOG
Downloads from configured catalogs.
@ LOCAL
Downloads from local sources.
#define SAVEDZONE
Save zone.
#define MANSELECT
Manual selection mode.
#define AUTOSELECT
Automatic selection mode.
@ AUTO_SELECTION
Area automatically set from current viewport bounds.
@ DRAW_SELECTION
Manual mode has been selected.
@ START_SELECTION
User has clicked Shift + Left click and is drawing the bounding box by dragging the mouse.
@ COMPLETE_SELECTION
Selection box completed in manual mode, coordinates have been captured after the user has released th...
@ SAVED_SELECTION
Area loaded from previously saved coordinates.
XyGrib Model Configuration and Definitions.
void SetRequestButtonBitmap(int type)
Set the icon and tooltip for the download request button.
wxString m_grib_dir
Directory containing GRIB files.
grib_pi * pPlugIn
Plugin instance that owns this control bar.
wxArrayString m_file_names
List of GRIB filenames being displayed.
Class GribRequestSettingBase.
wxButton * m_rButtonCancel
Button to Cancel a request to download, close the dialog without saving the configuration.
wxSpinCtrl * m_spMaxLon
A spinner for the max longitude of the bounding box for downloads.
wxSpinCtrl * m_spMaxLat
A spinner for the max latitude of the bounding box for downloads.
wxRadioButton * m_rbManualSelect
Radio button selected to indicate the download area is based on the area selected by the user.
wxRadioButton * m_rbCurrentView
Radio button selected to indicate the download area is based on the visible area of the chart in the ...
wxSpinCtrl * m_spMinLat
A spinner for the min latitude of the bounding box for downloads.
wxButton * m_rButtonApply
Button to Save the "download request" configuration.
wxButton * m_rButtonYes
Button to Send a download request through e-mail.
wxSpinCtrl * m_spMinLon
A spinner for the min longitude of the bounding box for downloads.
Manages GRIB file request configuration and downloads.
double m_StartLat
The latitude at the starting point of the bounding box.
double GetMinLat() const
Get the minimum latitude of the bounding box for the download request.
double GetMaxLat() const
Get the maximum latitude of the bounding box for the download request.
double m_Lat
The latitude at the mouse cursor while drawing a bounding box.
void OnVpUnderMouseChange(PlugIn_ViewPort *vp)
Callback invoked when the view port under mouse has changed.
bool RenderGlZoneOverlay()
Renders the GRIB area selection overlay using OpenGL.
bool RenderZoneOverlay(wxDC &dc)
Renders the GRIB area selection overlay using standard device context.
double m_Lon
The longitude at the mouse cursor while drawing a bounding box.
wxPoint m_StartPoint
Starting point of the bounding box in physical pixels.
bool DoRenderZoneOverlay()
Draws the GRIB area selection overlay on the chart.
bool MouseEventHook(wxMouseEvent &event)
Intercepts mouse events to handle GRIB area selection.
void OnVpWithFocusChange(PlugIn_ViewPort *vp)
Callback invoked when the focused view port has changed, such as in multi-chart mode when user switch...
PlugIn_ViewPort * m_VpMouse
The viewport under the mouse.
ZoneSelectionRenderState m_RenderSelectionZoneState
Current state of the bounding box overlay rendering.
double GetMaxLon() const
Get the maximum longitude of the bounding box for the download request.
PlugIn_ViewPort * m_VpFocus
The viewport currently in focus.
double m_StartLon
The longitude at the starting point of the bounding box.
double GetMinLon() const
Get the minimum longitude of the bounding box for the download request.
Contains view parameters and status information for a chart display viewport.
double lon_max
Maximum longitude of the viewport.
double lat_max
Maximum latitude of the viewport.
double lon_min
Minimum longitude of the viewport.
double lat_min
Minimum latitude of the viewport.
int Parse(const wxString &doc, wxJSONValue *val)
Parse the JSON document.
The JSON value class implementation.
int Size() const
Return the size of the array or map stored in this value.
bool HasMember(unsigned index) const
Return TRUE if the object contains an element at the specified index.
wxString AsString() const
Return the stored value as a wxWidget's string.
Email Request System for GRIB Data.
GRIB Weather Data Plugin for OpenCPN.
@ OCPN_DL_EVENT_TYPE_PROGRESS
Download progress update.
@ OCPN_DL_EVENT_TYPE_END
Download has completed.
@ OCPN_DL_NO_ERROR
Download completed successfully.
wxFont * OCPNGetFont(wxString TextElement, int default_size)
Gets a font for UI elements.
wxFileConfig * GetOCPNConfigObject()
Gets OpenCPN's configuration object.
void GetCanvasPixLL(PlugIn_ViewPort *vp, wxPoint *pp, double lat, double lon)
Converts lat/lon to canvas physical pixel coordinates.
void DimeWindow(wxWindow *win)
Applies system color scheme to window.
int GetCanvasIndexUnderMouse()
Gets index of chart canvas under mouse cursor.
double OCPN_GetWinDIPScaleFactor()
Gets Windows-specific DPI scaling factor.
void RequestRefresh(wxWindow *win)
Requests window refresh.
void GetCanvasLLPix(PlugIn_ViewPort *vp, wxPoint p, double *plat, double *plon)
Converts canvas physical pixel coordinates to lat/lon.
OpenGL Platform Abstraction Layer.
void OCPN_cancelDownloadFileBackground(long handle)
Cancels a background download.
int OCPNMessageBox_PlugIn(wxWindow *parent, const wxString &message, const wxString &caption, int style, int x, int y)
Shows a message box dialog.
_OCPN_DLStatus OCPN_downloadFileBackground(const wxString &url, const wxString &outputFile, wxEvtHandler *handler, long *handle)
Asynchronously downloads a file in the background.