Skip to content

Commit

Permalink
Merge branch 'master' of github.com:seandepagnier/weather_routing_pi
Browse files Browse the repository at this point in the history
Conflicts:
	src/Polar.cpp
  • Loading branch information
seandepagnier committed Mar 26, 2018
2 parents 4715200 + 1d57662 commit ed61be8
Show file tree
Hide file tree
Showing 14 changed files with 161 additions and 369 deletions.
263 changes: 7 additions & 256 deletions WeatherRouting.fbp

Large diffs are not rendered by default.

7 changes: 4 additions & 3 deletions data/boats/Boat-Climatology.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<OpenCPNWeatherRoutingBoat version="1.10" creator="Opencpn Weather Routing plugin">
<Polar FileName="TWS-0-6.pol" CrossOverPercentage="0" />
<Polar FileName="TWS-6-20.pol" CrossOverPercentage="0" />
<Polar FileName="TWS-20-60.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-0-10.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-06-24.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-15-30.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-24-60.pol" CrossOverPercentage="0" />
</OpenCPNWeatherRoutingBoat>
7 changes: 4 additions & 3 deletions data/boats/Boat-Test-Power.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<OpenCPNWeatherRoutingBoat version="1.10" creator="Opencpn Weather Routing plugin">
<Polar FileName="TWS-0-6-Power.pol" CrossOverPercentage="0" />
<Polar FileName="TWS-6-20.pol" CrossOverPercentage="0" />
<Polar FileName="TWS-20-60.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-0-6-Power.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-06-24.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-15-30.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-24-60.pol" CrossOverPercentage="0" />
</OpenCPNWeatherRoutingBoat>
7 changes: 4 additions & 3 deletions data/boats/Boat-Test.xml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="utf-8" ?>
<OpenCPNWeatherRoutingBoat version="1.10" creator="Opencpn Weather Routing plugin">
<Polar FileName="TWS-0-6.pol" CrossOverPercentage="0" />
<Polar FileName="TWS-6-20.pol" CrossOverPercentage="0" />
<Polar FileName="TWS-20-60.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-0-10.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-06-24.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-15-30.pol" CrossOverPercentage="0" />
<Polar FileName="Example/Example-24-60.pol" CrossOverPercentage="0" />
</OpenCPNWeatherRoutingBoat>
1 change: 1 addition & 0 deletions src/Boat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ wxString Boat::OpenXML(wxString filename, bool shortcut)
Polar polar; //(wxString::FromUTF8(e->Attribute("Name")));

polar.FileName = wxString::FromUTF8(e->Attribute("FileName"));
polar.FileName.Replace (_T("/"), wxFileName::GetPathSeparator());
if(!wxFileName::FileExists(polar.FileName))
polar.FileName = weather_routing_pi::StandardPath() + _T("polars") +
wxFileName::GetPathSeparator() + polar.FileName;
Expand Down
10 changes: 8 additions & 2 deletions src/EditPolarDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,10 @@ void EditPolarDialog::OnAddTrueWindAngle( wxCommandEvent& event )

void EditPolarDialog::OnRemoveTrueWindAngle( wxCommandEvent& event )
{
GetPolar()->RemoveDegreeStep(m_lTrueWindAngles->GetSelection());
int sel = m_lTrueWindAngles->GetSelection();
if (sel == -1)
return;
GetPolar()->RemoveDegreeStep(sel);
RebuildTrueWindAngles();
RebuildGrid();
}
Expand All @@ -104,7 +107,10 @@ void EditPolarDialog::OnAddTrueWindSpeed( wxCommandEvent& event )

void EditPolarDialog::OnRemoveTrueWindSpeed( wxCommandEvent& event )
{
GetPolar()->RemoveWindSpeed(m_lTrueWindSpeeds->GetSelection());
int sel = m_lTrueWindSpeeds->GetSelection();
if (sel == -1)
return;
GetPolar()->RemoveWindSpeed(sel);
RebuildTrueWindSpeeds();
RebuildGrid();
}
Expand Down
26 changes: 25 additions & 1 deletion src/PlotDialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ PlotDialog::PlotDialog( WeatherRouting &weatherrouting )
#endif
m_WeatherRouting(weatherrouting)
{

}

