31#include <wx/apptrait.h>
33#include <wx/filename.h>
35#include <wx/jsonval.h>
36#include <wx/listimpl.cpp>
37#include <wx/progdlg.h>
38#include <wx/stdpaths.h>
39#include <wx/tokenzr.h>
41#include "ais_decoder.h"
42#include "base_platform.h"
44#include "comm_n0183_output.h"
46#include "config_vars.h"
52#include "nav_object_database.h"
53#include "navutil_base.h"
56#include "ocpn_frame.h"
57#include "OCPNPlatform.h"
59#include "pluginmanager.h"
61#include "routemanagerdialog.h"
63#include "RoutePropDlgImpl.h"
69#include "color_handler.h"
75#include "androidUTIL.h"
84extern RouteList *pRouteList;
85extern std::vector<Track*> g_TrackList;
89extern wxRect g_blink_rect;
91extern bool g_bMagneticAPB;
97extern int g_track_line_width;
99extern int g_route_line_width;
101extern bool g_bAdvanceRouteWaypointOnArrivalOnly;
102extern Route *pAISMOBRoute;
104extern float g_ChartScaleFactorExp;
106extern bool g_bShowShipToActive;
107extern bool g_bAllowShipToActive;
109bool g_bPluginHandleAutopilotRoute;
112WX_DECLARE_LIST(wxBitmap, markicon_bitmap_list_type);
113WX_DECLARE_LIST(wxString, markicon_key_list_type);
114WX_DECLARE_LIST(wxString, markicon_description_list_type);
117#include <wx/listimpl.cpp>
118WX_DEFINE_LIST(markicon_bitmap_list_type);
119WX_DEFINE_LIST(markicon_key_list_type);
120WX_DEFINE_LIST(markicon_description_list_type);
123void appendOSDirSlash(wxString *pString);
131 std::function<
void()> dlg_update_list_ctrl) {
132 m_prop_dlg_ctx = ctx;
133 m_route_mgr_dlg_update_list_ctrl = dlg_update_list_ctrl;
136 pRouteActivatePoint = NULL;
139Routeman::~Routeman() {
140 if (pRouteActivatePoint)
delete pRouteActivatePoint;
143bool Routeman::IsRouteValid(
Route *pRoute) {
144 wxRouteListNode *node = pRouteList->GetFirst();
146 if (pRoute == node->GetData())
return true;
147 node = node->GetNext();
154 wxRouteListNode *node = pRouteList->GetFirst();
156 Route *proute = node->GetData();
158 wxRoutePointListNode *pnode = (proute->pRoutePointList)->GetFirst();
161 if (prp == pWP)
return proute;
162 pnode = pnode->GetNext();
165 node = node->GetNext();
173 wxRouteListNode *node = pRouteList->GetFirst();
175 Route *proute = node->GetData();
176 if (proute->IsVisible()) {
177 wxRoutePointListNode *pnode = (proute->pRoutePointList)->GetFirst();
180 if (prp == pWP)
return proute;
181 pnode = pnode->GetNext();
185 node = node->GetNext();
191wxArrayPtrVoid *Routeman::GetRouteArrayContaining(
RoutePoint *pWP) {
192 wxArrayPtrVoid *pArray =
new wxArrayPtrVoid;
194 wxRouteListNode *route_node = pRouteList->GetFirst();
196 Route *proute = route_node->GetData();
198 wxRoutePointListNode *waypoint_node = (proute->pRoutePointList)->GetFirst();
199 while (waypoint_node) {
202 pArray->Add((
void *)proute);
207 waypoint_node = waypoint_node->GetNext();
210 route_node = route_node->GetNext();
213 if (pArray->GetCount())
225 pSelect->DeleteAllSelectableRoutePoints(route);
226 pSelect->DeleteAllSelectableRouteSegments(route);
228 route->RemovePoint(point);
232 if (route->GetnPoints() <= 1 && route_state == 0) {
233 NavObjectChanges::getInstance()->DeleteConfigRoute(route);
234 g_pRouteMan->
DeleteRoute(route, NavObjectChanges::getInstance());
238 pSelect->AddSelectableRoutePoint(point->m_lat, point->m_lon, point);
243 m_prop_dlg_ctx.SetRouteAndUpdate(route);
247RoutePoint *Routeman::FindBestActivatePoint(
Route *pR,
double lat,
double lon,
248 double cog,
double sog) {
249 if (!pR)
return NULL;
253 double min_time_found = 1e6;
255 wxRoutePointListNode *node = (pR->pRoutePointList)->GetFirst();
260 DistanceBearingMercator(pn->m_lat, pn->m_lon, lat, lon, &brg, &dist);
262 double angle = brg - cog;
263 double soa = cos(angle * PI / 180.);
265 double time_to_wp = dist / soa;
267 if (time_to_wp > 0) {
268 if (time_to_wp < min_time_found) {
269 min_time_found = time_to_wp;
273 node = node->GetNext();
278bool Routeman::ActivateRoute(
Route *pRouteToActivate,
RoutePoint *pStartPoint) {
279 g_bAllowShipToActive =
false;
281 v[_T(
"Route_activated")] = pRouteToActivate->m_RouteNameString;
282 v[_T(
"GUID")] = pRouteToActivate->m_GUID;
283 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_ACTIVATED");
284 if (g_bPluginHandleAutopilotRoute)
return true;
286 pActiveRoute = pRouteToActivate;
289 pActivePoint = pStartPoint;
291 wxRoutePointListNode *node = (pActiveRoute->pRoutePointList)->GetFirst();
292 pActivePoint = node->GetData();
301 pRouteToActivate->m_bRtIsActive =
true;
303 m_bDataValid =
false;
306 console->ShowWithFreshFonts();
313 g_bAllowShipToActive =
false;
315 v[_T(
"GUID")] = pRP_target->m_GUID;
316 v[_T(
"WP_activated")] = pRP_target->GetName();
318 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_WPT_ACTIVATED");
320 if (g_bPluginHandleAutopilotRoute)
return true;
324 pActivePoint = pRP_target;
325 pActiveRoute->m_pRouteActivePoint = pRP_target;
327 wxRoutePointListNode *node = (pActiveRoute->pRoutePointList)->GetFirst();
330 pn->m_bBlink =
false;
331 pn->m_bIsActive =
false;
333 node = node->GetNext();
336 node = (pActiveRoute->pRoutePointList)->GetFirst();
341 if (pRP_target == prp_first) {
342 if (pRouteActivatePoint)
delete pRouteActivatePoint;
344 pRouteActivatePoint =
345 new RoutePoint(gLat, gLon, wxString(_T(
"")), wxString(_T(
"")),
346 wxEmptyString,
false);
347 pRouteActivatePoint->m_bShowName =
false;
349 pActiveRouteSegmentBeginPoint = pRouteActivatePoint;
353 prp_first->m_bBlink =
false;
354 node = node->GetNext();
358 if (pnext == pRP_target) {
359 pActiveRouteSegmentBeginPoint = np_prev;
364 node = node->GetNext();
368 pRP_target->m_bBlink =
true;
369 pRP_target->m_bIsActive =
true;
371 g_blink_rect = pRP_target->CurrentRect_in_DC;
383 m_prop_dlg_ctx.SetEnroutePoint(pA, pActivePoint);
388 g_bAllowShipToActive =
false;
391 pActivePoint->m_bBlink =
false;
392 pActivePoint->m_bIsActive =
false;
394 v[_T(
"isSkipped")] = skipped;
395 v[_T(
"GUID")] = pActivePoint->m_GUID;
396 v[_T(
"GUID_WP_arrived")] = pActivePoint->m_GUID;
397 v[_T(
"WP_arrived")] = pActivePoint->GetName();
399 int n_index_active = pActiveRoute->GetIndexOf(pActivePoint);
400 if ((n_index_active + 1) <= pActiveRoute->GetnPoints()) {
401 pActiveRouteSegmentBeginPoint = pActivePoint;
403 pActiveRoute->m_pRouteActivePoint =
404 pActiveRoute->GetPoint(n_index_active + 1);
406 pActivePoint = pActiveRoute->GetPoint(n_index_active + 1);
407 v[_T(
"Next_WP")] = pActivePoint->GetName();
408 v[_T(
"GUID_Next_WP")] = pActivePoint->m_GUID;
410 pActivePoint->m_bBlink =
true;
411 pActivePoint->m_bIsActive =
true;
412 g_blink_rect = pActivePoint->CurrentRect_in_DC;
424 m_prop_dlg_ctx.SetEnroutePoint(pr, pActivePoint);
426 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_WPT_ARRIVED");
433bool Routeman::DeactivateRoute(
bool b_arrival) {
435 pActivePoint->m_bBlink =
false;
436 pActivePoint->m_bIsActive =
false;
440 pActiveRoute->m_bRtIsActive =
false;
441 pActiveRoute->m_pRouteActivePoint = NULL;
445 v[_T(
"Route_deactivated")] = pActiveRoute->m_RouteNameString;
446 v[_T(
"GUID")] = pActiveRoute->m_GUID;
447 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_DEACTIVATED");
449 v[_T(
"GUID")] = pActiveRoute->m_GUID;
450 v[_T(
"Route_ended")] = pActiveRoute->m_RouteNameString;
451 json_msg.
Notify(std::make_shared<wxJSONValue>(v),
"OCPN_RTE_ENDED");
457 if (pRouteActivatePoint)
delete pRouteActivatePoint;
458 pRouteActivatePoint = NULL;
463 console->pCDI->ClearBackground();
464 console->Show(
false);
467 m_bDataValid =
false;
472bool Routeman::UpdateAutopilot() {
477 if ((g_maxWPNameLength >= 3) && (g_maxWPNameLength <= 32))
478 maxName = g_maxWPNameLength;
482 double r_Sog(0.0), r_Cog(0.0);
483 if (!std::isnan(gSog)) r_Sog = gSog;
484 if (!std::isnan(gCog)) r_Cog = gCog;
489 leg_info.Btw = CurrentBrgToActivePoint;
490 leg_info.Dtw = CurrentRngToActivePoint;
491 leg_info.Xte = CurrentXTEToActivePoint;
493 leg_info.Xte = -leg_info.Xte;
495 leg_info.wp_name = pActivePoint->GetName().Truncate(maxName);
496 leg_info.arrival = m_bArrival;
502 m_NMEA0183.TalkerID = _T(
"EC");
505 m_NMEA0183.Rmb.IsDataValid = NTrue;
506 m_NMEA0183.Rmb.CrossTrackError = CurrentXTEToActivePoint;
509 m_NMEA0183.Rmb.DirectionToSteer = Left;
511 m_NMEA0183.Rmb.DirectionToSteer = Right;
513 m_NMEA0183.Rmb.To = pActivePoint->GetName().Truncate(maxName);
514 m_NMEA0183.Rmb.From =
515 pActiveRouteSegmentBeginPoint->GetName().Truncate(maxName);
517 if (pActivePoint->m_lat < 0.)
518 m_NMEA0183.Rmb.DestinationPosition.Latitude.Set(-pActivePoint->m_lat,
521 m_NMEA0183.Rmb.DestinationPosition.Latitude.Set(pActivePoint->m_lat,
524 if (pActivePoint->m_lon < 0.)
525 m_NMEA0183.Rmb.DestinationPosition.Longitude.Set(-pActivePoint->m_lon,
528 m_NMEA0183.Rmb.DestinationPosition.Longitude.Set(pActivePoint->m_lon,
531 m_NMEA0183.Rmb.RangeToDestinationNauticalMiles = CurrentRngToActivePoint;
532 m_NMEA0183.Rmb.BearingToDestinationDegreesTrue = CurrentBrgToActivePoint;
533 m_NMEA0183.Rmb.DestinationClosingVelocityKnots =
534 r_Sog * cos((r_Cog - CurrentBrgToActivePoint) * PI / 180.0);
537 m_NMEA0183.Rmb.IsArrivalCircleEntered = NTrue;
539 m_NMEA0183.Rmb.IsArrivalCircleEntered = NFalse;
541 m_NMEA0183.Rmb.FAAModeIndicator =
"A";
542 m_NMEA0183.Rmb.Write(snt);
544 BroadcastNMEA0183Message(snt.Sentence);
549 m_NMEA0183.TalkerID = _T(
"EC");
552 m_NMEA0183.Rmc.IsDataValid = NTrue;
555 m_NMEA0183.Rmc.Position.Latitude.Set(-gLat, _T(
"S"));
557 m_NMEA0183.Rmc.Position.Latitude.Set(gLat, _T(
"N"));
560 m_NMEA0183.Rmc.Position.Longitude.Set(-gLon, _T(
"W"));
562 m_NMEA0183.Rmc.Position.Longitude.Set(gLon, _T(
"E"));
564 m_NMEA0183.Rmc.SpeedOverGroundKnots = r_Sog;
565 m_NMEA0183.Rmc.TrackMadeGoodDegreesTrue = r_Cog;
567 if (!std::isnan(gVar)) {
569 m_NMEA0183.Rmc.MagneticVariation = -gVar;
570 m_NMEA0183.Rmc.MagneticVariationDirection = West;
572 m_NMEA0183.Rmc.MagneticVariation = gVar;
573 m_NMEA0183.Rmc.MagneticVariationDirection = East;
576 m_NMEA0183.Rmc.MagneticVariation =
580 if (!gRmcTime.IsEmpty() && !gRmcDate.IsEmpty()) {
581 m_NMEA0183.Rmc.UTCTime = gRmcTime;
582 m_NMEA0183.Rmc.Date = gRmcDate;
584 wxDateTime now = wxDateTime::Now();
585 wxDateTime utc = now.ToUTC();
586 wxString time = utc.Format(_T(
"%H%M%S"));
587 m_NMEA0183.Rmc.UTCTime = time;
588 wxString date = utc.Format(_T(
"%d%m%y"));
589 m_NMEA0183.Rmc.Date = date;
592 m_NMEA0183.Rmc.FAAModeIndicator =
"A";
593 m_NMEA0183.Rmc.Write(snt);
595 BroadcastNMEA0183Message(snt.Sentence);
600 m_NMEA0183.TalkerID = _T(
"EC");
604 m_NMEA0183.Apb.IsLoranBlinkOK = NTrue;
605 m_NMEA0183.Apb.IsLoranCCycleLockOK = NTrue;
607 m_NMEA0183.Apb.CrossTrackErrorMagnitude = CurrentXTEToActivePoint;
610 m_NMEA0183.Apb.DirectionToSteer = Left;
612 m_NMEA0183.Apb.DirectionToSteer = Right;
614 m_NMEA0183.Apb.CrossTrackUnits = _T(
"N");
617 m_NMEA0183.Apb.IsArrivalCircleEntered = NTrue;
619 m_NMEA0183.Apb.IsArrivalCircleEntered = NFalse;
623 m_NMEA0183.Apb.IsPerpendicular = NFalse;
625 m_NMEA0183.Apb.To = pActivePoint->GetName().Truncate(maxName);
628 DistanceBearingMercator(pActivePoint->m_lat, pActivePoint->m_lon,
629 pActiveRouteSegmentBeginPoint->m_lat,
630 pActiveRouteSegmentBeginPoint->m_lon, &brg1,
633 if (g_bMagneticAPB && !std::isnan(gVar)) {
635 ((brg1 - gVar) >= 0.) ? (brg1 - gVar) : (brg1 - gVar + 360.);
636 double bapm = ((CurrentBrgToActivePoint - gVar) >= 0.)
637 ? (CurrentBrgToActivePoint - gVar)
638 : (CurrentBrgToActivePoint - gVar + 360.);
640 m_NMEA0183.Apb.BearingOriginToDestination = brg1m;
641 m_NMEA0183.Apb.BearingOriginToDestinationUnits = _T(
"M");
643 m_NMEA0183.Apb.BearingPresentPositionToDestination = bapm;
644 m_NMEA0183.Apb.BearingPresentPositionToDestinationUnits = _T(
"M");
646 m_NMEA0183.Apb.HeadingToSteer = bapm;
647 m_NMEA0183.Apb.HeadingToSteerUnits = _T(
"M");
649 m_NMEA0183.Apb.BearingOriginToDestination = brg1;
650 m_NMEA0183.Apb.BearingOriginToDestinationUnits = _T(
"T");
652 m_NMEA0183.Apb.BearingPresentPositionToDestination =
653 CurrentBrgToActivePoint;
654 m_NMEA0183.Apb.BearingPresentPositionToDestinationUnits = _T(
"T");
656 m_NMEA0183.Apb.HeadingToSteer = CurrentBrgToActivePoint;
657 m_NMEA0183.Apb.HeadingToSteerUnits = _T(
"T");
660 m_NMEA0183.Apb.Write(snt);
661 BroadcastNMEA0183Message(snt.Sentence);
666 m_NMEA0183.TalkerID = _T(
"EC");
670 m_NMEA0183.Xte.IsLoranBlinkOK = NTrue;
671 m_NMEA0183.Xte.IsLoranCCycleLockOK = NTrue;
673 m_NMEA0183.Xte.CrossTrackErrorDistance = CurrentXTEToActivePoint;
676 m_NMEA0183.Xte.DirectionToSteer = Left;
678 m_NMEA0183.Xte.DirectionToSteer = Right;
680 m_NMEA0183.Xte.CrossTrackUnits = _T(
"N");
682 m_NMEA0183.Xte.Write(snt);
683 BroadcastNMEA0183Message(snt.Sentence);
689bool Routeman::DoesRouteContainSharedPoints(
Route *pRoute) {
693 wxRoutePointListNode *pnode = (pRoute->pRoutePointList)->GetFirst();
698 wxArrayPtrVoid *pRA = GetRouteArrayContaining(prp);
701 for (
unsigned int ir = 0; ir < pRA->GetCount(); ir++) {
710 if (pnode) pnode = pnode->GetNext();
714 pnode = (pRoute->pRoutePointList)->GetFirst();
717 if (prp->IsShared())
return true;
719 if (pnode) pnode = pnode->GetNext();
728 if (pRoute == pAISMOBRoute) {
732 int ret = OCPNMessageBox(NULL,
733 _(
"You are trying to delete an active AIS MOB "
734 "route, are you REALLY sure?"),
735 _(
"OpenCPN Warning"), wxYES_NO);
743 ::wxBeginBusyCursor();
745 if (GetpActiveRoute() == pRoute) DeactivateRoute();
747 if (pRoute->m_bIsInLayer) {
755 m_prop_dlg_ctx.Hide(pRoute);
757 nav_obj_changes->DeleteConfigRoute(pRoute);
760 pSelect->DeleteAllSelectableRouteSegments(pRoute);
761 pRouteList->DeleteObject(pRoute);
763 m_route_mgr_dlg_update_list_ctrl();
769 wxRoutePointListNode *pnode = (pRoute->pRoutePointList)->GetFirst();
774 Route *pcontainer_route = FindRouteContainingWaypoint(prp);
776 if (pcontainer_route == NULL && prp->m_bIsInRoute) {
779 if (!prp->IsShared()) {
784 pSelect->DeleteSelectablePoint(prp, SELTYPE_ROUTEPOINT);
787 wxRoutePointListNode *pdnode = pnode;
789 pRoute->pRoutePointList->DeleteNode(pdnode);
790 pdnode = pRoute->pRoutePointList->Find(prp);
796 prp->m_bDynamicName =
false;
797 prp->m_bIsolatedMark =
true;
798 prp->SetShared(
false);
802 pnode = pnode->GetNext();
804 pnode = pRoute->pRoutePointList->GetFirst();
815 ::wxBeginBusyCursor();
818 wxRouteListNode *node = pRouteList->GetFirst();
820 Route *proute = node->GetData();
821 if (proute == pAISMOBRoute) {
826 int ret = OCPNMessageBox(NULL,
827 _(
"You are trying to delete an active AIS MOB "
828 "route, are you REALLY sure?"),
829 _(
"OpenCPN Warning"), wxYES_NO);
834 ::wxBeginBusyCursor();
838 node = node->GetNext();
839 if (proute->m_bIsInLayer)
continue;
841 nav_obj_changes->m_bSkipChangeSetUpdate =
true;
842 nav_obj_changes->DeleteConfigRoute(proute);
844 nav_obj_changes->m_bSkipChangeSetUpdate =
false;
851wxColour GetGlobalColor(wxString name) {
return *wxBLACK; }
854void Routeman::SetColorScheme(ColorScheme cs,
double displayDPmm) {
857 int scaled_line_width = g_route_line_width;
858 int track_scaled_line_width = g_track_line_width;
861 double nominal_line_width_pix = wxMax(1.5, floor(displayDPmm / 5.0));
863 double sline_width = wxMax(nominal_line_width_pix, g_route_line_width);
864 sline_width *= g_ChartScaleFactorExp;
865 scaled_line_width = wxMax(sline_width, 2);
867 double tsline_width = wxMax(nominal_line_width_pix, g_track_line_width);
868 tsline_width *= g_ChartScaleFactorExp;
869 track_scaled_line_width = wxMax(tsline_width, 2);
872 m_pActiveRoutePointPen = wxThePenList->FindOrCreatePen(
873 wxColour(0, 0, 255), scaled_line_width, wxPENSTYLE_SOLID);
874 m_pRoutePointPen = wxThePenList->FindOrCreatePen(
875 wxColour(0, 0, 255), scaled_line_width, wxPENSTYLE_SOLID);
879 m_pRoutePen = wxThePenList->FindOrCreatePen(
880 GetGlobalColor(_T(
"UINFB")), scaled_line_width, wxPENSTYLE_SOLID);
881 m_pSelectedRoutePen = wxThePenList->FindOrCreatePen(
882 GetGlobalColor(_T(
"UINFO")), scaled_line_width, wxPENSTYLE_SOLID);
883 m_pActiveRoutePen = wxThePenList->FindOrCreatePen(
884 GetGlobalColor(_T(
"UARTE")), scaled_line_width, wxPENSTYLE_SOLID);
885 m_pTrackPen = wxThePenList->FindOrCreatePen(
886 GetGlobalColor(_T(
"CHMGD")), track_scaled_line_width, wxPENSTYLE_SOLID);
888 m_pRouteBrush = wxTheBrushList->FindOrCreateBrush(GetGlobalColor(_T(
"UINFB")),
890 m_pSelectedRouteBrush = wxTheBrushList->FindOrCreateBrush(
891 GetGlobalColor(_T(
"UINFO")), wxBRUSHSTYLE_SOLID);
892 m_pActiveRouteBrush = wxTheBrushList->FindOrCreateBrush(
893 GetGlobalColor(_T(
"PLRTE")), wxBRUSHSTYLE_SOLID);
896wxString Routeman::GetRouteReverseMessage(
void) {
898 _(
"Waypoints can be renamed to reflect the new order, the names will be "
899 "'001', '002' etc.\n\nDo you want to rename the waypoints?"));
902wxString Routeman::GetRouteResequenceMessage(
void) {
904 _(
"Waypoints will be renamed to reflect the natural order, the names "
905 "will be '001', '002' etc.\n\nDo you want to rename the waypoints?"));
908Route *Routeman::FindRouteByGUID(
const wxString &guid) {
909 wxRouteListNode *node1 = pRouteList->GetFirst();
911 Route *pRoute = node1->GetData();
913 if (pRoute->m_GUID == guid)
return pRoute;
914 node1 = node1->GetNext();
920Track *Routeman::FindTrackByGUID(
const wxString &guid) {
921 for (
Track* pTrack : g_TrackList) {
922 if (pTrack->m_GUID == guid)
return pTrack;
928void Routeman::ZeroCurrentXTEToActivePoint() {
930 if (pRouteActivatePoint)
delete pRouteActivatePoint;
931 pRouteActivatePoint =
932 new RoutePoint(gLat, gLon, wxString(_T(
"")), wxString(_T(
"")),
933 wxEmptyString,
false);
934 pRouteActivatePoint->m_bShowName =
false;
936 pActiveRouteSegmentBeginPoint = pRouteActivatePoint;
944WayPointman::WayPointman() {
945 m_pWayPointList =
new RoutePointList;
947 pmarkicon_image_list = NULL;
950 m_pIconArray =
new ArrayOfMarkIcon;
951 m_pLegacyIconArray = NULL;
952 m_pExtendedIconArray = NULL;
954 m_cs = (ColorScheme)-1;
957 m_iconListScale = -999.0;
958 m_iconListHeight = -1;
961WayPointman::~WayPointman() {
967 RoutePointList temp_list;
969 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
973 temp_list.Append(pr);
974 node = node->GetNext();
977 temp_list.DeleteContents(
true);
980 m_pWayPointList->Clear();
981 delete m_pWayPointList;
983 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
985 delete pmi->piconBitmap;
989 m_pIconArray->Clear();
992 if (pmarkicon_image_list) pmarkicon_image_list->RemoveAll();
993 delete pmarkicon_image_list;
996bool WayPointman::AddRoutePoint(
RoutePoint *prp) {
997 if (!prp)
return false;
999 wxRoutePointListNode *prpnode = m_pWayPointList->Append(prp);
1000 prp->SetManagerListNode(prpnode);
1005bool WayPointman::RemoveRoutePoint(
RoutePoint *prp) {
1006 if (!prp)
return false;
1008 wxRoutePointListNode *prpnode =
1009 (wxRoutePointListNode *)prp->GetManagerListNode();
1014 m_pWayPointList->DeleteObject(prp);
1016 prp->SetManagerListNode(NULL);
1021wxImageList *WayPointman::Getpmarkicon_image_list(
int nominal_height) {
1023 if (pmarkicon_image_list && (nominal_height == m_iconListHeight)) {
1024 return pmarkicon_image_list;
1028 if (NULL != pmarkicon_image_list) {
1029 pmarkicon_image_list->RemoveAll();
1030 delete pmarkicon_image_list;
1032 pmarkicon_image_list =
new wxImageList(nominal_height, nominal_height);
1034 m_iconListHeight = nominal_height;
1035 m_bitmapSizeForList = nominal_height;
1037 return pmarkicon_image_list;
1040wxBitmap *WayPointman::CreateDimBitmap(wxBitmap *pBitmap,
double factor) {
1041 wxImage img = pBitmap->ConvertToImage();
1042 int sx = img.GetWidth();
1043 int sy = img.GetHeight();
1045 wxImage new_img(img);
1047 for (
int i = 0; i < sx; i++) {
1048 for (
int j = 0; j < sy; j++) {
1049 if (!img.IsTransparent(i, j)) {
1050 new_img.SetRGB(i, j, (
unsigned char)(img.GetRed(i, j) * factor),
1051 (
unsigned char)(img.GetGreen(i, j) * factor),
1052 (
unsigned char)(img.GetBlue(i, j) * factor));
1057 wxBitmap *pret =
new wxBitmap(new_img);
1062wxImage WayPointman::CreateDimImage(wxImage &image,
double factor) {
1063 int sx = image.GetWidth();
1064 int sy = image.GetHeight();
1066 wxImage new_img(image);
1068 for (
int i = 0; i < sx; i++) {
1069 for (
int j = 0; j < sy; j++) {
1070 if (!image.IsTransparent(i, j)) {
1071 new_img.SetRGB(i, j, (
unsigned char)(image.GetRed(i, j) * factor),
1072 (
unsigned char)(image.GetGreen(i, j) * factor),
1073 (
unsigned char)(image.GetBlue(i, j) * factor));
1078 return wxImage(new_img);
1081bool WayPointman::DoesIconExist(
const wxString &icon_key)
const {
1085 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1086 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1087 if (pmi->icon_name.IsSameAs(icon_key))
return true;
1093wxBitmap *WayPointman::GetIconBitmap(
const wxString &icon_key) {
1094 wxBitmap *pret = NULL;
1098 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1099 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1100 if (pmi->icon_name.IsSameAs(icon_key))
break;
1103 if (i == m_pIconArray->GetCount())
1106 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1107 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1113 if (i == m_pIconArray->GetCount())
1114 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1117 if (pmi->piconBitmap)
1118 pret = pmi->piconBitmap;
1120 if (pmi->iconImage.IsOk()) {
1121 pmi->piconBitmap =
new wxBitmap(pmi->iconImage);
1122 pret = pmi->piconBitmap;
1129bool WayPointman::GetIconPrescaled(
const wxString &icon_key) {
1133 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1134 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1135 if (pmi->icon_name.IsSameAs(icon_key))
break;
1138 if (i == m_pIconArray->GetCount())
1141 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1142 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1148 if (i == m_pIconArray->GetCount())
1149 pmi = (
MarkIcon *)m_pIconArray->Item(0);
1152 return pmi->preScaled;
1157unsigned int WayPointman::GetIconTexture(
const wxBitmap *pbm,
int &glw,
1160 int index = GetIconIndex(pbm);
1163 if (!pmi->icon_texture) {
1165 wxImage image = pbm->ConvertToImage();
1166 unsigned char *d = image.GetData();
1172 glGenTextures(1, &pmi->icon_texture);
1173 glBindTexture(GL_TEXTURE_2D, pmi->icon_texture);
1175 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1176 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1177 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
1179 int w = image.GetWidth(), h = image.GetHeight();
1181 pmi->tex_w = NextPow2(w);
1182 pmi->tex_h = NextPow2(h);
1184 unsigned char *a = image.GetAlpha();
1186 unsigned char mr, mg, mb;
1187 if (!a) image.GetOrFindMaskColour(&mr, &mg, &mb);
1189 unsigned char *e =
new unsigned char[4 * w * h];
1190 for (
int y = 0; y < h; y++) {
1191 for (
int x = 0; x < w; x++) {
1192 unsigned char r, g, b;
1193 int off = (y * w + x);
1202 a ? a[off] : ((r == mr) && (g == mg) && (b == mb) ? 0 : 255);
1206 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, pmi->tex_w, pmi->tex_h, 0, GL_RGBA,
1207 GL_UNSIGNED_BYTE, NULL);
1208 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, e);
1216 return pmi->icon_texture;
1222wxBitmap WayPointman::GetIconBitmapForList(
int index,
int height) {
1227 pmi = (
MarkIcon *)m_pIconArray->Item(index);
1229 if (pmi->iconImage.GetHeight() != height) {
1232 int w0 = pmi->iconImage.GetWidth();
1233 int h0 = pmi->iconImage.GetHeight();
1235 wxImage icon_resized = pmi->iconImage;
1236 if (h0 <= h && w0 <= w) {
1237 icon_resized = pmi->iconImage.Resize(
1238 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1245 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1248 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1250 icon_resized = pmi->iconImage.Rescale(w1, h1);
1251 icon_resized = pmi->iconImage.Resize(
1252 wxSize(w, h), wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1255 pret = wxBitmap(icon_resized);
1258 pret = wxBitmap(pmi->iconImage);
1264wxString *WayPointman::GetIconDescription(
int index) {
1265 wxString *pret = NULL;
1269 pret = &pmi->icon_description;
1274wxString WayPointman::GetIconDescription(wxString icon_key) {
1278 for (i = 0; i < m_pIconArray->GetCount(); i++) {
1279 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1280 if (pmi->icon_name.IsSameAs(icon_key))
1281 return wxString(pmi->icon_description);
1284 return wxEmptyString;
1287wxString *WayPointman::GetIconKey(
int index) {
1288 wxString *pret = NULL;
1290 if ((index >= 0) && ((
unsigned int)index < m_pIconArray->GetCount())) {
1292 pret = &pmi->icon_name;
1297int WayPointman::GetIconIndex(
const wxBitmap *pbm) {
1298 unsigned int ret = 0;
1301 wxASSERT(m_pIconArray->GetCount() >= 1);
1302 for (
unsigned int i = 0; i < m_pIconArray->GetCount(); i++) {
1303 pmi = (
MarkIcon *)m_pIconArray->Item(i);
1304 if (pmi->piconBitmap == pbm) {
1313int WayPointman::GetIconImageListIndex(
const wxBitmap *pbm) {
1317 if (pmarkicon_image_list && !pmi->m_blistImageOK) {
1318 int h0 = pmi->iconImage.GetHeight();
1319 int w0 = pmi->iconImage.GetWidth();
1320 int h = m_bitmapSizeForList;
1321 int w = m_bitmapSizeForList;
1323 wxImage icon_larger = pmi->iconImage;
1324 if (h0 <= h && w0 <= w) {
1325 icon_larger = pmi->iconImage.Resize(
1326 wxSize(w, h), wxPoint(w / 2 - w0 / 2, h / 2 - h0 / 2));
1333 w1 = wxRound((
double)w0 * ((
double)h / (
double)h0));
1336 h1 = wxRound((
double)h0 * ((
double)w / (
double)w0));
1338 icon_larger = pmi->iconImage.Rescale(w1, h1);
1339 icon_larger = icon_larger.Resize(wxSize(w, h),
1340 wxPoint(w / 2 - w1 / 2, h / 2 - h1 / 2));
1343 int index = pmarkicon_image_list->Add(wxBitmap(icon_larger));
1348 icon_larger.ConvertAlphaToMask(128);
1350 unsigned char r, g, b;
1351 icon_larger.GetOrFindMaskColour(&r, &g, &b);
1352 wxColour unused_color(r, g, b);
1355 wxBitmap xIcon(icon_larger);
1357 wxBitmap xbmp(w, h, -1);
1358 wxMemoryDC mdc(xbmp);
1359 mdc.SetBackground(wxBrush(unused_color));
1361 mdc.DrawBitmap(xIcon, 0, 0);
1362 int xm = xbmp.GetWidth() / 2;
1363 int ym = xbmp.GetHeight() / 2;
1365 int width = wxMax(xm / 10, 2);
1366 wxPen red(GetGlobalColor(_T(
"URED" )), width);
1368 mdc.DrawLine(xm - dp, ym - dp, xm + dp, ym + dp);
1369 mdc.DrawLine(xm - dp, ym + dp, xm + dp, ym - dp);
1370 mdc.SelectObject(wxNullBitmap);
1372 wxMask *pmask =
new wxMask(xbmp, unused_color);
1373 xbmp.SetMask(pmask);
1375 pmarkicon_image_list->Add(xbmp);
1378 wxBitmap fIcon(icon_larger);
1380 wxBitmap fbmp(w, h, -1);
1381 wxMemoryDC fmdc(fbmp);
1382 fmdc.SetBackground(wxBrush(unused_color));
1384 fmdc.DrawBitmap(xIcon, 0, 0);
1385 xm = fbmp.GetWidth() / 2;
1386 ym = fbmp.GetHeight() / 2;
1388 width = wxMax(xm / 10, 2);
1389 wxPen fred(GetGlobalColor(_T(
"UGREN" )), width);
1391 fmdc.DrawLine(xm - dp, ym + dp, xm + dp, ym + dp);
1392 fmdc.SelectObject(wxNullBitmap);
1394 wxMask *pfmask =
new wxMask(fbmp, unused_color);
1395 fbmp.SetMask(pfmask);
1397 pmarkicon_image_list->Add(fbmp);
1399 pmi->m_blistImageOK =
true;
1400 pmi->listIndex = index;
1403 return pmi->listIndex;
1406int WayPointman::GetXIconImageListIndex(
const wxBitmap *pbm) {
1407 return GetIconImageListIndex(pbm) +
1411int WayPointman::GetFIconImageListIndex(
const wxBitmap *pbm) {
1412 return GetIconImageListIndex(pbm) +
1417wxString WayPointman::CreateGUID(
RoutePoint *pRP) {
1428 return GpxDocument::GetUUID();
1431RoutePoint *WayPointman::FindRoutePointByGUID(
const wxString &guid) {
1432 wxRoutePointListNode *prpnode = m_pWayPointList->GetFirst();
1436 if (prp->m_GUID == guid)
return (prp);
1438 prpnode = prpnode->GetNext();
1444RoutePoint *WayPointman::GetNearbyWaypoint(
double lat,
double lon,
1445 double radius_meters) {
1448 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1452 double a = lat - pr->m_lat;
1453 double b = lon - pr->m_lon;
1454 double l = sqrt((a * a) + (b * b));
1456 if ((l * 60. * 1852.) < radius_meters)
return pr;
1458 node = node->GetNext();
1463RoutePoint *WayPointman::GetOtherNearbyWaypoint(
double lat,
double lon,
1464 double radius_meters,
1465 const wxString &guid) {
1468 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1472 double a = lat - pr->m_lat;
1473 double b = lon - pr->m_lon;
1474 double l = sqrt((a * a) + (b * b));
1476 if ((l * 60. * 1852.) < radius_meters)
1477 if (pr->m_GUID != guid)
return pr;
1479 node = node->GetNext();
1484bool WayPointman::IsReallyVisible(
RoutePoint *pWP) {
1485 if (pWP->m_bIsolatedMark)
1486 return pWP->IsVisible();
1488 wxRouteListNode *node = pRouteList->GetFirst();
1490 Route *proute = node->GetData();
1491 if (proute && proute->pRoutePointList) {
1492 if (proute->pRoutePointList->IndexOf(pWP) != wxNOT_FOUND) {
1493 if (proute->IsVisible())
return true;
1496 node = node->GetNext();
1499 if (pWP->IsShared())
1501 return pWP->IsVisible();
1506void WayPointman::ClearRoutePointFonts(
void) {
1510 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1514 pr->m_pMarkFont = NULL;
1515 node = node->GetNext();
1519bool WayPointman::SharedWptsExist() {
1520 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1523 if (prp->IsShared() && (prp->m_bIsInRoute || prp == pAnchorWatchPoint1 ||
1524 prp == pAnchorWatchPoint2))
1526 node = node->GetNext();
1531void WayPointman::DeleteAllWaypoints(
bool b_delete_used) {
1533 wxRoutePointListNode *node = m_pWayPointList->GetFirst();
1537 if (!prp->m_bIsInLayer && (prp->GetIconName() != _T(
"mob")) &&
1538 ((b_delete_used && prp->IsShared()) ||
1539 ((!prp->m_bIsInRoute) && !(prp == pAnchorWatchPoint1) &&
1540 !(prp == pAnchorWatchPoint2)))) {
1541 DestroyWaypoint(prp);
1543 node = m_pWayPointList->GetFirst();
1545 node = node->GetNext();
1550void WayPointman::DestroyWaypoint(
RoutePoint *pRp,
bool b_update_changeset) {
1551 if (!b_update_changeset)
1552 NavObjectChanges::getInstance()->m_bSkipChangeSetUpdate =
true;
1558 wxArrayPtrVoid *proute_array = g_pRouteMan->GetRouteArrayContaining(pRp);
1560 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1567 pr->RemovePoint(pRp);
1571 for (
unsigned int ir = 0; ir < proute_array->GetCount(); ir++) {
1573 if (pr->GetnPoints() < 2) {
1575 NavObjectChanges::getInstance()->m_bSkipChangeSetUpdate;
1576 NavObjectChanges::getInstance()->m_bSkipChangeSetUpdate =
true;
1577 NavObjectChanges::getInstance()->DeleteConfigRoute(pr);
1578 g_pRouteMan->
DeleteRoute(pr, NavObjectChanges::getInstance());
1579 NavObjectChanges::getInstance()->m_bSkipChangeSetUpdate = prev_bskip;
1583 delete proute_array;
1587 NavObjectChanges::getInstance()->DeleteWayPoint(pRp);
1588 NavObjectChanges::getInstance()->m_bSkipChangeSetUpdate =
false;
1590 pSelect->DeleteSelectableRoutePoint(pRp);
1593 if (pRp == pAnchorWatchPoint1) pAnchorWatchPoint1 = NULL;
1594 if (pRp == pAnchorWatchPoint2) pAnchorWatchPoint2 = NULL;
1596 RemoveRoutePoint(pRp);
const void Notify()
Notify all listeners, no data supplied.
bool ActivateRoutePoint(Route *pA, RoutePoint *pRP)
bool ActivateNextPoint(Route *pr, bool skipped)
bool DeleteRoute(Route *pRoute, NavObjectChanges *nav_obj_changes)
EventVar json_msg
Notified with message targeting all plugins.
EventVar json_leg_info
Notified with a shared_ptr<ActiveLegDat>, leg info to all plugins.