36#include <wx/jsonval.h>
37#include <wx/listimpl.cpp>
38#include <wx/tokenzr.h>
41#include "model/autopilot_output.h"
42#include "model/base_platform.h"
43#include "model/comm_n0183_output.h"
44#include "model/comm_vars.h"
45#include "model/config_vars.h"
46#include "model/cutil.h"
47#include "model/georef.h"
48#include "model/nav_object_database.h"
49#include "model/navutil_base.h"
50#include "model/nmea_ctx_factory.h"
51#include "model/own_ship.h"
52#include "model/route.h"
53#include "model/routeman.h"
54#include "model/track.h"
62#include "androidUTIL.h"
65bool g_bPluginHandleAutopilotRoute;
75float g_ChartScaleFactorExp;
78WX_DECLARE_LIST(wxBitmap, markicon_bitmap_list_type);
79WX_DECLARE_LIST(wxString, markicon_key_list_type);
80WX_DECLARE_LIST(wxString, markicon_description_list_type);
83#include <wx/listimpl.cpp>
84WX_DEFINE_LIST(markicon_bitmap_list_type);
85WX_DEFINE_LIST(markicon_key_list_type);
86WX_DEFINE_LIST(markicon_description_list_type);
89void appendOSDirSlash(wxString *pString);
91static void ActivatePersistedRoute(
Routeman *routeman) {
92 if (g_active_route ==
"") {
93 wxLogWarning(
"\"Persist route\" but no persisted route configured");
96 Route *route = routeman->FindRouteByGUID(g_active_route);
98 wxLogWarning(
"Persisted route GUID not available");
112 pRouteActivatePoint(0),
113 m_NMEA0183(NmeaCtxFactory()),
115 m_route_dlg_ctx(route_dlg_ctx) {
117 auto route_action = [&](wxCommandEvent) {
118 if (g_persist_active_route) ActivatePersistedRoute(
this);
120 active_route_listener.Init(active_route, route_action);
123Routeman::~Routeman() {
124 if (pRouteActivatePoint)
delete pRouteActivatePoint;
127bool Routeman::IsRouteValid(
Route *pRoute) {
128 wxRouteListNode *node = pRouteList->GetFirst();
130 if (pRoute == node->GetData())
return true;
131 node = node->GetNext();
138 wxRouteListNode *node = pRouteList->GetFirst();
140 Route *proute = node->GetData();
145 if (prp == pWP)
return proute;
146 pnode = pnode->GetNext();
149 node = node->GetNext();
156Route *Routeman::FindRouteContainingWaypoint(
const std::string &guid) {
157 wxRouteListNode *node = pRouteList->GetFirst();
159 Route *proute = node->GetData();
164 if (prp->
m_GUID == guid)
return proute;
165 pnode = pnode->GetNext();
168 node = node->GetNext();
176 wxRouteListNode *node = pRouteList->GetFirst();
178 Route *proute = node->GetData();
179 if (proute->IsVisible()) {
183 if (prp == pWP)
return proute;
184 pnode = pnode->GetNext();
188 node = node->GetNext();
195 wxArrayPtrVoid *pArray =
new wxArrayPtrVoid;
197 wxRouteListNode *route_node = pRouteList->GetFirst();
199 Route *proute = route_node->GetData();
201 wxRoutePointListNode *waypoint_node = (proute->
pRoutePointList)->GetFirst();
202 while (waypoint_node) {
205 pArray->Add((
void *)proute);
210 waypoint_node = waypoint_node->GetNext();
213 route_node = route_node->GetNext();
216 if (pArray->GetCount())
228 pSelect->DeleteAllSelectableRoutePoints(route);
229 pSelect->DeleteAllSelectableRouteSegments(route);
231 route->RemovePoint(point);
235 if (route->GetnPoints() <= 1 && route_state == 0) {
240 pSelect->AddSelectableRoutePoint(point->m_lat, point->m_lon, point);
245 m_prop_dlg_ctx.set_route_and_update(route);
248RoutePoint *Routeman::FindBestActivatePoint(
Route *pR,
double lat,
double lon,
249 double cog,
double sog) {
250 if (!pR)
return NULL;
254 double min_time_found = 1e6;
261 DistanceBearingMercator(pn->m_lat, pn->m_lon, lat, lon, &brg, &dist);
263 double angle = brg - cog;
264 double soa = cos(angle * PI / 180.);
266 double time_to_wp = dist / soa;
268 if (time_to_wp > 0) {
269 if (time_to_wp < min_time_found) {
270 min_time_found = time_to_wp;
274 node = node->GetNext();
280 g_bAllowShipToActive =
false;
283 v[_T(
"GUID")] = pRouteToActivate->
m_GUID;
284 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_ACTIVATED");
285 if (g_bPluginHandleAutopilotRoute)
return true;
289 m_have_n0183_out =
false;
290 m_have_n2000_out =
false;
292 m_output_drivers.clear();
295 if (attributes.find(
"protocol") == attributes.end())
continue;
296 if (attributes.at(
"protocol") ==
"nmea0183") {
297 if (attributes.find(
"ioDirection") != attributes.end()) {
298 if ((attributes.at(
"ioDirection") ==
"IN/OUT") ||
299 (attributes.at(
"ioDirection") ==
"OUT")) {
300 m_output_drivers.push_back(handle);
301 m_have_n0183_out =
true;
307 if (attributes.find(
"protocol") == attributes.end())
continue;
308 if (attributes.at(
"protocol") ==
"nmea2000") {
309 if (attributes.find(
"ioDirection") != attributes.end()) {
310 if ((attributes.at(
"ioDirection") ==
"IN/OUT") ||
311 (attributes.at(
"ioDirection") ==
"OUT")) {
312 m_output_drivers.push_back(handle);
313 m_have_n2000_out =
true;
320 pActiveRoute = pRouteToActivate;
321 g_active_route = pActiveRoute->GetGUID();
324 pActivePoint = pStartPoint;
326 wxRoutePointListNode *node = (pActiveRoute->
pRoutePointList)->GetFirst();
327 pActivePoint = node->GetData();
338 m_bDataValid =
false;
340 m_route_dlg_ctx.show_with_fresh_fonts();
345 g_bAllowShipToActive =
false;
347 v[_T(
"GUID")] = pRP_target->
m_GUID;
348 v[_T(
"WP_activated")] = pRP_target->GetName();
350 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_WPT_ACTIVATED");
352 if (g_bPluginHandleAutopilotRoute)
return true;
356 pActivePoint = pRP_target;
359 wxRoutePointListNode *node = (pActiveRoute->
pRoutePointList)->GetFirst();
365 node = node->GetNext();
373 if (pRP_target == prp_first) {
374 if (pRouteActivatePoint)
delete pRouteActivatePoint;
376 pRouteActivatePoint =
377 new RoutePoint(gLat, gLon, wxString(_T(
"")), wxString(_T(
"Begin")),
378 wxEmptyString,
false);
381 pActiveRouteSegmentBeginPoint = pRouteActivatePoint;
386 node = node->GetNext();
390 if (pnext == pRP_target) {
391 pActiveRouteSegmentBeginPoint = np_prev;
396 node = node->GetNext();
415 m_prop_dlg_ctx.set_enroute_point(pA, pActivePoint);
420 g_bAllowShipToActive =
false;
427 v[_T(
"isSkipped")] = skipped;
428 v[_T(
"GUID")] = pActivePoint->
m_GUID;
429 v[_T(
"GUID_WP_arrived")] = pActivePoint->
m_GUID;
430 v[_T(
"WP_arrived")] = pActivePoint->GetName();
432 int n_index_active = pActiveRoute->GetIndexOf(pActivePoint);
434 while (n_index_active == pActiveRoute->GetIndexOf(pActivePoint)) {
435 if ((n_index_active + step) <= pActiveRoute->GetnPoints()) {
436 pActiveRouteSegmentBeginPoint = pActivePoint;
438 pActiveRoute->GetPoint(n_index_active + step);
439 pActivePoint = pActiveRoute->GetPoint(n_index_active + step);
448 v[_T(
"Next_WP")] = pActivePoint->GetName();
449 v[_T(
"GUID_Next_WP")] = pActivePoint->
m_GUID;
464 m_prop_dlg_ctx.set_enroute_point(pr, pActivePoint);
466 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_WPT_ARRIVED");
471bool Routeman::DeactivateRoute(
bool b_arrival) {
480 g_active_route.Clear();
485 v[_T(
"GUID")] = pActiveRoute->
m_GUID;
486 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_DEACTIVATED");
488 v[_T(
"GUID")] = pActiveRoute->
m_GUID;
490 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_ENDED");
496 if (pRouteActivatePoint)
delete pRouteActivatePoint;
497 pRouteActivatePoint = NULL;
501 m_route_dlg_ctx.clear_console_background();
502 m_bDataValid =
false;
507bool Routeman::UpdateAutopilot() {
508 if (!pActiveRoute)
return false;
510 if (!bGPSValid)
return false;
515 if ((g_maxWPNameLength >= 3) && (g_maxWPNameLength <= 32))
516 maxName = g_maxWPNameLength;
518 if (m_have_n0183_out) rv |= UpdateAutopilotN0183(*
this);
519 if (m_have_n2000_out) rv |= UpdateAutopilotN2K(*
this);
523 if (!pActiveRoute)
return false;
527 leg_info.Btw = CurrentBrgToActivePoint;
528 leg_info.Dtw = CurrentRngToActivePoint;
529 leg_info.Xte = CurrentXTEToActivePoint;
531 leg_info.Xte = -leg_info.Xte;
533 leg_info.wp_name = pActivePoint->GetName().Truncate(maxName);
534 leg_info.arrival = m_bArrival;
545 if ((g_maxWPNameLength >= 3) && (g_maxWPNameLength <= 32))
546 maxName = g_maxWPNameLength;
550 double r_Sog(0.0), r_Cog(0.0);
551 if (!std::isnan(gSog)) r_Sog = gSog;
552 if (!std::isnan(gCog)) r_Cog = gCog;
557 leg_info.Btw = CurrentBrgToActivePoint;
558 leg_info.Dtw = CurrentRngToActivePoint;
559 leg_info.Xte = CurrentXTEToActivePoint;
561 leg_info.Xte = -leg_info.Xte;
563 leg_info.wp_name = pActivePoint->GetName().Truncate(maxName);
564 leg_info.arrival = m_bArrival;
570 m_NMEA0183.TalkerID =
"EC";
572 m_NMEA0183.Rmb.IsDataValid = bGPSValid ? NTrue : NFalse;
573 m_NMEA0183.Rmb.CrossTrackError = CurrentXTEToActivePoint;
574 m_NMEA0183.Rmb.DirectionToSteer = XTEDir < 0 ? Left : Right;
575 m_NMEA0183.Rmb.RangeToDestinationNauticalMiles = CurrentRngToActivePoint;
576 m_NMEA0183.Rmb.BearingToDestinationDegreesTrue = CurrentBrgToActivePoint;
578 if (pActivePoint->m_lat < 0.)
579 m_NMEA0183.Rmb.DestinationPosition.Latitude.Set(-pActivePoint->m_lat,
582 m_NMEA0183.Rmb.DestinationPosition.Latitude.Set(pActivePoint->m_lat,
"N");
584 if (pActivePoint->m_lon < 0.)
585 m_NMEA0183.Rmb.DestinationPosition.Longitude.Set(-pActivePoint->m_lon,
588 m_NMEA0183.Rmb.DestinationPosition.Longitude.Set(pActivePoint->m_lon,
591 m_NMEA0183.Rmb.DestinationClosingVelocityKnots =
592 r_Sog * cos((r_Cog - CurrentBrgToActivePoint) * PI / 180.0);
593 m_NMEA0183.Rmb.IsArrivalCircleEntered = m_bArrival ? NTrue : NFalse;
594 m_NMEA0183.Rmb.FAAModeIndicator = bGPSValid ?
"A" :
"N";
597 int wp_len = maxName;
599 m_NMEA0183.Rmb.To = pActivePoint->GetName().Truncate(wp_len);
600 m_NMEA0183.Rmb.From =
601 pActiveRouteSegmentBeginPoint->GetName().Truncate(wp_len);
602 m_NMEA0183.Rmb.Write(snt);
604 }
while (snt.Sentence.size() > 82 && wp_len > 0);
611 m_NMEA0183.TalkerID = _T(
"EC");
614 m_NMEA0183.Rmc.IsDataValid = NTrue;
615 if (!bGPSValid) m_NMEA0183.Rmc.IsDataValid = NFalse;
618 m_NMEA0183.Rmc.Position.Latitude.Set(-gLat, _T(
"S"));
620 m_NMEA0183.Rmc.Position.Latitude.Set(gLat, _T(
"N"));
623 m_NMEA0183.Rmc.Position.Longitude.Set(-gLon, _T(
"W"));
625 m_NMEA0183.Rmc.Position.Longitude.Set(gLon, _T(
"E"));
627 m_NMEA0183.Rmc.SpeedOverGroundKnots = r_Sog;
628 m_NMEA0183.Rmc.TrackMadeGoodDegreesTrue = r_Cog;
630 if (!std::isnan(gVar)) {
632 m_NMEA0183.Rmc.MagneticVariation = -gVar;
633 m_NMEA0183.Rmc.MagneticVariationDirection = West;
635 m_NMEA0183.Rmc.MagneticVariation = gVar;
636 m_NMEA0183.Rmc.MagneticVariationDirection = East;
639 m_NMEA0183.Rmc.MagneticVariation =
643 if (!gRmcTime.IsEmpty() && !gRmcDate.IsEmpty()) {
644 m_NMEA0183.Rmc.UTCTime = gRmcTime;
645 m_NMEA0183.Rmc.Date = gRmcDate;
647 wxDateTime now = wxDateTime::Now();
648 wxDateTime utc = now.ToUTC();
649 wxString time = utc.Format(_T(
"%H%M%S"));
650 m_NMEA0183.Rmc.UTCTime = time;
651 wxString date = utc.Format(_T(
"%d%m%y"));
652 m_NMEA0183.Rmc.Date = date;
655 m_NMEA0183.Rmc.FAAModeIndicator =
"A";
656 if (!bGPSValid) m_NMEA0183.Rmc.FAAModeIndicator =
"N";
658 m_NMEA0183.Rmc.Write(snt);
665 m_NMEA0183.TalkerID = _T(
"EC");
669 m_NMEA0183.Apb.IsLoranBlinkOK =
671 if (!bGPSValid) m_NMEA0183.Apb.IsLoranBlinkOK = NFalse;
673 m_NMEA0183.Apb.IsLoranCCycleLockOK = NTrue;
674 if (!bGPSValid) m_NMEA0183.Apb.IsLoranCCycleLockOK = NFalse;
676 m_NMEA0183.Apb.CrossTrackErrorMagnitude = CurrentXTEToActivePoint;
679 m_NMEA0183.Apb.DirectionToSteer = Left;
681 m_NMEA0183.Apb.DirectionToSteer = Right;
683 m_NMEA0183.Apb.CrossTrackUnits = _T(
"N");
686 m_NMEA0183.Apb.IsArrivalCircleEntered = NTrue;
688 m_NMEA0183.Apb.IsArrivalCircleEntered = NFalse;
692 m_NMEA0183.Apb.IsPerpendicular = NFalse;
694 m_NMEA0183.Apb.To = pActivePoint->GetName().Truncate(maxName);
697 DistanceBearingMercator(pActivePoint->m_lat, pActivePoint->m_lon,
698 pActiveRouteSegmentBeginPoint->m_lat,
699 pActiveRouteSegmentBeginPoint->m_lon, &brg1,
702 if (g_bMagneticAPB && !std::isnan(gVar)) {
704 ((brg1 - gVar) >= 0.) ? (brg1 - gVar) : (brg1 - gVar + 360.);
705 double bapm = ((CurrentBrgToActivePoint - gVar) >= 0.)
706 ? (CurrentBrgToActivePoint - gVar)
707 : (CurrentBrgToActivePoint - gVar + 360.);
709 m_NMEA0183.Apb.BearingOriginToDestination = brg1m;
710 m_NMEA0183.Apb.BearingOriginToDestinationUnits = _T(
"M");
712 m_NMEA0183.Apb.BearingPresentPositionToDestination = bapm;
713 m_NMEA0183.Apb.BearingPresentPositionToDestinationUnits = _T(
"M");
715 m_NMEA0183.Apb.HeadingToSteer = bapm;
716 m_NMEA0183.Apb.HeadingToSteerUnits = _T(
"M");
718 m_NMEA0183.Apb.BearingOriginToDestination = brg1;
719 m_NMEA0183.Apb.BearingOriginToDestinationUnits = _T(
"T");
721 m_NMEA0183.Apb.BearingPresentPositionToDestination =
722 CurrentBrgToActivePoint;
723 m_NMEA0183.Apb.BearingPresentPositionToDestinationUnits = _T(
"T");
725 m_NMEA0183.Apb.HeadingToSteer = CurrentBrgToActivePoint;
726 m_NMEA0183.Apb.HeadingToSteerUnits = _T(
"T");
729 m_NMEA0183.Apb.Write(snt);
735 m_NMEA0183.TalkerID = _T(
"EC");
739 m_NMEA0183.Xte.IsLoranBlinkOK =
741 if (!bGPSValid) m_NMEA0183.Xte.IsLoranBlinkOK = NFalse;
743 m_NMEA0183.Xte.IsLoranCCycleLockOK = NTrue;
744 if (!bGPSValid) m_NMEA0183.Xte.IsLoranCCycleLockOK = NFalse;
746 m_NMEA0183.Xte.CrossTrackErrorDistance = CurrentXTEToActivePoint;
749 m_NMEA0183.Xte.DirectionToSteer = Left;
751 m_NMEA0183.Xte.DirectionToSteer = Right;
753 m_NMEA0183.Xte.CrossTrackUnits = _T(
"N");
755 m_NMEA0183.Xte.Write(snt);
763bool Routeman::DoesRouteContainSharedPoints(
Route *pRoute) {
775 for (
unsigned int ir = 0; ir < pRA->GetCount(); ir++) {
785 if (pnode) pnode = pnode->GetNext();
792 if (prp->IsShared())
return true;
794 if (pnode) pnode = pnode->GetNext();
801bool Routeman::DeleteTrack(
Track *pTrack) {
802 if (pTrack && !pTrack->m_bIsInLayer) {
803 ::wxBeginBusyCursor();
819 pSelect->DeleteAllSelectableTrackSegments(pTrack);
820 auto it = std::find(g_TrackList.begin(), g_TrackList.end(), pTrack);
821 if (it != g_TrackList.end()) {
822 g_TrackList.erase(it);
836 if (pRoute == pAISMOBRoute) {
837 if (!m_route_dlg_ctx.confirm_delete_ais_mob()) {
842 ::wxBeginBusyCursor();
844 if (GetpActiveRoute() == pRoute) DeactivateRoute();
854 m_prop_dlg_ctx.hide(pRoute);
859 pSelect->DeleteAllSelectableRouteSegments(pRoute);
860 pRouteList->DeleteObject(pRoute);
862 m_route_dlg_ctx.route_mgr_dlg_update_list_ctrl();
871 Route *pcontainer_route = FindRouteContainingWaypoint(prp);
876 if (!prp->IsShared()) {
877 pSelect->DeleteSelectablePoint(prp, SELTYPE_ROUTEPOINT);
880 wxRoutePointListNode *pdnode = pnode;
887 NavObj_dB::GetInstance().DeleteRoutePoint(prp);
891 prp->SetShared(
false);
892 NavObj_dB::GetInstance().UpdateRoutePoint(prp);
896 pnode = pnode->GetNext();
901 NavObj_dB::GetInstance().DeleteRoute(pRoute);
909void Routeman::DeleteAllRoutes() {
910 ::wxBeginBusyCursor();
913 wxRouteListNode *node = pRouteList->GetFirst();
915 Route *proute = node->GetData();
916 if (proute == pAISMOBRoute) {
917 if (!m_route_dlg_ctx.confirm_delete_ais_mob()) {
921 ::wxBeginBusyCursor();
924 node = node->GetNext();
933void Routeman::SetColorScheme(ColorScheme cs,
double displayDPmm) {
936 int scaled_line_width = g_route_line_width;
937 int track_scaled_line_width = g_track_line_width;
940 double nominal_line_width_pix = wxMax(2.0, floor(displayDPmm * 0.4));
942 double sline_width = wxMax(nominal_line_width_pix, g_route_line_width);
943 sline_width *= g_ChartScaleFactorExp;
944 scaled_line_width = wxMax(sline_width, 2);
946 double tsline_width = wxMax(nominal_line_width_pix, g_track_line_width);
947 tsline_width *= g_ChartScaleFactorExp;
948 track_scaled_line_width = wxMax(tsline_width, 2);
951 m_pActiveRoutePointPen = wxThePenList->FindOrCreatePen(
952 wxColour(0, 0, 255), scaled_line_width, wxPENSTYLE_SOLID);
953 m_pRoutePointPen = wxThePenList->FindOrCreatePen(
954 wxColour(0, 0, 255), scaled_line_width, wxPENSTYLE_SOLID);
959 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UINFB"),
960 scaled_line_width, wxPENSTYLE_SOLID);
961 m_pSelectedRoutePen =
962 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UINFO"),
963 scaled_line_width, wxPENSTYLE_SOLID);
965 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UARTE"),
966 scaled_line_width, wxPENSTYLE_SOLID);
968 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"CHMGD"),
969 track_scaled_line_width, wxPENSTYLE_SOLID);
970 m_pRouteBrush = wxTheBrushList->FindOrCreateBrush(
971 m_route_dlg_ctx.get_global_colour(
"UINFB"), wxBRUSHSTYLE_SOLID);
972 m_pSelectedRouteBrush = wxTheBrushList->FindOrCreateBrush(
973 m_route_dlg_ctx.get_global_colour(
"UINFO"), wxBRUSHSTYLE_SOLID);
974 m_pActiveRouteBrush = wxTheBrushList->FindOrCreateBrush(
975 m_route_dlg_ctx.get_global_colour(
"PLRTE"), wxBRUSHSTYLE_SOLID);
978wxString Routeman::GetRouteReverseMessage(
void) {
980 _(
"Waypoints can be renamed to reflect the new order, the names will be "
981 "'001', '002' etc.\n\nDo you want to rename the waypoints?"));
984wxString Routeman::GetRouteResequenceMessage(
void) {
986 _(
"Waypoints will be renamed to reflect the natural order, the names "
987 "will be '001', '002' etc.\n\nDo you want to rename the waypoints?"));
990Route *Routeman::FindRouteByGUID(
const wxString &guid) {
991 wxRouteListNode *node1 = pRouteList->GetFirst();
993 Route *pRoute = node1->GetData();
995 if (pRoute->
m_GUID == guid)
return pRoute;
996 node1 = node1->GetNext();
1002Track *Routeman::FindTrackByGUID(
const wxString &guid) {
1003 for (
Track *pTrack : g_TrackList) {
1004 if (pTrack->m_GUID == guid)
return pTrack;
1010void Routeman::ZeroCurrentXTEToActivePoint() {
1012 if (pRouteActivatePoint)
delete pRouteActivatePoint;
1013 pRouteActivatePoint =
1014 new RoutePoint(gLat, gLon, wxString(_T(
"")), wxString(_T(
"")),
1015 wxEmptyString,
false);
1018 pActiveRouteSegmentBeginPoint = pRouteActivatePoint;
1019 m_arrival_min = 1e6;
1026WayPointman::WayPointman(GlobalColourFunc color_func)
1027 : m_get_global_colour(color_func) {
1028 m_pWayPointList =
new RoutePointList;
1030 pmarkicon_image_list = NULL;
1033 m_pIconArray =
new ArrayOfMarkIcon;
1034 m_pLegacyIconArray = NULL;
1035 m_pExtendedIconArray = NULL;
1037 m_cs = (ColorScheme)-1;
1040 m_iconListScale = -999.0;
1041 m_iconListHeight = -1;
1044WayPointman::~WayPointman() {
1050 RoutePointList temp_list;
1052 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1056 temp_list.Append(pr);
1057 node = node->GetNext();
1060 int a = temp_list.GetCount();
1062 temp_list.DeleteContents(
true);
1065 m_pWayPointList->Clear();
1066 delete m_pWayPointList;
1068 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
1070 delete pmi->piconBitmap;
1074 m_pIconArray->Clear();
1075 delete m_pIconArray;
1077 if (pmarkicon_image_list) pmarkicon_image_list->RemoveAll();
1078 delete pmarkicon_image_list;
1079 m_pLegacyIconArray->Clear();
1080 delete m_pLegacyIconArray;
1081 m_pExtendedIconArray->Clear();
1082 delete m_pExtendedIconArray;
1086 if (!prp)
return false;
1088 wxRoutePointListNode *prpnode = m_pWayPointList->Append(prp);
1089 prp->SetManagerListNode(prpnode);
1095 if (!prp)
return false;
1097 wxRoutePointListNode *prpnode =
1098 (wxRoutePointListNode *)prp->GetManagerListNode();
1103 m_pWayPointList->DeleteObject(prp);
1105 prp->SetManagerListNode(NULL);
1110wxImageList *WayPointman::Getpmarkicon_image_list(
int nominal_height) {
1112 if (pmarkicon_image_list && (nominal_height == m_iconListHeight)) {
1113 return pmarkicon_image_list;
1117 if (NULL != pmarkicon_image_list) {
1118 pmarkicon_image_list->RemoveAll();
1119 delete pmarkicon_image_list;
1121 pmarkicon_image_list =
new wxImageList(nominal_height, nominal_height);
1123 m_iconListHeight = nominal_height;
1124 m_bitmapSizeForList = nominal_height;
1126 return pmarkicon_image_list;
1129wxBitmap *WayPointman::CreateDimBitmap(wxBitmap *pBitmap,
double factor) {
1130 wxImage img = pBitmap->ConvertToImage();
1131 int sx = img.GetWidth();
1132 int sy = img.GetHeight();
1134 wxImage new_img(img);
1136 for (
int i = 0; i < sx; i++) {
1137 for (
int j = 0; j < sy; j++) {
1138 if (!img.IsTransparent(i, j)) {
1139 new_img.SetRGB(i, j, (
unsigned char)(img.GetRed(i, j) * factor),
1140 (
unsigned char)(img.GetGreen(i, j) * factor),
1141 (
unsigned char)(img.GetBlue(i, j) * factor));
1146 wxBitmap *pret =
new wxBitmap(new_img);
1151wxImage WayPointman::CreateDimImage(wxImage &image,
double factor) {
1152 int sx = image.GetWidth();
1153 int sy = image.GetHeight();
1155 wxImage new_img(image);
1157 for (
int i = 0; i < sx; i++) {
1158 for (
int j = 0; j < sy; j++) {
1159 if (!image.IsTransparent(i, j)) {
1160 new_img.SetRGB(i, j, (
unsigned char)(image.GetRed(i, j) * factor),
1161 (
unsigned char)(image.GetGreen(i, j) * factor),
1162 (
unsigned char)(image.GetBlue(i, j) * factor));
1167 return wxImage(new_img);
1170bool WayPointman::DoesIconExist(
const wxString &icon_key)
const {
1174 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1175 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1176 if (pmi->icon_name.IsSameAs(icon_key))
return true;
1182wxBitmap *WayPointman::GetIconBitmap(
const wxString &icon_key)
const {
1183 wxBitmap *pret = NULL;
1187 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1188 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1189 if (pmi->icon_name.IsSameAs(icon_key))
break;
1192 if (i == m_pIconArray->GetCount())
1195 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1196 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1202 if (i == m_pIconArray->GetCount())
1203 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1206 if (pmi->piconBitmap)
1207 pret = pmi->piconBitmap;
1209 if (pmi->iconImage.IsOk()) {
1210 pmi->piconBitmap =
new wxBitmap(pmi->iconImage);
1211 pret = pmi->piconBitmap;
1218bool WayPointman::GetIconPrescaled(
const wxString &icon_key)
const {
1222 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1223 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1224 if (pmi->icon_name.IsSameAs(icon_key))
break;
1227 if (i == m_pIconArray->GetCount())
1230 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1231 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1237 if (i == m_pIconArray->GetCount())
1238 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1241 return pmi->preScaled;
1246wxBitmap WayPointman::GetIconBitmapForList(
int index,
int height)
const {
1251 pmi = (
MarkIcon *)m_pIconArray->Item(index);
1253 if (pmi->iconImage.GetHeight() != height) {
1256 int w0 = pmi->iconImage.GetWidth();
1257 int h0 = pmi->iconImage.GetHeight();
1259 wxImage icon_resized = pmi->iconImage;
1260 if (h0 <= h && w0 <= w) {
1261 icon_resized = pmi->iconImage.Resize(
1262 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1269 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1272 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1274 icon_resized = pmi->iconImage.Rescale(w1, h1);
1275 icon_resized = pmi->iconImage.Resize(
1276 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1279 pret = wxBitmap(icon_resized);
1282 pret = wxBitmap(pmi->iconImage);
1288wxString *WayPointman::GetIconDescription(
int index)
const {
1289 wxString *pret = NULL;
1293 pret = &pmi->icon_description;
1298wxString WayPointman::GetIconDescription(wxString icon_key)
const {
1302 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1303 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1304 if (pmi->icon_name.IsSameAs(icon_key))
1305 return wxString(pmi->icon_description);
1308 return wxEmptyString;
1311wxString *WayPointman::GetIconKey(
int index)
const {
1312 wxString *pret = NULL;
1314 if ((index >= 0) && ((
unsigned int)index < m_pIconArray->GetCount())) {
1316 pret = &pmi->icon_name;
1321int WayPointman::GetIconIndex(
const wxBitmap *pbm)
const {
1322 unsigned int ret = 0;
1325 wxASSERT(m_pIconArray->GetCount() >= 1);
1326 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
1327 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1328 if (pmi->piconBitmap == pbm) {
1337int WayPointman::GetIconImageListIndex(
const wxBitmap *pbm)
const {
1341 if (pmarkicon_image_list && !pmi->m_blistImageOK) {
1342 int h0 = pmi->iconImage.GetHeight();
1343 int w0 = pmi->iconImage.GetWidth();
1344 int h = m_bitmapSizeForList;
1345 int w = m_bitmapSizeForList;
1347 wxImage icon_larger = pmi->iconImage;
1348 if (h0 <= h && w0 <= w) {
1349 icon_larger = pmi->iconImage.Resize(
1350 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1359 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1362 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1364 icon_larger = pmi->iconImage.Rescale(w1, h1).Resize(
1365 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1368 int index = pmarkicon_image_list->Add(wxBitmap(icon_larger));
1373 icon_larger.ConvertAlphaToMask(128);
1375 unsigned char r, g, b;
1376 icon_larger.GetOrFindMaskColour(&r, &g, &b);
1377 wxColour unused_color(r, g, b);
1380 wxBitmap xIcon(icon_larger);
1382 wxBitmap xbmp(w, h, -1);
1383 wxMemoryDC mdc(xbmp);
1384 mdc.SetBackground(wxBrush(unused_color));
1386 mdc.DrawBitmap(xIcon, 0, 0);
1387 int xm = xbmp.GetWidth() / 2;
1388 int ym = xbmp.GetHeight() / 2;
1390 int width = wxMax(xm / 10, 2);
1391 wxPen red(m_get_global_colour(
"URED"), width);
1393 mdc.DrawLine(xm - dp, ym - dp, xm + dp, ym + dp);
1394 mdc.DrawLine(xm - dp, ym + dp, xm + dp, ym - dp);
1395 mdc.SelectObject(wxNullBitmap);
1397 wxMask *pmask =
new wxMask(xbmp, unused_color);
1398 xbmp.SetMask(pmask);
1400 pmarkicon_image_list->Add(xbmp);
1403 wxBitmap fIcon(icon_larger);
1405 wxBitmap fbmp(w, h, -1);
1406 wxMemoryDC fmdc(fbmp);
1407 fmdc.SetBackground(wxBrush(unused_color));
1409 fmdc.DrawBitmap(xIcon, 0, 0);
1410 xm = fbmp.GetWidth() / 2;
1411 ym = fbmp.GetHeight() / 2;
1413 width = wxMax(xm / 10, 2);
1414 wxPen fred(m_get_global_colour(
"UGREN"), width);
1416 fmdc.DrawLine(xm - dp, ym + dp, xm + dp, ym + dp);
1417 fmdc.SelectObject(wxNullBitmap);
1419 wxMask *pfmask =
new wxMask(fbmp, unused_color);
1420 fbmp.SetMask(pfmask);
1422 pmarkicon_image_list->Add(fbmp);
1424 pmi->m_blistImageOK =
true;
1425 pmi->listIndex = index;
1428 return pmi->listIndex;
1432 return GetIconImageListIndex(pbm) + 1;
1436 return GetIconImageListIndex(pbm) + 2;
1440wxString WayPointman::CreateGUID(
RoutePoint *pRP) {
1444RoutePoint *WayPointman::FindRoutePointByGUID(
const wxString &guid) {
1445 wxRoutePointListNode *prpnode = m_pWayPointList->GetFirst();
1449 if (prp->
m_GUID == guid)
return (prp);
1451 prpnode = prpnode->GetNext();
1457RoutePoint *WayPointman::GetNearbyWaypoint(
double lat,
double lon,
1458 double radius_meters) {
1461 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1465 double a = lat - pr->m_lat;
1466 double b = lon - pr->m_lon;
1467 double l = sqrt((a * a) + (b * b));
1469 if ((l * 60. * 1852.) < radius_meters)
return pr;
1471 node = node->GetNext();
1476RoutePoint *WayPointman::GetOtherNearbyWaypoint(
double lat,
double lon,
1477 double radius_meters,
1478 const wxString &guid) {
1481 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1485 double a = lat - pr->m_lat;
1486 double b = lon - pr->m_lon;
1487 double l = sqrt((a * a) + (b * b));
1489 if ((l * 60. * 1852.) < radius_meters)
1490 if (pr->
m_GUID != guid)
return pr;
1492 node = node->GetNext();
1497bool WayPointman::IsReallyVisible(
RoutePoint *pWP) {
1499 return pWP->IsVisible();
1501 wxRouteListNode *node = pRouteList->GetFirst();
1503 Route *proute = node->GetData();
1506 if (proute->IsVisible())
return true;
1509 node = node->GetNext();
1512 if (pWP->IsShared())
1514 return pWP->IsVisible();
1519void WayPointman::ClearRoutePointFonts(
void) {
1523 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1528 node = node->GetNext();
1532bool WayPointman::SharedWptsExist() {
1533 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1536 if (prp->IsShared() && (prp->
m_bIsInRoute || prp == pAnchorWatchPoint1 ||
1537 prp == pAnchorWatchPoint2))
1539 node = node->GetNext();
1544void WayPointman::DeleteAllWaypoints(
bool b_delete_used) {
1546 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1550 if (!prp->
m_bIsInLayer && (prp->GetIconName() != _T(
"mob")) &&
1551 ((b_delete_used && prp->IsShared()) ||
1552 ((!prp->
m_bIsInRoute) && !(prp == pAnchorWatchPoint1) &&
1553 !(prp == pAnchorWatchPoint2)))) {
1554 DestroyWaypoint(prp);
1556 node = m_pWayPointList->GetFirst();
1558 node = node->GetNext();
1563RoutePoint *WayPointman::FindWaypointByGuid(
const std::string &guid) {
1564 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1567 if (guid == rp->
m_GUID)
return rp;
1568 node = node->GetNext();
1572void WayPointman::DestroyWaypoint(
RoutePoint *pRp,
bool b_update_changeset) {
1578 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1585 pr->RemovePoint(pRp);
1589 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1591 if (pr->GetnPoints() < 2) {
1596 delete proute_array;
1600 NavObj_dB::GetInstance().DeleteRoutePoint(pRp);
1602 pSelect->DeleteSelectableRoutePoint(pRp);
1605 if (pRp == pAnchorWatchPoint1) pAnchorWatchPoint1 = NULL;
1606 if (pRp == pAnchorWatchPoint2) pAnchorWatchPoint2 = NULL;
Class AisDecoder and helpers.
void Notify() override
Notify all listeners, no data supplied.
Wrapper for global variable, supports notification events when value changes.
static wxString GetUUID(void)
Return a unique RFC4122 version 4 compliant GUID string.
Represents a waypoint or mark within the navigation system.
wxRect CurrentRect_in_DC
Current rectangle occupied by the waypoint in the display.
wxString m_GUID
Globally Unique Identifier for the waypoint.
bool m_bIsolatedMark
Flag indicating if the waypoint is a standalone mark.
bool m_bIsActive
Flag indicating if this waypoint is active for navigation.
bool m_bIsInRoute
Flag indicating if this waypoint is part of a route.
wxFont * m_pMarkFont
Font used for rendering the waypoint name.
bool m_bShowName
Flag indicating if the waypoint name should be shown.
bool m_bBlink
Flag indicating if the waypoint should blink when displayed.
bool m_bIsInLayer
Flag indicating if the waypoint belongs to a layer.
Represents a navigational route in the navigation system.
RoutePointList * pRoutePointList
Ordered list of waypoints (RoutePoints) that make up this route.
bool m_bRtIsActive
Flag indicating whether this route is currently active for navigation.
RoutePoint * m_pRouteActivePoint
Pointer to the currently active waypoint within this route.
wxString m_RouteNameString
User-assigned name for the route.
wxString m_GUID
Globally unique identifier for this route.
bool m_bIsInLayer
Flag indicating whether this route belongs to a layer.
bool ActivateRoutePoint(Route *pA, RoutePoint *pRP)
Activates a specific waypoint within a route for navigation.
wxArrayPtrVoid * GetRouteArrayContaining(RoutePoint *pWP)
Find all routes that contain the given waypoint.
bool ActivateNextPoint(Route *pr, bool skipped)
Activates the next waypoint in a route when the current waypoint is reached.
bool DeleteRoute(Route *pRoute)
bool ActivateRoute(Route *pRouteToActivate, RoutePoint *pStartPoint=NULL)
Activates a route for navigation.
EventVar json_msg
Notified with message targeting all plugins.
EventVar json_leg_info
Notified with a shared_ptr<ActiveLegDat>, leg info to all plugins.
EventVar on_message_sent
Notified when a message available as GetString() is sent to garmin.
Represents a track, which is a series of connected track points.
int GetXIconImageListIndex(const wxBitmap *pbm) const
index of "X-ed out" icon in the image list
int GetFIconImageListIndex(const wxBitmap *pbm) const
index of "fixed viz" icon in the image list
bool AddRoutePoint(RoutePoint *prp)
Add a point to list which owns it.
bool RemoveRoutePoint(RoutePoint *prp)
Remove a routepoint from list if present, deallocate it all cases.
The JSON value class implementation.
Driver registration container, a singleton.
Global variables Listen()/Notify() wrapper.
std::vector< DriverHandle > GetActiveDrivers()
Comm port plugin TX support methods
const std::unordered_map< std::string, std::string > GetAttributes(DriverHandle handle)
Query a specific driver for attributes.
Callbacks for RoutePropDlg.