36#include <wx/datetime.h>
43#include "model/cutil.h"
44#include "model/georef.h"
45#include "model/georef.h"
47#include "model/nav_object_database.h"
48#include "model/route.h"
49#include "model/routeman.h"
50#include "model/select.h"
55#include <wx/listimpl.cpp>
57WX_DEFINE_LIST(RouteList);
76 m_GUID = pWayPointMan->CreateGUID(NULL);
79 m_ArrivalRadius = g_n_arrival_circle_radius;
90 if (g_defaultBoatSpeed != ROUTE_DEFAULT_SPEED)
97 m_bsharedWPViz =
false;
109void Route::CloneRoute(
Route *psourceroute,
int start_nPoint,
int end_nPoint,
110 const wxString &suffix,
111 const bool duplicate_first_point) {
117 for (i = start_nPoint; i <= end_nPoint; i++) {
119 !(i == start_nPoint && duplicate_first_point)) {
120 AddPoint(psourceroute->GetPoint(i),
false);
122 RoutePoint *psourcepoint = psourceroute->GetPoint(i);
124 psourcepoint->m_lat, psourcepoint->m_lon, psourcepoint->GetIconName(),
125 psourcepoint->GetName(), wxEmptyString,
true);
128 AddPoint(ptargetpoint,
false);
132 FinalizeForRendering();
135wxString Route::IsPointNameValid(
RoutePoint *pPoint,
136 const wxString &name)
const {
139 wxString substr = name;
142 point = node->GetData();
143 wxString exist = point->GetName();
146 node = node->GetNext();
147 }
else if (substr == exist) {
148 return _(
"Name is not unique in route");
150 node = node->GetNext();
154 return wxEmptyString;
157void Route::AddPoint(
RoutePoint *pNewPoint,
bool b_rename_in_sequence,
158 bool b_deferBoxCalc) {
160 pNewPoint->SetShared(
true);
168 if (!b_deferBoxCalc) FinalizeForRendering();
172 if (b_rename_in_sequence && pNewPoint->GetName().IsEmpty() &&
173 !pNewPoint->IsShared()) {
175 name.Printf(_T(
"%03d"), GetnPoints());
176 pNewPoint->SetName(name);
181void Route::AddPointAndSegment(
RoutePoint *pNewPoint,
bool b_rename_in_sequence,
182 bool b_deferBoxCalc) {
183 int npoints = GetnPoints();
186 newpoint =
new RoutePoint(pNewPoint->m_lat, pNewPoint->m_lon,
187 pNewPoint->GetIconName(), pNewPoint->GetName(),
188 wxEmptyString,
false);
192 AddPoint(newpoint,
false);
194 double rlat = GetPoint(npoints)->m_lat;
195 double rlon = GetPoint(npoints)->m_lon;
196 npoints = GetnPoints();
197 pSelect->AddSelectableRouteSegment(
198 rlat, rlon, GetPoint(npoints)->m_lat, GetPoint(npoints)->m_lon,
199 GetPoint(npoints - 1), GetPoint(npoints),
this);
204void Route::InsertPointAndSegment(
RoutePoint *pNewPoint,
int insert_after,
205 bool bRenamePoints,
bool b_deferBoxCalc) {
210 pNewPoint->SetShared(
true);
215 if (insert_after >= GetnPoints() - 1) {
216 wxLogMessage(wxT(
"Error insert after last point"));
220 int insert = insert_after++;
222 pNewPoint->SetNameShown(
false);
224 if (bRenamePoints) RenameRoutePoints();
226 FinalizeForRendering();
227 UpdateSegmentDistances();
238 prp = node->GetData();
239 if (i == nWhichPoint) {
243 node = node->GetNext();
249RoutePoint *Route::GetPoint(
const wxString &guid) {
254 prp = node->GetData();
255 if (guid == prp->
m_GUID)
return prp;
257 node = node->GetNext();
263static void TestLongitude(
double lon,
double min,
double max,
bool &lonl,
265 double clon = (min + max) / 2;
266 if (min - lon > 180) lon += 360;
270 if (lon < clon - 180)
274 }
else if (lon > max) {
275 if (lon > clon + 180)
282bool Route::ContainsSharedWP() {
284 node = node->GetNext()) {
286 if (prp->IsShared())
return true;
292int s_arrow_icon[] = {0, 0, 5, 2, 18, 6, 12, 0, 18, -6, 5, -2, 0, 0};
293void Route::ClearHighlights(
void) {
298 prp = node->GetData();
300 node = node->GetNext();
305 bool bRenamePoints) {
307 GetNewMarkSequenced(), wxEmptyString);
309 newpoint->SetNameShown(
false);
314 if (bRenamePoints) RenameRoutePoints();
316 FinalizeForRendering();
317 UpdateSegmentDistances();
323 bool bRenamePoints) {
325 if (nRP >= GetnPoints() - 1)
return NULL;
329 GetNewMarkSequenced(), wxEmptyString);
331 newpoint->SetNameShown(
false);
335 if (bRenamePoints) RenameRoutePoints();
337 FinalizeForRendering();
338 UpdateSegmentDistances();
343wxString Route::GetNewMarkSequenced(
void) {
345 ret.Printf(_T (
"NM%03d" ), m_nm_sequence);
359 if (ret == wxNOT_FOUND)
365void Route::DeletePoint(
RoutePoint *rp,
bool bRenamePoints) {
370 pSelect->DeleteAllSelectableRoutePoints(
this);
371 pSelect->DeleteAllSelectableRouteSegments(
this);
377 if (bRenamePoints) RenameRoutePoints();
379 if (GetnPoints() > 1) {
380 pSelect->AddAllSelectableRouteSegments(
this);
381 pSelect->AddAllSelectableRoutePoints(
this);
383 FinalizeForRendering();
384 UpdateSegmentDistances();
388void Route::RemovePoint(
RoutePoint *rp,
bool bRenamePoints) {
390 g_pRouteMan->DeactivateRoute();
392 pSelect->DeleteAllSelectableRoutePoints(
this);
393 pSelect->DeleteAllSelectableRouteSegments(
this);
404 Route *pcontainer_route = FindRouteContainingWaypoint(rp);
406 if (pcontainer_route == NULL) {
409 NavObj_dB::GetInstance().UpdateRoutePoint(rp);
412 if (bRenamePoints) RenameRoutePoints();
416 pSelect->AddAllSelectableRouteSegments(
this);
417 pSelect->AddAllSelectableRoutePoints(
this);
420 NavObj_dB::GetInstance().UpdateRoute(
this);
421 FinalizeForRendering();
422 UpdateSegmentDistances();
426void Route::DeSelectRoute() {
431 rp = node->GetData();
434 node = node->GetNext();
438void Route::ReloadRoutePointIcons() {
443 rp = node->GetData();
446 node = node->GetNext();
450void Route::FinalizeForRendering() { RBBox.Invalidate(); }
452LLBBox &Route::GetBBox(
void) {
453 if (RBBox.GetValid())
return RBBox;
455 double bbox_lonmin, bbox_lonmax, bbox_latmin, bbox_latmax;
460 if (data->m_wpBBox.GetValid()) {
461 bbox_lonmax = data->
m_wpBBox.GetMaxLon();
462 bbox_lonmin = data->m_wpBBox.GetMinLon();
463 bbox_latmax = data->m_wpBBox.GetMaxLat();
464 bbox_latmin = data->m_wpBBox.GetMinLat();
466 bbox_lonmax = bbox_lonmin = data->m_lon;
467 bbox_latmax = bbox_latmin = data->m_lat;
470 double lastlon = data->m_lon, wrap = 0;
472 node = node->GetNext();
474 data = node->GetData();
476 if (lastlon - data->m_lon > 180)
478 else if (data->m_lon - lastlon > 180)
481 double lon = data->m_lon + wrap;
483 if (lon > bbox_lonmax) bbox_lonmax = lon;
484 if (lon < bbox_lonmin) bbox_lonmin = lon;
486 if (data->m_lat > bbox_latmax) bbox_latmax = data->m_lat;
487 if (data->m_lat < bbox_latmin) bbox_latmin = data->m_lat;
489 lastlon = data->m_lon;
490 node = node->GetNext();
493 if (bbox_lonmin < -360)
494 bbox_lonmin += 360, bbox_lonmax += 360;
495 else if (bbox_lonmax > 360)
496 bbox_lonmin -= 360, bbox_lonmax -= 360;
498 if (bbox_lonmax - bbox_lonmin > 360) bbox_lonmin = -180, bbox_lonmax = 180;
500 RBBox.Set(bbox_latmin, bbox_lonmin, bbox_latmax, bbox_lonmax);
511 double slat1 = prp0->m_lat, slon1 = prp0->m_lon;
512 double slat2 = prp->m_lat, slon2 = prp->m_lon;
519 DistanceBearingMercator(slat2, slon2, slat1, slon1, &br, &dd);
522 prp->SetDistance(dd);
532 if (planspeed > 0.) {
535 double legspeed = planspeed;
538 if (legspeed > 0.1 && legspeed < 1000.) {
543 prp->SetETE(duration);
544 wxTimeSpan ts(0, 0, duration);
547 if (prp0->
GetETA().IsValid()) {
567void Route::UpdateSegmentDistances(
double planspeed) {
582 node = node->GetNext();
590 node = node->GetNext();
595void Route::Reverse(
bool bRenamePoints) {
597 wxArrayString RoutePointGUIDList;
600 for (
int i = 0; i < ncount; i++)
601 RoutePointGUIDList.Add(GetPoint(ncount - i)->
m_GUID);
608 for (
unsigned int ip = 0; ip < RoutePointGUIDList.GetCount(); ip++) {
609 wxString GUID = RoutePointGUIDList[ip];
612 wxRoutePointListNode *prpnode = pWayPointMan->GetWaypointList()->GetFirst();
616 if (prp->
m_GUID == GUID) {
620 prpnode = prpnode->GetNext();
624 if (bRenamePoints) RenameRoutePoints();
632void Route::SetVisible(
bool visible,
bool includeWpts) {
633 m_bVisible = visible;
635 if (!includeWpts)
return;
640 rp = node->GetData();
645 if (rp->IsShared()) {
646 if (visible) rp->SetVisible(visible);
648 node = node->GetNext();
652void Route::SetListed(
bool visible) { m_bListed = visible; }
654void Route::AssembleRoute(
void) {}
656void Route::ShowWaypointNames(
bool bshow) {
661 prp->SetNameShown(bshow);
663 node = node->GetNext();
667bool Route::AreWaypointNamesVisible() {
673 if (prp->GetNameShown()) bvis =
true;
675 node = node->GetNext();
681void Route::RenameRoutePoints(
void) {
691 wxString name = prp->GetName();
692 if (name.Len() == 3) {
693 name.Printf(_T (
"%03d" ), i);
694 }
else if (name.Left(2) ==
"NM") {
695 name.Printf(_T (
"%03d" ), i);
696 if (prp->GetName().Len() >= 5) {
697 name.Append(prp->GetName().Mid(5));
700 name.Printf(_T (
"%03d" ), i);
701 name.Append(prp->GetName().Mid(3));
706 node = node->GetNext();
713bool Route::IsEqualTo(
Route *ptargetroute) {
715 wxRoutePointListNode *pthatnode = (ptargetroute->
pRoutePointList)->GetFirst();
717 if (NULL == pthisnode)
return false;
721 if (this->GetnPoints() != ptargetroute->GetnPoints())
return false;
724 if (NULL == pthatnode)
return false;
729 if ((fabs(pthisrp->m_lat - pthatrp->m_lat) > 1.0e-6) ||
730 (fabs(pthisrp->m_lon - pthatrp->m_lon) > 1.0e-6))
733 if (!pthisrp->GetName().IsSameAs(pthatrp->GetName()))
return false;
735 pthisnode = pthisnode->GetNext();
736 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.
Global variables stored in configuration file.