25 #include <wx/wxprec.h>
35 #include <wx/arrstr.h>
36 #include <wx/datetime.h>
37 #include <wx/gdicmn.h>
40 #include <wx/string.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"
53 double g_defaultBoatSpeed;
55 #include <wx/listimpl.cpp>
56 WX_DEFINE_LIST(RouteList);
59 m_bRtIsSelected =
false;
60 m_bRtIsActive =
false;
61 m_pRouteActivePoint = NULL;
62 m_bIsBeingEdited =
false;
63 m_bIsBeingCreated =
false;
69 m_bDeleteOnArrival =
false;
70 m_width = WIDTH_UNDEFINED;
71 m_style = wxPENSTYLE_INVALID;
74 pRoutePointList =
new RoutePointList;
75 m_GUID = pWayPointMan->CreateGUID(NULL);
78 m_ArrivalRadius = g_n_arrival_circle_radius;
83 m_Colour = wxEmptyString;
85 m_lastMousePointIndex = 0;
86 m_NextLegGreatCircle =
false;
88 m_PlannedSpeed = ROUTE_DEFAULT_SPEED;
89 if (g_defaultBoatSpeed != ROUTE_DEFAULT_SPEED) m_PlannedSpeed = g_defaultBoatSpeed;
91 m_PlannedDeparture = RTE_UNDEF_DEPARTURE;
92 m_TimeDisplayFormat = RTE_TIME_DISP_PC;
93 m_HyperlinkList =
new HyperlinkList;
95 m_bsharedWPViz =
false;
99 pRoutePointList->DeleteContents(
false);
100 delete pRoutePointList;
101 delete m_HyperlinkList;
107 void Route::CloneRoute(
Route *psourceroute,
int start_nPoint,
int end_nPoint,
108 const wxString &suffix,
109 const bool duplicate_first_point) {
110 m_RouteNameString = psourceroute->m_RouteNameString + suffix;
111 m_RouteStartString = psourceroute->m_RouteStartString;
112 m_RouteEndString = psourceroute->m_RouteEndString;
115 for (i = start_nPoint; i <= end_nPoint; i++) {
116 if (!psourceroute->m_bIsInLayer &&
117 !(i == start_nPoint && duplicate_first_point)) {
118 AddPoint(psourceroute->GetPoint(i),
false);
121 RoutePoint *psourcepoint = psourceroute->GetPoint(i);
123 psourcepoint->m_lat, psourcepoint->m_lon, psourcepoint->GetIconName(),
124 psourcepoint->GetName(), wxEmptyString,
true);
125 ptargetpoint->m_bShowName =
126 psourcepoint->m_bShowName;
127 AddPoint(ptargetpoint,
false);
131 FinalizeForRendering();
134 void Route::AddPoint(
RoutePoint *pNewPoint,
bool b_rename_in_sequence,
135 bool b_deferBoxCalc) {
136 if (pNewPoint->m_bIsolatedMark) {
137 pNewPoint->SetShared(
true);
139 pNewPoint->m_bIsolatedMark =
false;
140 pNewPoint->m_bIsInRoute =
true;
143 pRoutePointList->Append(pNewPoint);
145 if (!b_deferBoxCalc) FinalizeForRendering();
147 if (prev) UpdateSegmentDistance(prev, pNewPoint);
149 if (b_rename_in_sequence && pNewPoint->GetName().IsEmpty() &&
150 !pNewPoint->IsShared()) {
152 name.Printf(_T(
"%03d"), GetnPoints());
153 pNewPoint->SetName(name);
154 pNewPoint->m_bDynamicName =
true;
159 void Route::AddPointAndSegment(
RoutePoint *pNewPoint,
bool b_rename_in_sequence,
160 bool b_deferBoxCalc) {
161 int npoints = GetnPoints();
163 if (newpoint->m_bIsInLayer) {
164 newpoint =
new RoutePoint(pNewPoint->m_lat, pNewPoint->m_lon,
165 pNewPoint->GetIconName(), pNewPoint->GetName(), wxEmptyString,
false);
166 newpoint->m_bShowName = pNewPoint->m_bShowName;
168 AddPoint(newpoint,
false);
170 double rlat = GetPoint(npoints)->m_lat;
171 double rlon = GetPoint(npoints)->m_lon;
172 npoints = GetnPoints();
173 pSelect->AddSelectableRouteSegment(rlat, rlon,
174 GetPoint(npoints)->m_lat, GetPoint(npoints)->m_lon, GetPoint(npoints - 1), GetPoint(npoints),
this);
176 m_lastMousePointIndex = GetnPoints();
179 void Route::InsertPointAndSegment(
RoutePoint *pNewPoint,
int insert_after,
bool bRenamePoints,
bool b_deferBoxCalc)
184 if (pNewPoint->m_bIsolatedMark) {
185 pNewPoint->SetShared(
true);
187 pNewPoint->m_bIsolatedMark =
false;
188 pNewPoint->m_bIsInRoute =
true;
190 if (insert_after >= GetnPoints() - 1) {
191 wxLogMessage(wxT(
"Error insert after last point"));
195 int insert = insert_after++;
196 pNewPoint->m_bIsInRoute =
true;
197 pNewPoint->m_bDynamicName =
true;
198 pNewPoint->SetNameShown(
false);
199 pRoutePointList->Insert(insert, pNewPoint);
200 if (bRenamePoints) RenameRoutePoints();
201 m_lastMousePointIndex = GetnPoints();
202 FinalizeForRendering();
203 UpdateSegmentDistances();
208 RoutePoint *Route::GetPoint(
int nWhichPoint) {
210 wxRoutePointListNode *node = pRoutePointList->GetFirst();
214 prp = node->GetData();
215 if (i == nWhichPoint) {
219 node = node->GetNext();
225 RoutePoint *Route::GetPoint(
const wxString &guid) {
227 wxRoutePointListNode *node = pRoutePointList->GetFirst();
230 prp = node->GetData();
231 if (guid == prp->m_GUID)
return prp;
233 node = node->GetNext();
239 static void TestLongitude(
double lon,
double min,
double max,
bool &lonl,
241 double clon = (min + max) / 2;
242 if (min - lon > 180) lon += 360;
246 if (lon < clon - 180)
250 }
else if (lon > max) {
251 if (lon > clon + 180)
258 bool Route::ContainsSharedWP() {
259 for (wxRoutePointListNode *node = pRoutePointList->GetFirst(); node;
260 node = node->GetNext()) {
262 if (prp->IsShared())
return true;
268 int s_arrow_icon[] = {0, 0, 5, 2, 18, 6, 12, 0, 18, -6, 5, -2, 0, 0};
269 void Route::ClearHighlights(
void) {
271 wxRoutePointListNode *node = pRoutePointList->GetFirst();
274 prp = node->GetData();
275 if (prp) prp->m_bPtIsSelected =
false;
276 node = node->GetNext();
281 bool bRenamePoints) {
283 GetNewMarkSequenced(), wxEmptyString);
284 newpoint->m_bIsInRoute =
true;
285 newpoint->m_bDynamicName =
true;
286 newpoint->SetNameShown(
false);
288 int nRP = pRoutePointList->IndexOf(pRP);
289 pRoutePointList->Insert(nRP, newpoint);
291 if (bRenamePoints) RenameRoutePoints();
293 FinalizeForRendering();
294 UpdateSegmentDistances();
300 bool bRenamePoints) {
301 int nRP = pRoutePointList->IndexOf(pRP);
302 if (nRP >= GetnPoints() - 1)
return NULL;
306 GetNewMarkSequenced(), wxEmptyString);
307 newpoint->m_bIsInRoute =
true;
308 newpoint->m_bDynamicName =
true;
309 newpoint->SetNameShown(
false);
311 pRoutePointList->Insert(nRP, newpoint);
313 if (bRenamePoints) RenameRoutePoints();
315 FinalizeForRendering();
316 UpdateSegmentDistances();
321 wxString Route::GetNewMarkSequenced(
void) {
323 ret.Printf(_T (
"NM%03d" ), m_nm_sequence);
330 if (pRoutePointList->IsEmpty())
return NULL;
332 return pRoutePointList->GetLast()->GetData();
336 int ret = pRoutePointList->IndexOf(prp) + 1;
337 if (ret == wxNOT_FOUND)
343 void Route::DeletePoint(
RoutePoint *rp,
bool bRenamePoints) {
346 if (rp->m_bIsInLayer)
return;
348 pSelect->DeleteAllSelectableRoutePoints(
this);
349 pSelect->DeleteAllSelectableRouteSegments(
this);
350 NavObjectChanges::getInstance()->DeleteWayPoint(rp);
352 pRoutePointList->DeleteObject(rp);
356 if (bRenamePoints) RenameRoutePoints();
358 if (GetnPoints() > 1) {
359 pSelect->AddAllSelectableRouteSegments(
this);
360 pSelect->AddAllSelectableRoutePoints(
this);
362 NavObjectChanges::getInstance()->UpdateRoute(
this);
364 FinalizeForRendering();
365 UpdateSegmentDistances();
369 void Route::RemovePoint(
RoutePoint *rp,
bool bRenamePoints) {
370 if (rp->m_bIsActive && this->IsActive())
371 g_pRouteMan->DeactivateRoute();
373 pSelect->DeleteAllSelectableRoutePoints(
this);
374 pSelect->DeleteAllSelectableRouteSegments(
this);
376 pRoutePointList->DeleteObject(rp);
379 Route *pcontainer_route = FindRouteContainingWaypoint(rp);
381 if (pcontainer_route == NULL) {
382 rp->m_bIsInRoute =
false;
383 rp->m_bDynamicName =
false;
384 rp->m_bIsolatedMark =
true;
387 if (bRenamePoints) RenameRoutePoints();
391 pSelect->AddAllSelectableRouteSegments(
this);
392 pSelect->AddAllSelectableRoutePoints(
this);
394 NavObjectChanges::getInstance()->UpdateRoute(
this);
396 FinalizeForRendering();
397 UpdateSegmentDistances();
401 void Route::DeSelectRoute() {
402 wxRoutePointListNode *node = pRoutePointList->GetFirst();
406 rp = node->GetData();
407 rp->m_bPtIsSelected =
false;
409 node = node->GetNext();
413 void Route::ReloadRoutePointIcons() {
414 wxRoutePointListNode *node = pRoutePointList->GetFirst();
418 rp = node->GetData();
421 node = node->GetNext();
425 void Route::FinalizeForRendering() { RBBox.Invalidate(); }
427 LLBBox &Route::GetBBox(
void) {
428 if (RBBox.GetValid())
return RBBox;
430 double bbox_lonmin, bbox_lonmax, bbox_latmin, bbox_latmax;
432 wxRoutePointListNode *node = pRoutePointList->GetFirst();
435 if (data->m_wpBBox.GetValid()) {
436 bbox_lonmax = data->m_wpBBox.GetMaxLon();
437 bbox_lonmin = data->m_wpBBox.GetMinLon();
438 bbox_latmax = data->m_wpBBox.GetMaxLat();
439 bbox_latmin = data->m_wpBBox.GetMinLat();
441 bbox_lonmax = bbox_lonmin = data->m_lon;
442 bbox_latmax = bbox_latmin = data->m_lat;
445 double lastlon = data->m_lon, wrap = 0;
447 node = node->GetNext();
449 data = node->GetData();
451 if (lastlon - data->m_lon > 180)
453 else if (data->m_lon - lastlon > 180)
456 double lon = data->m_lon + wrap;
458 if (lon > bbox_lonmax) bbox_lonmax = lon;
459 if (lon < bbox_lonmin) bbox_lonmin = lon;
461 if (data->m_lat > bbox_latmax) bbox_latmax = data->m_lat;
462 if (data->m_lat < bbox_latmin) bbox_latmin = data->m_lat;
464 lastlon = data->m_lon;
465 node = node->GetNext();
468 if (bbox_lonmin < -360)
469 bbox_lonmin += 360, bbox_lonmax += 360;
470 else if (bbox_lonmax > 360)
471 bbox_lonmin -= 360, bbox_lonmax -= 360;
473 if (bbox_lonmax - bbox_lonmin > 360) bbox_lonmin = -180, bbox_lonmax = 180;
475 RBBox.Set(bbox_latmin, bbox_lonmin, bbox_latmax, bbox_lonmax);
486 double slat1 = prp0->m_lat, slon1 = prp0->m_lon;
487 double slat2 = prp->m_lat, slon2 = prp->m_lon;
494 DistanceBearingMercator(slat2, slon2, slat1, slon1, &br, &dd);
497 prp->SetDistance(dd);
502 m_route_length += dd;
507 if (planspeed > 0.) {
510 double legspeed = planspeed;
511 if (prp->GetPlannedSpeed() > 0.1 && prp->GetPlannedSpeed() < 1000.)
512 legspeed = prp->GetPlannedSpeed();
513 if (legspeed > 0.1 && legspeed < 1000.) {
514 m_route_time += 3600. * dd / legspeed;
515 prp->m_seg_vmg = legspeed;
517 wxLongLong duration = wxLongLong(3600.0 * prp->m_seg_len / prp->m_seg_vmg);
518 prp->SetETE(duration);
519 wxTimeSpan ts(0, 0, duration);
520 if (!prp0->GetManualETD().IsValid()) {
521 prp0->m_manual_etd =
false;
522 if (prp0->GetETA().IsValid()) {
523 prp0->m_seg_etd = prp0->GetETA();
526 m_PlannedDeparture + wxTimeSpan(0, 0, m_route_time - duration);
530 prp->m_seg_eta = prp0->GetETD() + ts;
531 if (!prp->m_manual_etd || !prp->GetETD().IsValid()) {
532 prp->m_seg_etd = prp->m_seg_eta;
533 prp->m_manual_etd =
false;
542 void Route::UpdateSegmentDistances(
double planspeed) {
545 m_route_length = 0.0;
548 wxRoutePointListNode *node = pRoutePointList->GetFirst();
553 if (!prp0->m_manual_etd) {
554 prp0->m_seg_eta = m_PlannedDeparture;
555 prp0->m_seg_etd = m_PlannedDeparture;
557 node = node->GetNext();
561 UpdateSegmentDistance(prp0, prp, planspeed);
565 node = node->GetNext();
570 void Route::Reverse(
bool bRenamePoints) {
572 wxArrayString RoutePointGUIDList;
574 int ncount = pRoutePointList->GetCount();
575 for (
int i = 0; i < ncount; i++)
576 RoutePointGUIDList.Add(GetPoint(ncount - i)->m_GUID);
578 pRoutePointList->DeleteContents(
false);
579 pRoutePointList->Clear();
580 m_route_length = 0.0;
583 for (
unsigned int ip = 0; ip < RoutePointGUIDList.GetCount(); ip++) {
584 wxString GUID = RoutePointGUIDList[ip];
587 wxRoutePointListNode *prpnode = pWayPointMan->GetWaypointList()->GetFirst();
591 if (prp->m_GUID == GUID) {
595 prpnode = prpnode->GetNext();
599 if (bRenamePoints) RenameRoutePoints();
602 wxString tmp = m_RouteStartString;
603 m_RouteStartString = m_RouteEndString;
604 m_RouteEndString = tmp;
607 void Route::SetVisible(
bool visible,
bool includeWpts) {
608 m_bVisible = visible;
610 if (!includeWpts)
return;
612 wxRoutePointListNode *node = pRoutePointList->GetFirst();
615 rp = node->GetData();
620 if (rp->IsShared()) {
621 if (visible) rp->SetVisible(visible);
623 node = node->GetNext();
627 void Route::SetListed(
bool visible) { m_bListed = visible; }
629 void Route::AssembleRoute(
void) {}
631 void Route::ShowWaypointNames(
bool bshow) {
632 wxRoutePointListNode *node = pRoutePointList->GetFirst();
636 prp->SetNameShown(bshow);
638 node = node->GetNext();
642 bool Route::AreWaypointNamesVisible() {
644 wxRoutePointListNode *node = pRoutePointList->GetFirst();
648 if (prp->GetNameShown()) bvis =
true;
650 node = node->GetNext();
656 void Route::RenameRoutePoints(
void) {
660 wxRoutePointListNode *node = pRoutePointList->GetFirst();
665 if (prp->m_bDynamicName) {
667 name.Printf(_T (
"%03d" ), i);
671 node = node->GetNext();
678 bool Route::IsEqualTo(
Route *ptargetroute) {
679 wxRoutePointListNode *pthisnode = (this->pRoutePointList)->GetFirst();
680 wxRoutePointListNode *pthatnode = (ptargetroute->pRoutePointList)->GetFirst();
682 if (NULL == pthisnode)
return false;
684 if (this->m_bIsInLayer || ptargetroute->m_bIsInLayer)
return false;
686 if (this->GetnPoints() != ptargetroute->GetnPoints())
return false;
689 if (NULL == pthatnode)
return false;
694 if ((fabs(pthisrp->m_lat - pthatrp->m_lat) > 1.0e-6) ||
695 (fabs(pthisrp->m_lon - pthatrp->m_lon) > 1.0e-6))
698 if (!pthisrp->GetName().IsSameAs(pthatrp->GetName()))
return false;
700 pthisnode = pthisnode->GetNext();
701 pthatnode = pthatnode->GetNext();