35#include "ocpn-nlohmann/json.hpp"
36#include "observable/global_var.h"
45#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) {
98 obs::GlobalVar<wxString> active_route(&g_active_route);
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_evt.Notify(std::make_shared<nlohmann::json>(v),
228 "OCPN_RTE_ACTIVATED");
233 m_have_n0183_out =
false;
234 m_have_n2000_out =
false;
236 m_output_drivers.clear();
239 if (attributes.find(
"protocol") == attributes.end())
continue;
240 if (attributes.at(
"protocol") ==
"nmea0183") {
241 if (attributes.find(
"ioDirection") != attributes.end()) {
242 if ((attributes.at(
"ioDirection") ==
"IN/OUT") ||
243 (attributes.at(
"ioDirection") ==
"OUT")) {
244 m_output_drivers.push_back(handle);
245 m_have_n0183_out =
true;
251 if (attributes.find(
"protocol") == attributes.end())
continue;
252 if (attributes.at(
"protocol") ==
"nmea2000") {
253 if (attributes.find(
"ioDirection") != attributes.end()) {
254 if ((attributes.at(
"ioDirection") ==
"IN/OUT") ||
255 (attributes.at(
"ioDirection") ==
"OUT")) {
256 m_output_drivers.push_back(handle);
257 m_have_n2000_out =
true;
264 pActiveRoute = pRouteToActivate;
265 g_active_route = pActiveRoute->GetGUID();
268 pActivePoint = pStartPoint;
281 m_bDataValid =
false;
283 m_route_dlg_ctx.show_with_fresh_fonts();
288 g_bAllowShipToActive =
false;
290 v[
"GUID"] = pRP_target->
m_GUID;
291 v[
"WP_activated"] = pRP_target->GetName();
293 json_msg_evt.Notify(std::make_shared<nlohmann::json>(v),
294 "OCPN_WPT_ACTIVATED");
300 pActivePoint = pRP_target;
305 pn->m_bIsActive =
false;
313 if (pRP_target == prp_first) {
314 if (pRouteActivatePoint)
delete pRouteActivatePoint;
316 pRouteActivatePoint =
321 pActiveRouteSegmentBeginPoint = pRouteActivatePoint;
330 if (pnext == pRP_target) {
331 pActiveRouteSegmentBeginPoint = np_prev;
355 m_prop_dlg_ctx.set_enroute_point(pA, pActivePoint);
360 g_bAllowShipToActive =
false;
367 v[
"isSkipped"] = skipped;
368 v[
"GUID"] = pActivePoint->
m_GUID;
369 v[
"GUID_WP_arrived"] = pActivePoint->
m_GUID;
370 v[
"WP_arrived"] = pActivePoint->GetName();
372 int n_index_active = pActiveRoute->GetIndexOf(pActivePoint);
373 if (n_index_active < 0)
return false;
375 while (n_index_active == pActiveRoute->GetIndexOf(pActivePoint)) {
376 int candidate = n_index_active + step;
377 if (candidate < pActiveRoute->GetnPoints()) {
378 int candidate_point = candidate + 1;
379 pActiveRouteSegmentBeginPoint = pActivePoint;
381 pActiveRoute->GetPoint(candidate_point);
382 pActivePoint = pActiveRoute->GetPoint(candidate_point);
391 v[
"Next_WP"] = pActivePoint->GetName();
392 v[
"GUID_Next_WP"] = pActivePoint->
m_GUID;
407 m_prop_dlg_ctx.set_enroute_point(pr, pActivePoint);
409 json_msg_evt.Notify(std::make_shared<nlohmann::json>(v),
415bool Routeman::DeactivateRoute(
bool b_arrival) {
424 g_active_route.Clear();
429 v[
"GUID"] = pActiveRoute->
m_GUID;
430 json_msg_evt.Notify(std::make_shared<nlohmann::json>(v),
431 "OCPN_RTE_DEACTIVATED");
433 v[
"GUID"] = pActiveRoute->
m_GUID;
435 json_msg_evt.Notify(std::make_shared<nlohmann::json>(v),
442 if (pRouteActivatePoint)
delete pRouteActivatePoint;
443 pRouteActivatePoint = NULL;
447 m_route_dlg_ctx.clear_console_background();
448 m_bDataValid =
false;
453bool Routeman::UpdateAutopilot() {
454 if (!pActiveRoute)
return false;
461 if ((g_maxWPNameLength >= 3) && (g_maxWPNameLength <= 32))
462 maxName = g_maxWPNameLength;
464 if (m_have_n0183_out) rv |= UpdateAutopilotN0183(*
this);
465 if (m_have_n2000_out) rv |= UpdateAutopilotN2K(*
this);
469 if (!pActiveRoute)
return false;
473 leg_info.Btw = CurrentBrgToActivePoint;
474 leg_info.Dtw = CurrentRngToActivePoint;
475 leg_info.Xte = CurrentXTEToActivePoint;
477 leg_info.Xte = -leg_info.Xte;
479 leg_info.wp_name = pActivePoint->GetName().Truncate(maxName);
480 leg_info.arrival = m_bArrival;
482 json_leg_info.Notify(std::make_shared<ActiveLegDat>(leg_info),
"");
491 if ((g_maxWPNameLength >= 3) && (g_maxWPNameLength <= 32))
492 maxName = g_maxWPNameLength;
496 double r_Sog(0.0), r_Cog(0.0);
497 if (!std::isnan(
gSog)) r_Sog =
gSog;
498 if (!std::isnan(
gCog)) r_Cog =
gCog;
503 leg_info.Btw = CurrentBrgToActivePoint;
504 leg_info.Dtw = CurrentRngToActivePoint;
505 leg_info.Xte = CurrentXTEToActivePoint;
507 leg_info.Xte = -leg_info.Xte;
509 leg_info.wp_name = pActivePoint->GetName().Truncate(maxName);
510 leg_info.arrival = m_bArrival;
512 json_leg_info.Notify(std::make_shared<ActiveLegDat>(leg_info),
"");
516 m_NMEA0183.TalkerID =
"EC";
518 m_NMEA0183.Rmb.IsDataValid =
bGPSValid ? NTrue : NFalse;
519 m_NMEA0183.Rmb.CrossTrackError = CurrentXTEToActivePoint;
520 m_NMEA0183.Rmb.DirectionToSteer = XTEDir < 0 ? Left : Right;
521 m_NMEA0183.Rmb.RangeToDestinationNauticalMiles = CurrentRngToActivePoint;
522 m_NMEA0183.Rmb.BearingToDestinationDegreesTrue = CurrentBrgToActivePoint;
524 if (pActivePoint->m_lat < 0.)
525 m_NMEA0183.Rmb.DestinationPosition.Latitude.Set(-pActivePoint->m_lat,
528 m_NMEA0183.Rmb.DestinationPosition.Latitude.Set(pActivePoint->m_lat,
"N");
530 if (pActivePoint->m_lon < 0.)
531 m_NMEA0183.Rmb.DestinationPosition.Longitude.Set(-pActivePoint->m_lon,
534 m_NMEA0183.Rmb.DestinationPosition.Longitude.Set(pActivePoint->m_lon,
537 m_NMEA0183.Rmb.DestinationClosingVelocityKnots =
538 r_Sog * cos((r_Cog - CurrentBrgToActivePoint) * PI / 180.0);
539 m_NMEA0183.Rmb.IsArrivalCircleEntered = m_bArrival ? NTrue : NFalse;
540 m_NMEA0183.Rmb.FAAModeIndicator =
bGPSValid ?
"A" :
"N";
543 int wp_len = maxName;
545 m_NMEA0183.Rmb.To = pActivePoint->GetName().Truncate(wp_len);
546 m_NMEA0183.Rmb.From =
547 pActiveRouteSegmentBeginPoint->GetName().Truncate(wp_len);
548 m_NMEA0183.Rmb.Write(snt);
550 }
while (snt.Sentence.size() > 82 && wp_len > 0);
557 m_NMEA0183.TalkerID =
"EC";
560 m_NMEA0183.Rmc.IsDataValid = NTrue;
561 if (!
bGPSValid) m_NMEA0183.Rmc.IsDataValid = NFalse;
564 m_NMEA0183.Rmc.Position.Latitude.Set(-
gLat,
"S");
566 m_NMEA0183.Rmc.Position.Latitude.Set(
gLat,
"N");
569 m_NMEA0183.Rmc.Position.Longitude.Set(-
gLon,
"W");
571 m_NMEA0183.Rmc.Position.Longitude.Set(
gLon,
"E");
573 m_NMEA0183.Rmc.SpeedOverGroundKnots = r_Sog;
574 m_NMEA0183.Rmc.TrackMadeGoodDegreesTrue = r_Cog;
576 if (!std::isnan(
gVar)) {
578 m_NMEA0183.Rmc.MagneticVariation = -
gVar;
579 m_NMEA0183.Rmc.MagneticVariationDirection = West;
581 m_NMEA0183.Rmc.MagneticVariation =
gVar;
582 m_NMEA0183.Rmc.MagneticVariationDirection = East;
585 m_NMEA0183.Rmc.MagneticVariation =
589 if (!gRmcTime.IsEmpty() && !gRmcDate.IsEmpty()) {
590 m_NMEA0183.Rmc.UTCTime = gRmcTime;
591 m_NMEA0183.Rmc.Date = gRmcDate;
593 wxDateTime now = wxDateTime::Now();
594 wxDateTime utc = now.ToUTC();
595 wxString time = utc.Format(
"%H%M%S");
596 m_NMEA0183.Rmc.UTCTime = time;
597 wxString date = utc.Format(
"%d%m%y");
598 m_NMEA0183.Rmc.Date = date;
601 m_NMEA0183.Rmc.FAAModeIndicator =
"A";
602 if (!
bGPSValid) m_NMEA0183.Rmc.FAAModeIndicator =
"N";
604 m_NMEA0183.Rmc.Write(snt);
611 m_NMEA0183.TalkerID =
"EC";
615 m_NMEA0183.Apb.IsLoranBlinkOK =
617 if (!
bGPSValid) m_NMEA0183.Apb.IsLoranBlinkOK = NFalse;
619 m_NMEA0183.Apb.IsLoranCCycleLockOK = NTrue;
620 if (!
bGPSValid) m_NMEA0183.Apb.IsLoranCCycleLockOK = NFalse;
622 m_NMEA0183.Apb.CrossTrackErrorMagnitude = CurrentXTEToActivePoint;
625 m_NMEA0183.Apb.DirectionToSteer = Left;
627 m_NMEA0183.Apb.DirectionToSteer = Right;
629 m_NMEA0183.Apb.CrossTrackUnits =
"N";
632 m_NMEA0183.Apb.IsArrivalCircleEntered = NTrue;
634 m_NMEA0183.Apb.IsArrivalCircleEntered = NFalse;
638 m_NMEA0183.Apb.IsPerpendicular = NFalse;
640 m_NMEA0183.Apb.To = pActivePoint->GetName().Truncate(maxName);
643 DistanceBearingMercator(pActivePoint->m_lat, pActivePoint->m_lon,
644 pActiveRouteSegmentBeginPoint->m_lat,
645 pActiveRouteSegmentBeginPoint->m_lon, &brg1,
648 if (g_bMagneticAPB && !std::isnan(
gVar)) {
650 ((brg1 -
gVar) >= 0.) ? (brg1 -
gVar) : (brg1 -
gVar + 360.);
651 double bapm = ((CurrentBrgToActivePoint -
gVar) >= 0.)
652 ? (CurrentBrgToActivePoint -
gVar)
653 : (CurrentBrgToActivePoint -
gVar + 360.);
655 m_NMEA0183.Apb.BearingOriginToDestination = brg1m;
656 m_NMEA0183.Apb.BearingOriginToDestinationUnits =
"M";
658 m_NMEA0183.Apb.BearingPresentPositionToDestination = bapm;
659 m_NMEA0183.Apb.BearingPresentPositionToDestinationUnits =
"M";
661 m_NMEA0183.Apb.HeadingToSteer = bapm;
662 m_NMEA0183.Apb.HeadingToSteerUnits =
"M";
664 m_NMEA0183.Apb.BearingOriginToDestination = brg1;
665 m_NMEA0183.Apb.BearingOriginToDestinationUnits =
"T";
667 m_NMEA0183.Apb.BearingPresentPositionToDestination =
668 CurrentBrgToActivePoint;
669 m_NMEA0183.Apb.BearingPresentPositionToDestinationUnits =
"T";
671 m_NMEA0183.Apb.HeadingToSteer = CurrentBrgToActivePoint;
672 m_NMEA0183.Apb.HeadingToSteerUnits =
"T";
675 m_NMEA0183.Apb.Write(snt);
681 m_NMEA0183.TalkerID =
"EC";
685 m_NMEA0183.Xte.IsLoranBlinkOK =
687 if (!
bGPSValid) m_NMEA0183.Xte.IsLoranBlinkOK = NFalse;
689 m_NMEA0183.Xte.IsLoranCCycleLockOK = NTrue;
690 if (!
bGPSValid) m_NMEA0183.Xte.IsLoranCCycleLockOK = NFalse;
692 m_NMEA0183.Xte.CrossTrackErrorDistance = CurrentXTEToActivePoint;
695 m_NMEA0183.Xte.DirectionToSteer = Left;
697 m_NMEA0183.Xte.DirectionToSteer = Right;
699 m_NMEA0183.Xte.CrossTrackUnits =
"N";
701 m_NMEA0183.Xte.Write(snt);
709bool Routeman::DoesRouteContainSharedPoints(
Route *pRoute) {
713 for (
RoutePoint *prp : *pRoute->pRoutePointList) {
717 for (
unsigned int ir = 0; ir < pRA->GetCount(); ir++) {
729 for (
RoutePoint *prp : *pRoute->pRoutePointList) {
730 if (prp->IsShared())
return true;
737bool Routeman::DeleteTrack(
Track *pTrack) {
738 if (pTrack && !pTrack->m_bIsInLayer) {
739 ::wxBeginBusyCursor();
755 pSelect->DeleteAllSelectableTrackSegments(pTrack);
770bool Routeman::IsRouteInList(
Route *pRoute) {
771 if (!pRoute)
return false;
780 if (!m_route_dlg_ctx.confirm_delete_ais_mob()) {
785 ::wxBeginBusyCursor();
787 if (GetpActiveRoute() == pRoute) DeactivateRoute();
797 m_prop_dlg_ctx.hide(pRoute);
802 pSelect->DeleteAllSelectableRouteSegments(pRoute);
806 m_route_dlg_ctx.route_mgr_dlg_update_list_ctrl();
811 auto pnode = list->begin();
812 while (pnode != list->end()) {
816 Route *pcontainer_route = FindRouteContainingWaypoint(prp);
821 if (!prp->IsShared()) {
822 pSelect->DeleteSelectablePoint(prp, SELTYPE_ROUTEPOINT);
826 while (pdnode != list->end()) {
828 pdnode = std::find(list->begin(), list->end(), prp);
832 NavObj_dB::GetInstance().DeleteRoutePoint(prp);
836 prp->SetShared(
false);
837 NavObj_dB::GetInstance().UpdateRoutePoint(prp);
840 if (pnode != list->end())
843 pnode = list->begin();
846 NavObj_dB::GetInstance().DeleteRoute(pRoute);
854void Routeman::DeleteAllRoutes() {
855 ::wxBeginBusyCursor();
857 std::vector<Route *> delete_list;
862 if (!m_route_dlg_ctx.confirm_delete_ais_mob()) {
867 if (proute->m_bIsInLayer)
continue;
869 delete_list.push_back(proute);
874 while (delete_list.size()) {
876 delete_list.pop_back();
882void Routeman::SetColorScheme(ColorScheme cs,
double displayDPmm) {
885 int scaled_line_width = g_route_line_width;
886 int track_scaled_line_width = g_track_line_width;
889 double nominal_line_width_pix = wxMax(2.0, floor(displayDPmm * 0.4));
891 double sline_width = wxMax(nominal_line_width_pix, g_route_line_width);
893 scaled_line_width = wxMax(sline_width, 2);
895 double tsline_width = wxMax(nominal_line_width_pix, g_track_line_width);
897 track_scaled_line_width = wxMax(tsline_width, 2);
900 m_pActiveRoutePointPen = wxThePenList->FindOrCreatePen(
901 wxColour(0, 0, 255), scaled_line_width, wxPENSTYLE_SOLID);
902 m_pRoutePointPen = wxThePenList->FindOrCreatePen(
903 wxColour(0, 0, 255), scaled_line_width, wxPENSTYLE_SOLID);
908 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UINFB"),
909 scaled_line_width, wxPENSTYLE_SOLID);
910 m_pSelectedRoutePen =
911 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UINFO"),
912 scaled_line_width, wxPENSTYLE_SOLID);
914 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"UARTE"),
915 scaled_line_width, wxPENSTYLE_SOLID);
917 wxThePenList->FindOrCreatePen(m_route_dlg_ctx.get_global_colour(
"CHMGD"),
918 track_scaled_line_width, wxPENSTYLE_SOLID);
919 m_pRouteBrush = wxTheBrushList->FindOrCreateBrush(
920 m_route_dlg_ctx.get_global_colour(
"UINFB"), wxBRUSHSTYLE_SOLID);
921 m_pSelectedRouteBrush = wxTheBrushList->FindOrCreateBrush(
922 m_route_dlg_ctx.get_global_colour(
"UINFO"), wxBRUSHSTYLE_SOLID);
923 m_pActiveRouteBrush = wxTheBrushList->FindOrCreateBrush(
924 m_route_dlg_ctx.get_global_colour(
"PLRTE"), wxBRUSHSTYLE_SOLID);
927wxString Routeman::GetRouteReverseMessage() {
929 _(
"Waypoints can be renamed to reflect the new order, the names will be "
930 "'001', '002' etc.\n\nDo you want to rename the waypoints?"));
933wxString Routeman::GetRouteResequenceMessage() {
935 _(
"Waypoints will be renamed to reflect the natural order, the names "
936 "will be '001', '002' etc.\n\nDo you want to rename the waypoints?"));
939Route *Routeman::FindRouteByGUID(
const wxString &guid) {
941 if (pRoute->
m_GUID == guid)
return pRoute;
946Track *Routeman::FindTrackByGUID(
const wxString &guid) {
948 if (pTrack->m_GUID == guid)
return pTrack;
953void Routeman::ZeroCurrentXTEToActivePoint() {
955 if (pRouteActivatePoint)
delete pRouteActivatePoint;
960 pActiveRouteSegmentBeginPoint = pRouteActivatePoint;
968WayPointman::WayPointman(GlobalColourFunc color_func)
969 : m_get_global_colour(color_func) {
970 m_pWayPointList =
new RoutePointList;
972 pmarkicon_image_list = NULL;
975 m_pIconArray =
new ArrayOfMarkIcon;
976 m_pLegacyIconArray = NULL;
977 m_pExtendedIconArray = NULL;
979 m_cs = (ColorScheme)-1;
982 m_iconListScale = -999.0;
983 m_iconListHeight = -1;
986WayPointman::~WayPointman() {
992 RoutePointList temp_list;
995 temp_list.push_back(pr);
1001 m_pWayPointList->clear();
1002 delete m_pWayPointList;
1004 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
1006 delete pmi->piconBitmap;
1010 m_pIconArray->Clear();
1011 delete m_pIconArray;
1013 if (pmarkicon_image_list) pmarkicon_image_list->RemoveAll();
1014 delete pmarkicon_image_list;
1015 if (m_pLegacyIconArray) {
1016 m_pLegacyIconArray->Clear();
1017 delete m_pLegacyIconArray;
1019 if (m_pExtendedIconArray) {
1020 m_pExtendedIconArray->Clear();
1021 delete m_pExtendedIconArray;
1026 if (!prp)
return false;
1028 m_pWayPointList->push_back(prp);
1029 prp->SetManagerListNode(prp);
1035 if (!prp)
return false;
1037 auto *prpnode = (
RoutePoint *)(prp->GetManagerListNode());
1041 std::find(m_pWayPointList->begin(), m_pWayPointList->end(), prpnode);
1042 if (pos != m_pWayPointList->end()) m_pWayPointList->erase(pos);
1044 auto pos = std::find(m_pWayPointList->begin(), m_pWayPointList->end(), prp);
1045 if (pos != m_pWayPointList->end()) m_pWayPointList->erase(pos);
1048 prp->SetManagerListNode(NULL);
1053wxImageList *WayPointman::Getpmarkicon_image_list(
int nominal_height) {
1055 if (pmarkicon_image_list && (nominal_height == m_iconListHeight)) {
1056 return pmarkicon_image_list;
1060 if (NULL != pmarkicon_image_list) {
1061 pmarkicon_image_list->RemoveAll();
1062 delete pmarkicon_image_list;
1064 pmarkicon_image_list =
new wxImageList(nominal_height, nominal_height);
1066 m_iconListHeight = nominal_height;
1067 m_bitmapSizeForList = nominal_height;
1069 return pmarkicon_image_list;
1072wxBitmap *WayPointman::CreateDimBitmap(wxBitmap *pBitmap,
double factor) {
1073 wxImage img = pBitmap->ConvertToImage();
1074 int sx = img.GetWidth();
1075 int sy = img.GetHeight();
1077 wxImage new_img(img);
1079 for (
int i = 0; i < sx; i++) {
1080 for (
int j = 0; j < sy; j++) {
1081 if (!img.IsTransparent(i, j)) {
1082 new_img.SetRGB(i, j, (
unsigned char)(img.GetRed(i, j) * factor),
1083 (
unsigned char)(img.GetGreen(i, j) * factor),
1084 (
unsigned char)(img.GetBlue(i, j) * factor));
1089 wxBitmap *pret =
new wxBitmap(new_img);
1094wxImage WayPointman::CreateDimImage(wxImage &image,
double factor) {
1095 int sx = image.GetWidth();
1096 int sy = image.GetHeight();
1098 wxImage new_img(image);
1100 for (
int i = 0; i < sx; i++) {
1101 for (
int j = 0; j < sy; j++) {
1102 if (!image.IsTransparent(i, j)) {
1103 new_img.SetRGB(i, j, (
unsigned char)(image.GetRed(i, j) * factor),
1104 (
unsigned char)(image.GetGreen(i, j) * factor),
1105 (
unsigned char)(image.GetBlue(i, j) * factor));
1110 return wxImage(new_img);
1113bool WayPointman::DoesIconExist(
const wxString &icon_key)
const {
1117 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1118 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1119 if (pmi->icon_name.IsSameAs(icon_key))
return true;
1125wxBitmap *WayPointman::GetIconBitmap(
const wxString &icon_key)
const {
1126 wxBitmap *pret = NULL;
1130 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1131 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1132 if (pmi->icon_name.IsSameAs(icon_key))
break;
1135 if (i == m_pIconArray->GetCount())
1138 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1139 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1145 if (i == m_pIconArray->GetCount())
1146 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1149 if (pmi->piconBitmap)
1150 pret = pmi->piconBitmap;
1152 if (pmi->iconImage.IsOk()) {
1153 pmi->piconBitmap =
new wxBitmap(pmi->iconImage);
1154 pret = pmi->piconBitmap;
1161bool WayPointman::GetIconPrescaled(
const wxString &icon_key)
const {
1165 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1166 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1167 if (pmi->icon_name.IsSameAs(icon_key))
break;
1170 if (i == m_pIconArray->GetCount())
1173 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1174 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1180 if (i == m_pIconArray->GetCount())
1181 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1184 return pmi->preScaled;
1189wxBitmap WayPointman::GetIconBitmapForList(
int index,
int height)
const {
1194 pmi = (
MarkIcon *)m_pIconArray->Item(index);
1196 if (pmi->iconImage.GetHeight() != height) {
1199 int w0 = pmi->iconImage.GetWidth();
1200 int h0 = pmi->iconImage.GetHeight();
1202 wxImage icon_resized = pmi->iconImage;
1203 if (h0 <= h && w0 <= w) {
1204 icon_resized = pmi->iconImage.Resize(
1205 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1212 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1215 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1217 icon_resized = pmi->iconImage.Rescale(w1, h1);
1218 icon_resized = pmi->iconImage.Resize(
1219 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1222 pret = wxBitmap(icon_resized);
1225 pret = wxBitmap(pmi->iconImage);
1231wxString *WayPointman::GetIconDescription(
int index)
const {
1232 wxString *pret = NULL;
1236 pret = &pmi->icon_description;
1241wxString WayPointman::GetIconDescription(wxString icon_key)
const {
1245 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1246 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1247 if (pmi->icon_name.IsSameAs(icon_key))
1248 return wxString(pmi->icon_description);
1254wxString *WayPointman::GetIconKey(
int index)
const {
1255 wxString *pret = NULL;
1257 if ((index >= 0) && ((
unsigned int)index < m_pIconArray->GetCount())) {
1259 pret = &pmi->icon_name;
1264int WayPointman::GetIconIndex(
const wxBitmap *pbm)
const {
1265 unsigned int ret = 0;
1268 wxASSERT(m_pIconArray->GetCount() >= 1);
1269 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
1270 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1271 if (pmi->piconBitmap == pbm) {
1280int WayPointman::GetIconImageListIndex(
const wxBitmap *pbm)
const {
1284 if (pmarkicon_image_list && !pmi->m_blistImageOK) {
1285 int h0 = pmi->iconImage.GetHeight();
1286 int w0 = pmi->iconImage.GetWidth();
1287 int h = m_bitmapSizeForList;
1288 int w = m_bitmapSizeForList;
1290 wxImage icon_larger = pmi->iconImage;
1291 if (h0 <= h && w0 <= w) {
1292 icon_larger = pmi->iconImage.Resize(
1293 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1302 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1305 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1307 icon_larger = pmi->iconImage.Rescale(w1, h1).Resize(
1308 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1311 int index = pmarkicon_image_list->Add(wxBitmap(icon_larger));
1316 icon_larger.ConvertAlphaToMask(128);
1318 unsigned char r, g, b;
1319 icon_larger.GetOrFindMaskColour(&r, &g, &b);
1320 wxColour unused_color(r, g, b);
1323 wxBitmap xIcon(icon_larger);
1325 wxBitmap xbmp(w, h, -1);
1326 wxMemoryDC mdc(xbmp);
1327 mdc.SetBackground(wxBrush(unused_color));
1329 mdc.DrawBitmap(xIcon, 0, 0);
1330 int xm = xbmp.GetWidth() / 2;
1331 int ym = xbmp.GetHeight() / 2;
1333 int width = wxMax(xm / 10, 2);
1334 wxPen red(m_get_global_colour(
"URED"), width);
1336 mdc.DrawLine(xm - dp, ym - dp, xm + dp, ym + dp);
1337 mdc.DrawLine(xm - dp, ym + dp, xm + dp, ym - dp);
1338 mdc.SelectObject(wxNullBitmap);
1340 wxMask *pmask =
new wxMask(xbmp, unused_color);
1341 xbmp.SetMask(pmask);
1343 pmarkicon_image_list->Add(xbmp);
1346 wxBitmap fIcon(icon_larger);
1348 wxBitmap fbmp(w, h, -1);
1349 wxMemoryDC fmdc(fbmp);
1350 fmdc.SetBackground(wxBrush(unused_color));
1352 fmdc.DrawBitmap(xIcon, 0, 0);
1353 xm = fbmp.GetWidth() / 2;
1354 ym = fbmp.GetHeight() / 2;
1356 width = wxMax(xm / 10, 2);
1357 wxPen fred(m_get_global_colour(
"UGREN"), width);
1359 fmdc.DrawLine(xm - dp, ym + dp, xm + dp, ym + dp);
1360 fmdc.SelectObject(wxNullBitmap);
1362 wxMask *pfmask =
new wxMask(fbmp, unused_color);
1363 fbmp.SetMask(pfmask);
1365 pmarkicon_image_list->Add(fbmp);
1367 pmi->m_blistImageOK =
true;
1368 pmi->listIndex = index;
1371 return pmi->listIndex;
1375 return GetIconImageListIndex(pbm) + 1;
1379 return GetIconImageListIndex(pbm) + 2;
1383wxString WayPointman::CreateGUID(
RoutePoint *pRP) {
1387RoutePoint *WayPointman::FindRoutePointByGUID(
const wxString &guid) {
1389 if (prp->m_GUID == guid)
return (prp);
1394RoutePoint *WayPointman::GetNearbyWaypoint(
double lat,
double lon,
1395 double radius_meters) {
1399 double a = lat - pr->m_lat;
1400 double b = lon - pr->m_lon;
1401 double l = sqrt((a * a) + (b * b));
1403 if ((l * 60. * 1852.) < radius_meters)
return pr;
1408RoutePoint *WayPointman::GetOtherNearbyWaypoint(
double lat,
double lon,
1409 double radius_meters,
1410 const wxString &guid) {
1414 double a = lat - pr->m_lat;
1415 double b = lon - pr->m_lon;
1416 double l = sqrt((a * a) + (b * b));
1418 if ((l * 60. * 1852.) < radius_meters)
1419 if (pr->m_GUID != guid)
return pr;
1424bool WayPointman::IsReallyVisible(
RoutePoint *pWP) {
1427 if (proute && proute->pRoutePointList) {
1428 auto &list = proute->pRoutePointList;
1429 auto pos = std::find(list->begin(), list->end(), pWP);
1430 if (pos != list->end()) {
1431 if (proute->IsVisible())
return true;
1435 if (pWP->IsShared())
1437 return pWP->IsVisible();
1442void WayPointman::ClearRoutePointFonts() {
1446 pr->m_pMarkFont = NULL;
1450bool WayPointman::SharedWptsExist() {
1459void WayPointman::DeleteAllWaypoints(
bool b_delete_used) {
1461 auto it = m_pWayPointList->begin();
1462 while (it != m_pWayPointList->end()) {
1465 if (!prp->
m_bIsInLayer && (prp->GetIconName() !=
"mob") &&
1466 ((b_delete_used && prp->IsShared()) ||
1469 DestroyWaypoint(prp);
1471 it = m_pWayPointList->begin();
1478RoutePoint *WayPointman::FindWaypointByGuid(
const std::string &guid) {
1480 if (guid == rp->m_GUID)
return rp;
1484void WayPointman::DestroyWaypoint(
RoutePoint *pRp,
bool b_update_changeset) {
1490 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1497 pr->RemovePoint(pRp);
1501 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1503 if (pr->GetnPoints() < 2) {
1508 delete proute_array;
1512 NavObj_dB::GetInstance().DeleteRoutePoint(pRp);
1514 pSelect->DeleteSelectableRoutePoint(pRp);
Class AisDecoder and helpers.
Autopilot output support.
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)
obs::EventVar on_message_sent
Notified when a message available as GetString() is sent to garmin.
bool ActivateRoute(Route *pRouteToActivate, RoutePoint *pStartPoint=NULL)
Activates a route for navigation.
obs::EventVar json_leg_info
Notified with a shared_ptr<ActiveLegDat>, leg info to all plugins.
obs::EventVar json_msg_evt
Notified with message targeting all plugins.
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.
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.
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.