PlotDialog::~PlotDialog()
Expand Down Expand Up @@ -232,10 +233,28 @@ void PlotDialog::OnPaintPlot(wxPaintEvent& event)
lx = x, ly = y;
}
}

// Cursor Customization
// ----------------------------------------------------------------
// Draw a cursor on the graph to show
// the current time position by the GRIB file
wxDateTime gribTime = m_WeatherRouting.m_ConfigurationDialog.m_GribTimelineTime;
double cursorTime = (gribTime - m_StartTime).GetSeconds().ToDouble();
if (cursorTime <= m_maxtime || cursorTime >= m_mintime)
{
int x_cursor = w * (scale * ((cursorTime - m_mintime) / (m_maxtime - m_mintime) - \
position) + position);

wxColor orange(255, 165, 0);
wxPen cursorPen(orange, 3, wxPENSTYLE_DOT);
dc.SetPen(cursorPen);
dc.DrawLine(x_cursor, 0, x_cursor, h);
}
// ----------------------------------------------------------------

dc.SetTextForeground(*wxBLACK);
dc.SetPen(wxPen(*wxBLACK, 1, wxPENSTYLE_DOT));

const double steps = 10;
bool grid = true;
for(double i=1/steps; i<1-1/steps; i+=1/steps) {
Expand Down Expand Up @@ -283,3 +302,8 @@ void PlotDialog::SetRouteMapOverlay(RouteMapOverlay *routemapoverlay)
GetScale();
m_PlotWindow->Refresh();
}

void PlotDialog::OnUpdateUI(wxUpdateUIEvent &event)
{
SetRouteMapOverlay(m_WeatherRouting.FirstCurrentRouteMap());
}
2 changes: 2 additions & 0 deletions src/PlotDialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ class PlotDialog : public PlotDialogBase
void OnUpdatePlot( wxScrollEvent& event ) { m_PlotWindow->Refresh(); }
void OnUpdatePlotVariable( wxCommandEvent& event ) { GetScale(); m_PlotWindow->Refresh(); }
void OnUpdateRoute( wxCommandEvent& event );
void OnUpdateUI( wxUpdateUIEvent& event );

private:

Expand All @@ -72,6 +73,7 @@ class PlotDialog : public PlotDialogBase
std::list<PlotData> m_PlotData;

WeatherRouting &m_WeatherRouting;

};

#endif
4 changes: 4 additions & 0 deletions src/Polar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,10 @@ bool Polar::Save(const wxString &filename)
fputs("\n", f);
}
fclose(f);

for(unsigned int VWi = 0; VWi < wind_speeds.size(); VWi++)
CalculateVMG(VWi);

return true;
}

Expand Down
147 changes: 77 additions & 70 deletions src/RouteMapOverlay.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ RouteMapOverlay::RouteMapOverlay()
: m_UpdateOverlay(true), m_bEndRouteVisible(false), m_Thread(NULL),
last_cursor_lat(0), last_cursor_lon(0),
last_cursor_position(NULL), destination_position(NULL), last_destination_position(NULL),
m_bUpdated(false), m_overlaylist(0), wind_barb_cache_origin_size(0), current_cache_origin_size(0), wind_barb_route_cache_origin_size(0)
m_bUpdated(false), m_overlaylist(0), current_cache_origin_size(0)
{
}

Expand Down Expand Up @@ -495,57 +495,78 @@ void RouteMapOverlay::RenderPolarChangeMarks(Position *pos, wrDC &dc, PlugIn_Vie
}

