void WeatherRouting::Render(ocpnDC &dc, PlugIn_ViewPort &vp) { if(!dc.GetDC()) { glPushAttrib(GL_LINE_BIT | GL_ENABLE_BIT | GL_HINT_BIT ); //Save state glEnable( GL_LINE_SMOOTH ); glEnable( GL_BLEND ); glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); glHint( GL_LINE_SMOOTH_HINT, GL_NICEST ); } wxDateTime time = m_ConfigurationDialog.m_GribTimelineTime; if(!time.IsValid()) time = wxDateTime::Now(); RouteMapOverlay *routemapoverlay = CurrentRouteMap(); for(int i=0; i<m_lWeatherRoutes->GetItemCount(); i++) { WeatherRoute *weatherroute = reinterpret_cast<WeatherRoute*>(wxUIntToPtr(m_lWeatherRoutes->GetItemData(i))); if(weatherroute->routemapoverlay->m_bEndRouteVisible) weatherroute->routemapoverlay->Render(time, m_SettingsDialog, dc, vp, true); } if(routemapoverlay) routemapoverlay->Render(time, m_SettingsDialog, dc, vp, false); m_ConfigurationBatchDialog.Render(dc, vp); if(!dc.GetDC()) glPopAttrib(); }
void WeatherRouting::OnWeatherRouteSelected( wxListEvent& event ) { GetParent()->Refresh(); RouteMapOverlay *routemapoverlay = CurrentRouteMap(); if(routemapoverlay) { m_tHideConfiguration.Stop(); m_bSkipUpdateCurrentItem = true; m_ConfigurationDialog.SetConfiguration(routemapoverlay->GetConfiguration()); m_bSkipUpdateCurrentItem = false; } else m_tHideConfiguration.Start(25, true); if(m_StatisticsDialog.IsShown()) m_StatisticsDialog.SetRouteMapOverlay(routemapoverlay); if(m_ReportDialog.IsShown()) m_ReportDialog.SetRouteMapOverlay(routemapoverlay); if(m_ConfigurationBatchDialog.IsShown()) m_ConfigurationBatchDialog.Reset(); SetEnableConfigurationMenu(); }
void WeatherRouting::SetConfigurationRoute(RouteMapConfiguration configuration, WeatherRoute *weatherroute) { if(m_bSkipUpdateCurrentItem) return; RouteMapOverlay *rmo = weatherroute->routemapoverlay; for(std::list<RouteMapOverlay*>::iterator it = m_RunningRouteMaps.begin(); it != m_RunningRouteMaps.end(); it++) if(*it == rmo) (*it)->Stop(); rmo->SetConfiguration(configuration); weatherroute->Update(); for(long index = 0; index<m_lWeatherRoutes->GetItemCount(); index++) { WeatherRoute *wr = reinterpret_cast<WeatherRoute*> (wxUIntToPtr(m_lWeatherRoutes->GetItemData(index))); if(weatherroute == wr) { UpdateItem(index); break; } } }
void WeatherRouting::OnEditConfiguration() { RouteMapOverlay *routemapoverlay = CurrentRouteMap(true); if(routemapoverlay) { m_ConfigurationDialog.Show(); /* if boat filename doesn't exist open boat dialog immediately */ if(!wxFileName::FileExists(routemapoverlay->GetConfiguration().boatFileName)) m_ConfigurationDialog.EditBoat(); } }
void WeatherRouting::GenerateBatch() { RouteMapOverlay *routemapoverlay = CurrentRouteMap(true); if(!routemapoverlay) { wxMessageDialog mdlg(this, _("Must select a configuration to generate from"), _("Weather Routing"), wxOK | wxICON_ERROR); mdlg.ShowModal(); return; } RouteMapConfiguration configuration = routemapoverlay->GetConfiguration(); ConfigurationBatchDialog &dlg = m_ConfigurationBatchDialog; wxTimeSpan StartSpan, StartSpacingSpan; double days, hours; dlg.m_tStartDays->GetValue().ToDouble(&days); StartSpan = wxTimeSpan::Days(days); dlg.m_tStartHours->GetValue().ToDouble(&hours); StartSpan += wxTimeSpan::Hours(hours); dlg.m_tStartSpacingDays->GetValue().ToDouble(&days); StartSpacingSpan = wxTimeSpan::Days(days); dlg.m_tStartSpacingHours->GetValue().ToDouble(&hours); StartSpacingSpan += wxTimeSpan::Hours(hours); wxDateTime EndTime = configuration.StartTime+StartSpan; for(; configuration.StartTime <= EndTime; configuration.StartTime += StartSpacingSpan) { for(std::vector<BatchSource*>::iterator it = dlg.sources.begin(); it != dlg.sources.end(); it++) { configuration.Start = (*it)->Name; for(std::list<BatchDestination*>::iterator it2 = (*it)->destinations.begin(); it2 != (*it)->destinations.end(); it2++) { configuration.End = (*it2)->Name; for(unsigned int boatindex = 0; boatindex < dlg.m_lBoats->GetCount(); boatindex++) { configuration.boatFileName = dlg.m_lBoats->GetString(boatindex); AddConfiguration(configuration); } } } } DeleteRouteMap(routemapoverlay); }
void WeatherRouting::OnGoTo( wxCommandEvent& event ) { RouteMapOverlay *rmo = CurrentRouteMap(true); if(rmo) { RouteMapConfiguration config = rmo->GetConfiguration(); double distance; DistanceBearingMercator_Plugin(config.StartLat, config.StartLon, config.EndLat, config.EndLon, NULL, &distance); JumpToPosition(config.StartLat, config.StartLon, .25/distance); } }
void WeatherRouting::Export(RouteMapOverlay &routemapoverlay) { std::list<PlotData> plotdata = routemapoverlay.GetPlotData(); if(plotdata.size() == 0) { wxMessageDialog mdlg(this, _("Empty Route, nothing to export\n"), _("Weather Routing"), wxOK | wxICON_WARNING); mdlg.ShowModal(); return; } PlugIn_Track* newTrack = new PlugIn_Track; newTrack->m_NameString = _("Weather Route"); for(std::list<PlotData>::iterator it = plotdata.begin(); it != plotdata.end(); it++) { PlugIn_Waypoint* newPoint = new PlugIn_Waypoint ((*it).lat, (*it).lon, _T("circle"), _("Weather Route Point")); newPoint->m_CreateTime = (*it).time; newTrack->pWaypointList->Append(newPoint); } AddPlugInTrack(newTrack); GetParent()->Refresh(); }
void WeatherRouting::AddConfiguration(RouteMapConfiguration configuration) { m_ConfigurationDialog.EditBoat(); // ???? WeatherRoute *weatherroute = new WeatherRoute; RouteMapOverlay *routemapoverlay = weatherroute->routemapoverlay; routemapoverlay->SetConfiguration(configuration); routemapoverlay->Reset(); weatherroute->Update(); m_WeatherRoutes.push_back(weatherroute); // Test WXOSX Crash hier wxListItem item; item.SetData(weatherroute); UpdateItem(m_lWeatherRoutes->InsertItem(item)); // Crash m_mDeleteAll->Enable(); m_mComputeAll->Enable(); m_mExportAll->Enable(); }
void ReportDialog::GenerateRoutesReport() { if(!m_bReportStale) return; m_bReportStale = false; /* sort configurations interate over each group of configurations with the same start and end to determine best and worst times, and cyclone crossings to determine cyclone times */ std::map<wxString, std::list<RouteMapOverlay *> > routes; for(std::list<WeatherRoute*>::iterator it = m_WeatherRouting.m_WeatherRoutes.begin(); it != m_WeatherRouting.m_WeatherRoutes.end(); it++) { if(!(*it)->routemapoverlay->ReachedDestination()) continue; wxString route_string = (*it)->Start + _T(" - ") + (*it)->End; std::list<RouteMapOverlay *> overlays = routes[route_string]; overlays.push_back((*it)->routemapoverlay); routes[route_string] = overlays; } if(routes.size() == 0) { m_htmlRoutesReport->SetPage(_("No routes to report yet.")); return; } wxString page; for(std::map<wxString, std::list<RouteMapOverlay *> >::iterator it = routes.begin(); it != routes.end(); it++) { std::list<RouteMapOverlay *> overlays = it->second; if (overlays.begin() == overlays.end()) { // XXX not possible? but shut up compilers warnings continue; } RouteMapOverlay *first = *overlays.begin(); RouteMapConfiguration c = first->GetConfiguration(); page += _T("<p>"); page += c.Start + _T(" ") + _("to") + _T(" ") + c.End + _T(" ") + wxString::Format (_T("(%ld ") + wxString(_("configurations")) + _T(")\n"), overlays.size()); /* determine fastest time */ wxTimeSpan fastest_time; RouteMapOverlay *fastest; std::multimap< wxDateTime, RouteMapOverlay * > sort_by_start; bool any_bad = false; bool any_good = false; for(std::list<RouteMapOverlay *>::iterator it2 = overlays.begin(); it2 != overlays.end(); it2++) { RouteMapOverlay *r = *it2; wxTimeSpan current_time = r->EndTime() - r->StartTime(); sort_by_start.insert(std::pair< wxDateTime, RouteMapOverlay * >(r->StartTime() , r)); if(r == first || current_time < fastest_time) { fastest_time = current_time; fastest = r; } if (r->RouteInfo(RouteMapOverlay::PERCENTAGE_UPWIND) > 50) { any_bad = true; } else { any_good = true; } } page += _("<dt>Fastest configuration ") + FormatTime(fastest->StartTime()); page += wxString(_T(" ")) + _("avg speed") + wxString::Format (_T(": %.2f "), fastest->RouteInfo(RouteMapOverlay::AVGSPEED)) + _("knots"); /* determine best times if upwind percentage is below 50 */ page += _T("<dt>"); page += _("Best Times (mostly downwind)") + wxString(_T(": ")); if (any_good == false) { // no downwind route page += _("none"); } else if (any_bad == false) { // all routes are downwind page += _("any"); } else { bool first_print = true; std::multimap< wxDateTime, RouteMapOverlay * > reduce_by_start; // merge downwind routes in bigger interval // assume most routes with same start time are of same kind (downwind or upwind) std::multimap< wxDateTime, RouteMapOverlay * >::iterator it = sort_by_start.begin(); while (it != sort_by_start.end() ) { // remove first upwind routes, from any_good test there's at least one downwind route for(; it != sort_by_start.end(); it++) { RouteMapOverlay *r = it->second; if (r->RouteInfo(RouteMapOverlay::PERCENTAGE_UPWIND) <= 50) { break; } } if (it == sort_by_start.end()) break; RouteMapOverlay *r = it->second; wxDateTime s = DisplayedTime(r->StartTime()); wxDateTime e = DisplayedTime(r->EndTime()); // merge downwind for(; it != sort_by_start.end(); it++) { RouteMapOverlay *r = it->second; if (r->RouteInfo(RouteMapOverlay::PERCENTAGE_UPWIND) > 50) { break; } e = r->EndTime(); } if(first_print) first_print = false; else page += _(" and "); page += s.Format(_T("%d %B ")) + _("to") + e.Format(_T(" %d %B")); } } // CUSTOMIZATION // Display the best option to travel in order // to get the most comfortable sailing page += _T("<dt>"); page += _("Best Sailing Comfort") + wxString(_T(": ")); wxDateTime best_comfort_date; int best_sailing_comfort = 6; for(std::multimap< wxDateTime, RouteMapOverlay * >::iterator it3 = sort_by_start.begin(); it3 != sort_by_start.end(); it3++) { RouteMapOverlay *r = it3->second; if (!best_comfort_date.IsValid() || (best_comfort_date < r->StartTime() && best_sailing_comfort > r->RouteInfo(RouteMapOverlay::COMFORT))) { best_comfort_date = r->StartTime(); best_sailing_comfort = r->RouteInfo(RouteMapOverlay::COMFORT); } } page += RouteMapOverlay::sailingConditionText(best_sailing_comfort); page += _T(" on "); page += FormatTime(best_comfort_date); page += _T("<dt>"); page += _("Cyclones") + wxString(_T(": ")); wxProgressDialog progressdialog(_("Weather Routing"), _("Calculating Cyclone Crossings"), overlays.size(), this, wxPD_ELAPSED_TIME); int pdi = 0; int cyclonemonths[12] = {0}; std::list<RouteMapOverlay *> cyclone_safe_routes; bool allsafe = true, nonesafe = true; for(std::list<RouteMapOverlay *>::iterator it2 = overlays.begin(); it2 != overlays.end(); it2++) { switch((*it2)->Cyclones(cyclonemonths)) { case -1: page += _("Climatology data unavailable."); goto cyclonesfailed; case 0: cyclone_safe_routes.push_back(*it2); nonesafe = false; default: cyclone_safe_routes.push_back(NULL); allsafe = false; } progressdialog.Update(pdi++); } int i, j; for(i=0, j=11; i<12; j=i++) /* get first cyclone month */ if(cyclonemonths[i] && !cyclonemonths[j]) { int lm = i; page += wxDateTime::GetMonthName((wxDateTime::Month)i); for(int k=i+1, l=i; ; l = k++) { if(k==12) k = 0; if(k == i) break; if(cyclonemonths[k] && !cyclonemonths[l]) { page += _(" and ") + wxDateTime::GetMonthName((wxDateTime::Month)k); lm = k; } else if(!cyclonemonths[k] && cyclonemonths[l] && l!=lm) page += _(" to ") + wxDateTime::GetMonthName((wxDateTime::Month)l); } goto had_some_cyclones; } if(cyclonemonths[0]) page += _("all months"); else page += _("none"); had_some_cyclones:; page += _T("<dt>"); if(allsafe) page += _("All routes are safe from cyclones."); else if(nonesafe) page += _("No routes found to be safe from cyclones."); else { page += _("Start times for cyclone safe routes: "); /* note: does not merge beginning and end of linked list for safe times, this sometimes might be nice, but they will be in different years. */ bool first = true; for(std::list<RouteMapOverlay *>::iterator it2 = cyclone_safe_routes.begin(); it2 != cyclone_safe_routes.end(); it2++) { if(!*it2) continue; if(!first) page += _(" and "); first = false; page += DisplayedTime((*it2)->StartTime()).Format(_T("%x")); if(++it2 == cyclone_safe_routes.end()) break; if(!*it2) continue; while(*it2 && ++it2 != cyclone_safe_routes.end()); it2--; page += _(" to ") + DisplayedTime((*it2)->StartTime()).Format(_T("%x")); } } cyclonesfailed:; } m_htmlRoutesReport->SetPage(page); }
void WeatherRouting::OnComputationTimer( wxTimerEvent & ) { bool update = false; for(std::list<RouteMapOverlay*>::iterator it = m_RunningRouteMaps.begin(); it != m_RunningRouteMaps.end(); ) { RouteMapOverlay *routemapoverlay = *it; if(!routemapoverlay->Running()) { UpdateRouteMap(routemapoverlay); it = m_RunningRouteMaps.erase(it); m_gProgress->SetValue(m_RoutesToRun - m_WaitingRouteMaps.size() - m_RunningRouteMaps.size()); update = true; /* update report if needed */ if(m_ReportDialog.IsShown()) { if(routemapoverlay == CurrentRouteMap()) m_ReportDialog.SetRouteMapOverlay(routemapoverlay); } continue; } else it++; /* get a new grib for the route map if needed */ if(routemapoverlay->NeedsGrib()) { m_RouteMapOverlayNeedingGrib = routemapoverlay; routemapoverlay->RequestGrib(routemapoverlay->NewTime()); m_RouteMapOverlayNeedingGrib = NULL; } } if((int)m_RunningRouteMaps.size() < m_SettingsDialog.m_sConcurrentThreads->GetValue() && m_WaitingRouteMaps.size()) { RouteMapOverlay *routemapoverlay = m_WaitingRouteMaps.front(); m_WaitingRouteMaps.pop_front(); routemapoverlay->Start(); UpdateRouteMap(routemapoverlay); m_RunningRouteMaps.push_back(routemapoverlay); update = true; } static int cycles; /* don't refresh all the time */ if(++cycles > 25 && CurrentRouteMap() && CurrentRouteMap()->Updated()) { cycles = 0; m_StatisticsDialog.SetRunTime(m_RunTime += wxDateTime::Now() - m_StartTime); if(m_StatisticsDialog.IsShown()) m_StatisticsDialog.SetRouteMapOverlay(CurrentRouteMap()); m_StartTime = wxDateTime::Now(); GetParent()->Refresh(); } if(update) UpdateStates(); if(m_RunningRouteMaps.size()) { /* todo, instead of respawning the funky timer here, maybe we can do it from the thread instead to eliminate the delay */ m_tCompute.Start(25, true); return; } Stop(); }
void ReportDialog::GenerateRoutesReport() { if(!m_bReportStale) return; m_bReportStale = false; /* sort configurations interate over each group of configurations with the same start and end to determine best and worst times, and cyclone crossings to determine cyclone times */ std::map<wxString, std::list<RouteMapOverlay *> > routes; for(std::list<WeatherRoute*>::iterator it = m_WeatherRouting.m_WeatherRoutes.begin(); it != m_WeatherRouting.m_WeatherRoutes.end(); it++) { if(!(*it)->routemapoverlay->ReachedDestination()) continue; wxString route_string = (*it)->Start + _T(" - ") + (*it)->End; std::list<RouteMapOverlay *> overlays = routes[route_string]; overlays.push_back((*it)->routemapoverlay); routes[route_string] = overlays; } if(routes.size() == 0) { m_htmlRoutesReport->SetPage(_("No routes to report yet.")); return; } wxString page; for(std::map<wxString, std::list<RouteMapOverlay *> >::iterator it = routes.begin(); it != routes.end(); it++) { std::list<RouteMapOverlay *> overlays = it->second; RouteMapOverlay *first = *overlays.begin(); RouteMapConfiguration c = first->GetConfiguration(); page += _T("<p>"); page += c.Start + _T(" ") + _("to") + _T(" ") + c.End + _T(" ") + wxString::Format (_T("(%ld ") + wxString(_("configurations")) + _T(")\n"), overlays.size()); /* determine fastest time */ wxTimeSpan fastest_time; RouteMapOverlay *fastest = NULL; for(std::list<RouteMapOverlay *>::iterator it2 = overlays.begin(); it2 != overlays.end(); it2++) { wxTimeSpan current_time = ((*it2)->EndTime() - (*it2)->StartTime()); if(*it2 == first || current_time < fastest_time) { fastest_time = current_time; fastest = *it2; } } page += _("<dt>Fastest configuration ") + fastest->StartTime().Format(_T("%x")); page += wxString(_T(" ")) + _("avg speed") + wxString::Format (_T(": %.2f knots"), fastest->RouteInfo(RouteMapOverlay::AVGSPEED)); /* determine best times if upwind percentage is below 50 */ page += _T("<dt>"); page += _("Best Times (mostly downwind)") + wxString(_T(": ")); bool last_bad, any_bad, any_good = false, first_print = true; wxDateTime best_time_start; std::list<RouteMapOverlay *>::iterator it2, it2end = overlays.begin(), prev; last_bad = overlays.back()->RouteInfo(RouteMapOverlay::PERCENTAGE_UPWIND) > 50; for(it2 = overlays.begin(); it2 != overlays.end(); it2++) if((*it2)->RouteInfo(RouteMapOverlay::PERCENTAGE_UPWIND) > 50) { any_bad = last_bad = true; } else { if(!best_time_start.IsValid() && last_bad) { best_time_start = (*it2)->StartTime(); it2end = it2; it2++; break; } last_bad = false; } if(it2 == overlays.end()) it2++; for(;;) { if(it2 == it2end) break; it2++; if(it2 == overlays.end()) it2++; if((*it2)->RouteInfo(RouteMapOverlay::PERCENTAGE_UPWIND) > 50) { if(!last_bad) { prev = it2; prev--; if(prev == overlays.end()) prev--; if(first_print) first_print = false; else page += _(" and "); page += best_time_start.Format(_T("%d %B ")) + _("to") + (*prev)->EndTime().Format(_T(" %d %B")); } last_bad = any_bad = true; } else { if(last_bad) best_time_start = (*it2)->StartTime(); last_bad = false; any_good = true; } } if(!any_bad) page += _("any"); else if(!any_good) page += _("none"); page += _T("<dt>"); page += _("Cyclones") + wxString(_T(": ")); wxProgressDialog progressdialog(_("Weather Routing"), _("Calculating Cyclone Crossings"), overlays.size(), this, wxPD_ELAPSED_TIME); int pdi = 0; int cyclonemonths[12] = {0}; std::list<RouteMapOverlay *> cyclone_safe_routes; bool allsafe = true, nonesafe = true; for(it2 = overlays.begin(); it2 != overlays.end(); it2++) { switch((*it2)->Cyclones(cyclonemonths)) { case -1: page += _("Climatology data unavailable."); goto cyclonesfailed; case 0: cyclone_safe_routes.push_back(*it2); nonesafe = false; default: cyclone_safe_routes.push_back(NULL); allsafe = false; } progressdialog.Update(pdi++); } int i, j; for(i=0, j=11; i<12; j=i++) /* get first cyclone month */ if(cyclonemonths[i] && !cyclonemonths[j]) { int lm = i; page += wxDateTime::GetMonthName((wxDateTime::Month)i); for(int k=i+1, l=i; ; l = k++) { if(k==12) k = 0; if(k == i) break; if(cyclonemonths[k] && !cyclonemonths[l]) { page += _(" and ") + wxDateTime::GetMonthName((wxDateTime::Month)k); lm = k; } else if(!cyclonemonths[k] && cyclonemonths[l] && l!=lm) page += _(" to ") + wxDateTime::GetMonthName((wxDateTime::Month)l); } goto had_some_cyclones; } if(cyclonemonths[0]) page += _("all months"); else page += _("none"); had_some_cyclones:; page += _T("<dt>"); if(allsafe) page += _("All routes are safe from cyclones."); else if(nonesafe) page += _("No routes found to be safe from cyclones."); else { page += _("Start times for cyclone safe routes: "); /* note: does not merge beginning and end of linked list for safe times, this sometimes might be nice, but they will be in different years. */ bool first = true; for(it2 = cyclone_safe_routes.begin(); it2 != cyclone_safe_routes.end(); it2++) { if(!*it2) continue; if(!first) page += _(" and "); first = false; page += (*it2)->StartTime().Format(_T("%x")); if(++it2 == cyclone_safe_routes.end()) break; if(!*it2) continue; while(*it2 && ++it2 != cyclone_safe_routes.end()); it2--; page += _(" to ") + (*it2)->StartTime().Format(_T("%x")); } } cyclonesfailed:; } m_htmlRoutesReport->SetPage(page); }
void weather_routing_pi::SetPluginMessage(wxString &message_id, wxString &message_body) { if(message_id == _T("GRIB_TIMELINE")) { wxJSONReader r; wxJSONValue v; r.Parse(message_body, &v); wxDateTime time; time.Set (v[_T("Day")].AsInt(), (wxDateTime::Month)v[_T("Month")].AsInt(), v[_T("Year")].AsInt(), v[_T("Hour")].AsInt(), v[_T("Minute")].AsInt(), v[_T("Second")].AsInt()); if(m_pWeather_Routing) { m_pWeather_Routing->m_ConfigurationDialog.m_GribTimelineTime = time.ToUTC(); // m_pWeather_Routing->m_ConfigurationDialog.m_cbUseGrib->Enable(); RequestRefresh(m_parent_window); } } if(message_id == _T("GRIB_TIMELINE_RECORD")) { wxJSONReader r; wxJSONValue v; r.Parse(message_body, &v); static bool shown_warnings; if(!shown_warnings) { shown_warnings = true; int grib_version_major = v[_T("GribVersionMajor")].AsInt(); int grib_version_minor = v[_T("GribVersionMinor")].AsInt(); int grib_version = 1000*grib_version_major + grib_version_minor; int grib_min = 1000*GRIB_MIN_MAJOR + GRIB_MIN_MINOR; int grib_max = 1000*GRIB_MAX_MAJOR + GRIB_MAX_MINOR; if(grib_version < grib_min || grib_version > grib_max) { wxMessageDialog mdlg(m_parent_window, _("Grib plugin version not supported.") + _T("\n\n") + wxString::Format(_("Use versions %d.%d to %d.%d"), GRIB_MIN_MAJOR, GRIB_MIN_MINOR, GRIB_MAX_MAJOR, GRIB_MAX_MINOR), _("Weather Routing"), wxOK | wxICON_WARNING); mdlg.ShowModal(); } } wxString sptr = v[_T("TimelineSetPtr")].AsString(); wxCharBuffer bptr = sptr.To8BitData(); const char* ptr = bptr.data(); GribRecordSet *gptr; sscanf(ptr, "%p", &gptr); if(m_pWeather_Routing) { RouteMapOverlay *routemapoverlay = m_pWeather_Routing->m_RouteMapOverlayNeedingGrib; if(routemapoverlay) { routemapoverlay->Lock(); routemapoverlay->SetNewGrib(gptr); routemapoverlay->Unlock(); } } } if(message_id == _T("CLIMATOLOGY")) { if(!m_pWeather_Routing) return; /* not ready */ wxJSONReader r; wxJSONValue v; r.Parse(message_body, &v); static bool shown_warnings; if(!shown_warnings) { shown_warnings = true; int climatology_version_major = v[_T("ClimatologyVersionMajor")].AsInt(); int climatology_version_minor = v[_T("ClimatologyVersionMinor")].AsInt(); int climatology_version = 1000*climatology_version_major + climatology_version_minor; int climatology_min = 1000*CLIMATOLOGY_MIN_MAJOR + CLIMATOLOGY_MIN_MINOR; int climatology_max = 1000*CLIMATOLOGY_MAX_MAJOR + CLIMATOLOGY_MAX_MINOR; if(climatology_version < climatology_min || climatology_version > climatology_max) { wxMessageDialog mdlg(m_parent_window, _("Climatology plugin version not supported, no climatology data.") + _T("\n\n") + wxString::Format(_("Use versions %d.%d to %d.%d"), CLIMATOLOGY_MIN_MAJOR, CLIMATOLOGY_MIN_MINOR, CLIMATOLOGY_MAX_MAJOR, CLIMATOLOGY_MAX_MINOR), _("Weather Routing"), wxOK | wxICON_WARNING); mdlg.ShowModal(); return; } } wxString sptr = v[_T("ClimatologyDataPtr")].AsString(); sscanf(sptr.To8BitData().data(), "%p", &RouteMap::ClimatologyData); sptr = v[_T("ClimatologyWindAtlasDataPtr")].AsString(); sscanf(sptr.To8BitData().data(), "%p", &RouteMap::ClimatologyWindAtlasData); sptr = v[_T("ClimatologyCycloneTrackCrossingsPtr")].AsString(); sscanf(sptr.To8BitData().data(), "%p", &RouteMap::ClimatologyCycloneTrackCrossings); if(m_pWeather_Routing) { m_pWeather_Routing->m_ConfigurationDialog.m_cClimatologyType->Enable (RouteMap::ClimatologyData!=NULL); m_pWeather_Routing->m_ConfigurationDialog.m_pCyclones->Enable (RouteMap::ClimatologyCycloneTrackCrossings!=NULL); } } if(message_id == wxS("WEATHER_ROUTING_PI")) { // construct the JSON root object wxJSONValue root; // construct a JSON parser wxJSONReader reader; // now read the JSON text and store it in the 'root' structure // check for errors before retreiving values... int numErrors = reader.Parse( message_body, &root ); if ( numErrors > 0 ) { wxLogMessage(_T("weather_routing_pi: Error parsing JSON message - ")); const wxArrayString& errors = reader.GetErrors(); for(int i = 0; i < (int)errors.GetCount(); i++) { wxLogMessage( errors.Item( i ) ); return; } } if(root[wxS("Type")].AsString() == wxS("Response") && root[wxS("Source")].AsString() == wxS("OCPN_DRAW_PI")) { if(root[wxS("Msg")].AsString() == wxS("Version") ) { if(root[wxS("MsgId")].AsString() == wxS("version")) g_ReceivedODVersionJSONMsg = root; } else if(root[wxS("Msg")].AsString() == wxS("GetAPIAddresses") ) { wxString sptr = root[_T("OD_FindClosestBoundaryLineCrossing")].AsString(); sscanf(sptr.To8BitData().data(), "%p", &RouteMap::ODFindClosestBoundaryLineCrossing); } } } }