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 if (m_pLegacyIconArray) {
993 m_pLegacyIconArray->Clear();
994 delete m_pLegacyIconArray;
996 if (m_pExtendedIconArray) {
997 m_pExtendedIconArray->Clear();
998 delete m_pExtendedIconArray;
1003 if (!prp)
return false;
1005 m_pWayPointList->push_back(prp);
1006 prp->SetManagerListNode(prp);
1012 if (!prp)
return false;
1014 auto *prpnode = (
RoutePoint *)(prp->GetManagerListNode());
1018 std::find(m_pWayPointList->begin(), m_pWayPointList->end(), prpnode);
1019 if (pos != m_pWayPointList->end()) m_pWayPointList->erase(pos);
1021 auto pos = std::find(m_pWayPointList->begin(), m_pWayPointList->end(), prp);
1022 if (pos != m_pWayPointList->end()) m_pWayPointList->erase(pos);
1025 prp->SetManagerListNode(NULL);
1030wxImageList *WayPointman::Getpmarkicon_image_list(
int nominal_height) {
1032 if (pmarkicon_image_list && (nominal_height == m_iconListHeight)) {
1033 return pmarkicon_image_list;
1037 if (NULL != pmarkicon_image_list) {
1038 pmarkicon_image_list->RemoveAll();
1039 delete pmarkicon_image_list;
1041 pmarkicon_image_list =
new wxImageList(nominal_height, nominal_height);
1043 m_iconListHeight = nominal_height;
1044 m_bitmapSizeForList = nominal_height;
1046 return pmarkicon_image_list;
1049wxBitmap *WayPointman::CreateDimBitmap(wxBitmap *pBitmap,
double factor) {
1050 wxImage img = pBitmap->ConvertToImage();
1051 int sx = img.GetWidth();
1052 int sy = img.GetHeight();
1054 wxImage new_img(img);
1056 for (
int i = 0; i < sx; i++) {
1057 for (
int j = 0; j < sy; j++) {
1058 if (!img.IsTransparent(i, j)) {
1059 new_img.SetRGB(i, j, (
unsigned char)(img.GetRed(i, j) * factor),
1060 (
unsigned char)(img.GetGreen(i, j) * factor),
1061 (
unsigned char)(img.GetBlue(i, j) * factor));
1066 wxBitmap *pret =
new wxBitmap(new_img);
1071wxImage WayPointman::CreateDimImage(wxImage &image,
double factor) {
1072 int sx = image.GetWidth();
1073 int sy = image.GetHeight();
1075 wxImage new_img(image);
1077 for (
int i = 0; i < sx; i++) {
1078 for (
int j = 0; j < sy; j++) {
1079 if (!image.IsTransparent(i, j)) {
1080 new_img.SetRGB(i, j, (
unsigned char)(image.GetRed(i, j) * factor),
1081 (
unsigned char)(image.GetGreen(i, j) * factor),
1082 (
unsigned char)(image.GetBlue(i, j) * factor));
1087 return wxImage(new_img);
1090bool WayPointman::DoesIconExist(
const wxString &icon_key)
const {
1094 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1095 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1096 if (pmi->icon_name.IsSameAs(icon_key))
return true;
1102wxBitmap *WayPointman::GetIconBitmap(
const wxString &icon_key)
const {
1103 wxBitmap *pret = NULL;
1107 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1108 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1109 if (pmi->icon_name.IsSameAs(icon_key))
break;
1112 if (i == m_pIconArray->GetCount())
1115 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1116 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1122 if (i == m_pIconArray->GetCount())
1123 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1126 if (pmi->piconBitmap)
1127 pret = pmi->piconBitmap;
1129 if (pmi->iconImage.IsOk()) {
1130 pmi->piconBitmap =
new wxBitmap(pmi->iconImage);
1131 pret = pmi->piconBitmap;
1138bool WayPointman::GetIconPrescaled(
const wxString &icon_key)
const {
1142 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1143 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1144 if (pmi->icon_name.IsSameAs(icon_key))
break;
1147 if (i == m_pIconArray->GetCount())
1150 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1151 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1157 if (i == m_pIconArray->GetCount())
1158 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1161 return pmi->preScaled;
1166wxBitmap WayPointman::GetIconBitmapForList(
int index,
int height)
const {
1171 pmi = (
MarkIcon *)m_pIconArray->Item(index);
1173 if (pmi->iconImage.GetHeight() != height) {
1176 int w0 = pmi->iconImage.GetWidth();
1177 int h0 = pmi->iconImage.GetHeight();
1179 wxImage icon_resized = pmi->iconImage;
1180 if (h0 <= h && w0 <= w) {
1181 icon_resized = pmi->iconImage.Resize(
1182 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1189 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1192 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1194 icon_resized = pmi->iconImage.Rescale(w1, h1);
1195 icon_resized = pmi->iconImage.Resize(
1196 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1199 pret = wxBitmap(icon_resized);
1202 pret = wxBitmap(pmi->iconImage);
1208wxString *WayPointman::GetIconDescription(
int index)
const {
1209 wxString *pret = NULL;
1213 pret = &pmi->icon_description;
1218wxString WayPointman::GetIconDescription(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))
1225 return wxString(pmi->icon_description);
1231wxString *WayPointman::GetIconKey(
int index)
const {
1232 wxString *pret = NULL;
1234 if ((index >= 0) && ((
unsigned int)index < m_pIconArray->GetCount())) {
1236 pret = &pmi->icon_name;
1241int WayPointman::GetIconIndex(
const wxBitmap *pbm)
const {
1242 unsigned int ret = 0;
1245 wxASSERT(m_pIconArray->GetCount() >= 1);
1246 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
1247 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1248 if (pmi->piconBitmap == pbm) {
1257int WayPointman::GetIconImageListIndex(
const wxBitmap *pbm)
const {
1261 if (pmarkicon_image_list && !pmi->m_blistImageOK) {
1262 int h0 = pmi->iconImage.GetHeight();
1263 int w0 = pmi->iconImage.GetWidth();
1264 int h = m_bitmapSizeForList;
1265 int w = m_bitmapSizeForList;
1267 wxImage icon_larger = pmi->iconImage;
1268 if (h0 <= h && w0 <= w) {
1269 icon_larger = pmi->iconImage.Resize(
1270 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1279 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1282 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1284 icon_larger = pmi->iconImage.Rescale(w1, h1).Resize(
1285 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1288 int index = pmarkicon_image_list->Add(wxBitmap(icon_larger));
1293 icon_larger.ConvertAlphaToMask(128);
1295 unsigned char r, g, b;
1296 icon_larger.GetOrFindMaskColour(&r, &g, &b);
1297 wxColour unused_color(r, g, b);
1300 wxBitmap xIcon(icon_larger);
1302 wxBitmap xbmp(w, h, -1);
1303 wxMemoryDC mdc(xbmp);
1304 mdc.SetBackground(wxBrush(unused_color));
1306 mdc.DrawBitmap(xIcon, 0, 0);
1307 int xm = xbmp.GetWidth() / 2;
1308 int ym = xbmp.GetHeight() / 2;
1310 int width = wxMax(xm / 10, 2);
1311 wxPen red(m_get_global_colour(
"URED"), width);
1313 mdc.DrawLine(xm - dp, ym - dp, xm + dp, ym + dp);
1314 mdc.DrawLine(xm - dp, ym + dp, xm + dp, ym - dp);
1315 mdc.SelectObject(wxNullBitmap);
1317 wxMask *pmask =
new wxMask(xbmp, unused_color);
1318 xbmp.SetMask(pmask);
1320 pmarkicon_image_list->Add(xbmp);
1323 wxBitmap fIcon(icon_larger);
1325 wxBitmap fbmp(w, h, -1);
1326 wxMemoryDC fmdc(fbmp);
1327 fmdc.SetBackground(wxBrush(unused_color));
1329 fmdc.DrawBitmap(xIcon, 0, 0);
1330 xm = fbmp.GetWidth() / 2;
1331 ym = fbmp.GetHeight() / 2;
1333 width = wxMax(xm / 10, 2);
1334 wxPen fred(m_get_global_colour(
"UGREN"), width);
1336 fmdc.DrawLine(xm - dp, ym + dp, xm + dp, ym + dp);
1337 fmdc.SelectObject(wxNullBitmap);
1339 wxMask *pfmask =
new wxMask(fbmp, unused_color);
1340 fbmp.SetMask(pfmask);
1342 pmarkicon_image_list->Add(fbmp);
1344 pmi->m_blistImageOK =
true;
1345 pmi->listIndex = index;
1348 return pmi->listIndex;
1352 return GetIconImageListIndex(pbm) + 1;
1356 return GetIconImageListIndex(pbm) + 2;
1360wxString WayPointman::CreateGUID(
RoutePoint *pRP) {
1364RoutePoint *WayPointman::FindRoutePointByGUID(
const wxString &guid) {
1366 if (prp->m_GUID == guid)
return (prp);
1371RoutePoint *WayPointman::GetNearbyWaypoint(
double lat,
double lon,
1372 double radius_meters) {
1376 double a = lat - pr->m_lat;
1377 double b = lon - pr->m_lon;
1378 double l = sqrt((a * a) + (b * b));
1380 if ((l * 60. * 1852.) < radius_meters)
return pr;
1385RoutePoint *WayPointman::GetOtherNearbyWaypoint(
double lat,
double lon,
1386 double radius_meters,
1387 const wxString &guid) {
1391 double a = lat - pr->m_lat;
1392 double b = lon - pr->m_lon;
1393 double l = sqrt((a * a) + (b * b));
1395 if ((l * 60. * 1852.) < radius_meters)
1396 if (pr->m_GUID != guid)
return pr;
1401bool WayPointman::IsReallyVisible(
RoutePoint *pWP) {
1404 if (proute && proute->pRoutePointList) {
1405 auto &list = proute->pRoutePointList;
1406 auto pos = std::find(list->begin(), list->end(), pWP);
1407 if (pos != list->end()) {
1408 if (proute->IsVisible())
return true;
1412 if (pWP->IsShared())
1414 return pWP->IsVisible();
1419void WayPointman::ClearRoutePointFonts() {
1423 pr->m_pMarkFont = NULL;
1427bool WayPointman::SharedWptsExist() {
1436void WayPointman::DeleteAllWaypoints(
bool b_delete_used) {
1438 auto it = m_pWayPointList->begin();
1439 while (it != m_pWayPointList->end()) {
1442 if (!prp->
m_bIsInLayer && (prp->GetIconName() !=
"mob") &&
1443 ((b_delete_used && prp->IsShared()) ||
1446 DestroyWaypoint(prp);
1448 it = m_pWayPointList->begin();
1455RoutePoint *WayPointman::FindWaypointByGuid(
const std::string &guid) {
1457 if (guid == rp->m_GUID)
return rp;
1461void WayPointman::DestroyWaypoint(
RoutePoint *pRp,
bool b_update_changeset) {
1467 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1474 pr->RemovePoint(pRp);
1478 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1480 if (pr->GetnPoints() < 2) {
1485 delete proute_array;
1489 NavObj_dB::GetInstance().DeleteRoutePoint(pRp);
1491 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.