36#include <wx/datetime.h>
42#include "model/config_vars.h"
43#include "model/cutil.h"
44#include "model/georef.h"
45#include "model/georef.h"
46#include "model/config_vars.h"
47#include "model/nav_object_database.h"
48#include "model/route.h"
49#include "model/routeman.h"
50#include "model/select.h"
54double g_defaultBoatSpeed;
56#include <wx/listimpl.cpp>
58WX_DEFINE_LIST(RouteList);
77 m_GUID = pWayPointMan->CreateGUID(NULL);
80 m_ArrivalRadius = g_n_arrival_circle_radius;
91 if (g_defaultBoatSpeed != ROUTE_DEFAULT_SPEED)
98 m_bsharedWPViz =
false;
110void Route::CloneRoute(
Route *psourceroute,
int start_nPoint,
int end_nPoint,
111 const wxString &suffix,
112 const bool duplicate_first_point) {
118 for (i = start_nPoint; i <= end_nPoint; i++) {
120 !(i == start_nPoint && duplicate_first_point)) {
121 AddPoint(psourceroute->GetPoint(i),
false);
123 RoutePoint *psourcepoint = psourceroute->GetPoint(i);
125 psourcepoint->m_lat, psourcepoint->m_lon, psourcepoint->GetIconName(),
126 psourcepoint->GetName(), wxEmptyString,
true);
129 AddPoint(ptargetpoint,
false);
133 FinalizeForRendering();
136wxString Route::IsPointNameValid(
RoutePoint *pPoint,
137 const wxString &name)
const {
140 wxString substr = name.SubString(0, 6);
143 point = node->GetData();
144 wxString exist = point->GetName().SubString(0, 6);
147 node = node->GetNext();
148 }
else if (substr == exist) {
149 return wxString(
"Name is not unique in route");
151 node = node->GetNext();
155 return wxEmptyString;
158void Route::AddPoint(
RoutePoint *pNewPoint,
bool b_rename_in_sequence,
159 bool b_deferBoxCalc) {
161 pNewPoint->SetShared(
true);
169 if (!b_deferBoxCalc) FinalizeForRendering();
173 if (b_rename_in_sequence && pNewPoint->GetName().IsEmpty() &&
174 !pNewPoint->IsShared()) {
176 name.Printf(_T(
"%03d"), GetnPoints());
177 pNewPoint->SetName(name);
182void Route::AddPointAndSegment(
RoutePoint *pNewPoint,
bool b_rename_in_sequence,
183 bool b_deferBoxCalc) {
184 int npoints = GetnPoints();
187 newpoint =
new RoutePoint(pNewPoint->m_lat, pNewPoint->m_lon,
188 pNewPoint->GetIconName(), pNewPoint->GetName(),
189 wxEmptyString,
false);
193 AddPoint(newpoint,
false);
195 double rlat = GetPoint(npoints)->m_lat;
196 double rlon = GetPoint(npoints)->m_lon;
197 npoints = GetnPoints();
198 pSelect->AddSelectableRouteSegment(
199 rlat, rlon, GetPoint(npoints)->m_lat, GetPoint(npoints)->m_lon,
200 GetPoint(npoints - 1), GetPoint(npoints),
this);
205void Route::InsertPointAndSegment(
RoutePoint *pNewPoint,
int insert_after,
206 bool bRenamePoints,
bool b_deferBoxCalc) {
211 pNewPoint->SetShared(
true);
216 if (insert_after >= GetnPoints() - 1) {
217 wxLogMessage(wxT(
"Error insert after last point"));
221 int insert = insert_after++;
223 pNewPoint->SetNameShown(
false);
225 if (bRenamePoints) RenameRoutePoints();
227 FinalizeForRendering();
228 UpdateSegmentDistances();
239 prp = node->GetData();
240 if (i == nWhichPoint) {
244 node = node->GetNext();
250RoutePoint *Route::GetPoint(
const wxString &guid) {
255 prp = node->GetData();
256 if (guid == prp->
m_GUID)
return prp;
258 node = node->GetNext();
264static void TestLongitude(
double lon,
double min,
double max,
bool &lonl,
266 double clon = (min + max) / 2;
267 if (min - lon > 180) lon += 360;
271 if (lon < clon - 180)
275 }
else if (lon > max) {
276 if (lon > clon + 180)
283bool Route::ContainsSharedWP() {
285 node = node->GetNext()) {
287 if (prp->IsShared())
return true;
293int s_arrow_icon[] = {0, 0, 5, 2, 18, 6, 12, 0, 18, -6, 5, -2, 0, 0};
294void Route::ClearHighlights(
void) {
299 prp = node->GetData();
301 node = node->GetNext();
306 bool bRenamePoints) {
308 GetNewMarkSequenced(), wxEmptyString);
310 newpoint->SetNameShown(
false);
315 if (bRenamePoints) RenameRoutePoints();
317 FinalizeForRendering();
318 UpdateSegmentDistances();
324 bool bRenamePoints) {
326 if (nRP >= GetnPoints() - 1)
return NULL;
330 GetNewMarkSequenced(), wxEmptyString);
332 newpoint->SetNameShown(
false);
336 if (bRenamePoints) RenameRoutePoints();
338 FinalizeForRendering();
339 UpdateSegmentDistances();
344wxString Route::GetNewMarkSequenced(
void) {
346 ret.Printf(_T (
"NM%03d" ), m_nm_sequence);
360 if (ret == wxNOT_FOUND)
366void Route::DeletePoint(
RoutePoint *rp,
bool bRenamePoints) {
371 pSelect->DeleteAllSelectableRoutePoints(
this);
372 pSelect->DeleteAllSelectableRouteSegments(
this);
378 if (bRenamePoints) RenameRoutePoints();
380 if (GetnPoints() > 1) {
381 pSelect->AddAllSelectableRouteSegments(
this);
382 pSelect->AddAllSelectableRoutePoints(
this);
384 FinalizeForRendering();
385 UpdateSegmentDistances();
389void Route::RemovePoint(
RoutePoint *rp,
bool bRenamePoints) {
391 g_pRouteMan->DeactivateRoute();
393 pSelect->DeleteAllSelectableRoutePoints(
this);
394 pSelect->DeleteAllSelectableRouteSegments(
this);
405 Route *pcontainer_route = FindRouteContainingWaypoint(rp);
407 if (pcontainer_route == NULL) {
410 NavObj_dB::GetInstance().UpdateRoutePoint(rp);
413 if (bRenamePoints) RenameRoutePoints();
417 pSelect->AddAllSelectableRouteSegments(
this);
418 pSelect->AddAllSelectableRoutePoints(
this);
421 NavObj_dB::GetInstance().UpdateRoute(
this);
422 FinalizeForRendering();
423 UpdateSegmentDistances();
427void Route::DeSelectRoute() {
432 rp = node->GetData();
435 node = node->GetNext();
439void Route::ReloadRoutePointIcons() {
444 rp = node->GetData();
447 node = node->GetNext();
451void Route::FinalizeForRendering() { RBBox.Invalidate(); }
453LLBBox &Route::GetBBox(
void) {
454 if (RBBox.GetValid())
return RBBox;
456 double bbox_lonmin, bbox_lonmax, bbox_latmin, bbox_latmax;
461 if (data->m_wpBBox.GetValid()) {
462 bbox_lonmax = data->
m_wpBBox.GetMaxLon();
463 bbox_lonmin = data->m_wpBBox.GetMinLon();
464 bbox_latmax = data->m_wpBBox.GetMaxLat();
465 bbox_latmin = data->m_wpBBox.GetMinLat();
467 bbox_lonmax = bbox_lonmin = data->m_lon;
468 bbox_latmax = bbox_latmin = data->m_lat;
471 double lastlon = data->m_lon, wrap = 0;
473 node = node->GetNext();
475 data = node->GetData();
477 if (lastlon - data->m_lon > 180)
479 else if (data->m_lon - lastlon > 180)
482 double lon = data->m_lon + wrap;
484 if (lon > bbox_lonmax) bbox_lonmax = lon;
485 if (lon < bbox_lonmin) bbox_lonmin = lon;
487 if (data->m_lat > bbox_latmax) bbox_latmax = data->m_lat;
488 if (data->m_lat < bbox_latmin) bbox_latmin = data->m_lat;
490 lastlon = data->m_lon;
491 node = node->GetNext();
494 if (bbox_lonmin < -360)
495 bbox_lonmin += 360, bbox_lonmax += 360;
496 else if (bbox_lonmax > 360)
497 bbox_lonmin -= 360, bbox_lonmax -= 360;
499 if (bbox_lonmax - bbox_lonmin > 360) bbox_lonmin = -180, bbox_lonmax = 180;
501 RBBox.Set(bbox_latmin, bbox_lonmin, bbox_latmax, bbox_lonmax);
512 double slat1 = prp0->m_lat, slon1 = prp0->m_lon;
513 double slat2 = prp->m_lat, slon2 = prp->m_lon;
520 DistanceBearingMercator(slat2, slon2, slat1, slon1, &br, &dd);
523 prp->SetDistance(dd);
533 if (planspeed > 0.) {
536 double legspeed = planspeed;
539 if (legspeed > 0.1 && legspeed < 1000.) {
544 prp->SetETE(duration);
545 wxTimeSpan ts(0, 0, duration);
548 if (prp0->
GetETA().IsValid()) {
568void Route::UpdateSegmentDistances(
double planspeed) {
583 node = node->GetNext();
591 node = node->GetNext();
596void Route::Reverse(
bool bRenamePoints) {
598 wxArrayString RoutePointGUIDList;
601 for (
int i = 0; i < ncount; i++)
602 RoutePointGUIDList.Add(GetPoint(ncount - i)->
m_GUID);
609 for (
unsigned int ip = 0; ip < RoutePointGUIDList.GetCount(); ip++) {
610 wxString GUID = RoutePointGUIDList[ip];
613 wxRoutePointListNode *prpnode = pWayPointMan->GetWaypointList()->GetFirst();
617 if (prp->
m_GUID == GUID) {
621 prpnode = prpnode->GetNext();
625 if (bRenamePoints) RenameRoutePoints();
633void Route::SetVisible(
bool visible,
bool includeWpts) {
634 m_bVisible = visible;
636 if (!includeWpts)
return;
641 rp = node->GetData();
646 if (rp->IsShared()) {
647 if (visible) rp->SetVisible(visible);
649 node = node->GetNext();
653void Route::SetListed(
bool visible) { m_bListed = visible; }
655void Route::AssembleRoute(
void) {}
657void Route::ShowWaypointNames(
bool bshow) {
662 prp->SetNameShown(bshow);
664 node = node->GetNext();
668bool Route::AreWaypointNamesVisible() {
674 if (prp->GetNameShown()) bvis =
true;
676 node = node->GetNext();
682void Route::RenameRoutePoints(
void) {
692 wxString name = prp->GetName();
693 if (name.Len() == 3) {
694 name.Printf(_T (
"%03d" ), i);
695 }
else if (name.Left(2) ==
"NM") {
696 name.Printf(_T (
"%03d" ), i);
697 if (prp->GetName().Len() >= 5) {
698 name.Append(prp->GetName().Mid(5));
701 name.Printf(_T (
"%03d" ), i);
702 name.Append(prp->GetName().Mid(3));
707 node = node->GetNext();
714bool Route::IsEqualTo(
Route *ptargetroute) {
716 wxRoutePointListNode *pthatnode = (ptargetroute->
pRoutePointList)->GetFirst();
718 if (NULL == pthisnode)
return false;
722 if (this->GetnPoints() != ptargetroute->GetnPoints())
return false;
725 if (NULL == pthatnode)
return false;
730 if ((fabs(pthisrp->m_lat - pthatrp->m_lat) > 1.0e-6) ||
731 (fabs(pthisrp->m_lon - pthatrp->m_lon) > 1.0e-6))
734 if (!pthisrp->GetName().IsSameAs(pthatrp->GetName()))
return false;
736 pthisnode = pthisnode->GetNext();
737 pthatnode = pthatnode->GetNext();
Represents a waypoint or mark within the navigation system.
LLBBox m_wpBBox
Bounding box for the waypoint.
wxString m_GUID
Globally Unique Identifier for the waypoint.
wxDateTime GetETD()
Retrieves the Estimated Time of Departure for this waypoint, in UTC.
bool m_bIsolatedMark
Flag indicating if the waypoint is a standalone mark.
bool m_bIsActive
Flag indicating if this waypoint is active for navigation.
wxDateTime GetManualETD()
Retrieves the manually set Estimated Time of Departure for this waypoint, in UTC.
wxDateTime m_seg_etd
Estimated Time of Departure from this waypoint, in UTC.
bool m_bIsInRoute
Flag indicating if this waypoint is part of a route.
double m_seg_len
Length of the leg from previous waypoint to this waypoint in nautical miles.
bool m_bShowName
Flag indicating if the waypoint name should be shown.
double GetPlannedSpeed()
Return the planned speed associated with this waypoint.
bool m_bPtIsSelected
Flag indicating if this waypoint is currently selected.
bool m_bIsInLayer
Flag indicating if the waypoint belongs to a layer.
bool m_manual_etd
Flag indicating whether the ETD has been manually set by the user.
double m_seg_vmg
Planned speed for traveling FROM this waypoint TO the next waypoint.
wxDateTime m_seg_eta
Estimated Time of Arrival at this waypoint, in UTC.
wxDateTime GetETA()
Retrieves the Estimated Time of Arrival for this waypoint, in UTC.
Represents a navigational route in the navigation system.
int m_hiliteWidth
Width in pixels for highlighting the route when selected.
bool m_bRtIsSelected
Flag indicating whether this route is currently selected in the UI.
double m_PlannedSpeed
Default planned speed for the route in knots.
wxString m_RouteStartString
Name or description of the route's starting point.
bool m_bIsBeingCreated
Flag indicating that the route is currently being created by the user.
void UpdateSegmentDistance(RoutePoint *prp0, RoutePoint *prp, double planspeed=-1.0)
Updates the navigation data for a single route segment between two waypoints.
RoutePointList * pRoutePointList
Ordered list of waypoints (RoutePoints) that make up this route.
double m_route_length
Total length of the route in nautical miles, calculated using rhumb line (Mercator) distances.
bool m_bRtIsActive
Flag indicating whether this route is currently active for navigation.
wxString m_Colour
Color name for rendering the route on the chart.
bool m_bDeleteOnArrival
Flag indicating whether the route should be deleted once navigation reaches the end.
wxString m_RouteEndString
Name or description of the route's ending point.
RoutePoint * m_pRouteActivePoint
Pointer to the currently active waypoint within this route.
bool m_btemp
Flag indicating if this is a temporary route.
wxPenStyle m_style
Style of the route line when rendered on the chart.
wxString m_TimeDisplayFormat
Format for displaying times in the UI.
int m_width
Width of the route line in pixels when rendered on the chart.
wxString m_RouteNameString
User-assigned name for the route.
wxString m_GUID
Globally unique identifier for this route.
wxDateTime m_PlannedDeparture
Planned departure time for the route, in UTC.
bool m_bIsInLayer
Flag indicating whether this route belongs to a layer.
double m_route_time
Total estimated time to complete the route in seconds.
int m_lastMousePointIndex
Index of the most recently interacted with route point.
HyperlinkList * m_HyperlinkList
List of hyperlinks associated with this route.
bool m_bIsBeingEdited
Flag indicating that the route is currently being edited by the user.
bool m_NextLegGreatCircle
Flag indicating whether the next leg should be calculated using great circle navigation or rhumb line...
int m_LayerID
Identifier of the layer containing this route.