24 #include <wx/string.h>
26 #include "model/nav_object_database.h"
27 #include "model/routeman.h"
28 #include "model/navutil_base.h"
29 #include "model/select.h"
30 #include "model/track.h"
31 #include "model/route.h"
37 NavObjectCollection1::NavObjectCollection1()
38 : pugi::xml_document(), m_bSkipChangeSetUpdate(false) {}
40 NavObjectCollection1::~NavObjectCollection1() {}
42 RoutePoint *GPXLoadWaypoint1(pugi::xml_node &wpt_node,
43 wxString def_symbol_name, wxString GUID,
44 bool b_fullviz,
bool b_layer,
45 bool b_layerviz,
int layer_id) {
47 bool bviz_name =
false;
48 bool bauto_name =
false;
50 bool b_propvizname =
false;
51 bool b_propviz =
false;
53 wxString SymString = def_symbol_name;
57 double plan_speed = 0.0;
60 wxString GuidString = GUID;
65 HyperlinkList *linklist = NULL;
67 double rlat = wpt_node.attribute(
"lat").as_double();
68 double rlon = wpt_node.attribute(
"lon").as_double();
69 double ArrivalRadius = 0;
70 int l_iWaypointRangeRingsNumber = -1;
71 float l_fWaypointRangeRingsStep = -1;
72 int l_pWaypointRangeRingsStepUnits = -1;
73 bool l_bWaypointRangeRingsVisible =
false;
74 long l_iWaypointScaleMin = 2147483646;
75 long l_iWaypoinScaleMax = 0;
76 bool l_bWaypointUseScale =
false;
77 wxColour l_wxcWaypointRangeRingsColour;
78 l_wxcWaypointRangeRingsColour.Set(_T(
"#FFFFFF" ));
80 for (pugi::xml_node child = wpt_node.first_child(); child != 0;
81 child = child.next_sibling()) {
82 const char *pcn = child.name();
84 if (!strcmp(pcn,
"sym")) {
85 SymString = wxString::FromUTF8(child.first_child().value());
86 }
else if (!strcmp(pcn,
"time"))
87 TimeString = wxString::FromUTF8(child.first_child().value());
89 else if (!strcmp(pcn,
"name")) {
90 NameString = wxString::FromUTF8(child.first_child().value());
91 if (NameString.StartsWith(
"@~~")) {
95 TideStation = NameString.Right(NameString.length() - 3);
96 NameString.Replace(
"@~~",
"@-~");
100 else if (!strcmp(pcn,
"desc")) {
101 DescString = wxString::FromUTF8(child.first_child().value());
104 else if (!strcmp(pcn,
"type")) {
105 TypeString = wxString::FromUTF8(child.first_child().value());
109 if (!strcmp(pcn,
"link")) {
111 wxString HrefTextString;
112 wxString HrefTypeString;
113 if (linklist == NULL) linklist =
new HyperlinkList;
114 HrefString = wxString::FromUTF8(child.first_attribute().value());
116 for (pugi::xml_node child1 = child.first_child(); child1;
117 child1 = child1.next_sibling()) {
118 wxString LinkString = wxString::FromUTF8(child1.name());
120 if (LinkString == _T (
"text" ))
121 HrefTextString = wxString::FromUTF8(child1.first_child().value());
122 if (LinkString == _T (
"type" ))
123 HrefTypeString = wxString::FromUTF8(child1.first_child().value());
127 link->Link = HrefString;
128 link->DescrText = HrefTextString;
129 link->LType = HrefTypeString;
130 linklist->Append(link);
134 else if (!strcmp(pcn,
"extensions")) {
135 for (pugi::xml_node ext_child = child.first_child(); ext_child;
136 ext_child = ext_child.next_sibling()) {
137 wxString ext_name = wxString::FromUTF8(ext_child.name());
138 if (ext_name == _T (
"opencpn:guid" )) {
139 GuidString = wxString::FromUTF8(ext_child.first_child().value());
140 }
else if (ext_name == _T (
"opencpn:viz" )) {
142 wxString s = wxString::FromUTF8(ext_child.first_child().value());
144 if (s.ToLong(&v)) bviz = (v != 0);
145 }
else if (ext_name == _T (
"opencpn:viz_name" )) {
146 b_propvizname =
true;
147 wxString s = wxString::FromUTF8(ext_child.first_child().value());
149 if (s.ToLong(&v)) bviz_name = (v != 0);
150 }
else if (ext_name == _T (
"opencpn:auto_name" )) {
151 wxString s = wxString::FromUTF8(ext_child.first_child().value());
153 if (s.ToLong(&v)) bauto_name = (v != 0);
154 }
else if (ext_name == _T (
"opencpn:shared" )) {
155 wxString s = wxString::FromUTF8(ext_child.first_child().value());
157 if (s.ToLong(&v)) bshared = (v != 0);
159 if (ext_name == _T (
"opencpn:arrival_radius" )) {
160 wxString::FromUTF8(ext_child.first_child().value())
161 .ToDouble(&ArrivalRadius);
163 if (ext_name == _T(
"opencpn:waypoint_range_rings")) {
164 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
165 attr = attr.next_attribute()) {
166 if (wxString::FromUTF8(attr.name()) == _T(
"number"))
167 l_iWaypointRangeRingsNumber = attr.as_int();
168 else if (wxString::FromUTF8(attr.name()) == _T(
"step"))
169 l_fWaypointRangeRingsStep = attr.as_float();
170 else if (wxString::FromUTF8(attr.name()) == _T(
"units"))
171 l_pWaypointRangeRingsStepUnits = attr.as_int();
172 else if (wxString::FromUTF8(attr.name()) == _T(
"visible"))
173 l_bWaypointRangeRingsVisible = attr.as_bool();
174 else if (wxString::FromUTF8(attr.name()) == _T(
"colour"))
175 l_wxcWaypointRangeRingsColour.Set(
176 wxString::FromUTF8(attr.as_string()));
179 if (ext_name == _T(
"opencpn:scale_min_max")) {
180 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
181 attr = attr.next_attribute()) {
182 if (wxString::FromUTF8(attr.name()) == _T(
"UseScale"))
183 l_bWaypointUseScale = attr.as_bool();
184 else if (wxString::FromUTF8(attr.name()) == _T(
"ScaleMin"))
185 l_iWaypointScaleMin = attr.as_int();
186 else if (wxString::FromUTF8(attr.name()) == _T(
"ScaleMax"))
187 l_iWaypoinScaleMax = attr.as_float();
190 if (ext_name == _T (
"opencpn:tidestation" )) {
191 TideStation = wxString::FromUTF8(ext_child.first_child().value());
193 if (ext_name == _T (
"opencpn:rte_properties" )) {
194 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
195 attr = attr.next_attribute()) {
196 if (!strcmp(attr.name(),
"planned_speed"))
197 plan_speed = attr.as_double();
198 else if (!strcmp(attr.name(),
"etd"))
199 etd = attr.as_string();
209 if (GuidString.IsEmpty()) GuidString = pWayPointMan->CreateGUID(NULL);
212 pWP =
new RoutePoint(rlat, rlon, SymString, NameString, GuidString,
214 pWP->m_MarkDescription = DescString;
215 pWP->m_TideStation = TideStation;
216 pWP->m_bIsolatedMark = bshared;
217 pWP->SetWaypointArrivalRadius(ArrivalRadius);
218 pWP->SetWaypointRangeRingsNumber(l_iWaypointRangeRingsNumber);
219 pWP->SetWaypointRangeRingsStep(l_fWaypointRangeRingsStep);
220 pWP->SetWaypointRangeRingsStepUnits(l_pWaypointRangeRingsStepUnits);
221 pWP->SetShowWaypointRangeRings(l_bWaypointRangeRingsVisible);
227 if (!l_bWaypointRangeRingsVisible) pWP->SetWaypointRangeRingsNumber(0);
229 pWP->SetWaypointRangeRingsColour(l_wxcWaypointRangeRingsColour);
230 pWP->SetScaMin(l_iWaypointScaleMin);
231 pWP->SetScaMax(l_iWaypoinScaleMax);
232 pWP->SetUseSca(l_bWaypointUseScale);
233 pWP->SetPlannedSpeed(plan_speed);
236 pWP->m_bShowNameData = bviz_name;
238 pWP->m_bShowName = bviz_name;
240 pWP->m_bShowName =
true;
242 pWP->m_bShowName =
false;
245 pWP->m_bIsVisible = bviz;
247 pWP->m_bIsVisible =
true;
250 pWP->m_bIsInLayer =
true;
251 pWP->m_LayerID = layer_id;
252 pWP->m_bIsVisible = b_layerviz;
253 pWP->SetListed(
false);
256 pWP->SetShared(bshared);
257 pWP->m_bDynamicName = bauto_name;
259 if (TimeString.Len()) {
260 pWP->m_timestring = TimeString;
261 pWP->SetCreateTime(wxInvalidDateTime);
265 delete pWP->m_HyperlinkList;
266 pWP->m_HyperlinkList = linklist;
272 static TrackPoint *GPXLoadTrackPoint1(pugi::xml_node &wpt_node) {
275 double rlat = wpt_node.attribute(
"lat").as_double();
276 double rlon = wpt_node.attribute(
"lon").as_double();
278 for (pugi::xml_node child = wpt_node.first_child(); child != 0;
279 child = child.next_sibling()) {
280 const char *pcn = child.name();
281 if (!strcmp(pcn,
"time"))
282 TimeString = wxString::FromUTF8(child.first_child().value());
285 else if (!strcmp(pcn,
"extensions")) {
286 for (pugi::xml_node ext_child = child.first_child(); ext_child;
287 ext_child = ext_child.next_sibling()) {
288 wxString ext_name = wxString::FromUTF8(ext_child.name());
289 if (ext_name == _T (
"opencpn:action" )) {
296 return new TrackPoint(rlat, rlon, TimeString);
299 Track *GPXLoadTrack1(pugi::xml_node &trk_node,
bool b_fullviz,
300 bool b_layer,
bool b_layerviz,
int layer_id) {
303 unsigned short int GPXSeg;
304 bool b_propviz =
false;
306 Track *pTentTrack = NULL;
307 HyperlinkList *linklist = NULL;
309 wxString Name = wxString::FromUTF8(trk_node.name());
310 if (Name == _T (
"trk" )) {
311 pTentTrack =
new Track();
316 for (pugi::xml_node tschild = trk_node.first_child(); tschild;
317 tschild = tschild.next_sibling()) {
318 wxString ChildName = wxString::FromUTF8(tschild.name());
319 if (ChildName == _T (
"trkseg" )) {
323 for (pugi::xml_node tpchild = tschild.first_child(); tpchild;
324 tpchild = tpchild.next_sibling()) {
325 wxString tpChildName = wxString::FromUTF8(tpchild.name());
326 if (tpChildName == _T(
"trkpt")) {
327 pWp = ::GPXLoadTrackPoint1(tpchild);
329 pTentTrack->AddPoint(pWp);
330 pWp->m_GPXTrkSegNo = GPXSeg;
334 }
else if (ChildName == _T (
"name" ))
335 TrackName = wxString::FromUTF8(tschild.first_child().value());
336 else if (ChildName == _T (
"desc" ))
337 DescString = wxString::FromUTF8(tschild.first_child().value());
340 if (ChildName == _T (
"link")) {
342 wxString HrefTextString;
343 wxString HrefTypeString;
344 if (linklist == NULL) linklist =
new HyperlinkList;
345 HrefString = wxString::FromUTF8(tschild.first_attribute().value());
347 for (pugi::xml_node child1 = tschild.first_child(); child1;
348 child1 = child1.next_sibling()) {
349 wxString LinkString = wxString::FromUTF8(child1.name());
351 if (LinkString == _T (
"text" ))
352 HrefTextString = wxString::FromUTF8(child1.first_child().value());
353 if (LinkString == _T (
"type" ))
354 HrefTypeString = wxString::FromUTF8(child1.first_child().value());
358 link->Link = HrefString;
359 link->DescrText = HrefTextString;
360 link->LType = HrefTypeString;
361 linklist->Append(link);
364 else if (ChildName == _T (
"extensions" )) {
365 for (pugi::xml_node ext_child = tschild.first_child(); ext_child;
366 ext_child = ext_child.next_sibling()) {
367 wxString ext_name = wxString::FromUTF8(ext_child.name());
368 if (ext_name == _T (
"opencpn:start" )) {
369 pTentTrack->m_TrackStartString =
370 wxString::FromUTF8(ext_child.first_child().value());
371 }
else if (ext_name == _T (
"opencpn:end" )) {
372 pTentTrack->m_TrackEndString =
373 wxString::FromUTF8(ext_child.first_child().value());
376 else if (ext_name == _T (
"opencpn:viz" )) {
377 wxString viz = wxString::FromUTF8(ext_child.first_child().value());
379 b_viz = (viz == _T(
"1"));
380 }
else if (ext_name == _T (
"opencpn:style" )) {
381 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
382 attr = attr.next_attribute()) {
383 if (!strcmp(attr.name(),
"style"))
384 pTentTrack->m_style = (wxPenStyle)attr.as_int();
385 else if (!strcmp(attr.name(),
"width"))
386 pTentTrack->m_width = attr.as_int();
390 else if (ext_name == _T (
"opencpn:guid" )) {
392 wxString::FromUTF8(ext_child.first_child().value());
395 else if (ext_name.EndsWith(
396 _T (
"TrackExtension" )))
398 for (pugi::xml_node gpxx_child = ext_child.first_child();
399 gpxx_child; gpxx_child = gpxx_child.next_sibling()) {
400 wxString gpxx_name = wxString::FromUTF8(gpxx_child.name());
401 if (gpxx_name.EndsWith(_T (
"DisplayColor" )))
402 pTentTrack->m_Colour =
403 wxString::FromUTF8(gpxx_child.first_child().value());
410 pTentTrack->SetName(TrackName);
411 pTentTrack->m_TrackDescription = DescString;
414 pTentTrack->SetVisible(b_viz);
416 if (b_fullviz) pTentTrack->SetVisible();
420 pTentTrack->SetVisible(b_layerviz);
421 pTentTrack->m_bIsInLayer =
true;
422 pTentTrack->m_LayerID = layer_id;
423 pTentTrack->SetListed(
false);
426 pTentTrack->SetCurrentTrackSeg(GPXSeg);
430 delete pTentTrack->m_HyperlinkList;
431 pTentTrack->m_HyperlinkList = linklist;
437 Route *GPXLoadRoute1(pugi::xml_node &wpt_node,
bool b_fullviz,
438 bool b_layer,
bool b_layerviz,
int layer_id,
439 bool b_change,
bool load_points) {
442 bool b_propviz =
false;
443 bool b_propSWPviz =
false;
446 Route *pTentRoute = NULL;
448 wxString Name = wxString::FromUTF8(wpt_node.name());
449 if (Name == _T (
"rte" )) {
450 pTentRoute =
new Route();
451 HyperlinkList *linklist = NULL;
454 bool route_existing =
false;
455 pTentRoute->m_TimeDisplayFormat = RTE_TIME_DISP_UTC;
457 for (pugi::xml_node tschild = wpt_node.first_child(); tschild;
458 tschild = tschild.next_sibling()) {
459 wxString ChildName = wxString::FromUTF8(tschild.name());
462 if (ChildName == _T (
"extensions" )) {
463 for (pugi::xml_node ext_child = tschild.first_child(); ext_child;
464 ext_child = ext_child.next_sibling()) {
465 wxString ext_name = wxString::FromUTF8(ext_child.name());
467 if (ext_name == _T (
"opencpn:start" )) {
468 pTentRoute->m_RouteStartString =
469 wxString::FromUTF8(ext_child.first_child().value());
470 }
else if (ext_name == _T (
"opencpn:end" )) {
471 pTentRoute->m_RouteEndString =
472 wxString::FromUTF8(ext_child.first_child().value());
475 else if (ext_name == _T (
"opencpn:viz" )) {
476 wxString viz = wxString::FromUTF8(ext_child.first_child().value());
478 b_viz = (viz == _T(
"1"));
481 else if (ext_name == _T (
"opencpn:sharedWPviz" )) {
482 wxString viz = wxString::FromUTF8(ext_child.first_child().value());
484 swpViz = (viz == _T(
"1"));
485 }
else if (ext_name == _T (
"opencpn:style" )) {
486 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
487 attr = attr.next_attribute()) {
488 if (!strcmp(attr.name(),
"style"))
489 pTentRoute->m_style = (wxPenStyle)attr.as_int();
490 else if (!strcmp(attr.name(),
"width"))
491 pTentRoute->m_width = attr.as_int();
495 else if (ext_name == _T (
"opencpn:guid" )) {
497 wxString::FromUTF8(ext_child.first_child().value());
500 else if (ext_name == _T (
"opencpn:planned_speed" )) {
501 pTentRoute->m_PlannedSpeed = atof(ext_child.first_child().value());
504 else if (ext_name == _T (
"opencpn:planned_departure" )) {
506 pTentRoute->m_PlannedDeparture,
507 wxString::FromUTF8(ext_child.first_child().value()));
510 else if (ext_name == _T (
"opencpn:time_display" )) {
511 pTentRoute->m_TimeDisplayFormat =
512 wxString::FromUTF8(ext_child.first_child().value());
513 }
else if (ext_name.EndsWith(
514 _T (
"RouteExtension" )))
516 for (pugi::xml_node gpxx_child = ext_child.first_child();
517 gpxx_child; gpxx_child = gpxx_child.next_sibling()) {
518 wxString gpxx_name = wxString::FromUTF8(gpxx_child.name());
519 if (gpxx_name.EndsWith(_T (
"DisplayColor" )))
520 pTentRoute->m_Colour =
521 wxString::FromUTF8(gpxx_child.first_child().value());
526 if (RouteExists(pTentRoute->m_GUID)) {
529 pTentRoute->m_GUID = pWayPointMan->CreateGUID(NULL);
530 route_existing =
true;
534 else if (load_points && ChildName == _T (
"rtept" )) {
536 ::GPXLoadWaypoint1(tschild, _T(
"square"), _T(
""), b_fullviz,
537 b_layer, b_layerviz, layer_id);
539 if (!b_layer) erp = ::WaypointExists(tpWp->m_GUID);
553 (!route_existing || (route_existing && tpWp->IsShared()))) {
557 if (route_existing) tpWp->m_GUID = pWayPointMan->CreateGUID(NULL);
562 pTentRoute->AddPoint(pWp,
false,
true);
563 pWp->m_bIsInRoute =
true;
567 pWayPointMan->AddRoutePoint(pWp);
573 }
else if (ChildName == _T (
"name" )) {
574 RouteName = wxString::FromUTF8(tschild.first_child().value());
575 }
else if (ChildName == _T (
"desc" )) {
576 DescString = wxString::FromUTF8(tschild.first_child().value());
579 if (ChildName == _T (
"link")) {
581 wxString HrefTextString;
582 wxString HrefTypeString;
583 if (linklist == NULL) linklist =
new HyperlinkList;
584 HrefString = wxString::FromUTF8(tschild.first_attribute().value());
586 for (pugi::xml_node child1 = tschild.first_child(); child1;
587 child1 = child1.next_sibling()) {
588 wxString LinkString = wxString::FromUTF8(child1.name());
590 if (LinkString == _T (
"text" ))
591 HrefTextString = wxString::FromUTF8(child1.first_child().value());
592 if (LinkString == _T (
"type" ))
593 HrefTypeString = wxString::FromUTF8(child1.first_child().value());
597 link->Link = HrefString;
598 link->DescrText = HrefTextString;
599 link->LType = HrefTypeString;
600 linklist->Append(link);
606 if (ChildName.EndsWith(_T (
"RouteExtension" )))
608 for (pugi::xml_node gpxx_child = tschild.first_child(); gpxx_child;
609 gpxx_child = gpxx_child.next_sibling()) {
610 wxString gpxx_name = wxString::FromUTF8(gpxx_child.name());
611 if (gpxx_name.EndsWith(_T (
"DisplayColor" )))
612 pTentRoute->m_Colour =
613 wxString::FromUTF8(gpxx_child.first_child().value());
618 pTentRoute->m_RouteNameString = RouteName;
619 pTentRoute->m_RouteDescription = DescString;
621 pTentRoute->m_HyperlinkList = linklist;
625 pTentRoute->SetVisible(b_viz);
626 }
else if (b_fullviz) {
627 pTentRoute->SetVisible();
630 if (b_propSWPviz) pTentRoute->SetSharedWPViz(swpViz);
633 pTentRoute->SetVisible(b_layerviz);
634 pTentRoute->m_bIsInLayer =
true;
635 pTentRoute->m_LayerID = layer_id;
636 pTentRoute->SetListed(
false);
643 static bool GPXCreateWpt(pugi::xml_node node,
RoutePoint *pr,
644 unsigned int flags) {
646 pugi::xml_node child;
647 pugi::xml_attribute attr;
649 s.Printf(_T(
"%.9f"), pr->m_lat);
650 node.append_attribute(
"lat") = s.mb_str();
651 s.Printf(_T(
"%.9f"), pr->m_lon);
652 node.append_attribute(
"lon") = s.mb_str();
654 if (flags & OUT_TIME) {
655 child = node.append_child(
"time");
656 if (pr->m_timestring.Len())
657 child.append_child(pugi::node_pcdata)
658 .set_value(pr->m_timestring.mb_str());
660 wxDateTime dt = pr->GetCreateTime();
662 dt = wxDateTime::Now();
664 wxString t = dt.ToUTC().FormatISODate()
666 .Append(dt.ToUTC().FormatISOTime())
668 child.append_child(pugi::node_pcdata).set_value(t.mb_str());
672 if ((!pr->GetName().IsEmpty() && (flags & OUT_NAME)) ||
673 (flags & OUT_NAME_FORCE)) {
674 wxCharBuffer buffer = pr->GetName().ToUTF8();
676 child = node.append_child(
"name");
677 child.append_child(pugi::node_pcdata).set_value(buffer.data());
681 if ((!pr->GetDescription().IsEmpty() && (flags & OUT_DESC)) ||
682 (flags & OUT_DESC_FORCE)) {
683 wxCharBuffer buffer = pr->GetDescription().ToUTF8();
685 child = node.append_child(
"desc");
686 child.append_child(pugi::node_pcdata).set_value(buffer.data());
691 if (flags & OUT_HYPERLINKS) {
692 HyperlinkList *linklist = pr->m_HyperlinkList;
693 if (linklist && linklist->GetCount()) {
694 wxHyperlinkListNode *linknode = linklist->GetFirst();
698 pugi::xml_node child_link = node.append_child(
"link");
700 wxCharBuffer buffer = link->Link.ToUTF8();
701 if (buffer.data()) child_link.append_attribute(
"href") = buffer.data();
703 buffer = link->DescrText.ToUTF8();
705 child = child_link.append_child(
"text");
706 child.append_child(pugi::node_pcdata).set_value(buffer.data());
709 buffer = link->LType.ToUTF8();
710 if (buffer.data() && strlen(buffer.data()) > 0) {
711 child = child_link.append_child(
"type");
712 child.append_child(pugi::node_pcdata).set_value(buffer.data());
715 linknode = linknode->GetNext();
720 if (flags & OUT_SYM_FORCE) {
721 child = node.append_child(
"sym");
722 if (!pr->GetIconName().IsEmpty()) {
723 child.append_child(pugi::node_pcdata)
724 .set_value(pr->GetIconName().mb_str());
726 child.append_child(
"empty");
730 if (flags & OUT_TYPE) {
731 child = node.append_child(
"type");
732 child.append_child(pugi::node_pcdata).set_value(
"WPT");
735 if ((flags & OUT_GUID) || (flags & OUT_VIZ) || (flags & OUT_VIZ_NAME) ||
736 (flags & OUT_SHARED) || (flags & OUT_AUTO_NAME) ||
737 (flags & OUT_EXTENSION) || (flags & OUT_TIDE_STATION) ||
738 (flags & OUT_RTE_PROPERTIES)) {
739 pugi::xml_node child_ext = node.append_child(
"extensions");
741 if (!pr->m_GUID.IsEmpty() && (flags & OUT_GUID)) {
742 child = child_ext.append_child(
"opencpn:guid");
743 child.append_child(pugi::node_pcdata).set_value(pr->m_GUID.mb_str());
746 if ((flags & OUT_VIZ) && !pr->m_bIsVisible) {
747 child = child_ext.append_child(
"opencpn:viz");
748 child.append_child(pugi::node_pcdata).set_value(
"0");
751 if ((flags & OUT_VIZ_NAME) && pr->m_bShowName) {
752 child = child_ext.append_child(
"opencpn:viz_name");
753 child.append_child(pugi::node_pcdata).set_value(
"1");
756 if ((flags & OUT_AUTO_NAME) && pr->m_bDynamicName) {
757 child = child_ext.append_child(
"opencpn:auto_name");
758 child.append_child(pugi::node_pcdata).set_value(
"1");
760 if ((flags & OUT_SHARED) && pr->IsShared()) {
761 child = child_ext.append_child(
"opencpn:shared");
762 child.append_child(pugi::node_pcdata).set_value(
"1");
764 if (flags & OUT_ARRIVAL_RADIUS) {
765 child = child_ext.append_child(
"opencpn:arrival_radius");
766 s.Printf(_T(
"%.3f"), pr->GetWaypointArrivalRadius());
767 child.append_child(pugi::node_pcdata).set_value(s.mbc_str());
769 if (flags & OUT_WAYPOINT_RANGE_RINGS) {
770 child = child_ext.append_child(
"opencpn:waypoint_range_rings");
771 pugi::xml_attribute viz = child.append_attribute(
"visible");
772 viz.set_value(pr->m_bShowWaypointRangeRings);
773 pugi::xml_attribute number = child.append_attribute(
"number");
774 number.set_value(pr->m_iWaypointRangeRingsNumber);
775 pugi::xml_attribute step = child.append_attribute(
"step");
776 step.set_value(pr->m_fWaypointRangeRingsStep);
777 pugi::xml_attribute units = child.append_attribute(
"units");
778 units.set_value(pr->m_iWaypointRangeRingsStepUnits);
781 if (pr->m_wxcWaypointRangeRingsColour.IsOk()) {
782 pr->m_wxcWaypointRangeRingsColour.Set(
783 pr->m_wxcWaypointRangeRingsColour.Red(),
784 pr->m_wxcWaypointRangeRingsColour.Green(),
785 pr->m_wxcWaypointRangeRingsColour.Blue(),
789 pr->m_wxcWaypointRangeRingsColour.Set(0,0,0,wxALPHA_OPAQUE);
792 pugi::xml_attribute colour = child.append_attribute(
"colour");
794 pr->m_wxcWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX)
797 if (flags & OUT_WAYPOINT_SCALE) {
798 child = child_ext.append_child(
"opencpn:scale_min_max");
799 pugi::xml_attribute use = child.append_attribute(
"UseScale");
800 use.set_value(pr->GetUseSca());
801 pugi::xml_attribute sca = child.append_attribute(
"ScaleMin");
802 sca.set_value(pr->GetScaMin());
803 pugi::xml_attribute max = child.append_attribute(
"ScaleMax");
804 max.set_value(pr->GetScaMax());
806 if ((flags & OUT_TIDE_STATION) && !pr->m_TideStation.IsEmpty()) {
807 child = child_ext.append_child(
"opencpn:tidestation");
808 child.append_child(pugi::node_pcdata)
809 .set_value(pr->m_TideStation.mb_str());
811 if ((flags & OUT_RTE_PROPERTIES) &&
812 (pr->GetPlannedSpeed() > 0.0001 || pr->m_manual_etd)) {
813 child = child_ext.append_child(
"opencpn:rte_properties");
814 if (pr->GetPlannedSpeed() > 0.0001) {
815 pugi::xml_attribute use = child.append_attribute(
"planned_speed");
817 wxString::Format(_T(
"%.1lf"), pr->GetPlannedSpeed()).mb_str());
819 if (pr->m_manual_etd) {
820 pugi::xml_attribute use = child.append_attribute(
"etd");
821 use.set_value(pr->GetManualETD().FormatISOCombined().mb_str());
829 static bool GPXCreateTrkpt(pugi::xml_node node,
TrackPoint *pt,
830 unsigned int flags) {
832 pugi::xml_node child;
833 pugi::xml_attribute attr;
835 s.Printf(_T(
"%.9f"), pt->m_lat);
836 node.append_attribute(
"lat") = s.mb_str();
837 s.Printf(_T(
"%.9f"), pt->m_lon);
838 node.append_attribute(
"lon") = s.mb_str();
840 if (flags & OUT_TIME && pt->HasValidTimestamp()) {
841 child = node.append_child(
"time");
842 child.append_child(pugi::node_pcdata).set_value(pt->GetTimeString());
848 static bool GPXCreateTrk(pugi::xml_node node,
Track *pTrack,
849 unsigned int flags) {
850 pugi::xml_node child;
852 if (pTrack->GetName().Len()) {
853 wxCharBuffer buffer = pTrack->GetName().ToUTF8();
855 child = node.append_child(
"name");
856 child.append_child(pugi::node_pcdata).set_value(buffer.data());
860 if (pTrack->m_TrackDescription.Len()) {
861 wxCharBuffer buffer = pTrack->m_TrackDescription.ToUTF8();
863 child = node.append_child(
"desc");
864 child.append_child(pugi::node_pcdata).set_value(buffer.data());
869 HyperlinkList *linklist = pTrack->m_HyperlinkList;
870 if (linklist && linklist->GetCount()) {
871 wxHyperlinkListNode *linknode = linklist->GetFirst();
875 pugi::xml_node child_link = node.append_child(
"link");
876 wxCharBuffer buffer = link->Link.ToUTF8();
877 if (buffer.data()) child_link.append_attribute(
"href") = buffer.data();
879 buffer = link->DescrText.ToUTF8();
881 child = child_link.append_child(
"text");
882 child.append_child(pugi::node_pcdata).set_value(buffer.data());
885 buffer = link->LType.ToUTF8();
886 if (buffer.data() && strlen(buffer.data()) > 0) {
887 child = child_link.append_child(
"type");
888 child.append_child(pugi::node_pcdata).set_value(buffer.data());
891 linknode = linknode->GetNext();
895 pugi::xml_node child_ext = node.append_child(
"extensions");
897 child = child_ext.append_child(
"opencpn:guid");
898 child.append_child(pugi::node_pcdata).set_value(pTrack->m_GUID.mb_str());
900 child = child_ext.append_child(
"opencpn:viz");
901 child.append_child(pugi::node_pcdata)
902 .set_value(pTrack->IsVisible() ==
true ?
"1" :
"0");
904 if (pTrack->m_TrackStartString.Len()) {
905 wxCharBuffer buffer = pTrack->m_TrackStartString.ToUTF8();
907 child = child_ext.append_child(
"opencpn:start");
908 child.append_child(pugi::node_pcdata).set_value(buffer.data());
912 if (pTrack->m_TrackEndString.Len()) {
913 wxCharBuffer buffer = pTrack->m_TrackEndString.ToUTF8();
915 child = child_ext.append_child(
"opencpn:end");
916 child.append_child(pugi::node_pcdata).set_value(buffer.data());
920 if (pTrack->m_width != WIDTH_UNDEFINED ||
921 pTrack->m_style != wxPENSTYLE_INVALID) {
922 child = child_ext.append_child(
"opencpn:style");
924 if (pTrack->m_width != WIDTH_UNDEFINED)
925 child.append_attribute(
"width") = pTrack->m_width;
926 if (pTrack->m_style != wxPENSTYLE_INVALID)
927 child.append_attribute(
"style") = pTrack->m_style;
930 if (pTrack->m_Colour != wxEmptyString) {
931 pugi::xml_node gpxx_ext = child_ext.append_child(
"gpxx:TrackExtension");
932 child = gpxx_ext.append_child(
"gpxx:DisplayColor");
933 child.append_child(pugi::node_pcdata).set_value(pTrack->m_Colour.mb_str());
936 if (flags & RT_OUT_NO_RTPTS)
return true;
941 unsigned short int GPXTrkSegNo1 = 1;
944 unsigned short int GPXTrkSegNo2 = GPXTrkSegNo1;
946 pugi::xml_node seg = node.append_child(
"trkseg");
948 while (node2 < pTrack->GetnPoints()) {
949 prp = pTrack->GetPoint(node2);
950 GPXTrkSegNo1 = prp->m_GPXTrkSegNo;
951 if (GPXTrkSegNo1 != GPXTrkSegNo2)
break;
953 GPXCreateTrkpt(seg.append_child(
"trkpt"), prp, OPT_TRACKPT);
957 }
while (node2 < pTrack->GetnPoints());
962 static bool GPXCreateRoute(pugi::xml_node node,
Route *pRoute) {
963 pugi::xml_node child;
965 if (pRoute->m_RouteNameString.Len()) {
966 wxCharBuffer buffer = pRoute->m_RouteNameString.ToUTF8();
968 child = node.append_child(
"name");
969 child.append_child(pugi::node_pcdata).set_value(buffer.data());
973 if (pRoute->m_RouteDescription.Len()) {
974 wxCharBuffer buffer = pRoute->m_RouteDescription.ToUTF8();
976 child = node.append_child(
"desc");
977 child.append_child(pugi::node_pcdata).set_value(buffer.data());
982 HyperlinkList *linklist = pRoute->m_HyperlinkList;
983 if (linklist && linklist->GetCount()) {
984 wxHyperlinkListNode *linknode = linklist->GetFirst();
988 pugi::xml_node child_link = node.append_child(
"link");
989 wxCharBuffer buffer = link->Link.ToUTF8();
990 if (buffer.data()) child_link.append_attribute(
"href") = buffer.data();
992 buffer = link->DescrText.ToUTF8();
994 child = child_link.append_child(
"text");
995 child.append_child(pugi::node_pcdata).set_value(buffer.data());
998 buffer = link->LType.ToUTF8();
999 if (buffer.data() && strlen(buffer.data()) > 0) {
1000 child = child_link.append_child(
"type");
1001 child.append_child(pugi::node_pcdata).set_value(buffer.data());
1004 linknode = linknode->GetNext();
1008 pugi::xml_node child_ext = node.append_child(
"extensions");
1010 child = child_ext.append_child(
"opencpn:guid");
1011 child.append_child(pugi::node_pcdata).set_value(pRoute->m_GUID.mb_str());
1013 child = child_ext.append_child(
"opencpn:viz");
1014 child.append_child(pugi::node_pcdata)
1015 .set_value(pRoute->IsVisible() ==
true ?
"1" :
"0");
1017 if (pRoute->ContainsSharedWP()) {
1018 child = child_ext.append_child(
"opencpn:sharedWPviz");
1019 child.append_child(pugi::node_pcdata)
1020 .set_value(pRoute->GetSharedWPViz() ==
true ?
"1" :
"0");
1023 if (pRoute->m_RouteStartString.Len()) {
1024 wxCharBuffer buffer = pRoute->m_RouteStartString.ToUTF8();
1025 if (buffer.data()) {
1026 child = child_ext.append_child(
"opencpn:start");
1027 child.append_child(pugi::node_pcdata).set_value(buffer.data());
1031 if (pRoute->m_RouteEndString.Len()) {
1032 wxCharBuffer buffer = pRoute->m_RouteEndString.ToUTF8();
1033 if (buffer.data()) {
1034 child = child_ext.append_child(
"opencpn:end");
1035 child.append_child(pugi::node_pcdata).set_value(buffer.data());
1039 if (pRoute->m_PlannedSpeed != ROUTE_DEFAULT_SPEED) {
1040 child = child_ext.append_child(
"opencpn:planned_speed");
1042 s.Printf(_T(
"%.2f"), pRoute->m_PlannedSpeed);
1043 child.append_child(pugi::node_pcdata).set_value(s.mb_str());
1046 if (pRoute->m_PlannedDeparture.IsValid()) {
1047 child = child_ext.append_child(
"opencpn:planned_departure");
1048 wxString t = pRoute->m_PlannedDeparture.FormatISODate()
1050 .Append(pRoute->m_PlannedDeparture.FormatISOTime())
1052 child.append_child(pugi::node_pcdata).set_value(t.mb_str());
1055 child = child_ext.append_child(
"opencpn:time_display");
1056 child.append_child(pugi::node_pcdata)
1057 .set_value(pRoute->m_TimeDisplayFormat.mb_str());
1059 if (pRoute->m_width != WIDTH_UNDEFINED ||
1060 pRoute->m_style != wxPENSTYLE_INVALID) {
1061 child = child_ext.append_child(
"opencpn:style");
1063 if (pRoute->m_width != WIDTH_UNDEFINED)
1064 child.append_attribute(
"width") = pRoute->m_width;
1065 if (pRoute->m_style != wxPENSTYLE_INVALID)
1066 child.append_attribute(
"style") = pRoute->m_style;
1069 pugi::xml_node gpxx_ext = child_ext.append_child(
"gpxx:RouteExtension");
1070 child = gpxx_ext.append_child(
"gpxx:IsAutoNamed");
1071 child.append_child(pugi::node_pcdata).set_value(
"false");
1073 if (pRoute->m_Colour != wxEmptyString) {
1074 child = gpxx_ext.append_child(
"gpxx:DisplayColor");
1075 child.append_child(pugi::node_pcdata).set_value(pRoute->m_Colour.mb_str());
1078 RoutePointList *pRoutePointList = pRoute->pRoutePointList;
1079 wxRoutePointListNode *node2 = pRoutePointList->GetFirst();
1083 prp = node2->GetData();
1085 GPXCreateWpt(node.append_child(
"rtept"), prp, OPT_ROUTEPT);
1087 node2 = node2->GetNext();
1094 if (!pTentRoute)
return false;
1096 bool bAddroute =
true;
1098 if (pTentRoute->GetnPoints() < 2) bAddroute =
false;
1103 pRouteList->Append(pTentRoute);
1106 pTentRoute->FinalizeForRendering();
1111 float prev_rlat = 0., prev_rlon = 0.;
1114 wxRoutePointListNode *node = pTentRoute->pRoutePointList->GetFirst();
1119 pSelect->AddSelectableRouteSegment(prev_rlat, prev_rlon, prp->m_lat,
1120 prp->m_lon, prev_pConfPoint, prp,
1122 pSelect->AddSelectableRoutePoint(prp->m_lat, prp->m_lon, prp);
1123 prev_rlat = prp->m_lat;
1124 prev_rlon = prp->m_lon;
1125 prev_pConfPoint = prp;
1129 node = node->GetNext();
1133 wxRoutePointListNode *pnode = (pTentRoute->pRoutePointList)->GetFirst();
1138 Route *pcontainer_route = g_pRouteMan->FindRouteContainingWaypoint(prp);
1140 if (pcontainer_route == NULL) {
1143 if (!prp->IsShared()) {
1144 navobj->m_bSkipChangeSetUpdate =
true;
1145 NavObjectChanges::getInstance()->DeleteWayPoint(prp);
1146 navobj->m_bSkipChangeSetUpdate =
false;
1151 pnode = pnode->GetNext();
1159 bool InsertTrack(
Track *pTentTrack,
bool bApplyChanges) {
1160 if (!pTentTrack)
return false;
1162 bool bAddtrack =
true;
1165 if (!bApplyChanges && pTentTrack->GetnPoints() < 2) bAddtrack =
false;
1170 g_TrackList.push_back(pTentTrack);
1177 float prev_rlat = 0., prev_rlon = 0.;
1180 for (
int i = 0; i < pTentTrack->GetnPoints(); i++) {
1184 pSelect->AddSelectableTrackSegment(prev_rlat, prev_rlon, prp->m_lat,
1185 prp->m_lon, prev_pConfPoint, prp,
1188 prev_rlat = prp->m_lat;
1189 prev_rlon = prp->m_lon;
1190 prev_pConfPoint = prp;
1198 bool InsertWpt(
RoutePoint *pWp,
bool overwrite) {
1201 WaypointExists(pWp->GetName(), pWp->m_lat, pWp->m_lon);
1202 if (!pExisting || overwrite) {
1203 if (NULL != pWayPointMan) {
1205 pWayPointMan->DestroyWaypoint(pExisting);
1207 pWayPointMan->AddRoutePoint(pWp);
1210 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1215 static void UpdateRouteA(
Route* pTentRoute,
1218 if (!pTentRoute)
return;
1219 if (pTentRoute->GetnPoints() < 2)
return;
1222 Route *pExisting = ::RouteExists(pTentRoute->m_GUID);
1224 navobj->m_bSkipChangeSetUpdate =
true;
1225 g_pRouteMan->
DeleteRoute(pExisting, nav_obj_changes);
1226 navobj->m_bSkipChangeSetUpdate =
false;
1231 pRouteList->Append(pChangeRoute);
1234 pChangeRoute->m_GUID = pTentRoute->m_GUID;
1235 pChangeRoute->m_RouteNameString = pTentRoute->m_RouteNameString;
1236 pChangeRoute->m_RouteStartString = pTentRoute->m_RouteStartString;
1237 pChangeRoute->m_RouteEndString = pTentRoute->m_RouteEndString;
1238 pChangeRoute->SetVisible(pTentRoute->IsVisible());
1242 float prev_rlat = 0., prev_rlon = 0.;
1245 wxRoutePointListNode *node = pTentRoute->pRoutePointList->GetFirst();
1251 RoutePoint *ex_rp = ::WaypointExists(prp->m_GUID);
1253 pSelect->DeleteSelectableRoutePoint(ex_rp);
1254 ex_rp->m_lat = prp->m_lat;
1255 ex_rp->m_lon = prp->m_lon;
1256 ex_rp->SetIconName(prp->GetIconName());
1257 ex_rp->m_MarkDescription = prp->m_MarkDescription;
1258 ex_rp->SetName(prp->GetName());
1259 ex_rp->m_TideStation = prp->m_TideStation;
1260 ex_rp->SetPlannedSpeed(prp->GetPlannedSpeed());
1261 pChangeRoute->AddPoint(ex_rp);
1262 pSelect->AddSelectableRoutePoint(prp->m_lat, prp->m_lon, ex_rp);
1265 pChangeRoute->AddPoint(prp);
1266 pSelect->AddSelectableRoutePoint(prp->m_lat, prp->m_lon, prp);
1267 pWayPointMan->AddRoutePoint(prp);
1271 pSelect->AddSelectableRouteSegment(prev_rlat, prev_rlon, prp->m_lat,
1272 prp->m_lon, prev_pConfPoint, prp,
1274 prev_rlat = prp->m_lat;
1275 prev_rlon = prp->m_lon;
1276 prev_pConfPoint = prp;
1280 node = node->GetNext();
1283 pChangeRoute->FinalizeForRendering();
1287 wxRouteListNode *node = pRouteList->GetFirst();
1289 Route *proute = node->GetData();
1291 wxRoutePointListNode *pnode = (proute->pRoutePointList)->GetFirst();
1294 if (prp == pWP)
return proute;
1295 pnode = pnode->GetNext();
1298 node = node->GetNext();
1305 bool NavObjectCollection1::CreateNavObjGPXPoints(
void) {
1310 if (!pWayPointMan)
return false;
1312 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
1317 pr = node->GetData();
1319 if ((pr->m_bIsolatedMark) && !(pr->m_bIsInLayer) && !(pr->m_btemp)) {
1320 pugi::xml_node doc = root();
1321 pugi::xml_node gpx = doc.first_child();
1322 pugi::xml_node new_node = gpx.append_child(
"wpt");
1324 GPXCreateWpt(new_node, pr, OPT_WPT);
1326 node = node->GetNext();
1332 bool NavObjectCollection1::CreateNavObjGPXRoutes(
void) {
1334 if (!pRouteList)
return false;
1336 wxRouteListNode *node1 = pRouteList->GetFirst();
1338 Route *pRoute = node1->GetData();
1340 if (!pRoute->m_bIsInLayer && !pRoute->m_btemp){
1341 pugi::xml_node doc = root();
1342 pugi::xml_node gpx = doc.first_child();
1343 pugi::xml_node new_node = gpx.append_child(
"rte");
1345 GPXCreateRoute(new_node, pRoute);
1348 node1 = node1->GetNext();
1354 bool NavObjectCollection1::CreateNavObjGPXTracks(
void) {
1356 for (
Track *pTrack : g_TrackList) {
1357 if (pTrack->GetnPoints()) {
1358 if (!pTrack->m_bIsInLayer && !pTrack->m_btemp){
1359 pugi::xml_node doc = root();
1360 pugi::xml_node gpx = doc.first_child();
1361 pugi::xml_node new_node = gpx.append_child(
"trk");
1363 GPXCreateTrk(new_node, pTrack, 0);
1371 bool NavObjectCollection1::CreateAllGPXObjects() {
1374 CreateNavObjGPXPoints();
1375 CreateNavObjGPXRoutes();
1376 CreateNavObjGPXTracks();
1381 bool NavObjectCollection1::AddGPXRoute(
Route *pRoute) {
1383 pugi::xml_node doc = root();
1384 pugi::xml_node gpx = doc.first_child();
1385 pugi::xml_node new_node = gpx.append_child(
"rte");
1387 GPXCreateRoute(new_node, pRoute);
1391 bool NavObjectCollection1::AddGPXTrack(
Track *pTrk) {
1393 pugi::xml_node doc = root();
1394 pugi::xml_node gpx = doc.first_child();
1395 pugi::xml_node new_node = gpx.append_child(
"trk");
1397 GPXCreateTrk(new_node, pTrk, 0);
1401 bool NavObjectCollection1::AddGPXWaypoint(
RoutePoint *pWP) {
1403 pugi::xml_node doc = root();
1404 pugi::xml_node gpx = doc.first_child();
1405 pugi::xml_node new_node = gpx.append_child(
"wpt");
1407 GPXCreateWpt(new_node, pWP, OPT_WPT);
1411 void NavObjectCollection1::AddGPXRoutesList(RouteList *pRoutes) {
1414 wxRouteListNode *pRoute = pRoutes->GetFirst();
1416 Route *pRData = pRoute->GetData();
1417 AddGPXRoute(pRData);
1418 pRoute = pRoute->GetNext();
1422 void NavObjectCollection1::AddGPXTracksList(std::vector<Track*> *pTracks) {
1425 for (
Track *pRData : *pTracks) {
1426 AddGPXTrack(pRData);
1430 bool NavObjectCollection1::AddGPXPointsList(RoutePointList *pRoutePoints) {
1433 wxRoutePointListNode *pRoutePointNode = pRoutePoints->GetFirst();
1434 while (pRoutePointNode) {
1435 RoutePoint *pRP = pRoutePointNode->GetData();
1436 AddGPXWaypoint(pRP);
1437 pRoutePointNode = pRoutePointNode->GetNext();
1443 void NavObjectCollection1::SetRootGPXNode(
void) {
1444 if (!strlen(first_child().name())) {
1445 pugi::xml_node gpx_root = append_child(
"gpx");
1446 gpx_root.append_attribute(
"version") =
"1.1";
1447 gpx_root.append_attribute(
"creator") =
"OpenCPN";
1448 gpx_root.append_attribute(
"xmlns:xsi") =
1449 "http://www.w3.org/2001/XMLSchema-instance";
1450 gpx_root.append_attribute(
"xmlns") =
"http://www.topografix.com/GPX/1/1";
1451 gpx_root.append_attribute(
"xmlns:gpxx") =
1452 "http://www.garmin.com/xmlschemas/GpxExtensions/v3";
1453 gpx_root.append_attribute(
"xsi:schemaLocation") =
1454 "http://www.topografix.com/GPX/1/1 "
1455 "http://www.topografix.com/GPX/1/1/gpx.xsd "
1456 "http://www.garmin.com/xmlschemas/GpxExtensions/v3 "
1457 "http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd";
1458 gpx_root.append_attribute(
"xmlns:opencpn") =
"http://www.opencpn.org";
1462 bool NavObjectCollection1::IsOpenCPN() {
1463 for (pugi::xml_attribute attr = root().first_child().first_attribute(); attr;
1464 attr = attr.next_attribute())
1465 if (!strcmp(attr.name(),
"creator") && !strcmp(attr.value(),
"OpenCPN"))
1470 bool NavObjectCollection1::SaveFile(
const wxString filename) {
1471 wxString tmp_filename = filename +
".tmp";
1472 if (wxFileExists(tmp_filename)) {
1473 wxRemoveFile(tmp_filename);
1475 save_file(tmp_filename.fn_str(),
" ");
1476 wxRenameFile(tmp_filename.fn_str(), filename.fn_str(),
true);
1480 bool NavObjectCollection1::LoadAllGPXObjects(
bool b_full_viz,
1481 int &wpt_duplicates,
1482 bool b_compute_bbox) {
1484 pugi::xml_node objects = this->child(
"gpx");
1486 for (pugi::xml_node
object = objects.first_child();
object;
1487 object =
object.next_sibling()) {
1488 if (!strcmp(
object.name(),
"wpt")) {
1489 RoutePoint *pWp = ::GPXLoadWaypoint1(
object, _T(
"circle"), _T(
""),
1490 b_full_viz,
false,
false, 0);
1492 pWp->m_bIsolatedMark =
true;
1494 WaypointExists(pWp->GetName(), pWp->m_lat, pWp->m_lon);
1496 if (NULL != pWayPointMan) pWayPointMan->AddRoutePoint(pWp);
1497 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1499 wptbox.Set(pWp->m_lat, pWp->m_lon, pWp->m_lat, pWp->m_lon);
1500 BBox.Expand(wptbox);
1505 }
else if (!strcmp(
object.name(),
"trk")) {
1506 Track *pTrack = GPXLoadTrack1(
object, b_full_viz,
false,
false, 0);
1507 if (InsertTrack(pTrack) && b_compute_bbox && pTrack->IsVisible()) {
1510 }
else if (!strcmp(
object.name(),
"rte")) {
1511 Route *pRoute = GPXLoadRoute1(
object, b_full_viz,
false,
false, 0,
false);
1512 if (InsertRouteA(pRoute,
this) && b_compute_bbox && pRoute->IsVisible()) {
1513 BBox.Expand(pRoute->GetBBox());
1522 int NavObjectCollection1::LoadAllGPXObjectsAsLayer(
int layer_id,
1524 wxCheckBoxState b_namesviz) {
1525 if (!pWayPointMan)
return 0;
1528 pugi::xml_node objects = this->child(
"gpx");
1530 for (pugi::xml_node
object = objects.first_child();
object;
1531 object =
object.next_sibling()) {
1532 if (!strcmp(
object.name(),
"wpt")) {
1533 RoutePoint *pWp = ::GPXLoadWaypoint1(
object, _T(
"circle"), _T(
""),
1534 b_namesviz != wxCHK_UNDETERMINED,
1535 true, b_layerviz, layer_id);
1536 if (b_namesviz != wxCHK_UNDETERMINED) {
1537 pWp->SetNameShown(b_namesviz == wxCHK_CHECKED);
1539 pWp->m_bIsolatedMark =
true;
1540 pWayPointMan->AddRoutePoint(pWp);
1541 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1544 if (!strcmp(
object.name(),
"trk")) {
1546 GPXLoadTrack1(
object,
false,
true, b_layerviz, layer_id);
1548 InsertTrack(pTrack);
1549 }
else if (!strcmp(
object.name(),
"rte")) {
1551 GPXLoadRoute1(
object,
true,
true, b_layerviz, layer_id,
false);
1553 InsertRouteA(pRoute,
this);
1561 NavObjectChanges::NavObjectChanges(wxString file_name)
1563 m_filename = file_name;
1564 m_changes_file = fopen(m_filename.mb_str(),
"a");
1568 NavObjectChanges::~NavObjectChanges() {
1569 if (m_changes_file) fclose(m_changes_file);
1570 if (::wxFileExists(m_filename)) ::wxRemoveFile(m_filename);
1573 void NavObjectChanges::AddRoute(
Route *pr,
const char *action) {
1576 pugi::xml_node
object = root().append_child(
"rte");
1577 GPXCreateRoute(
object, pr);
1579 pugi::xml_node xchild =
object.child(
"extensions");
1581 pugi::xml_node child = xchild.append_child(
"opencpn:action");
1582 child.append_child(pugi::node_pcdata).set_value(action);
1584 if (m_changes_file){
1585 pugi::xml_writer_file writer(m_changes_file);
1586 object.print(writer,
" ");
1587 fflush(m_changes_file);
1592 void NavObjectChanges::AddTrack(
Track *pr,
const char *action) {
1595 pugi::xml_node
object = root().append_child(
"trk");
1596 GPXCreateTrk(
object, pr, RT_OUT_NO_RTPTS);
1598 pugi::xml_node xchild =
object.child(
"extensions");
1599 pugi::xml_node child = xchild.append_child(
"opencpn:action");
1600 child.append_child(pugi::node_pcdata).set_value(action);
1602 if (m_changes_file){
1603 pugi::xml_writer_file writer(m_changes_file);
1604 object.print(writer,
" ");
1605 fflush(m_changes_file);
1610 void NavObjectChanges::AddWP(
RoutePoint *pWP,
const char *action) {
1613 pugi::xml_node
object = root().append_child(
"wpt");
1615 int flags = OPT_WPT;
1617 if(!strncmp(action,
"delete", 6))
1618 flags = OUT_GUID | OUT_NAME;
1620 GPXCreateWpt(
object, pWP, flags);
1622 pugi::xml_node xchild =
object.child(
"extensions");
1623 pugi::xml_node child = xchild.append_child(
"opencpn:action");
1624 child.append_child(pugi::node_pcdata).set_value(action);
1626 if (m_changes_file){
1627 pugi::xml_writer_file writer(m_changes_file);
1628 object.print(writer,
" ");
1629 fflush(m_changes_file);
1634 void NavObjectChanges::AddTrackPoint(
TrackPoint *pWP,
const char *action,
1635 const wxString &parent_GUID) {
1638 pugi::xml_node
object = root().append_child(
"tkpt");
1639 GPXCreateTrkpt(
object, pWP, OPT_TRACKPT);
1641 pugi::xml_node xchild =
object.append_child(
"extensions");
1643 pugi::xml_node child = xchild.append_child(
"opencpn:action");
1644 child.append_child(pugi::node_pcdata).set_value(action);
1646 pugi::xml_node gchild = xchild.append_child(
"opencpn:track_GUID");
1647 gchild.append_child(pugi::node_pcdata).set_value(parent_GUID.mb_str());
1649 if (m_changes_file){
1650 pugi::xml_writer_file writer(m_changes_file);
1651 object.print(writer,
" ");
1652 fflush(m_changes_file);
1657 bool NavObjectChanges::ApplyChanges(
void) {
1660 pugi::xml_node
object = this->first_child();
1662 while (strlen(
object.name())) {
1663 if (!strcmp(
object.name(),
"wpt") && pWayPointMan) {
1664 RoutePoint *pWp = ::GPXLoadWaypoint1(
object, _T(
"circle"), _T(
""),
false,
1667 pWp->m_bIsolatedMark =
true;
1668 RoutePoint *pExisting = WaypointExists(pWp->m_GUID);
1670 pugi::xml_node xchild =
object.child(
"extensions");
1671 pugi::xml_node child = xchild.child(
"opencpn:action");
1673 if (!strcmp(child.first_child().value(),
"add")) {
1674 if (!pExisting) pWayPointMan->AddRoutePoint(pWp);
1675 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1678 else if (!strcmp(child.first_child().value(),
"update")) {
1680 pWayPointMan->RemoveRoutePoint(pExisting);
1681 pWayPointMan->DestroyWaypoint(pExisting,
false);
1683 pWayPointMan->AddRoutePoint(pWp);
1684 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1690 else if (!strcmp(child.first_child().value(),
"delete")) {
1691 if (pExisting) pWayPointMan->DestroyWaypoint(pExisting,
false);
1696 }
else if (!strcmp(
object.name(),
"trk") && g_pRouteMan) {
1697 Track *pTrack = GPXLoadTrack1(
object,
false,
false,
false, 0);
1700 pugi::xml_node xchild =
object.child(
"extensions");
1701 pugi::xml_node child = xchild.child(
"opencpn:action");
1703 Track *pExisting = TrackExists(pTrack->m_GUID);
1704 if (!strcmp(child.first_child().value(),
"update")) {
1706 pExisting->SetName(pTrack->GetName());
1707 pExisting->m_TrackStartString = pTrack->m_TrackStartString;
1708 pExisting->m_TrackEndString = pTrack->m_TrackEndString;
1713 else if (!strcmp(child.first_child().value(),
"delete")) {
1715 m_bSkipChangeSetUpdate =
true;
1717 g_pRouteMan->DeleteTrack(pExisting);
1718 m_bSkipChangeSetUpdate =
false;
1723 else if (!strcmp(child.first_child().value(),
"add")) {
1724 if (!pExisting) ::InsertTrack(pTrack,
true);
1732 else if (!strcmp(
object.name(),
"rte") && g_pRouteMan) {
1733 Route *pRoute = GPXLoadRoute1(
object,
false,
false,
false, 0,
true,
false);
1736 Route *pExisting = RouteExists(pRoute->m_GUID);
1737 pugi::xml_node xchild =
object.child(
"extensions");
1738 pugi::xml_node child = xchild.child(
"opencpn:action");
1740 if (!strcmp(child.first_child().value(),
"add")) {
1742 pRoute = GPXLoadRoute1(
object,
false,
false,
false, 0,
true,
true);
1743 ::UpdateRouteA(pRoute,
this,
this);
1747 else if (!strcmp(child.first_child().value(),
"update")) {
1750 pRoute = GPXLoadRoute1(
object,
false,
false,
false, 0,
true,
true);
1751 ::UpdateRouteA(pRoute,
this,
this);
1756 else if (!strcmp(child.first_child().value(),
"delete")) {
1758 m_bSkipChangeSetUpdate =
true;
1761 m_bSkipChangeSetUpdate =
false;
1770 }
else if (!strcmp(
object.name(),
"tkpt") && pWayPointMan) {
1771 TrackPoint *pWp = ::GPXLoadTrackPoint1(
object);
1776 pugi::xml_node xchild =
object.child(
"extensions");
1777 pugi::xml_node child = xchild.child(
"opencpn:action");
1779 pugi::xml_node guid_child = xchild.child(
"opencpn:track_GUID");
1780 wxString track_GUID(guid_child.first_child().value(), wxConvUTF8);
1782 Track *pExistingTrack = TrackExists(track_GUID);
1784 if (!strcmp(child.first_child().value(),
"add") && pExistingTrack && pWp) {
1785 pExistingTrack->AddPoint(pWp);
1786 pWp->m_GPXTrkSegNo = pExistingTrack->GetCurrentTrackSeg() + 1;
1791 object =
object.next_sibling();
1794 auto it = g_TrackList.begin();
1795 while (it != g_TrackList.end()) {
1796 Track *pTrack = *it;
1797 if (pTrack->GetnPoints() < 2) {
1800 g_TrackList.erase(to_erase);
1810 void NavObjectChanges::AddNewRoute(
Route *pr) {
1813 if (!m_bSkipChangeSetUpdate) AddRoute(pr,
"add");
1816 void NavObjectChanges::UpdateRoute(
Route *pr) {
1818 if (!m_bSkipChangeSetUpdate) AddRoute(pr,
"update");
1821 void NavObjectChanges::DeleteConfigRoute(
Route *pr) {
1824 if (!m_bSkipChangeSetUpdate) AddRoute(pr,
"delete");
1827 void NavObjectChanges::AddNewTrack(
Track *pt) {
1828 if (!pt->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddTrack(pt,
"add");
1831 void NavObjectChanges::UpdateTrack(
Track *pt) {
1832 if (pt->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddTrack(pt,
"update");
1835 void NavObjectChanges::DeleteConfigTrack(
Track *pt) {
1836 if (!pt->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddTrack(pt,
"delete");
1839 void NavObjectChanges::AddNewWayPoint(
RoutePoint *pWP,
int crm) {
1840 if (!pWP->m_bIsInLayer && pWP->m_bIsolatedMark && !m_bSkipChangeSetUpdate)
1844 void NavObjectChanges::UpdateWayPoint(
RoutePoint *pWP) {
1845 if (!pWP->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddWP(pWP,
"update");
1848 void NavObjectChanges::DeleteWayPoint(
RoutePoint *pWP) {
1849 if (!pWP->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddWP(pWP,
"delete");
1852 void NavObjectChanges::AddNewTrackPoint(
TrackPoint *pWP,
1853 const wxString &parent_GUID) {
1854 if (!m_bSkipChangeSetUpdate) AddTrackPoint(pWP,
"add", parent_GUID);
1857 RoutePoint *WaypointExists(
const wxString &name,
double lat,
double lon) {
1860 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
1866 if (name == pr->GetName()) {
1867 if (fabs(lat - pr->m_lat) < 1.e-6 && fabs(lon - pr->m_lon) < 1.e-6) {
1872 node = node->GetNext();
1878 RoutePoint *WaypointExists(
const wxString &guid) {
1879 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
1885 if (guid == pr->m_GUID) {
1888 node = node->GetNext();
1895 bool IsInList =
false;
1897 wxRouteListNode *node1 = pRouteList->GetFirst();
1899 Route *pRoute = node1->GetData();
1900 RoutePointList *pRoutePointList = pRoute->pRoutePointList;
1902 wxRoutePointListNode *node2 = pRoutePointList->GetFirst();
1906 prp = node2->GetData();
1908 if (pr->IsSame(prp)) {
1913 node2 = node2->GetNext();
1915 node1 = node1->GetNext();
1920 Route *RouteExists(
const wxString &guid) {
1921 wxRouteListNode *route_node = pRouteList->GetFirst();
1923 while (route_node) {
1924 Route *proute = route_node->GetData();
1926 if (guid == proute->m_GUID)
return proute;
1928 route_node = route_node->GetNext();
1934 wxRouteListNode *route_node = pRouteList->GetFirst();
1935 while (route_node) {
1936 Route *proute = route_node->GetData();
1938 if (proute->IsEqualTo(pTentRoute))
return proute;
1940 route_node = route_node->GetNext();
1945 Track *TrackExists(
const wxString &guid) {
1946 for (
Track* ptrack : g_TrackList) {
1947 if (guid == ptrack->m_GUID)
return ptrack;
bool DeleteRoute(Route *pRoute, NavObjectChanges *nav_obj_changes)