34#include <wx/jsonval.h>
43#include "model/nav_object_database.h"
55#include "androidUTIL.h"
71void appendOSDirSlash(wxString *pString);
73static void ActivatePersistedRoute(
Routeman *routeman) {
74 if (g_active_route ==
"") {
75 wxLogWarning(
"\"Persist route\" but no persisted route configured");
78 Route *route = routeman->FindRouteByGUID(g_active_route);
80 wxLogWarning(
"Persisted route GUID not available");
94 pRouteActivatePoint(0),
95 m_NMEA0183(NmeaCtxFactory()),
97 m_route_dlg_ctx(route_dlg_ctx) {
99 auto route_action = [&](wxCommandEvent) {
100 if (g_persist_active_route) ActivatePersistedRoute(
this);
102 active_route_listener.Init(active_route, route_action);
105Routeman::~Routeman() {
106 if (pRouteActivatePoint)
delete pRouteActivatePoint;
109bool Routeman::IsRouteValid(
Route *pRoute) {
111 if (pRoute == route)
return true;
119 for (
RoutePoint *prp : *proute->pRoutePointList) {
120 if (prp == pWP)
return proute;
127Route *Routeman::FindRouteContainingWaypoint(
const std::string &guid) {
129 for (
RoutePoint *prp : *proute->pRoutePointList) {
130 if (prp->m_GUID == guid)
return proute;
140 if (proute->IsVisible()) {
141 for (
RoutePoint *prp : *proute->pRoutePointList) {
142 if (prp == pWP)
return proute;
151 wxArrayPtrVoid *pArray =
new wxArrayPtrVoid;
154 for (
RoutePoint *prp : *proute->pRoutePointList) {
156 pArray->Add((
void *)proute);
163 if (pArray->GetCount())
175 pSelect->DeleteAllSelectableRoutePoints(route);
176 pSelect->DeleteAllSelectableRouteSegments(route);
178 route->RemovePoint(point);
182 if (route->GetnPoints() <= 1 && route_state == 0) {
187 pSelect->AddSelectableRoutePoint(point->m_lat, point->m_lon, point);
192 m_prop_dlg_ctx.set_route_and_update(route);
195RoutePoint *Routeman::FindBestActivatePoint(
Route *pR,
double lat,
double lon,
196 double cog,
double sog) {
197 if (!pR)
return NULL;
201 double min_time_found = 1e6;
205 DistanceBearingMercator(pn->m_lat, pn->m_lon, lat, lon, &brg, &dist);
207 double angle = brg - cog;
208 double soa = cos(angle * PI / 180.);
210 double time_to_wp = dist / soa;
212 if (time_to_wp > 0) {
213 if (time_to_wp < min_time_found) {
214 min_time_found = time_to_wp;
223 g_bAllowShipToActive =
false;
226 v[
"GUID"] = pRouteToActivate->
m_GUID;
227 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_ACTIVATED");
232 m_have_n0183_out =
false;
233 m_have_n2000_out =
false;
235 m_output_drivers.clear();
238 if (attributes.find(
"protocol") == attributes.end())
continue;
239 if (attributes.at(
"protocol") ==
"nmea0183") {
240 if (attributes.find(
"ioDirection") != attributes.end()) {
241 if ((attributes.at(
"ioDirection") ==
"IN/OUT") ||
242 (attributes.at(
"ioDirection") ==
"OUT")) {
243 m_output_drivers.push_back(handle);
244 m_have_n0183_out =
true;
250 if (attributes.find(
"protocol") == attributes.end())
continue;
251 if (attributes.at(
"protocol") ==
"nmea2000") {
252 if (attributes.find(
"ioDirection") != attributes.end()) {
253 if ((attributes.at(
"ioDirection") ==
"IN/OUT") ||
254 (attributes.at(
"ioDirection") ==
"OUT")) {
255 m_output_drivers.push_back(handle);
256 m_have_n2000_out =
true;
263 pActiveRoute = pRouteToActivate;
264 g_active_route = pActiveRoute->GetGUID();
267 pActivePoint = pStartPoint;
280 m_bDataValid =
false;
282 m_route_dlg_ctx.show_with_fresh_fonts();
287 g_bAllowShipToActive =
false;
289 v[
"GUID"] = pRP_target->
m_GUID;
290 v[
"WP_activated"] = pRP_target->GetName();
292 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_WPT_ACTIVATED");
298 pActivePoint = pRP_target;
303 pn->m_bIsActive =
false;
311 if (pRP_target == prp_first) {
312 if (pRouteActivatePoint)
delete pRouteActivatePoint;
314 pRouteActivatePoint =
319 pActiveRouteSegmentBeginPoint = pRouteActivatePoint;
328 if (pnext == pRP_target) {
329 pActiveRouteSegmentBeginPoint = np_prev;
353 m_prop_dlg_ctx.set_enroute_point(pA, pActivePoint);
358 g_bAllowShipToActive =
false;
365 v[
"isSkipped"] = skipped;
366 v[
"GUID"] = pActivePoint->
m_GUID;
367 v[
"GUID_WP_arrived"] = pActivePoint->
m_GUID;
368 v[
"WP_arrived"] = pActivePoint->GetName();
370 int n_index_active = pActiveRoute->GetIndexOf(pActivePoint);
372 while (n_index_active == pActiveRoute->GetIndexOf(pActivePoint)) {
373 if ((n_index_active + step) <= pActiveRoute->GetnPoints()) {
374 pActiveRouteSegmentBeginPoint = pActivePoint;
376 pActiveRoute->GetPoint(n_index_active + step);
377 pActivePoint = pActiveRoute->GetPoint(n_index_active + step);
386 v[
"Next_WP"] = pActivePoint->GetName();
387 v[
"GUID_Next_WP"] = pActivePoint->
m_GUID;
402 m_prop_dlg_ctx.set_enroute_point(pr, pActivePoint);
404 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_WPT_ARRIVED");
409bool Routeman::DeactivateRoute(
bool b_arrival) {
418 g_active_route.Clear();
423 v[
"GUID"] = pActiveRoute->
m_GUID;
424 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_DEACTIVATED");
426 v[
"GUID"] = pActiveRoute->
m_GUID;
428 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_ENDED");
434 if (pRouteActivatePoint)
delete pRouteActivatePoint;
435 pRouteActivatePoint = NULL;
439 m_route_dlg_ctx.clear_console_background();
440 m_bDataValid =
false;
445bool Routeman::UpdateAutopilot() {
446 if (!pActiveRoute)
return false;
453 if ((g_maxWPNameLength >= 3) && (g_maxWPNameLength <= 32))
454 maxName = g_maxWPNameLength;
456 if (m_have_n0183_out) rv |= UpdateAutopilotN0183(*
this);
457 if (m_have_n2000_out) rv |= UpdateAutopilotN2K(*
this);
461 if (!pActiveRoute)
return false;
465 leg_info.Btw = CurrentBrgToActivePoint;
466 leg_info.Dtw = CurrentRngToActivePoint;
467 leg_info.Xte = CurrentXTEToActivePoint;
469 leg_info.Xte = -leg_info.Xte;
471 leg_info.wp_name = pActivePoint->GetName().Truncate(maxName);
472 leg_info.arrival = m_bArrival;
483 if ((g_maxWPNameLength >= 3) && (g_maxWPNameLength <= 32))
484 maxName = g_maxWPNameLength;
488 double r_Sog(0.0), r_Cog(0.0);
489 if (!std::isnan(
gSog)) r_Sog =
gSog;
490 if (!std::isnan(
gCog)) r_Cog =
gCog;
495 leg_info.Btw = CurrentBrgToActivePoint;
496 leg_info.Dtw = CurrentRngToActivePoint;
497 leg_info.Xte = CurrentXTEToActivePoint;
499 leg_info.Xte = -leg_info.Xte;
501 leg_info.wp_name = pActivePoint->GetName().Truncate(maxName);
502 leg_info.arrival = m_bArrival;
508 m_NMEA0183.TalkerID =
"EC";
510 m_NMEA0183.Rmb.IsDataValid =
bGPSValid ? NTrue : NFalse;
511 m_NMEA0183.Rmb.CrossTrackError = CurrentXTEToActivePoint;
512 m_NMEA0183.Rmb.DirectionToSteer = XTEDir < 0 ? Left : Right;
513 m_NMEA0183.Rmb.RangeToDestinationNauticalMiles = CurrentRngToActivePoint;
514 m_NMEA0183.Rmb.BearingToDestinationDegreesTrue = CurrentBrgToActivePoint;
516 if (pActivePoint->m_lat < 0.)
517 m_NMEA0183.Rmb.DestinationPosition.Latitude.Set(-pActivePoint->m_lat,
520 m_NMEA0183.Rmb.DestinationPosition.Latitude.Set(pActivePoint->m_lat,
"N");
522 if (pActivePoint->m_lon < 0.)
523 m_NMEA0183.Rmb.DestinationPosition.Longitude.Set(-pActivePoint->m_lon,
526 m_NMEA0183.Rmb.DestinationPosition.Longitude.Set(pActivePoint->m_lon,
529 m_NMEA0183.Rmb.DestinationClosingVelocityKnots =
530 r_Sog * cos((r_Cog - CurrentBrgToActivePoint) * PI / 180.0);
531 m_NMEA0183.Rmb.IsArrivalCircleEntered = m_bArrival ? NTrue : NFalse;
532 m_NMEA0183.Rmb.FAAModeIndicator =
bGPSValid ?
"A" :
"N";
535 int wp_len = maxName;
537 m_NMEA0183.Rmb.To = pActivePoint->GetName().Truncate(wp_len);
538 m_NMEA0183.Rmb.From =
539 pActiveRouteSegmentBeginPoint->GetName().Truncate(wp_len);
540 m_NMEA0183.Rmb.Write(snt);
542 }
while (snt.Sentence.size() > 82 && wp_len > 0);
549 m_NMEA0183.TalkerID =
"EC";
552 m_NMEA0183.Rmc.IsDataValid = NTrue;
553 if (!
bGPSValid) m_NMEA0183.Rmc.IsDataValid = NFalse;
556 m_NMEA0183.Rmc.Position.Latitude.Set(-
gLat,
"S");
558 m_NMEA0183.Rmc.Position.Latitude.Set(
gLat,
"N");
561 m_NMEA0183.Rmc.Position.Longitude.Set(-
gLon,
"W");
563 m_NMEA0183.Rmc.Position.Longitude.Set(
gLon,
"E");
565 m_NMEA0183.Rmc.SpeedOverGroundKnots = r_Sog;
566 m_NMEA0183.Rmc.TrackMadeGoodDegreesTrue = r_Cog;
568 if (!std::isnan(
gVar)) {
570 m_NMEA0183.Rmc.MagneticVariation = -
gVar;
571 m_NMEA0183.Rmc.MagneticVariationDirection = West;
573 m_NMEA0183.Rmc.MagneticVariation =
gVar;
574 m_NMEA0183.Rmc.MagneticVariationDirection = East;
577 m_NMEA0183.Rmc.MagneticVariation =
581 if (!gRmcTime.IsEmpty() && !gRmcDate.IsEmpty()) {
582 m_NMEA0183.Rmc.UTCTime = gRmcTime;
583 m_NMEA0183.Rmc.Date = gRmcDate;
585 wxDateTime now = wxDateTime::Now();
586 wxDateTime utc = now.ToUTC();
587 wxString time = utc.Format(
"%H%M%S");
588 m_NMEA0183.Rmc.UTCTime = time;
589 wxString date = utc.Format(
"%d%m%y");
590 m_NMEA0183.Rmc.Date = date;
593 m_NMEA0183.Rmc.FAAModeIndicator =
"A";
594 if (!
bGPSValid) m_NMEA0183.Rmc.FAAModeIndicator =
"N";
596 m_NMEA0183.Rmc.Write(snt);
603 m_NMEA0183.TalkerID =
"EC";
607 m_NMEA0183.Apb.IsLoranBlinkOK =
609 if (!
bGPSValid) m_NMEA0183.Apb.IsLoranBlinkOK = NFalse;
611 m_NMEA0183.Apb.IsLoranCCycleLockOK = NTrue;
612 if (!
bGPSValid) m_NMEA0183.Apb.IsLoranCCycleLockOK = NFalse;
614 m_NMEA0183.Apb.CrossTrackErrorMagnitude = CurrentXTEToActivePoint;
617 m_NMEA0183.Apb.DirectionToSteer = Left;
619 m_NMEA0183.Apb.DirectionToSteer = Right;
621 m_NMEA0183.Apb.CrossTrackUnits =
"N";
624 m_NMEA0183.Apb.IsArrivalCircleEntered = NTrue;
626 m_NMEA0183.Apb.IsArrivalCircleEntered = NFalse;
630 m_NMEA0183.Apb.IsPerpendicular = NFalse;
632 m_NMEA0183.Apb.To = pActivePoint->GetName().Truncate(maxName);
635 DistanceBearingMercator(pActivePoint->m_lat, pActivePoint->m_lon,
636 pActiveRouteSegmentBeginPoint->m_lat,
637 pActiveRouteSegmentBeginPoint->m_lon, &brg1,
640 if (g_bMagneticAPB && !std::isnan(
gVar)) {
642 ((brg1 -
gVar) >= 0.) ? (brg1 -
gVar) : (brg1 -
gVar + 360.);
643 double bapm = ((CurrentBrgToActivePoint -
gVar) >= 0.)
644 ? (CurrentBrgToActivePoint -
gVar)
645 : (CurrentBrgToActivePoint -
gVar + 360.);
647 m_NMEA0183.Apb.BearingOriginToDestination = brg1m;
648 m_NMEA0183.Apb.BearingOriginToDestinationUnits =
"M";
650 m_NMEA0183.Apb.BearingPresentPositionToDestination = bapm;
651 m_NMEA0183.Apb.BearingPresentPositionToDestinationUnits =
"M";
653 m_NMEA0183.Apb.HeadingToSteer = bapm;
654 m_NMEA0183.Apb.HeadingToSteerUnits =
"M";
656 m_NMEA0183.Apb.BearingOriginToDestination = brg1;
657 m_NMEA0183.Apb.BearingOriginToDestinationUnits =
"T";
659 m_NMEA0183.Apb.BearingPresentPositionToDestination =
660 CurrentBrgToActivePoint;
661 m_NMEA0183.Apb.BearingPresentPositionToDestinationUnits =
"T";
663 m_NMEA0183.Apb.HeadingToSteer = CurrentBrgToActivePoint;
664 m_NMEA0183.Apb.HeadingToSteerUnits =
"T";
667 m_NMEA0183.Apb.Write(snt);
673 m_NMEA0183.TalkerID =
"EC";
677 m_NMEA0183.Xte.IsLoranBlinkOK =
679 if (!
bGPSValid) m_NMEA0183.Xte.IsLoranBlinkOK = NFalse;
681 m_NMEA0183.Xte.IsLoranCCycleLockOK = NTrue;
682 if (!
bGPSValid) m_NMEA0183.Xte.IsLoranCCycleLockOK = NFalse;
684 m_NMEA0183.Xte.CrossTrackErrorDistance = CurrentXTEToActivePoint;
687 m_NMEA0183.Xte.DirectionToSteer = Left;
689 m_NMEA0183.Xte.DirectionToSteer = Right;
691 m_NMEA0183.Xte.CrossTrackUnits =
"N";
693 m_NMEA0183.Xte.Write(snt);
701bool Routeman::DoesRouteContainSharedPoints(
Route *pRoute) {
705 for (
RoutePoint *prp : *pRoute->pRoutePointList) {
709 for (
unsigned int ir = 0; ir < pRA->GetCount(); ir++) {
721 for (
RoutePoint *prp : *pRoute->pRoutePointList) {
722 if (prp->IsShared())
return true;
729bool Routeman::DeleteTrack(
Track *pTrack) {
730 if (pTrack && !pTrack->m_bIsInLayer) {
731 ::wxBeginBusyCursor();
747 pSelect->DeleteAllSelectableTrackSegments(pTrack);
765 if (!m_route_dlg_ctx.confirm_delete_ais_mob()) {
770 ::wxBeginBusyCursor();
772 if (GetpActiveRoute() == pRoute) DeactivateRoute();
782 m_prop_dlg_ctx.hide(pRoute);
787 pSelect->DeleteAllSelectableRouteSegments(pRoute);
791 m_route_dlg_ctx.route_mgr_dlg_update_list_ctrl();
796 auto pnode = list->begin();
797 while (pnode != list->end()) {
801 Route *pcontainer_route = FindRouteContainingWaypoint(prp);
806 if (!prp->IsShared()) {
807 pSelect->DeleteSelectablePoint(prp, SELTYPE_ROUTEPOINT);
811 while (pdnode != list->end()) {
813 pdnode = std::find(list->begin(), list->end(), prp);
817 NavObj_dB::GetInstance().DeleteRoutePoint(prp);
821 prp->SetShared(
false);
822 NavObj_dB::GetInstance().UpdateRoutePoint(prp);
825 if (pnode != list->end())
828 pnode = list->begin();
831 NavObj_dB::GetInstance().DeleteRoute(pRoute);
839void Routeman::DeleteAllRoutes() {
840 ::wxBeginBusyCursor();
845 if (!m_route_dlg_ctx.confirm_delete_ais_mob()) {
849 ::wxBeginBusyCursor();
851 if (proute->m_bIsInLayer)
continue;
859void Routeman::SetColorScheme(ColorScheme cs,
double displayDPmm) {
862 int scaled_line_width = g_route_line_width;
863 int track_scaled_line_width = g_track_line_width;
866 double nominal_line_width_pix = wxMax(2.0, floor(displayDPmm * 0.4));
868 double sline_width = wxMax(nominal_line_width_pix, g_route_line_width);
870 scaled_line_width = wxMax(sline_width, 2);
872 double tsline_width = wxMax(nominal_line_width_pix, g_track_line_width);
874 track_scaled_line_width = wxMax(tsline_width, 2);
877 m_pActiveRoutePointPen = wxThePenList->FindOrCreatePen(
878 wxColour(0, 0, 255), scaled_line_width, wxPENSTYLE_SOLID);
879 m_pRoutePointPen = wxThePenList->FindOrCreatePen(
880 wxColour(0, 0, 255), scaled_line_width, wxPENSTYLE_SOLID);
885 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UINFB"),
886 scaled_line_width, wxPENSTYLE_SOLID);
887 m_pSelectedRoutePen =
888 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UINFO"),
889 scaled_line_width, wxPENSTYLE_SOLID);
891 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UARTE"),
892 scaled_line_width, wxPENSTYLE_SOLID);
894 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"CHMGD"),
895 track_scaled_line_width, wxPENSTYLE_SOLID);
896 m_pRouteBrush = wxTheBrushList->FindOrCreateBrush(
897 m_route_dlg_ctx.get_global_colour(
"UINFB"), wxBRUSHSTYLE_SOLID);
898 m_pSelectedRouteBrush = wxTheBrushList->FindOrCreateBrush(
899 m_route_dlg_ctx.get_global_colour(
"UINFO"), wxBRUSHSTYLE_SOLID);
900 m_pActiveRouteBrush = wxTheBrushList->FindOrCreateBrush(
901 m_route_dlg_ctx.get_global_colour(
"PLRTE"), wxBRUSHSTYLE_SOLID);
904wxString Routeman::GetRouteReverseMessage() {
906 _(
"Waypoints can be renamed to reflect the new order, the names will be "
907 "'001', '002' etc.\n\nDo you want to rename the waypoints?"));
910wxString Routeman::GetRouteResequenceMessage() {
912 _(
"Waypoints will be renamed to reflect the natural order, the names "
913 "will be '001', '002' etc.\n\nDo you want to rename the waypoints?"));
916Route *Routeman::FindRouteByGUID(
const wxString &guid) {
918 if (pRoute->
m_GUID == guid)
return pRoute;
923Track *Routeman::FindTrackByGUID(
const wxString &guid) {
925 if (pTrack->m_GUID == guid)
return pTrack;
930void Routeman::ZeroCurrentXTEToActivePoint() {
932 if (pRouteActivatePoint)
delete pRouteActivatePoint;
937 pActiveRouteSegmentBeginPoint = pRouteActivatePoint;
945WayPointman::WayPointman(GlobalColourFunc color_func)
946 : m_get_global_colour(color_func) {
947 m_pWayPointList =
new RoutePointList;
949 pmarkicon_image_list = NULL;
952 m_pIconArray =
new ArrayOfMarkIcon;
953 m_pLegacyIconArray = NULL;
954 m_pExtendedIconArray = NULL;
956 m_cs = (ColorScheme)-1;
959 m_iconListScale = -999.0;
960 m_iconListHeight = -1;
963WayPointman::~WayPointman() {
969 RoutePointList temp_list;
972 temp_list.push_back(pr);
978 m_pWayPointList->clear();
979 delete m_pWayPointList;
981 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
983 delete pmi->piconBitmap;
987 m_pIconArray->Clear();
990 if (pmarkicon_image_list) pmarkicon_image_list->RemoveAll();
991 delete pmarkicon_image_list;
992 m_pLegacyIconArray->Clear();
993 delete m_pLegacyIconArray;
994 m_pExtendedIconArray->Clear();
995 delete m_pExtendedIconArray;
999 if (!prp)
return false;
1001 m_pWayPointList->push_back(prp);
1002 prp->SetManagerListNode(prp);
1008 if (!prp)
return false;
1010 auto *prpnode = (
RoutePoint *)(prp->GetManagerListNode());
1014 std::find(m_pWayPointList->begin(), m_pWayPointList->end(), prpnode);
1015 if (pos != m_pWayPointList->end()) m_pWayPointList->erase(pos);
1017 auto pos = std::find(m_pWayPointList->begin(), m_pWayPointList->end(), prp);
1018 if (pos != m_pWayPointList->end()) m_pWayPointList->erase(pos);
1021 prp->SetManagerListNode(NULL);
1026wxImageList *WayPointman::Getpmarkicon_image_list(
int nominal_height) {
1028 if (pmarkicon_image_list && (nominal_height == m_iconListHeight)) {
1029 return pmarkicon_image_list;
1033 if (NULL != pmarkicon_image_list) {
1034 pmarkicon_image_list->RemoveAll();
1035 delete pmarkicon_image_list;
1037 pmarkicon_image_list =
new wxImageList(nominal_height, nominal_height);
1039 m_iconListHeight = nominal_height;
1040 m_bitmapSizeForList = nominal_height;
1042 return pmarkicon_image_list;
1045wxBitmap *WayPointman::CreateDimBitmap(wxBitmap *pBitmap,
double factor) {
1046 wxImage img = pBitmap->ConvertToImage();
1047 int sx = img.GetWidth();
1048 int sy = img.GetHeight();
1050 wxImage new_img(img);
1052 for (
int i = 0; i < sx; i++) {
1053 for (
int j = 0; j < sy; j++) {
1054 if (!img.IsTransparent(i, j)) {
1055 new_img.SetRGB(i, j, (
unsigned char)(img.GetRed(i, j) * factor),
1056 (
unsigned char)(img.GetGreen(i, j) * factor),
1057 (
unsigned char)(img.GetBlue(i, j) * factor));
1062 wxBitmap *pret =
new wxBitmap(new_img);
1067wxImage WayPointman::CreateDimImage(wxImage &image,
double factor) {
1068 int sx = image.GetWidth();
1069 int sy = image.GetHeight();
1071 wxImage new_img(image);
1073 for (
int i = 0; i < sx; i++) {
1074 for (
int j = 0; j < sy; j++) {
1075 if (!image.IsTransparent(i, j)) {
1076 new_img.SetRGB(i, j, (
unsigned char)(image.GetRed(i, j) * factor),
1077 (
unsigned char)(image.GetGreen(i, j) * factor),
1078 (
unsigned char)(image.GetBlue(i, j) * factor));
1083 return wxImage(new_img);
1086bool WayPointman::DoesIconExist(
const wxString &icon_key)
const {
1090 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1091 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1092 if (pmi->icon_name.IsSameAs(icon_key))
return true;
1098wxBitmap *WayPointman::GetIconBitmap(
const wxString &icon_key)
const {
1099 wxBitmap *pret = NULL;
1103 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1104 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1105 if (pmi->icon_name.IsSameAs(icon_key))
break;
1108 if (i == m_pIconArray->GetCount())
1111 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1112 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1118 if (i == m_pIconArray->GetCount())
1119 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1122 if (pmi->piconBitmap)
1123 pret = pmi->piconBitmap;
1125 if (pmi->iconImage.IsOk()) {
1126 pmi->piconBitmap =
new wxBitmap(pmi->iconImage);
1127 pret = pmi->piconBitmap;
1134bool WayPointman::GetIconPrescaled(
const wxString &icon_key)
const {
1138 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1139 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1140 if (pmi->icon_name.IsSameAs(icon_key))
break;
1143 if (i == m_pIconArray->GetCount())
1146 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1147 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1153 if (i == m_pIconArray->GetCount())
1154 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1157 return pmi->preScaled;
1162wxBitmap WayPointman::GetIconBitmapForList(
int index,
int height)
const {
1167 pmi = (
MarkIcon *)m_pIconArray->Item(index);
1169 if (pmi->iconImage.GetHeight() != height) {
1172 int w0 = pmi->iconImage.GetWidth();
1173 int h0 = pmi->iconImage.GetHeight();
1175 wxImage icon_resized = pmi->iconImage;
1176 if (h0 <= h && w0 <= w) {
1177 icon_resized = pmi->iconImage.Resize(
1178 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1185 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1188 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1190 icon_resized = pmi->iconImage.Rescale(w1, h1);
1191 icon_resized = pmi->iconImage.Resize(
1192 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1195 pret = wxBitmap(icon_resized);
1198 pret = wxBitmap(pmi->iconImage);
1204wxString *WayPointman::GetIconDescription(
int index)
const {
1205 wxString *pret = NULL;
1209 pret = &pmi->icon_description;
1214wxString WayPointman::GetIconDescription(wxString icon_key)
const {
1218 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1219 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1220 if (pmi->icon_name.IsSameAs(icon_key))
1221 return wxString(pmi->icon_description);
1227wxString *WayPointman::GetIconKey(
int index)
const {
1228 wxString *pret = NULL;
1230 if ((index >= 0) && ((
unsigned int)index < m_pIconArray->GetCount())) {
1232 pret = &pmi->icon_name;
1237int WayPointman::GetIconIndex(
const wxBitmap *pbm)
const {
1238 unsigned int ret = 0;
1241 wxASSERT(m_pIconArray->GetCount() >= 1);
1242 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
1243 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1244 if (pmi->piconBitmap == pbm) {
1253int WayPointman::GetIconImageListIndex(
const wxBitmap *pbm)
const {
1257 if (pmarkicon_image_list && !pmi->m_blistImageOK) {
1258 int h0 = pmi->iconImage.GetHeight();
1259 int w0 = pmi->iconImage.GetWidth();
1260 int h = m_bitmapSizeForList;
1261 int w = m_bitmapSizeForList;
1263 wxImage icon_larger = pmi->iconImage;
1264 if (h0 <= h && w0 <= w) {
1265 icon_larger = pmi->iconImage.Resize(
1266 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1275 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1278 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1280 icon_larger = pmi->iconImage.Rescale(w1, h1).Resize(
1281 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1284 int index = pmarkicon_image_list->Add(wxBitmap(icon_larger));
1289 icon_larger.ConvertAlphaToMask(128);
1291 unsigned char r, g, b;
1292 icon_larger.GetOrFindMaskColour(&r, &g, &b);
1293 wxColour unused_color(r, g, b);
1296 wxBitmap xIcon(icon_larger);
1298 wxBitmap xbmp(w, h, -1);
1299 wxMemoryDC mdc(xbmp);
1300 mdc.SetBackground(wxBrush(unused_color));
1302 mdc.DrawBitmap(xIcon, 0, 0);
1303 int xm = xbmp.GetWidth() / 2;
1304 int ym = xbmp.GetHeight() / 2;
1306 int width = wxMax(xm / 10, 2);
1307 wxPen red(m_get_global_colour(
"URED"), width);
1309 mdc.DrawLine(xm - dp, ym - dp, xm + dp, ym + dp);
1310 mdc.DrawLine(xm - dp, ym + dp, xm + dp, ym - dp);
1311 mdc.SelectObject(wxNullBitmap);
1313 wxMask *pmask =
new wxMask(xbmp, unused_color);
1314 xbmp.SetMask(pmask);
1316 pmarkicon_image_list->Add(xbmp);
1319 wxBitmap fIcon(icon_larger);
1321 wxBitmap fbmp(w, h, -1);
1322 wxMemoryDC fmdc(fbmp);
1323 fmdc.SetBackground(wxBrush(unused_color));
1325 fmdc.DrawBitmap(xIcon, 0, 0);
1326 xm = fbmp.GetWidth() / 2;
1327 ym = fbmp.GetHeight() / 2;
1329 width = wxMax(xm / 10, 2);
1330 wxPen fred(m_get_global_colour(
"UGREN"), width);
1332 fmdc.DrawLine(xm - dp, ym + dp, xm + dp, ym + dp);
1333 fmdc.SelectObject(wxNullBitmap);
1335 wxMask *pfmask =
new wxMask(fbmp, unused_color);
1336 fbmp.SetMask(pfmask);
1338 pmarkicon_image_list->Add(fbmp);
1340 pmi->m_blistImageOK =
true;
1341 pmi->listIndex = index;
1344 return pmi->listIndex;
1348 return GetIconImageListIndex(pbm) + 1;
1352 return GetIconImageListIndex(pbm) + 2;
1356wxString WayPointman::CreateGUID(
RoutePoint *pRP) {
1360RoutePoint *WayPointman::FindRoutePointByGUID(
const wxString &guid) {
1362 if (prp->m_GUID == guid)
return (prp);
1367RoutePoint *WayPointman::GetNearbyWaypoint(
double lat,
double lon,
1368 double radius_meters) {
1372 double a = lat - pr->m_lat;
1373 double b = lon - pr->m_lon;
1374 double l = sqrt((a * a) + (b * b));
1376 if ((l * 60. * 1852.) < radius_meters)
return pr;
1381RoutePoint *WayPointman::GetOtherNearbyWaypoint(
double lat,
double lon,
1382 double radius_meters,
1383 const wxString &guid) {
1387 double a = lat - pr->m_lat;
1388 double b = lon - pr->m_lon;
1389 double l = sqrt((a * a) + (b * b));
1391 if ((l * 60. * 1852.) < radius_meters)
1392 if (pr->m_GUID != guid)
return pr;
1397bool WayPointman::IsReallyVisible(
RoutePoint *pWP) {
1400 if (proute && proute->pRoutePointList) {
1401 auto &list = proute->pRoutePointList;
1402 auto pos = std::find(list->begin(), list->end(), pWP);
1403 if (pos != list->end()) {
1404 if (proute->IsVisible())
return true;
1408 if (pWP->IsShared())
1410 return pWP->IsVisible();
1415void WayPointman::ClearRoutePointFonts() {
1419 pr->m_pMarkFont = NULL;
1423bool WayPointman::SharedWptsExist() {
1432void WayPointman::DeleteAllWaypoints(
bool b_delete_used) {
1434 auto it = m_pWayPointList->begin();
1435 while (it != m_pWayPointList->end()) {
1438 if (!prp->
m_bIsInLayer && (prp->GetIconName() !=
"mob") &&
1439 ((b_delete_used && prp->IsShared()) ||
1442 DestroyWaypoint(prp);
1444 it = m_pWayPointList->begin();
1451RoutePoint *WayPointman::FindWaypointByGuid(
const std::string &guid) {
1453 if (guid == rp->m_GUID)
return rp;
1457void WayPointman::DestroyWaypoint(
RoutePoint *pRp,
bool b_update_changeset) {
1463 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1470 pr->RemovePoint(pRp);
1474 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1476 if (pr->GetnPoints() < 2) {
1481 delete proute_array;
1485 NavObj_dB::GetInstance().DeleteRoutePoint(pRp);
1487 pSelect->DeleteSelectableRoutePoint(pRp);
Class AisDecoder and helpers.
Autopilot output support.
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.
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.
NMEA Data Multiplexer Object.
Global variables stored in configuration file.
MySQL based storage for routes, tracks, etc.
Navigation Utility Functions without GUI dependencies.
Wrapper for creating an NmeaContext based on global vars.
Global variables Listen()/Notify() wrapper.
bool bGPSValid
Indicate whether the Global Navigation Satellite System (GNSS) has a valid position.
double gVar
Magnetic variation in degrees.
double gLat
Vessel's current latitude in decimal degrees.
double gCog
Course over ground in degrees (0-359.99).
double gSog
Speed over ground in knots.
double gLon
Vessel's current longitude in decimal degrees.
Position, course, speed, etc.
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.
wxRect g_blink_rect
Global instance.
RoutePoint * pAnchorWatchPoint2
Global instance.
Routeman * g_pRouteMan
Global instance.
RouteList * pRouteList
Global instance.
bool g_bPluginHandleAutopilotRoute
Global instance.
RoutePoint * pAnchorWatchPoint1
Global instance.
Route * pAISMOBRoute
Global instance.
float g_ChartScaleFactorExp
Global instance.
RoutePoint * pAnchorWatchPoint2
Global instance.
Routeman * g_pRouteMan
Global instance.
RouteList * pRouteList
Global instance.
bool g_bPluginHandleAutopilotRoute
Global instance.
RoutePoint * pAnchorWatchPoint1
Global instance.
Route * pAISMOBRoute
Global instance.
float g_ChartScaleFactorExp
Global instance.
Select * pSelect
Global instance.
Callbacks for RoutePropDlg.
std::vector< Track * > g_TrackList
Global instance.
Recorded track abstraction.