From 7492c1608a9c129134d75e09d9a00de5d1a4dc36 Mon Sep 17 00:00:00 2001 From: Sylvain Carlioz Date: Thu, 3 May 2018 18:09:29 +0200 Subject: [PATCH 1/2] ADD option for a safety distance from land The idea is to add a safety distance to calculate the weather route from any land that can be found on the way. --- src/RouteMap.cpp | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/src/RouteMap.cpp b/src/RouteMap.cpp index 1a9ca328..d8264684 100644 --- a/src/RouteMap.cpp +++ b/src/RouteMap.cpp @@ -810,10 +810,51 @@ bool Position::Propagate(IsoRouteList &routelist, RouteMapConfiguration &configu /* landfall test */ if(configuration.DetectLand) { double ndlon1 = dlon1; + + // Check first if crossing land. if (ndlon1 > 360) { ndlon1 -= 360; } - if (CrossesLand(dlat1, ndlon1)) { + if (CrossesLand(dlat1, ndlon1)) + { + configuration.land_crossing = true; + continue; + } + + // CUSTOMIZATION - Safety distance from land + // ----------------------------------------- + // Modify the routing according to a safety + // margin defined by the user from the land. + // CONFIG: 15 NM as a security distance from land + double distSecure = 5; + double latBorderUp1, lonBorderUp1, latBorderUp2, lonBorderUp2; + double latBorderDown1, lonBorderDown1, latBorderDown2, lonBorderDown2; + + // Test if land is found within a rectangle with + // dimensiosn (dist, distSecure). Tests borders, plus diag, + // and middle of each side... + // <- dist -> + // |-------------------------------| + // | | ^ + // | | distSafety + // |-------------------------------| ^ + // | | + // | | + // |-------------------------------| + + // Fist, find the (lat,long) of each + // points of the rectangle + ll_gc_ll(lat, lon, 90, distSecure, &latBorderUp1, &lonBorderUp1); + ll_gc_ll(dlat1, dlon1, 90, distSecure, &latBorderUp2, &lonBorderUp2); + ll_gc_ll(lat, lon, 180, distSecure, &latBorderDown1, &lonBorderDown1); + ll_gc_ll(dlat1, dlon1, 180, distSecure, &latBorderDown2, &lonBorderDown2); + + // Then, test if there is land + if (PlugIn_GSHHS_CrossesLand(latBorderUp1, lonBorderUp1, latBorderUp2, lonBorderUp2) || + PlugIn_GSHHS_CrossesLand(latBorderDown1, lonBorderDown1, latBorderDown2, lonBorderDown2) || + PlugIn_GSHHS_CrossesLand(latBorderUp1, lonBorderUp1, latBorderDown2, lonBorderDown2) || + PlugIn_GSHHS_CrossesLand(latBorderDown1, lonBorderDown1, latBorderUp2, lonBorderUp2)) + { configuration.land_crossing = true; continue; } From 3907c0bafb0504d01c8828c702ddbd8f32c28e6e Mon Sep 17 00:00:00 2001 From: Sylvain Carlioz Date: Fri, 4 May 2018 00:55:57 +0200 Subject: [PATCH 2/2] ADD in configuration dialog safety margin input --- WeatherRouting.fbp | 312 +++++++++++++++++++++++++++++++++--- src/ConfigurationDialog.cpp | 1 + src/RouteMap.cpp | 12 +- src/RouteMap.h | 1 + src/WeatherRoutingUI.cpp | 29 +++- src/WeatherRoutingUI.h | 5 +- 6 files changed, 330 insertions(+), 30 deletions(-) diff --git a/WeatherRouting.fbp b/WeatherRouting.fbp index 4744e960..1e4d298e 100644 --- a/WeatherRouting.fbp +++ b/WeatherRouting.fbp @@ -3504,7 +3504,7 @@ - + 0 wxAUI_MGR_DEFAULT @@ -3566,7 +3566,7 @@ - + 2 wxBOTH 0,1 @@ -3578,11 +3578,11 @@ none 0 0 - + 5 wxEXPAND | wxALL 1 - + 1 1 1 @@ -7325,11 +7325,11 @@ - + Advanced 0 - + 1 1 1 @@ -7403,7 +7403,7 @@ - + 2 wxBOTH 0,1 @@ -7415,11 +7415,11 @@ none 0 0 - + 5 wxEXPAND 1 - + 1 wxBOTH 0 @@ -7431,11 +7431,11 @@ none 0 0 - + 5 wxEXPAND 1 - + wxID_ANY Constraints @@ -7444,7 +7444,7 @@ 1 none - + 5 wxEXPAND 1 @@ -8405,11 +8405,11 @@ - + 5 wxEXPAND 1 - + 1 wxBOTH @@ -8509,11 +8509,11 @@ - + 5 wxEXPAND 1 - + 5 wxBOTH @@ -8958,11 +8958,11 @@ - + 5 wxEXPAND 1 - + 1 wxBOTH 0 @@ -9794,7 +9794,7 @@ 0 0 wxID_ANY - 0 + 1 1000 0 @@ -9935,11 +9935,283 @@ + + 5 + wxEXPAND + 1 + + 0 + wxBOTH + + + 0 + + fgSizer11511 + wxFLEX_GROWMODE_SPECIFIED + none + 1 + 0 + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + Safety Margin From Land + + 0 + + + 0 + + 1 + m_staticText241 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + 5 + wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + 2 + 100 + + 0 + + 0 + + 0 + + 1 + m_sSafetyMarginLand + 1 + + + protected + 1 + + Resizable + 1 + 60,-1 + wxSP_ARROW_KEYS + + 0 + + + + + + + + + + + + + + + + + + + EnableSpin + + + + + + + + + OnUpdateSpin + + + + + + + 5 + wxALIGN_CENTER_VERTICAL|wxALL + 0 + + 1 + 1 + 1 + 1 + + + + + + + + 1 + 0 + 1 + + 1 + 0 + Dock + 0 + Left + 1 + + 1 + + 0 + 0 + wxID_ANY + NM + + 0 + + + 0 + + 1 + m_staticText1211 + 1 + + + protected + 1 + + Resizable + 1 + + + + 0 + + + + + -1 + + + + + + + + + + + + + + + + + + + + + + + + + + + - + 5 wxEXPAND 1 diff --git a/src/ConfigurationDialog.cpp b/src/ConfigurationDialog.cpp index e1677d84..96203da5 100644 --- a/src/ConfigurationDialog.cpp +++ b/src/ConfigurationDialog.cpp @@ -411,6 +411,7 @@ void ConfigurationDialog::Update() GET_CHECKBOX(AvoidCycloneTracks); GET_SPIN(CycloneMonths); GET_SPIN(CycloneDays); + GET_SPIN(SafetyMarginLand); GET_CHECKBOX(DetectLand); GET_CHECKBOX(DetectBoundary); diff --git a/src/RouteMap.cpp b/src/RouteMap.cpp index d8264684..ca38c365 100644 --- a/src/RouteMap.cpp +++ b/src/RouteMap.cpp @@ -825,8 +825,8 @@ bool Position::Propagate(IsoRouteList &routelist, RouteMapConfiguration &configu // ----------------------------------------- // Modify the routing according to a safety // margin defined by the user from the land. - // CONFIG: 15 NM as a security distance from land - double distSecure = 5; + // CONFIG: 2 NM as a security distance by default. + double distSecure = configuration.SafetyMarginLand; double latBorderUp1, lonBorderUp1, latBorderUp2, lonBorderUp2; double latBorderDown1, lonBorderDown1, latBorderDown2, lonBorderDown2; @@ -844,10 +844,10 @@ bool Position::Propagate(IsoRouteList &routelist, RouteMapConfiguration &configu // Fist, find the (lat,long) of each // points of the rectangle - ll_gc_ll(lat, lon, 90, distSecure, &latBorderUp1, &lonBorderUp1); - ll_gc_ll(dlat1, dlon1, 90, distSecure, &latBorderUp2, &lonBorderUp2); - ll_gc_ll(lat, lon, 180, distSecure, &latBorderDown1, &lonBorderDown1); - ll_gc_ll(dlat1, dlon1, 180, distSecure, &latBorderDown2, &lonBorderDown2); + ll_gc_ll(lat, lon, heading_resolve(BG)-90, distSecure, &latBorderUp1, &lonBorderUp1); + ll_gc_ll(dlat1, dlon1, heading_resolve(BG)-90, distSecure, &latBorderUp2, &lonBorderUp2); + ll_gc_ll(lat, lon, heading_resolve(BG)+90, distSecure, &latBorderDown1, &lonBorderDown1); + ll_gc_ll(dlat1, dlon1, heading_resolve(BG)+90, distSecure, &latBorderDown2, &lonBorderDown2); // Then, test if there is land if (PlugIn_GSHHS_CrossesLand(latBorderUp1, lonBorderUp1, latBorderUp2, lonBorderUp2) || diff --git a/src/RouteMap.h b/src/RouteMap.h index a05ccebf..3f9ef9b3 100644 --- a/src/RouteMap.h +++ b/src/RouteMap.h @@ -302,6 +302,7 @@ struct RouteMapConfiguration { double MaxDivertedCourse, MaxCourseAngle, MaxSearchAngle, MaxTrueWindKnots, MaxApparentWindKnots; double MaxSwellMeters, MaxLatitude, TackingTime, WindVSCurrent; + double SafetyMarginLand; bool AvoidCycloneTracks; int CycloneMonths, CycloneDays; diff --git a/src/WeatherRoutingUI.cpp b/src/WeatherRoutingUI.cpp index 718e9916..bc4fbd0d 100644 --- a/src/WeatherRoutingUI.cpp +++ b/src/WeatherRoutingUI.cpp @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Feb 20 2018) +// C++ code generated with wxFormBuilder (version Mar 29 2018) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -1032,7 +1032,7 @@ ConfigurationDialogBase::ConfigurationDialogBase( wxWindow* parent, wxWindowID i m_staticText24->Wrap( -1 ); fgSizer1151->Add( m_staticText24, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); - m_sTackingTime = new wxSpinCtrl( sbSizer29->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxSP_ARROW_KEYS, 0, 1000, 0 ); + m_sTackingTime = new wxSpinCtrl( sbSizer29->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 80,-1 ), wxSP_ARROW_KEYS, 0, 1000, 1 ); fgSizer1151->Add( m_sTackingTime, 0, wxALL, 5 ); m_staticText121 = new wxStaticText( sbSizer29->GetStaticBox(), wxID_ANY, _("Seconds"), wxDefaultPosition, wxDefaultSize, 0 ); @@ -1042,6 +1042,25 @@ ConfigurationDialogBase::ConfigurationDialogBase( wxWindow* parent, wxWindowID i fgSizer113->Add( fgSizer1151, 1, wxEXPAND, 5 ); + wxFlexGridSizer* fgSizer11511; + fgSizer11511 = new wxFlexGridSizer( 1, 0, 0, 0 ); + fgSizer11511->SetFlexibleDirection( wxBOTH ); + fgSizer11511->SetNonFlexibleGrowMode( wxFLEX_GROWMODE_SPECIFIED ); + + m_staticText241 = new wxStaticText( sbSizer29->GetStaticBox(), wxID_ANY, _("Safety Margin From Land"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText241->Wrap( -1 ); + fgSizer11511->Add( m_staticText241, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + m_sSafetyMarginLand = new wxSpinCtrl( sbSizer29->GetStaticBox(), wxID_ANY, wxEmptyString, wxDefaultPosition, wxSize( 60,-1 ), wxSP_ARROW_KEYS, 0, 100, 2 ); + fgSizer11511->Add( m_sSafetyMarginLand, 0, wxALL, 5 ); + + m_staticText1211 = new wxStaticText( sbSizer29->GetStaticBox(), wxID_ANY, _("NM"), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1211->Wrap( -1 ); + fgSizer11511->Add( m_staticText1211, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5 ); + + + fgSizer113->Add( fgSizer11511, 1, wxEXPAND, 5 ); + sbSizer29->Add( fgSizer113, 1, wxEXPAND, 5 ); @@ -1221,6 +1240,8 @@ ConfigurationDialogBase::ConfigurationDialogBase( wxWindow* parent, wxWindowID i m_sTackingTime->Connect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( ConfigurationDialogBase::EnableSpin ), NULL, this ); m_sTackingTime->Connect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( ConfigurationDialogBase::EnableSpin ), NULL, this ); m_sTackingTime->Connect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( ConfigurationDialogBase::OnUpdateSpin ), NULL, this ); + m_sSafetyMarginLand->Connect( wxEVT_MOTION, wxMouseEventHandler( ConfigurationDialogBase::EnableSpin ), NULL, this ); + m_sSafetyMarginLand->Connect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( ConfigurationDialogBase::OnUpdateSpin ), NULL, this ); m_sFromDegree->Connect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( ConfigurationDialogBase::OnUpdateSpin ), NULL, this ); m_sToDegree->Connect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( ConfigurationDialogBase::OnUpdateSpin ), NULL, this ); m_tByDegrees->Connect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( ConfigurationDialogBase::OnUpdate ), NULL, this ); @@ -1342,6 +1363,8 @@ ConfigurationDialogBase::~ConfigurationDialogBase() m_sTackingTime->Disconnect( wxEVT_ENTER_WINDOW, wxMouseEventHandler( ConfigurationDialogBase::EnableSpin ), NULL, this ); m_sTackingTime->Disconnect( wxEVT_MOUSEWHEEL, wxMouseEventHandler( ConfigurationDialogBase::EnableSpin ), NULL, this ); m_sTackingTime->Disconnect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( ConfigurationDialogBase::OnUpdateSpin ), NULL, this ); + m_sSafetyMarginLand->Disconnect( wxEVT_MOTION, wxMouseEventHandler( ConfigurationDialogBase::EnableSpin ), NULL, this ); + m_sSafetyMarginLand->Disconnect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( ConfigurationDialogBase::OnUpdateSpin ), NULL, this ); m_sFromDegree->Disconnect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( ConfigurationDialogBase::OnUpdateSpin ), NULL, this ); m_sToDegree->Disconnect( wxEVT_COMMAND_SPINCTRL_UPDATED, wxSpinEventHandler( ConfigurationDialogBase::OnUpdateSpin ), NULL, this ); m_tByDegrees->Disconnect( wxEVT_COMMAND_TEXT_UPDATED, wxCommandEventHandler( ConfigurationDialogBase::OnUpdate ), NULL, this ); @@ -2796,7 +2819,7 @@ EditPolarDialogBase::EditPolarDialogBase( wxWindow* parent, wxWindowID id, const fgSizer93->Add( m_gPolar, 0, wxALL|wxEXPAND, 5 ); - m_staticText1351 = new wxStaticText( m_panel19, wxID_ANY, _("Leave any cell blank to automatically interpolate from nearby values.\n View the polar plot in the boat dialog while editing the polar."), wxDefaultPosition, wxDefaultSize, 0 ); + m_staticText1351 = new wxStaticText( m_panel19, wxID_ANY, _("Leave any cell blank to automatically interpolate from nearby values. Use a value of 0.0 to specify invalid (cannot be used)\n View the polar plot in the boat dialog while editing the polar."), wxDefaultPosition, wxDefaultSize, 0 ); m_staticText1351->Wrap( -1 ); fgSizer93->Add( m_staticText1351, 0, wxALL, 5 ); diff --git a/src/WeatherRoutingUI.h b/src/WeatherRoutingUI.h index 156757de..12e475e4 100644 --- a/src/WeatherRoutingUI.h +++ b/src/WeatherRoutingUI.h @@ -1,5 +1,5 @@ /////////////////////////////////////////////////////////////////////////// -// C++ code generated with wxFormBuilder (version Feb 20 2018) +// C++ code generated with wxFormBuilder (version Mar 29 2018) // http://www.wxformbuilder.org/ // // PLEASE DO *NOT* EDIT THIS FILE! @@ -276,6 +276,9 @@ class ConfigurationDialogBase : public wxDialog wxStaticText* m_staticText24; wxSpinCtrl* m_sTackingTime; wxStaticText* m_staticText121; + wxStaticText* m_staticText241; + wxSpinCtrl* m_sSafetyMarginLand; + wxStaticText* m_staticText1211; wxStaticText* m_staticText113; wxStaticText* m_staticText115; wxStaticText* m_staticText117;