/* Customization ComfortDisplay
* -----------------------------------------------------
* The idea is to display the weather route with different
* colors giving an idea of the sailing comfort:
* Green = Light conditions, relax and enjoy
* Orange = Can be tough, stay focus
* Red = Strong conditions, heavy sailors, be prepared
* ----------------------------------------------------------------------------
* The idea is to display on the weather route different colors giving an idea
* of the sailing comfort along the trip:
* Green = Light conditions, relax and enjoy
* Orange = Can be tough, stay focus
* Red = Strong conditions, heavy sailors, be prepared
*/
int RouteMapOverlay::sailingConditionLevel(PlotData plot)
{
/* Method to calculate a indicator between 1 and 3
* of the sailing conditions based on sea conditions
* such as waves, wind, current.
*/

double level_calc = 0.0;

/* Define coefficient to weight relative impact
* of the parameter on sailing comfort
/* Method to calculate a indicator between 1 and 3 of the sailing conditions
* based on wind, wind course and waves.
*
* Definitions:
* C - Sea Current Direction over ground
* VC - Velocity of Current
* W - Wind Direction
* WG - Wind direction over ground
* VWG - Velocity of wind over ground
* WA - Angle of wind relative to true north
* VW - velocity of wind over water
* All these calculations are empirical and just made from experience and how
* people feel sailing comfort which is a highly subjective value...
*/

double coef_WV = 1.0;
double coef_W = 1.0;
double level_calc = 0.0;

// Define MAX constants. Over this value, the ratio
// is more than 1 which means it is very impacting
// the sailing comfort.
double MAX_WV = 30; // No more than 30knt, please
double MAX_W = 50; // No more than 50° app. wind
// Define mximum constants. Over this value, sailing comfort is very impacted
// (coef > 1) and automatically displayed in red.
// Definitions:
// AW - Apparent Wind Direction from the boat (0 = upwind)
// VW - Velocity of wind over water
//WVHT - Swell (if available)
double MAX_WV = 27; // Vigilant over 27knts/7B
double MAX_AW = 30; // Upwind
double MAX_WVHT = 5; // No more than 5m waves

// Use a exp function for wind as difficulty sailing comfort
// is exponentially degraded with wind speed.
// Over 30knts, it starts to be difficult
double WV = plot.VW;
double W = plot.W;
double WV_normal = exp((1.32*WV-MAX_WV)/MAX_WV)-exp(-1);
if (WV_normal > 1)
WV_normal = 1.0;

// Use a normal distribution to set the maximum difficulty at 30° upwind,
// and reduce when we go downwind. Also, take into account that sailing
// on the wind becomes much more difficult when wind speed increases.
double AW = heading_resolve(plot.B-plot.W);
double AW_normal = ((1/((0.67*MAX_AW)*sqrt(2*M_PI))) * \
exp(-(pow(AW-MAX_AW, 2))/(2*pow(0.67*MAX_AW,2))) * \
75.19) * WV_normal;
if (AW_normal > 1)
AW_normal = 1.0;

// If available, add swell conditions in comfort model.
// Use same exponential function for swell as sailing
// comfort exponentially decrease with swell height.
double WVHT = plot.WVHT;
double WVHT_normal = 0.0;
if (WVHT > 0)
WVHT_normal = exp((1.32*WVHT-MAX_WVHT)/MAX_WVHT)-exp(-1);
if (WVHT_normal > 1)
WVHT_normal = 1;

level_calc = (coef_WV * WV/MAX_WV + coef_W * MAX_W/W) / (coef_WV + coef_W);
// Calculate score
// Use an OR function X,Y E [0,1], f(X,Y) = 1-(1-X)(1-Y)
double WV_coef = 1.0;
double AW_coef = 0.6;
double WVHT_coef = 0.5;
level_calc = 1 - (1 - WV_coef * WV_normal) * \
(1 - AW_coef * AW_normal) * \
(1 - WVHT_coef * WVHT_normal);

if (level_calc <= 0.5)
// Light conditions, enjoy ;-)
return 1;
if (level_calc > 0.5 && level_calc <= 1)
if (level_calc > 0.5 && level_calc < 1)
// Can be tough
return 2;
if (level_calc > 1)
if (level_calc >= 1)
// Strong conditions
return 3;
return 0;
Expand Down Expand Up @@ -689,13 +710,6 @@ void RouteMapOverlay::RenderWindBarbsOnRoute(wrDC &dc, PlugIn_ViewPort &vp)
if (origin.size() < 2)
return;

// if not, then check if wind barbs have to be
// calculated or are stored in cache line buffer.
bool toCompute = origin.size() != wind_barb_route_cache_origin_size ||
vp.view_scale_ppm != wind_barb_route_cache_scale ||
vp.m_projection_type != wind_barb_route_cache_projection ||
vp.m_projection_type != PI_PROJECTION_MERCATOR;

// Create a specific viewport at position (0,0)
// to draw the winds barbs, and then translate it
PlugIn_ViewPort nvp = vp;
Expand All @@ -708,37 +722,30 @@ void RouteMapOverlay::RenderWindBarbsOnRoute(wrDC &dc, PlugIn_ViewPort &vp)
// calculate wind barbs along the route by looping
// over [GetPlotData(false)] list which contains lat,
// lon, wind info for each points, only if needed.
if (toCompute)
std::list<PlotData> plot = GetPlotData(false);
std::list<PlotData>::iterator it;
for (it = plot.begin(); it != plot.end(); it++)
{
wind_barb_route_cache_origin_size = origin.size();
wind_barb_route_cache_scale = vp.view_scale_ppm;
wind_barb_route_cache_projection = vp.m_projection_type;
wxPoint p;
GetCanvasPixLL(&nvp, &p, it->lat, it->lon);

std::list<PlotData> plot = GetPlotData(false);
std::list<PlotData>::iterator it;
for (it = plot.begin(); it != plot.end(); it++)
{
wxPoint p;
GetCanvasPixLL(&nvp, &p, it->lat, it->lon);

double VW = it->VW;
double W = it->W;

// Calculate the offset to put the head
// of the arrow on the route (and not the
// middle of the arrow) for readability.
int xOffset, yOffset;
xOffset = (int)(0.5 * 35 * sin(deg2rad(W)));
yOffset = (int)(0.5 * 35 * cos(deg2rad(W)));

// Draw barbs
g_barbsOnRoute_LineBufferOverlay.pushWindArrowWithBarbs(
wind_barb_route_cache, p.x + xOffset, p.y - yOffset, VW,
deg2rad(W) + vp.rotation, it->lat < 0
);
}
wind_barb_route_cache.Finalize();
double VW = it->VW;
double W = it->W;

// Calculate the offset to put the head
// of the arrow on the route (and not the
// middle of the arrow) for readability.
int xOffset, yOffset;
xOffset = (int)(0.5 * 35 * sin(deg2rad(W)));
yOffset = (int)(0.5 * 35 * cos(deg2rad(W)));

// Draw barbs
g_barbsOnRoute_LineBufferOverlay.pushWindArrowWithBarbs(
wind_barb_route_cache, p.x + xOffset, p.y - yOffset, VW,
deg2rad(W) + vp.rotation, it->lat < 0
);
}
wind_barb_route_cache.Finalize();

// Draw the wind barbs
wxPoint point;
Expand Down
3 changes: 0 additions & 3 deletions src/RouteMapOverlay.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,6 @@ class RouteMapOverlay : public RouteMap

// Customization WindBarbsOnRoute
LineBuffer wind_barb_route_cache;
double wind_barb_route_cache_scale;
size_t wind_barb_route_cache_origin_size;
int wind_barb_route_cache_projection;

LineBuffer current_cache;
double current_cache_scale;
Expand Down
24 changes: 18 additions & 6 deletions src/WeatherRouting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ WeatherRouting::WeatherRouting(wxWindow *parent, weather_routing_pi &plugin)

/* ensure the directories exist */
wxFileName fn;
fn.Mkdir(weather_routing_pi::StandardPath());
fn.Mkdir(weather_routing_pi::StandardPath(), wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);
fn.Mkdir(boatsdir);
fn.Mkdir(polarsdir);

Expand Down Expand Up @@ -333,11 +333,23 @@ WeatherRouting::~WeatherRouting( )

void WeatherRouting::CopyDataFiles(wxString from, wxString to)
{
wxArrayString fns;
wxDir::GetAllFiles(from, &fns);
for (unsigned int i = 0; i < fns.Count(); i++) {
wxFileName f(fns.Item(i));
wxCopyFile(fns.Item(i), to + wxFileName::GetPathSeparator() + f.GetFullName());
if (from[from.Len() - 1] != '\\' && from[from.Len() - 1] != '/') from += wxFILE_SEP_PATH;
if (to[to.Len() - 1] != '\\' && to[to.Len() - 1] != '/') to += wxFILE_SEP_PATH;

if (!wxDirExists(to))
wxFileName::Mkdir(to, wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL);

wxDir dir(from);
wxString next = wxEmptyString;
bool b = dir.GetFirst(&next);
while (b) {
const wxString fileFrom = from + next;
const wxString fileTo = to + next;
if (wxDirExists(fileFrom))
CopyDataFiles(fileFrom, fileTo);
else
wxCopyFile(fileFrom, fileTo);
b = dir.GetNext(&next);
}
}

Expand Down
Loading

0 comments on commit ed61be8

Please sign in to comment.