OpenCPN Partial API docs
Loading...
Searching...
No Matches
nav_object_database.cpp
1/******************************************************************************
2 *
3 * Project: OpenCPN
4 *
5 ***************************************************************************
6 * Copyright (C) 2010 by David S. Register *
7 * *
8 * This program is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the *
20 * Free Software Foundation, Inc., *
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
22 ***************************************************************************
23 */
24#include <wx/string.h>
25
26#include "nav_object_database.h"
27#include "routeman.h"
28#include "navutil_base.h"
29#include "nav_object_database.h"
30#include "select.h"
31#include "track.h"
32#include "route.h"
33
34#ifdef __ANDROID__
35#include <QDebug>
36#endif
37
38extern WayPointman *pWayPointMan;
39extern Routeman *g_pRouteMan;
40
41extern RouteList *pRouteList;
42extern std::vector<Track*> g_TrackList;
43extern Select *pSelect;
44
45NavObjectCollection1::NavObjectCollection1()
46 : pugi::xml_document(), m_bSkipChangeSetUpdate(false) {}
47
48NavObjectCollection1::~NavObjectCollection1() {}
49
50RoutePoint *GPXLoadWaypoint1(pugi::xml_node &wpt_node,
51 wxString def_symbol_name, wxString GUID,
52 bool b_fullviz, bool b_layer,
53 bool b_layerviz, int layer_id) {
54 bool bviz = false;
55 bool bviz_name = false;
56 bool bauto_name = false;
57 bool bshared = false;
58 bool b_propvizname = false;
59 bool b_propviz = false;
60
61 wxString SymString = def_symbol_name; // default icon
62 wxString NameString;
63 wxString DescString;
64 wxString TideStation;
65 double plan_speed = 0.0;
66 wxString etd;
67 wxString TypeString;
68 wxString GuidString = GUID; // default
69 wxString TimeString;
70 wxDateTime dt;
71 RoutePoint *pWP;
72
73 HyperlinkList *linklist = NULL;
74
75 double rlat = wpt_node.attribute("lat").as_double();
76 double rlon = wpt_node.attribute("lon").as_double();
77 double ArrivalRadius = 0;
78 int l_iWaypointRangeRingsNumber = -1;
79 float l_fWaypointRangeRingsStep = -1;
80 int l_pWaypointRangeRingsStepUnits = -1;
81 bool l_bWaypointRangeRingsVisible = false;
82 long l_iWaypointScaleMin = 2147483646;
83 long l_iWaypoinScaleMax = 0;
84 bool l_bWaypointUseScale = false;
85 wxColour l_wxcWaypointRangeRingsColour;
86 l_wxcWaypointRangeRingsColour.Set(_T( "#FFFFFF" ));
87
88 for (pugi::xml_node child = wpt_node.first_child(); child != 0;
89 child = child.next_sibling()) {
90 const char *pcn = child.name();
91
92 if (!strcmp(pcn, "sym")) {
93 SymString = wxString::FromUTF8(child.first_child().value());
94 } else if (!strcmp(pcn, "time"))
95 TimeString = wxString::FromUTF8(child.first_child().value());
96
97 else if (!strcmp(pcn, "name")) {
98 NameString = wxString::FromUTF8(child.first_child().value());
99 if (NameString.StartsWith("@~~")) {
100 // Convert the legacy tidal event definition and change the name so
101 // that it does not kick in next time and cause overiding subsequent
102 // changes
103 TideStation = NameString.Right(NameString.length() - 3);
104 NameString.Replace("@~~", "@-~");
105 }
106 }
107
108 else if (!strcmp(pcn, "desc")) {
109 DescString = wxString::FromUTF8(child.first_child().value());
110 }
111
112 else if (!strcmp(pcn, "type")) {
113 TypeString = wxString::FromUTF8(child.first_child().value());
114 }
115
116 else // Read hyperlink
117 if (!strcmp(pcn, "link")) {
118 wxString HrefString;
119 wxString HrefTextString;
120 wxString HrefTypeString;
121 if (linklist == NULL) linklist = new HyperlinkList;
122 HrefString = wxString::FromUTF8(child.first_attribute().value());
123
124 for (pugi::xml_node child1 = child.first_child(); child1;
125 child1 = child1.next_sibling()) {
126 wxString LinkString = wxString::FromUTF8(child1.name());
127
128 if (LinkString == _T ( "text" ))
129 HrefTextString = wxString::FromUTF8(child1.first_child().value());
130 if (LinkString == _T ( "type" ))
131 HrefTypeString = wxString::FromUTF8(child1.first_child().value());
132 }
133
134 Hyperlink *link = new Hyperlink;
135 link->Link = HrefString;
136 link->DescrText = HrefTextString;
137 link->LType = HrefTypeString;
138 linklist->Append(link);
139 }
140
141 // OpenCPN Extensions....
142 else if (!strcmp(pcn, "extensions")) {
143 for (pugi::xml_node ext_child = child.first_child(); ext_child;
144 ext_child = ext_child.next_sibling()) {
145 wxString ext_name = wxString::FromUTF8(ext_child.name());
146 if (ext_name == _T ( "opencpn:guid" )) {
147 GuidString = wxString::FromUTF8(ext_child.first_child().value());
148 } else if (ext_name == _T ( "opencpn:viz" )) {
149 b_propviz = true;
150 wxString s = wxString::FromUTF8(ext_child.first_child().value());
151 long v = 0;
152 if (s.ToLong(&v)) bviz = (v != 0);
153 } else if (ext_name == _T ( "opencpn:viz_name" )) {
154 b_propvizname = true;
155 wxString s = wxString::FromUTF8(ext_child.first_child().value());
156 long v = 0;
157 if (s.ToLong(&v)) bviz_name = (v != 0);
158 } else if (ext_name == _T ( "opencpn:auto_name" )) {
159 wxString s = wxString::FromUTF8(ext_child.first_child().value());
160 long v = 0;
161 if (s.ToLong(&v)) bauto_name = (v != 0);
162 } else if (ext_name == _T ( "opencpn:shared" )) {
163 wxString s = wxString::FromUTF8(ext_child.first_child().value());
164 long v = 0;
165 if (s.ToLong(&v)) bshared = (v != 0);
166 }
167 if (ext_name == _T ( "opencpn:arrival_radius" )) {
168 wxString::FromUTF8(ext_child.first_child().value())
169 .ToDouble(&ArrivalRadius);
170 }
171 if (ext_name == _T("opencpn:waypoint_range_rings")) {
172 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
173 attr = attr.next_attribute()) {
174 if (wxString::FromUTF8(attr.name()) == _T("number"))
175 l_iWaypointRangeRingsNumber = attr.as_int();
176 else if (wxString::FromUTF8(attr.name()) == _T("step"))
177 l_fWaypointRangeRingsStep = attr.as_float();
178 else if (wxString::FromUTF8(attr.name()) == _T("units"))
179 l_pWaypointRangeRingsStepUnits = attr.as_int();
180 else if (wxString::FromUTF8(attr.name()) == _T("visible"))
181 l_bWaypointRangeRingsVisible = attr.as_bool();
182 else if (wxString::FromUTF8(attr.name()) == _T("colour"))
183 l_wxcWaypointRangeRingsColour.Set(
184 wxString::FromUTF8(attr.as_string()));
185 }
186 }
187 if (ext_name == _T("opencpn:scale_min_max")) {
188 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
189 attr = attr.next_attribute()) {
190 if (wxString::FromUTF8(attr.name()) == _T("UseScale"))
191 l_bWaypointUseScale = attr.as_bool();
192 else if (wxString::FromUTF8(attr.name()) == _T("ScaleMin"))
193 l_iWaypointScaleMin = attr.as_int();
194 else if (wxString::FromUTF8(attr.name()) == _T("ScaleMax"))
195 l_iWaypoinScaleMax = attr.as_float();
196 }
197 }
198 if (ext_name == _T ( "opencpn:tidestation" )) {
199 TideStation = wxString::FromUTF8(ext_child.first_child().value());
200 }
201 if (ext_name == _T ( "opencpn:rte_properties" )) {
202 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
203 attr = attr.next_attribute()) {
204 if (!strcmp(attr.name(), "planned_speed"))
205 plan_speed = attr.as_double();
206 else if (!strcmp(attr.name(), "etd"))
207 etd = attr.as_string();
208 }
209 }
210 } // for
211 } // extensions
212 } // for
213
214 // Create waypoint
215
216 if (b_layer) {
217 if (GuidString.IsEmpty()) GuidString = pWayPointMan->CreateGUID(NULL);
218 }
219
220 pWP = new RoutePoint(rlat, rlon, SymString, NameString, GuidString,
221 false); // do not add to global WP list yet...
222 pWP->m_MarkDescription = DescString;
223 pWP->m_TideStation = TideStation;
224 pWP->m_bIsolatedMark = bshared; // This is an isolated mark
225 pWP->SetWaypointArrivalRadius(ArrivalRadius);
226 pWP->SetWaypointRangeRingsNumber(l_iWaypointRangeRingsNumber);
227 pWP->SetWaypointRangeRingsStep(l_fWaypointRangeRingsStep);
228 pWP->SetWaypointRangeRingsStepUnits(l_pWaypointRangeRingsStepUnits);
229 pWP->SetShowWaypointRangeRings(l_bWaypointRangeRingsVisible);
230
231 // Migrate from O4.x XML format.
232 // In O5, the attribute "range rings visible" is synonymous with ( "range
233 // rings number" != 0 ) So, if we see an attribute "visible"=false in
234 // importing from XML, we must set "number" = 0 to be consistent
235 if (!l_bWaypointRangeRingsVisible) pWP->SetWaypointRangeRingsNumber(0);
236
237 pWP->SetWaypointRangeRingsColour(l_wxcWaypointRangeRingsColour);
238 pWP->SetScaMin(l_iWaypointScaleMin);
239 pWP->SetScaMax(l_iWaypoinScaleMax);
240 pWP->SetUseSca(l_bWaypointUseScale);
241 pWP->SetPlannedSpeed(plan_speed);
242 pWP->SetETD(etd);
243
244 pWP->m_bShowNameData = bviz_name;
245 if (b_propvizname)
246 pWP->m_bShowName = bviz_name;
247 else if (b_fullviz)
248 pWP->m_bShowName = true;
249 else
250 pWP->m_bShowName = false;
251
252 if (b_propviz)
253 pWP->m_bIsVisible = bviz;
254 else if (b_fullviz)
255 pWP->m_bIsVisible = true;
256
257 if (b_layer) {
258 pWP->m_bIsInLayer = true;
259 pWP->m_LayerID = layer_id;
260 pWP->m_bIsVisible = b_layerviz;
261 pWP->SetListed(false);
262 }
263
264 pWP->SetShared(bshared);
265 pWP->m_bDynamicName = bauto_name;
266
267 if (TimeString.Len()) {
268 pWP->m_timestring = TimeString;
269 pWP->SetCreateTime(wxInvalidDateTime); // cause deferred timestamp parsing
270 }
271
272 if (linklist) {
273 delete pWP->m_HyperlinkList; // created in RoutePoint ctor
274 pWP->m_HyperlinkList = linklist;
275 }
276
277 return pWP;
278}
279
280static TrackPoint *GPXLoadTrackPoint1(pugi::xml_node &wpt_node) {
281 wxString TimeString;
282
283 double rlat = wpt_node.attribute("lat").as_double();
284 double rlon = wpt_node.attribute("lon").as_double();
285
286 for (pugi::xml_node child = wpt_node.first_child(); child != 0;
287 child = child.next_sibling()) {
288 const char *pcn = child.name();
289 if (!strcmp(pcn, "time"))
290 TimeString = wxString::FromUTF8(child.first_child().value());
291
292 // OpenCPN Extensions....
293 else if (!strcmp(pcn, "extensions")) {
294 for (pugi::xml_node ext_child = child.first_child(); ext_child;
295 ext_child = ext_child.next_sibling()) {
296 wxString ext_name = wxString::FromUTF8(ext_child.name());
297 if (ext_name == _T ( "opencpn:action" )) {
298 }
299 } // for
300 } // extensions
301 } // for
302
303 // Create trackpoint
304 return new TrackPoint(rlat, rlon, TimeString);
305}
306
307Track *GPXLoadTrack1(pugi::xml_node &trk_node, bool b_fullviz,
308 bool b_layer, bool b_layerviz, int layer_id) {
309 wxString TrackName;
310 wxString DescString;
311 unsigned short int GPXSeg;
312 bool b_propviz = false;
313 bool b_viz = true;
314 Track *pTentTrack = NULL;
315 HyperlinkList *linklist = NULL;
316
317 wxString Name = wxString::FromUTF8(trk_node.name());
318 if (Name == _T ( "trk" )) {
319 pTentTrack = new Track();
320 GPXSeg = 0;
321
322 TrackPoint *pWp = NULL;
323
324 for (pugi::xml_node tschild = trk_node.first_child(); tschild;
325 tschild = tschild.next_sibling()) {
326 wxString ChildName = wxString::FromUTF8(tschild.name());
327 if (ChildName == _T ( "trkseg" )) {
328 GPXSeg += 1;
329
330 // Official GPX spec calls for trkseg to have children trkpt
331 for (pugi::xml_node tpchild = tschild.first_child(); tpchild;
332 tpchild = tpchild.next_sibling()) {
333 wxString tpChildName = wxString::FromUTF8(tpchild.name());
334 if (tpChildName == _T("trkpt")) {
335 pWp = ::GPXLoadTrackPoint1(tpchild);
336 if (pWp){
337 pTentTrack->AddPoint(pWp); // defer BBox calculation
338 pWp->m_GPXTrkSegNo = GPXSeg;
339 }
340 }
341 }
342 } else if (ChildName == _T ( "name" ))
343 TrackName = wxString::FromUTF8(tschild.first_child().value());
344 else if (ChildName == _T ( "desc" ))
345 DescString = wxString::FromUTF8(tschild.first_child().value());
346 else
347
348 if (ChildName == _T ( "link")) {
349 wxString HrefString;
350 wxString HrefTextString;
351 wxString HrefTypeString;
352 if (linklist == NULL) linklist = new HyperlinkList;
353 HrefString = wxString::FromUTF8(tschild.first_attribute().value());
354
355 for (pugi::xml_node child1 = tschild.first_child(); child1;
356 child1 = child1.next_sibling()) {
357 wxString LinkString = wxString::FromUTF8(child1.name());
358
359 if (LinkString == _T ( "text" ))
360 HrefTextString = wxString::FromUTF8(child1.first_child().value());
361 if (LinkString == _T ( "type" ))
362 HrefTypeString = wxString::FromUTF8(child1.first_child().value());
363 }
364
365 Hyperlink *link = new Hyperlink;
366 link->Link = HrefString;
367 link->DescrText = HrefTextString;
368 link->LType = HrefTypeString;
369 linklist->Append(link);
370 }
371
372 else if (ChildName == _T ( "extensions" )) {
373 for (pugi::xml_node ext_child = tschild.first_child(); ext_child;
374 ext_child = ext_child.next_sibling()) {
375 wxString ext_name = wxString::FromUTF8(ext_child.name());
376 if (ext_name == _T ( "opencpn:start" )) {
377 pTentTrack->m_TrackStartString =
378 wxString::FromUTF8(ext_child.first_child().value());
379 } else if (ext_name == _T ( "opencpn:end" )) {
380 pTentTrack->m_TrackEndString =
381 wxString::FromUTF8(ext_child.first_child().value());
382 }
383
384 else if (ext_name == _T ( "opencpn:viz" )) {
385 wxString viz = wxString::FromUTF8(ext_child.first_child().value());
386 b_propviz = true;
387 b_viz = (viz == _T("1"));
388 } else if (ext_name == _T ( "opencpn:style" )) {
389 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
390 attr = attr.next_attribute()) {
391 if (!strcmp(attr.name(), "style"))
392 pTentTrack->m_style = (wxPenStyle)attr.as_int();
393 else if (!strcmp(attr.name(), "width"))
394 pTentTrack->m_width = attr.as_int();
395 }
396 }
397
398 else if (ext_name == _T ( "opencpn:guid" )) {
399 pTentTrack->m_GUID =
400 wxString::FromUTF8(ext_child.first_child().value());
401 }
402
403 else if (ext_name.EndsWith(
404 _T ( "TrackExtension" ))) // Parse GPXX color
405 {
406 for (pugi::xml_node gpxx_child = ext_child.first_child();
407 gpxx_child; gpxx_child = gpxx_child.next_sibling()) {
408 wxString gpxx_name = wxString::FromUTF8(gpxx_child.name());
409 if (gpxx_name.EndsWith(_T ( "DisplayColor" )))
410 pTentTrack->m_Colour =
411 wxString::FromUTF8(gpxx_child.first_child().value());
412 }
413 }
414 } // extensions
415 }
416 }
417
418 pTentTrack->SetName(TrackName);
419 pTentTrack->m_TrackDescription = DescString;
420
421 if (b_propviz)
422 pTentTrack->SetVisible(b_viz);
423 else {
424 if (b_fullviz) pTentTrack->SetVisible();
425 }
426
427 if (b_layer) {
428 pTentTrack->SetVisible(b_layerviz);
429 pTentTrack->m_bIsInLayer = true;
430 pTentTrack->m_LayerID = layer_id;
431 pTentTrack->SetListed(false);
432 }
433
434 pTentTrack->SetCurrentTrackSeg(GPXSeg);
435 }
436
437 if (linklist) {
438 delete pTentTrack->m_HyperlinkList; // created in TrackPoint ctor
439 pTentTrack->m_HyperlinkList = linklist;
440 }
441
442 return pTentTrack;
443}
444
445Route *GPXLoadRoute1(pugi::xml_node &wpt_node, bool b_fullviz,
446 bool b_layer, bool b_layerviz, int layer_id,
447 bool b_change) {
448 wxString RouteName;
449 wxString DescString;
450 bool b_propviz = false;
451 bool b_propSWPviz = false;
452 bool b_viz = true;
453 bool swpViz = false;
454 Route *pTentRoute = NULL;
455
456 wxString Name = wxString::FromUTF8(wpt_node.name());
457 if (Name == _T ( "rte" )) {
458 pTentRoute = new Route();
459 HyperlinkList *linklist = NULL;
460
461 RoutePoint *pWp = NULL;
462 bool route_existing = false;
463 pTentRoute->m_TimeDisplayFormat = RTE_TIME_DISP_UTC;
464
465 for (pugi::xml_node tschild = wpt_node.first_child(); tschild;
466 tschild = tschild.next_sibling()) {
467 wxString ChildName = wxString::FromUTF8(tschild.name());
468
469 // load extentions first to determine if the route still exists
470 if (ChildName == _T ( "extensions" )) {
471 for (pugi::xml_node ext_child = tschild.first_child(); ext_child;
472 ext_child = ext_child.next_sibling()) {
473 wxString ext_name = wxString::FromUTF8(ext_child.name());
474
475 if (ext_name == _T ( "opencpn:start" )) {
476 pTentRoute->m_RouteStartString =
477 wxString::FromUTF8(ext_child.first_child().value());
478 } else if (ext_name == _T ( "opencpn:end" )) {
479 pTentRoute->m_RouteEndString =
480 wxString::FromUTF8(ext_child.first_child().value());
481 }
482
483 else if (ext_name == _T ( "opencpn:viz" )) {
484 wxString viz = wxString::FromUTF8(ext_child.first_child().value());
485 b_propviz = true;
486 b_viz = (viz == _T("1"));
487 }
488
489 else if (ext_name == _T ( "opencpn:sharedWPviz" )) {
490 wxString viz = wxString::FromUTF8(ext_child.first_child().value());
491 b_propSWPviz = true;
492 swpViz = (viz == _T("1"));
493 } else if (ext_name == _T ( "opencpn:style" )) {
494 for (pugi::xml_attribute attr = ext_child.first_attribute(); attr;
495 attr = attr.next_attribute()) {
496 if (!strcmp(attr.name(), "style"))
497 pTentRoute->m_style = (wxPenStyle)attr.as_int();
498 else if (!strcmp(attr.name(), "width"))
499 pTentRoute->m_width = attr.as_int();
500 }
501 }
502
503 else if (ext_name == _T ( "opencpn:guid" )) {
504 // if ( !g_bIsNewLayer ) )
505 pTentRoute->m_GUID =
506 wxString::FromUTF8(ext_child.first_child().value());
507 }
508
509 else if (ext_name == _T ( "opencpn:planned_speed" )) {
510 pTentRoute->m_PlannedSpeed = atof(ext_child.first_child().value());
511 }
512
513 else if (ext_name == _T ( "opencpn:planned_departure" )) {
514 ParseGPXDateTime(
515 pTentRoute->m_PlannedDeparture,
516 wxString::FromUTF8(ext_child.first_child().value()));
517 }
518
519 else if (ext_name == _T ( "opencpn:time_display" )) {
520 pTentRoute->m_TimeDisplayFormat =
521 wxString::FromUTF8(ext_child.first_child().value());
522 } else if (ext_name.EndsWith(
523 _T ( "RouteExtension" ))) // Parse GPXX color
524 {
525 for (pugi::xml_node gpxx_child = ext_child.first_child();
526 gpxx_child; gpxx_child = gpxx_child.next_sibling()) {
527 wxString gpxx_name = wxString::FromUTF8(gpxx_child.name());
528 if (gpxx_name.EndsWith(_T ( "DisplayColor" )))
529 pTentRoute->m_Colour =
530 wxString::FromUTF8(gpxx_child.first_child().value());
531 }
532 }
533 }
534 if (!b_change) {
535 if (RouteExists(pTentRoute->m_GUID)) { // we are loading a different
536 // route with the same guid so
537 // let's generate a new guid
538 pTentRoute->m_GUID = pWayPointMan->CreateGUID(NULL);
539 route_existing = true;
540 }
541 }
542 } // extension
543 else if (ChildName == _T ( "rtept" )) {
544 RoutePoint *tpWp =
545 ::GPXLoadWaypoint1(tschild, _T("square"), _T(""), b_fullviz,
546 b_layer, b_layerviz, layer_id);
547 RoutePoint *erp = NULL;
548 if (!b_layer) erp = ::WaypointExists(tpWp->m_GUID);
549 // 1) if b_change is true, that means we are after crash - load the
550 // route and points as found in source file 2) if route_existing, we are
551 // loading a different route with the same guid. In this case load
552 // points as found in
553 // source file, changing the guid, but keep existing "isolated point" as
554 // found in the DB
555 // 3) in all other cases keep existing points if found and load new
556 // points if not found
557 bool new_wpt = true;
558 if (b_change)
559 pWp = tpWp;
560 else {
561 if (erp != NULL &&
562 (!route_existing || (route_existing && tpWp->IsShared()))) {
563 pWp = erp;
564 new_wpt = false;
565 } else {
566 if (route_existing) tpWp->m_GUID = pWayPointMan->CreateGUID(NULL);
567 pWp = tpWp;
568 }
569 }
570
571 pTentRoute->AddPoint(pWp, false, true); // defer BBox calculation
572 pWp->m_bIsInRoute = true; // Hack
573
574 if (new_wpt){
575 if (erp == NULL)
576 pWayPointMan->AddRoutePoint(pWp);
577 }
578 else
579 delete tpWp;
580 } else if (ChildName == _T ( "name" )) {
581 RouteName = wxString::FromUTF8(tschild.first_child().value());
582 } else if (ChildName == _T ( "desc" )) {
583 DescString = wxString::FromUTF8(tschild.first_child().value());
584 }
585
586 if (ChildName == _T ( "link")) {
587 wxString HrefString;
588 wxString HrefTextString;
589 wxString HrefTypeString;
590 if (linklist == NULL) linklist = new HyperlinkList;
591 HrefString = wxString::FromUTF8(tschild.first_attribute().value());
592
593 for (pugi::xml_node child1 = tschild.first_child(); child1;
594 child1 = child1.next_sibling()) {
595 wxString LinkString = wxString::FromUTF8(child1.name());
596
597 if (LinkString == _T ( "text" ))
598 HrefTextString = wxString::FromUTF8(child1.first_child().value());
599 if (LinkString == _T ( "type" ))
600 HrefTypeString = wxString::FromUTF8(child1.first_child().value());
601 }
602
603 Hyperlink *link = new Hyperlink;
604 link->Link = HrefString;
605 link->DescrText = HrefTextString;
606 link->LType = HrefTypeString;
607 linklist->Append(link);
608 }
609
610 else
611 // TODO: This is wrong, left here just to save data of the 3.3 beta
612 // series users.
613 if (ChildName.EndsWith(_T ( "RouteExtension" ))) // Parse GPXX color
614 {
615 for (pugi::xml_node gpxx_child = tschild.first_child(); gpxx_child;
616 gpxx_child = gpxx_child.next_sibling()) {
617 wxString gpxx_name = wxString::FromUTF8(gpxx_child.name());
618 if (gpxx_name.EndsWith(_T ( "DisplayColor" )))
619 pTentRoute->m_Colour =
620 wxString::FromUTF8(gpxx_child.first_child().value());
621 }
622 }
623 }
624
625 pTentRoute->m_RouteNameString = RouteName;
626 pTentRoute->m_RouteDescription = DescString;
627 if (linklist) {
628 pTentRoute->m_HyperlinkList = linklist;
629 }
630
631 if (b_propviz) {
632 pTentRoute->SetVisible(b_viz);
633 } else if (b_fullviz) {
634 pTentRoute->SetVisible();
635 }
636
637 if (b_propSWPviz) pTentRoute->SetSharedWPViz(swpViz);
638
639 if (b_layer) {
640 pTentRoute->SetVisible(b_layerviz);
641 pTentRoute->m_bIsInLayer = true;
642 pTentRoute->m_LayerID = layer_id;
643 pTentRoute->SetListed(false);
644 }
645 }
646
647 return pTentRoute;
648}
649
650static bool GPXCreateWpt(pugi::xml_node node, RoutePoint *pr,
651 unsigned int flags) {
652 wxString s;
653 pugi::xml_node child;
654 pugi::xml_attribute attr;
655
656 s.Printf(_T("%.9f"), pr->m_lat);
657 node.append_attribute("lat") = s.mb_str();
658 s.Printf(_T("%.9f"), pr->m_lon);
659 node.append_attribute("lon") = s.mb_str();
660
661 if (flags & OUT_TIME) {
662 child = node.append_child("time");
663 if (pr->m_timestring.Len())
664 child.append_child(pugi::node_pcdata)
665 .set_value(pr->m_timestring.mb_str());
666 else {
667 wxDateTime dt = pr->GetCreateTime();
668 if ( !dt.IsValid() )
669 dt = wxDateTime::Now();
670
671 wxString t = dt.FormatISODate()
672 .Append(_T("T"))
673 .Append(dt.FormatISOTime())
674 .Append(_T("Z"));
675 child.append_child(pugi::node_pcdata).set_value(t.mb_str());
676 }
677 }
678
679 if ((!pr->GetName().IsEmpty() && (flags & OUT_NAME)) ||
680 (flags & OUT_NAME_FORCE)) {
681 wxCharBuffer buffer = pr->GetName().ToUTF8();
682 if (buffer.data()) {
683 child = node.append_child("name");
684 child.append_child(pugi::node_pcdata).set_value(buffer.data());
685 }
686 }
687
688 if ((!pr->GetDescription().IsEmpty() && (flags & OUT_DESC)) ||
689 (flags & OUT_DESC_FORCE)) {
690 wxCharBuffer buffer = pr->GetDescription().ToUTF8();
691 if (buffer.data()) {
692 child = node.append_child("desc");
693 child.append_child(pugi::node_pcdata).set_value(buffer.data());
694 }
695 }
696
697 // Hyperlinks
698 if (flags & OUT_HYPERLINKS) {
699 HyperlinkList *linklist = pr->m_HyperlinkList;
700 if (linklist && linklist->GetCount()) {
701 wxHyperlinkListNode *linknode = linklist->GetFirst();
702 while (linknode) {
703 Hyperlink *link = linknode->GetData();
704
705 pugi::xml_node child_link = node.append_child("link");
706 ;
707 wxCharBuffer buffer = link->Link.ToUTF8();
708 if (buffer.data()) child_link.append_attribute("href") = buffer.data();
709
710 buffer = link->DescrText.ToUTF8();
711 if (buffer.data()) {
712 child = child_link.append_child("text");
713 child.append_child(pugi::node_pcdata).set_value(buffer.data());
714 }
715
716 buffer = link->LType.ToUTF8();
717 if (buffer.data() && strlen(buffer.data()) > 0) {
718 child = child_link.append_child("type");
719 child.append_child(pugi::node_pcdata).set_value(buffer.data());
720 }
721
722 linknode = linknode->GetNext();
723 }
724 }
725 }
726
727 if (flags & OUT_SYM_FORCE) {
728 child = node.append_child("sym");
729 if (!pr->GetIconName().IsEmpty()) {
730 child.append_child(pugi::node_pcdata)
731 .set_value(pr->GetIconName().mb_str());
732 } else {
733 child.append_child("empty");
734 }
735 }
736
737 if (flags & OUT_TYPE) {
738 child = node.append_child("type");
739 child.append_child(pugi::node_pcdata).set_value("WPT");
740 }
741
742 if ((flags & OUT_GUID) || (flags & OUT_VIZ) || (flags & OUT_VIZ_NAME) ||
743 (flags & OUT_SHARED) || (flags & OUT_AUTO_NAME) ||
744 (flags & OUT_EXTENSION) || (flags & OUT_TIDE_STATION) ||
745 (flags & OUT_RTE_PROPERTIES)) {
746 pugi::xml_node child_ext = node.append_child("extensions");
747
748 if (!pr->m_GUID.IsEmpty() && (flags & OUT_GUID)) {
749 child = child_ext.append_child("opencpn:guid");
750 child.append_child(pugi::node_pcdata).set_value(pr->m_GUID.mb_str());
751 }
752
753 if ((flags & OUT_VIZ) && !pr->m_bIsVisible) {
754 child = child_ext.append_child("opencpn:viz");
755 child.append_child(pugi::node_pcdata).set_value("0");
756 }
757
758 if ((flags & OUT_VIZ_NAME) && pr->m_bShowName) {
759 child = child_ext.append_child("opencpn:viz_name");
760 child.append_child(pugi::node_pcdata).set_value("1");
761 }
762
763 if ((flags & OUT_AUTO_NAME) && pr->m_bDynamicName) {
764 child = child_ext.append_child("opencpn:auto_name");
765 child.append_child(pugi::node_pcdata).set_value("1");
766 }
767 if ((flags & OUT_SHARED) && pr->IsShared()) {
768 child = child_ext.append_child("opencpn:shared");
769 child.append_child(pugi::node_pcdata).set_value("1");
770 }
771 if (flags & OUT_ARRIVAL_RADIUS) {
772 child = child_ext.append_child("opencpn:arrival_radius");
773 s.Printf(_T("%.3f"), pr->GetWaypointArrivalRadius());
774 child.append_child(pugi::node_pcdata).set_value(s.mbc_str());
775 }
776 if (flags & OUT_WAYPOINT_RANGE_RINGS) {
777 child = child_ext.append_child("opencpn:waypoint_range_rings");
778 pugi::xml_attribute viz = child.append_attribute("visible");
779 viz.set_value(pr->m_bShowWaypointRangeRings);
780 pugi::xml_attribute number = child.append_attribute("number");
781 number.set_value(pr->m_iWaypointRangeRingsNumber);
782 pugi::xml_attribute step = child.append_attribute("step");
783 step.set_value(pr->m_fWaypointRangeRingsStep);
784 pugi::xml_attribute units = child.append_attribute("units");
785 units.set_value(pr->m_iWaypointRangeRingsStepUnits);
786 pugi::xml_attribute colour = child.append_attribute("colour");
787 colour.set_value(
788 pr->m_wxcWaypointRangeRingsColour.GetAsString(wxC2S_HTML_SYNTAX)
789 .utf8_str());
790 }
791 if (flags & OUT_WAYPOINT_SCALE) {
792 child = child_ext.append_child("opencpn:scale_min_max");
793 pugi::xml_attribute use = child.append_attribute("UseScale");
794 use.set_value(pr->GetUseSca());
795 pugi::xml_attribute sca = child.append_attribute("ScaleMin");
796 sca.set_value(pr->GetScaMin());
797 pugi::xml_attribute max = child.append_attribute("ScaleMax");
798 max.set_value(pr->GetScaMax());
799 }
800 if ((flags & OUT_TIDE_STATION) && !pr->m_TideStation.IsEmpty()) {
801 child = child_ext.append_child("opencpn:tidestation");
802 child.append_child(pugi::node_pcdata)
803 .set_value(pr->m_TideStation.mb_str());
804 }
805 if ((flags & OUT_RTE_PROPERTIES) &&
806 (pr->GetPlannedSpeed() > 0.0001 || pr->m_manual_etd)) {
807 child = child_ext.append_child("opencpn:rte_properties");
808 if (pr->GetPlannedSpeed() > 0.0001) {
809 pugi::xml_attribute use = child.append_attribute("planned_speed");
810 use.set_value(
811 wxString::Format(_T("%.1lf"), pr->GetPlannedSpeed()).mb_str());
812 }
813 if (pr->m_manual_etd) {
814 pugi::xml_attribute use = child.append_attribute("etd");
815 use.set_value(pr->GetManualETD().FormatISOCombined().mb_str());
816 }
817 }
818 }
819
820 return true;
821}
822
823static bool GPXCreateTrkpt(pugi::xml_node node, TrackPoint *pt,
824 unsigned int flags) {
825 wxString s;
826 pugi::xml_node child;
827 pugi::xml_attribute attr;
828
829 s.Printf(_T("%.9f"), pt->m_lat);
830 node.append_attribute("lat") = s.mb_str();
831 s.Printf(_T("%.9f"), pt->m_lon);
832 node.append_attribute("lon") = s.mb_str();
833
834 if (flags & OUT_TIME && pt->HasValidTimestamp()) {
835 child = node.append_child("time");
836 child.append_child(pugi::node_pcdata).set_value(pt->GetTimeString());
837 }
838
839 return true;
840}
841
842static bool GPXCreateTrk(pugi::xml_node node, Track *pTrack,
843 unsigned int flags) {
844 pugi::xml_node child;
845
846 if (pTrack->GetName().Len()) {
847 wxCharBuffer buffer = pTrack->GetName().ToUTF8();
848 if (buffer.data()) {
849 child = node.append_child("name");
850 child.append_child(pugi::node_pcdata).set_value(buffer.data());
851 }
852 }
853
854 if (pTrack->m_TrackDescription.Len()) {
855 wxCharBuffer buffer = pTrack->m_TrackDescription.ToUTF8();
856 if (buffer.data()) {
857 child = node.append_child("desc");
858 child.append_child(pugi::node_pcdata).set_value(buffer.data());
859 }
860 }
861
862 // Hyperlinks
863 HyperlinkList *linklist = pTrack->m_HyperlinkList;
864 if (linklist && linklist->GetCount()) {
865 wxHyperlinkListNode *linknode = linklist->GetFirst();
866 while (linknode) {
867 Hyperlink *link = linknode->GetData();
868
869 pugi::xml_node child_link = node.append_child("link");
870 wxCharBuffer buffer = link->Link.ToUTF8();
871 if (buffer.data()) child_link.append_attribute("href") = buffer.data();
872
873 buffer = link->DescrText.ToUTF8();
874 if (buffer.data()) {
875 child = child_link.append_child("text");
876 child.append_child(pugi::node_pcdata).set_value(buffer.data());
877 }
878
879 buffer = link->LType.ToUTF8();
880 if (buffer.data() && strlen(buffer.data()) > 0) {
881 child = child_link.append_child("type");
882 child.append_child(pugi::node_pcdata).set_value(buffer.data());
883 }
884
885 linknode = linknode->GetNext();
886 }
887 }
888
889 pugi::xml_node child_ext = node.append_child("extensions");
890
891 child = child_ext.append_child("opencpn:guid");
892 child.append_child(pugi::node_pcdata).set_value(pTrack->m_GUID.mb_str());
893
894 child = child_ext.append_child("opencpn:viz");
895 child.append_child(pugi::node_pcdata)
896 .set_value(pTrack->IsVisible() == true ? "1" : "0");
897
898 if (pTrack->m_TrackStartString.Len()) {
899 wxCharBuffer buffer = pTrack->m_TrackStartString.ToUTF8();
900 if (buffer.data()) {
901 child = child_ext.append_child("opencpn:start");
902 child.append_child(pugi::node_pcdata).set_value(buffer.data());
903 }
904 }
905
906 if (pTrack->m_TrackEndString.Len()) {
907 wxCharBuffer buffer = pTrack->m_TrackEndString.ToUTF8();
908 if (buffer.data()) {
909 child = child_ext.append_child("opencpn:end");
910 child.append_child(pugi::node_pcdata).set_value(buffer.data());
911 }
912 }
913
914 if (pTrack->m_width != WIDTH_UNDEFINED ||
915 pTrack->m_style != wxPENSTYLE_INVALID) {
916 child = child_ext.append_child("opencpn:style");
917
918 if (pTrack->m_width != WIDTH_UNDEFINED)
919 child.append_attribute("width") = pTrack->m_width;
920 if (pTrack->m_style != wxPENSTYLE_INVALID)
921 child.append_attribute("style") = pTrack->m_style;
922 }
923
924 if (pTrack->m_Colour != wxEmptyString) {
925 pugi::xml_node gpxx_ext = child_ext.append_child("gpxx:TrackExtension");
926 child = gpxx_ext.append_child("gpxx:DisplayColor");
927 child.append_child(pugi::node_pcdata).set_value(pTrack->m_Colour.mb_str());
928 }
929
930 if (flags & RT_OUT_NO_RTPTS) return true;
931
932 int node2 = 0;
933 TrackPoint *prp;
934
935 unsigned short int GPXTrkSegNo1 = 1;
936
937 do {
938 unsigned short int GPXTrkSegNo2 = GPXTrkSegNo1;
939
940 pugi::xml_node seg = node.append_child("trkseg");
941
942 while (node2 < pTrack->GetnPoints()) {
943 prp = pTrack->GetPoint(node2);
944 GPXTrkSegNo1 = prp->m_GPXTrkSegNo;
945 if (GPXTrkSegNo1 != GPXTrkSegNo2) break;
946
947 GPXCreateTrkpt(seg.append_child("trkpt"), prp, OPT_TRACKPT);
948
949 node2++;
950 }
951 } while (node2 < pTrack->GetnPoints());
952
953 return true;
954}
955
956static bool GPXCreateRoute(pugi::xml_node node, Route *pRoute) {
957 pugi::xml_node child;
958
959 if (pRoute->m_RouteNameString.Len()) {
960 wxCharBuffer buffer = pRoute->m_RouteNameString.ToUTF8();
961 if (buffer.data()) {
962 child = node.append_child("name");
963 child.append_child(pugi::node_pcdata).set_value(buffer.data());
964 }
965 }
966
967 if (pRoute->m_RouteDescription.Len()) {
968 wxCharBuffer buffer = pRoute->m_RouteDescription.ToUTF8();
969 if (buffer.data()) {
970 child = node.append_child("desc");
971 child.append_child(pugi::node_pcdata).set_value(buffer.data());
972 }
973 }
974
975 // Hyperlinks
976 HyperlinkList *linklist = pRoute->m_HyperlinkList;
977 if (linklist && linklist->GetCount()) {
978 wxHyperlinkListNode *linknode = linklist->GetFirst();
979 while (linknode) {
980 Hyperlink *link = linknode->GetData();
981
982 pugi::xml_node child_link = node.append_child("link");
983 wxCharBuffer buffer = link->Link.ToUTF8();
984 if (buffer.data()) child_link.append_attribute("href") = buffer.data();
985
986 buffer = link->DescrText.ToUTF8();
987 if (buffer.data()) {
988 child = child_link.append_child("text");
989 child.append_child(pugi::node_pcdata).set_value(buffer.data());
990 }
991
992 buffer = link->LType.ToUTF8();
993 if (buffer.data() && strlen(buffer.data()) > 0) {
994 child = child_link.append_child("type");
995 child.append_child(pugi::node_pcdata).set_value(buffer.data());
996 }
997
998 linknode = linknode->GetNext();
999 }
1000 }
1001
1002 pugi::xml_node child_ext = node.append_child("extensions");
1003
1004 child = child_ext.append_child("opencpn:guid");
1005 child.append_child(pugi::node_pcdata).set_value(pRoute->m_GUID.mb_str());
1006
1007 child = child_ext.append_child("opencpn:viz");
1008 child.append_child(pugi::node_pcdata)
1009 .set_value(pRoute->IsVisible() == true ? "1" : "0");
1010
1011 if (pRoute->ContainsSharedWP()) {
1012 child = child_ext.append_child("opencpn:sharedWPviz");
1013 child.append_child(pugi::node_pcdata)
1014 .set_value(pRoute->GetSharedWPViz() == true ? "1" : "0");
1015 }
1016
1017 if (pRoute->m_RouteStartString.Len()) {
1018 wxCharBuffer buffer = pRoute->m_RouteStartString.ToUTF8();
1019 if (buffer.data()) {
1020 child = child_ext.append_child("opencpn:start");
1021 child.append_child(pugi::node_pcdata).set_value(buffer.data());
1022 }
1023 }
1024
1025 if (pRoute->m_RouteEndString.Len()) {
1026 wxCharBuffer buffer = pRoute->m_RouteEndString.ToUTF8();
1027 if (buffer.data()) {
1028 child = child_ext.append_child("opencpn:end");
1029 child.append_child(pugi::node_pcdata).set_value(buffer.data());
1030 }
1031 }
1032
1033 if (pRoute->m_PlannedSpeed != ROUTE_DEFAULT_SPEED) {
1034 child = child_ext.append_child("opencpn:planned_speed");
1035 wxString s;
1036 s.Printf(_T("%.2f"), pRoute->m_PlannedSpeed);
1037 child.append_child(pugi::node_pcdata).set_value(s.mb_str());
1038 }
1039
1040 if (pRoute->m_PlannedDeparture.IsValid()) {
1041 child = child_ext.append_child("opencpn:planned_departure");
1042 wxString t = pRoute->m_PlannedDeparture.FormatISODate()
1043 .Append(_T("T"))
1044 .Append(pRoute->m_PlannedDeparture.FormatISOTime())
1045 .Append(_T("Z"));
1046 child.append_child(pugi::node_pcdata).set_value(t.mb_str());
1047 }
1048
1049 child = child_ext.append_child("opencpn:time_display");
1050 child.append_child(pugi::node_pcdata)
1051 .set_value(pRoute->m_TimeDisplayFormat.mb_str());
1052
1053 if (pRoute->m_width != WIDTH_UNDEFINED ||
1054 pRoute->m_style != wxPENSTYLE_INVALID) {
1055 child = child_ext.append_child("opencpn:style");
1056
1057 if (pRoute->m_width != WIDTH_UNDEFINED)
1058 child.append_attribute("width") = pRoute->m_width;
1059 if (pRoute->m_style != wxPENSTYLE_INVALID)
1060 child.append_attribute("style") = pRoute->m_style;
1061 }
1062
1063 pugi::xml_node gpxx_ext = child_ext.append_child("gpxx:RouteExtension");
1064 child = gpxx_ext.append_child("gpxx:IsAutoNamed");
1065 child.append_child(pugi::node_pcdata).set_value("false");
1066
1067 if (pRoute->m_Colour != wxEmptyString) {
1068 child = gpxx_ext.append_child("gpxx:DisplayColor");
1069 child.append_child(pugi::node_pcdata).set_value(pRoute->m_Colour.mb_str());
1070 }
1071
1072 RoutePointList *pRoutePointList = pRoute->pRoutePointList;
1073 wxRoutePointListNode *node2 = pRoutePointList->GetFirst();
1074 RoutePoint *prp;
1075
1076 while (node2) {
1077 prp = node2->GetData();
1078
1079 GPXCreateWpt(node.append_child("rtept"), prp, OPT_ROUTEPT);
1080
1081 node2 = node2->GetNext();
1082 }
1083
1084 return true;
1085}
1086
1087bool InsertRouteA(Route *pTentRoute, NavObjectCollection1* navobj) {
1088 if (!pTentRoute) return false;
1089
1090 bool bAddroute = true;
1091 // If the route has only 1 point, don't load it.
1092 if (pTentRoute->GetnPoints() < 2) bAddroute = false;
1093
1094 // TODO All this trouble for a tentative route.......Should make some
1095 // Route methods????
1096 if (bAddroute) {
1097 pRouteList->Append(pTentRoute);
1098
1099 // Do the (deferred) calculation of BBox
1100 pTentRoute->FinalizeForRendering();
1101
1102 // Add the selectable points and segments
1103
1104 int ip = 0;
1105 float prev_rlat = 0., prev_rlon = 0.;
1106 RoutePoint *prev_pConfPoint = NULL;
1107
1108 wxRoutePointListNode *node = pTentRoute->pRoutePointList->GetFirst();
1109 while (node) {
1110 RoutePoint *prp = node->GetData();
1111
1112 if (ip)
1113 pSelect->AddSelectableRouteSegment(prev_rlat, prev_rlon, prp->m_lat,
1114 prp->m_lon, prev_pConfPoint, prp,
1115 pTentRoute);
1116 pSelect->AddSelectableRoutePoint(prp->m_lat, prp->m_lon, prp);
1117 prev_rlat = prp->m_lat;
1118 prev_rlon = prp->m_lon;
1119 prev_pConfPoint = prp;
1120
1121 ip++;
1122
1123 node = node->GetNext();
1124 }
1125 } else {
1126 // walk the route, deleting points used only by this route
1127 wxRoutePointListNode *pnode = (pTentRoute->pRoutePointList)->GetFirst();
1128 while (pnode) {
1129 RoutePoint *prp = pnode->GetData();
1130
1131 // check all other routes to see if this point appears in any other route
1132 Route *pcontainer_route = g_pRouteMan->FindRouteContainingWaypoint(prp);
1133
1134 if (pcontainer_route == NULL) {
1135 prp->m_bIsInRoute =
1136 false; // Take this point out of this (and only) track/route
1137 if (!prp->IsShared()) {
1138 navobj->m_bSkipChangeSetUpdate = true;
1139 NavObjectChanges::getInstance()->DeleteWayPoint(prp);
1140 navobj->m_bSkipChangeSetUpdate = false;
1141 delete prp;
1142 }
1143 }
1144
1145 pnode = pnode->GetNext();
1146 }
1147
1148 delete pTentRoute;
1149 }
1150 return bAddroute;
1151}
1152
1153bool InsertTrack(Track *pTentTrack, bool bApplyChanges = false) {
1154 if (!pTentTrack) return false;
1155
1156 bool bAddtrack = true;
1157 // If the track has only 1 point, don't load it.
1158 // This usually occurs if some points were discarded as being co-incident.
1159 if (!bApplyChanges && pTentTrack->GetnPoints() < 2) bAddtrack = false;
1160
1161 // TODO All this trouble for a tentative track.......Should make some
1162 // Track methods????
1163 if (bAddtrack) {
1164 g_TrackList.push_back(pTentTrack);
1165
1166 // Do the (deferred) calculation of Track BBox
1167 // pTentTrack->FinalizeForRendering();
1168
1169 // Add the selectable points and segments
1170
1171 float prev_rlat = 0., prev_rlon = 0.;
1172 TrackPoint *prev_pConfPoint = NULL;
1173
1174 for (int i = 0; i < pTentTrack->GetnPoints(); i++) {
1175 TrackPoint *prp = pTentTrack->GetPoint(i);
1176
1177 if (i)
1178 pSelect->AddSelectableTrackSegment(prev_rlat, prev_rlon, prp->m_lat,
1179 prp->m_lon, prev_pConfPoint, prp,
1180 pTentTrack);
1181
1182 prev_rlat = prp->m_lat;
1183 prev_rlon = prp->m_lon;
1184 prev_pConfPoint = prp;
1185 }
1186 } else
1187 delete pTentTrack;
1188
1189 return bAddtrack;
1190}
1191
1192bool InsertWpt(RoutePoint *pWp, bool overwrite) {
1193 bool res = false;
1194 RoutePoint *pExisting =
1195 WaypointExists(pWp->GetName(), pWp->m_lat, pWp->m_lon);
1196 if (!pExisting || overwrite) {
1197 if (NULL != pWayPointMan) {
1198 if (pExisting) {
1199 pWayPointMan->DestroyWaypoint(pExisting);
1200 }
1201 pWayPointMan->AddRoutePoint(pWp);
1202 res = true;
1203 }
1204 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1205 }
1206 return res;
1207}
1208
1209static void UpdateRouteA(Route* pTentRoute,
1210 NavObjectCollection1* navobj,
1211 NavObjectChanges* nav_obj_changes) {
1212 if (!pTentRoute) return;
1213 if (pTentRoute->GetnPoints() < 2) return;
1214
1215 // first delete the route to be modified if exists
1216 Route *pExisting = ::RouteExists(pTentRoute->m_GUID);
1217 if (pExisting) {
1218 navobj->m_bSkipChangeSetUpdate = true;
1219 g_pRouteMan->DeleteRoute(pExisting, nav_obj_changes);
1220 navobj->m_bSkipChangeSetUpdate = false;
1221 }
1222
1223 // create a new route
1224 Route *pChangeRoute = new Route();
1225 pRouteList->Append(pChangeRoute);
1226
1227 // update new route keeping the same gui
1228 pChangeRoute->m_GUID = pTentRoute->m_GUID;
1229 pChangeRoute->m_RouteNameString = pTentRoute->m_RouteNameString;
1230 pChangeRoute->m_RouteStartString = pTentRoute->m_RouteStartString;
1231 pChangeRoute->m_RouteEndString = pTentRoute->m_RouteEndString;
1232 pChangeRoute->SetVisible(pTentRoute->IsVisible());
1233
1234 // Add points and segments to new route
1235 int ip = 0;
1236 float prev_rlat = 0., prev_rlon = 0.;
1237 RoutePoint *prev_pConfPoint = NULL;
1238
1239 wxRoutePointListNode *node = pTentRoute->pRoutePointList->GetFirst();
1240 while (node) {
1241 RoutePoint *prp = node->GetData();
1242
1243 // if some wpts have been not deleted, that meens they should be used in
1244 // other routes or are isolated way points so need to be updated
1245 RoutePoint *ex_rp = ::WaypointExists(prp->m_GUID);
1246 if (ex_rp) {
1247 pSelect->DeleteSelectableRoutePoint(ex_rp);
1248 ex_rp->m_lat = prp->m_lat;
1249 ex_rp->m_lon = prp->m_lon;
1250 ex_rp->SetIconName(prp->GetIconName());
1251 ex_rp->m_MarkDescription = prp->m_MarkDescription;
1252 ex_rp->SetName(prp->GetName());
1253 ex_rp->m_TideStation = prp->m_TideStation;
1254 ex_rp->SetPlannedSpeed(prp->GetPlannedSpeed());
1255 pChangeRoute->AddPoint(ex_rp);
1256 pSelect->AddSelectableRoutePoint(prp->m_lat, prp->m_lon, ex_rp);
1257
1258 } else {
1259 pChangeRoute->AddPoint(prp);
1260 pSelect->AddSelectableRoutePoint(prp->m_lat, prp->m_lon, prp);
1261 pWayPointMan->AddRoutePoint(prp);
1262 }
1263
1264 if (ip)
1265 pSelect->AddSelectableRouteSegment(prev_rlat, prev_rlon, prp->m_lat,
1266 prp->m_lon, prev_pConfPoint, prp,
1267 pChangeRoute);
1268 prev_rlat = prp->m_lat;
1269 prev_rlon = prp->m_lon;
1270 prev_pConfPoint = prp;
1271
1272 ip++;
1273
1274 node = node->GetNext();
1275 }
1276 // Do the (deferred) calculation of BBox
1277 pChangeRoute->FinalizeForRendering();
1278}
1279
1280Route* FindRouteContainingWaypoint(RoutePoint *pWP) {
1281 wxRouteListNode *node = pRouteList->GetFirst();
1282 while (node) {
1283 Route *proute = node->GetData();
1284
1285 wxRoutePointListNode *pnode = (proute->pRoutePointList)->GetFirst();
1286 while (pnode) {
1287 RoutePoint *prp = pnode->GetData();
1288 if (prp == pWP) return proute;
1289 pnode = pnode->GetNext();
1290 }
1291
1292 node = node->GetNext();
1293 }
1294
1295 return NULL; // not found
1296}
1297
1298
1299bool NavObjectCollection1::CreateNavObjGPXPoints(void) {
1300 // Iterate over the Routepoint list, creating Nodes for
1301 // Routepoints that are not in any Route
1302 // as indicated by m_bIsolatedMark == false
1303
1304 if (!pWayPointMan) return false;
1305
1306 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
1307
1308 RoutePoint *pr;
1309
1310 while (node) {
1311 pr = node->GetData();
1312
1313 if ((pr->m_bIsolatedMark) && !(pr->m_bIsInLayer) && !(pr->m_btemp)) {
1314 pugi::xml_node doc = root();
1315 pugi::xml_node gpx = doc.first_child();
1316 pugi::xml_node new_node = gpx.append_child("wpt");
1317
1318 GPXCreateWpt(new_node, pr, OPT_WPT);
1319 }
1320 node = node->GetNext();
1321 }
1322
1323 return true;
1324}
1325
1326bool NavObjectCollection1::CreateNavObjGPXRoutes(void) {
1327 // Routes
1328 if (!pRouteList) return false;
1329
1330 wxRouteListNode *node1 = pRouteList->GetFirst();
1331 while (node1) {
1332 Route *pRoute = node1->GetData();
1333
1334 if (!pRoute->m_bIsInLayer && !pRoute->m_btemp){
1335 pugi::xml_node doc = root();
1336 pugi::xml_node gpx = doc.first_child();
1337 pugi::xml_node new_node = gpx.append_child("rte");
1338
1339 GPXCreateRoute(new_node, pRoute);
1340 }
1341
1342 node1 = node1->GetNext();
1343 }
1344
1345 return true;
1346}
1347
1348bool NavObjectCollection1::CreateNavObjGPXTracks(void) {
1349 // Tracks
1350 for (Track *pTrack : g_TrackList) {
1351 if (pTrack->GetnPoints()) {
1352 if (!pTrack->m_bIsInLayer && !pTrack->m_btemp){
1353 pugi::xml_node doc = root();
1354 pugi::xml_node gpx = doc.first_child();
1355 pugi::xml_node new_node = gpx.append_child("trk");
1356
1357 GPXCreateTrk(new_node, pTrack, 0);
1358 }
1359 }
1360 }
1361
1362 return true;
1363}
1364
1365bool NavObjectCollection1::CreateAllGPXObjects() {
1366 SetRootGPXNode();
1367
1368 CreateNavObjGPXPoints();
1369 CreateNavObjGPXRoutes();
1370 CreateNavObjGPXTracks();
1371
1372 return true;
1373}
1374
1375bool NavObjectCollection1::AddGPXRoute(Route *pRoute) {
1376 SetRootGPXNode();
1377 pugi::xml_node doc = root();
1378 pugi::xml_node gpx = doc.first_child();
1379 pugi::xml_node new_node = gpx.append_child("rte");
1380
1381 GPXCreateRoute(new_node, pRoute);
1382 return true;
1383}
1384
1385bool NavObjectCollection1::AddGPXTrack(Track *pTrk) {
1386 SetRootGPXNode();
1387 pugi::xml_node doc = root();
1388 pugi::xml_node gpx = doc.first_child();
1389 pugi::xml_node new_node = gpx.append_child("trk");
1390
1391 GPXCreateTrk(new_node, pTrk, 0);
1392 return true;
1393}
1394
1395bool NavObjectCollection1::AddGPXWaypoint(RoutePoint *pWP) {
1396 SetRootGPXNode();
1397 pugi::xml_node doc = root();
1398 pugi::xml_node gpx = doc.first_child();
1399 pugi::xml_node new_node = gpx.append_child("wpt");
1400
1401 GPXCreateWpt(new_node, pWP, OPT_WPT);
1402 return true;
1403}
1404
1405void NavObjectCollection1::AddGPXRoutesList(RouteList *pRoutes) {
1406 SetRootGPXNode();
1407
1408 wxRouteListNode *pRoute = pRoutes->GetFirst();
1409 while (pRoute) {
1410 Route *pRData = pRoute->GetData();
1411 AddGPXRoute(pRData);
1412 pRoute = pRoute->GetNext();
1413 }
1414}
1415
1416void NavObjectCollection1::AddGPXTracksList(std::vector<Track*> *pTracks) {
1417 SetRootGPXNode();
1418
1419 for (Track *pRData : *pTracks) {
1420 AddGPXTrack(pRData);
1421 }
1422}
1423
1424bool NavObjectCollection1::AddGPXPointsList(RoutePointList *pRoutePoints) {
1425 SetRootGPXNode();
1426
1427 wxRoutePointListNode *pRoutePointNode = pRoutePoints->GetFirst();
1428 while (pRoutePointNode) {
1429 RoutePoint *pRP = pRoutePointNode->GetData();
1430 AddGPXWaypoint(pRP);
1431 pRoutePointNode = pRoutePointNode->GetNext();
1432 }
1433
1434 return true;
1435}
1436
1437void NavObjectCollection1::SetRootGPXNode(void) {
1438 if (!strlen(first_child().name())) {
1439 pugi::xml_node gpx_root = append_child("gpx");
1440 gpx_root.append_attribute("version") = "1.1";
1441 gpx_root.append_attribute("creator") = "OpenCPN";
1442 gpx_root.append_attribute("xmlns:xsi") =
1443 "http://www.w3.org/2001/XMLSchema-instance";
1444 gpx_root.append_attribute("xmlns") = "http://www.topografix.com/GPX/1/1";
1445 gpx_root.append_attribute("xmlns:gpxx") =
1446 "http://www.garmin.com/xmlschemas/GpxExtensions/v3";
1447 gpx_root.append_attribute("xsi:schemaLocation") =
1448 "http://www.topografix.com/GPX/1/1 "
1449 "http://www.topografix.com/GPX/1/1/gpx.xsd "
1450 "http://www.garmin.com/xmlschemas/GpxExtensions/v3 "
1451 "http://www8.garmin.com/xmlschemas/GpxExtensionsv3.xsd";
1452 gpx_root.append_attribute("xmlns:opencpn") = "http://www.opencpn.org";
1453 }
1454}
1455
1456bool NavObjectCollection1::IsOpenCPN() {
1457 for (pugi::xml_attribute attr = root().first_child().first_attribute(); attr;
1458 attr = attr.next_attribute())
1459 if (!strcmp(attr.name(), "creator") && !strcmp(attr.value(), "OpenCPN"))
1460 return true;
1461 return false;
1462}
1463
1464bool NavObjectCollection1::SaveFile(const wxString filename) {
1465 save_file(filename.fn_str(), " ");
1466 return true;
1467}
1468bool NavObjectCollection1::LoadAllGPXObjects(bool b_full_viz,
1469 int &wpt_duplicates,
1470 bool b_compute_bbox) {
1471 wpt_duplicates = 0;
1472 pugi::xml_node objects = this->child("gpx");
1473
1474 for (pugi::xml_node object = objects.first_child(); object;
1475 object = object.next_sibling()) {
1476 if (!strcmp(object.name(), "wpt")) {
1477 RoutePoint *pWp = ::GPXLoadWaypoint1(object, _T("circle"), _T(""),
1478 b_full_viz, false, false, 0);
1479
1480 pWp->m_bIsolatedMark = true; // This is an isolated mark
1481 RoutePoint *pExisting =
1482 WaypointExists(pWp->GetName(), pWp->m_lat, pWp->m_lon);
1483 if (!pExisting) {
1484 if (NULL != pWayPointMan) pWayPointMan->AddRoutePoint(pWp);
1485 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1486 LLBBox wptbox;
1487 wptbox.Set(pWp->m_lat, pWp->m_lon, pWp->m_lat, pWp->m_lon);
1488 BBox.Expand(wptbox);
1489 } else {
1490 delete pWp;
1491 wpt_duplicates++;
1492 }
1493 } else if (!strcmp(object.name(), "trk")) {
1494 Track *pTrack = GPXLoadTrack1(object, b_full_viz, false, false, 0);
1495 if (InsertTrack(pTrack) && b_compute_bbox && pTrack->IsVisible()) {
1496 // BBox.Expand(pTrack->GetBBox());
1497 }
1498 } else if (!strcmp(object.name(), "rte")) {
1499 Route *pRoute = GPXLoadRoute1(object, b_full_viz, false, false, 0, false);
1500 if (InsertRouteA(pRoute, this) && b_compute_bbox && pRoute->IsVisible()) {
1501 BBox.Expand(pRoute->GetBBox());
1502 }
1503 }
1504 }
1505
1506 return true;
1507}
1508
1509
1510int NavObjectCollection1::LoadAllGPXObjectsAsLayer(int layer_id,
1511 bool b_layerviz,
1512 wxCheckBoxState b_namesviz) {
1513 if (!pWayPointMan) return 0;
1514
1515 int n_obj = 0;
1516 pugi::xml_node objects = this->child("gpx");
1517
1518 for (pugi::xml_node object = objects.first_child(); object;
1519 object = object.next_sibling()) {
1520 if (!strcmp(object.name(), "wpt")) {
1521 RoutePoint *pWp = ::GPXLoadWaypoint1(object, _T("circle"), _T(""),
1522 b_namesviz != wxCHK_UNDETERMINED,
1523 true, b_layerviz, layer_id);
1524 if (b_namesviz != wxCHK_UNDETERMINED) {
1525 pWp->SetNameShown(b_namesviz == wxCHK_CHECKED);
1526 }
1527 pWp->m_bIsolatedMark = true; // This is an isolated mark
1528 pWayPointMan->AddRoutePoint(pWp);
1529 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1530 n_obj++;
1531 } else {
1532 if (!strcmp(object.name(), "trk")) {
1533 Track *pTrack =
1534 GPXLoadTrack1(object, false, true, b_layerviz, layer_id);
1535 n_obj++;
1536 InsertTrack(pTrack);
1537 } else if (!strcmp(object.name(), "rte")) {
1538 Route *pRoute =
1539 GPXLoadRoute1(object, true, true, b_layerviz, layer_id, false);
1540 n_obj++;
1541 InsertRouteA(pRoute, this);
1542 }
1543 }
1544 }
1545
1546 return n_obj;
1547}
1548
1549NavObjectChanges::NavObjectChanges(wxString file_name)
1551 m_filename = file_name;
1552 m_changes_file = fopen(m_filename.mb_str(), "a");
1553 m_bdirty = false;
1554}
1555
1556NavObjectChanges::~NavObjectChanges() {
1557 if (m_changes_file) fclose(m_changes_file);
1558 if (::wxFileExists(m_filename)) ::wxRemoveFile(m_filename);
1559}
1560
1561void NavObjectChanges::AddRoute(Route *pr, const char *action) {
1562 SetRootGPXNode();
1563
1564 pugi::xml_node object = root().append_child("rte");
1565 GPXCreateRoute(object, pr);
1566
1567 pugi::xml_node xchild = object.child("extensions");
1568 // FIXME What if extensions do not exist?
1569 pugi::xml_node child = xchild.append_child("opencpn:action");
1570 child.append_child(pugi::node_pcdata).set_value(action);
1571
1572 pugi::xml_writer_file writer(m_changes_file);
1573 object.print(writer, " ");
1574 fflush(m_changes_file);
1575 m_bdirty = true;
1576}
1577
1578void NavObjectChanges::AddTrack(Track *pr, const char *action) {
1579 SetRootGPXNode();
1580
1581 pugi::xml_node object = root().append_child("trk");
1582 GPXCreateTrk(object, pr, RT_OUT_NO_RTPTS); // emit a void track, no waypoints
1583
1584 pugi::xml_node xchild = object.child("extensions");
1585 pugi::xml_node child = xchild.append_child("opencpn:action");
1586 child.append_child(pugi::node_pcdata).set_value(action);
1587
1588 pugi::xml_writer_file writer(m_changes_file);
1589 object.print(writer, " ");
1590 fflush(m_changes_file);
1591 m_bdirty = true;
1592}
1593
1594void NavObjectChanges::AddWP(RoutePoint *pWP, const char *action) {
1595 SetRootGPXNode();
1596
1597 pugi::xml_node object = root().append_child("wpt");
1598 GPXCreateWpt(object, pWP, OPT_WPT);
1599
1600 pugi::xml_node xchild = object.child("extensions");
1601 pugi::xml_node child = xchild.append_child("opencpn:action");
1602 child.append_child(pugi::node_pcdata).set_value(action);
1603
1604 pugi::xml_writer_file writer(m_changes_file);
1605 object.print(writer, " ");
1606 fflush(m_changes_file);
1607 m_bdirty = true;
1608}
1609
1610void NavObjectChanges::AddTrackPoint(TrackPoint *pWP, const char *action,
1611 const wxString &parent_GUID) {
1612 SetRootGPXNode();
1613
1614 pugi::xml_node object = root().append_child("tkpt");
1615 GPXCreateTrkpt(object, pWP, OPT_TRACKPT);
1616
1617 pugi::xml_node xchild = object.append_child("extensions");
1618
1619 pugi::xml_node child = xchild.append_child("opencpn:action");
1620 child.append_child(pugi::node_pcdata).set_value(action);
1621
1622 pugi::xml_node gchild = xchild.append_child("opencpn:track_GUID");
1623 gchild.append_child(pugi::node_pcdata).set_value(parent_GUID.mb_str());
1624
1625 pugi::xml_writer_file writer(m_changes_file);
1626 object.print(writer, " ");
1627 fflush(m_changes_file);
1628 m_bdirty = true;
1629}
1630
1631bool NavObjectChanges::ApplyChanges(void) {
1632 // Let's reconstruct the unsaved changes
1633
1634 pugi::xml_node object = this->first_child();
1635
1636 while (strlen(object.name())) {
1637 if (!strcmp(object.name(), "wpt") && pWayPointMan) {
1638 RoutePoint *pWp = ::GPXLoadWaypoint1(object, _T("circle"), _T(""), false,
1639 false, false, 0);
1640
1641 pWp->m_bIsolatedMark = true;
1642 RoutePoint *pExisting = WaypointExists(pWp->m_GUID);
1643
1644 pugi::xml_node xchild = object.child("extensions");
1645 pugi::xml_node child = xchild.child("opencpn:action");
1646
1647 if (!strcmp(child.first_child().value(), "add")) {
1648 if (!pExisting) pWayPointMan->AddRoutePoint(pWp);
1649 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1650 }
1651
1652 else if (!strcmp(child.first_child().value(), "update")) {
1653 if (pExisting) pWayPointMan->RemoveRoutePoint(pExisting);
1654 pWayPointMan->AddRoutePoint(pWp);
1655 pSelect->AddSelectableRoutePoint(pWp->m_lat, pWp->m_lon, pWp);
1656 }
1657
1658 else if (!strcmp(child.first_child().value(), "delete")) {
1659 if (pExisting) pWayPointMan->DestroyWaypoint(pExisting, false);
1660 } else
1661 delete pWp;
1662 } else if (!strcmp(object.name(), "trk") && g_pRouteMan) {
1663 Track *pTrack = GPXLoadTrack1(object, false, false, false, 0);
1664
1665 if (pTrack) {
1666 pugi::xml_node xchild = object.child("extensions");
1667 pugi::xml_node child = xchild.child("opencpn:action");
1668
1669 Track *pExisting = TrackExists(pTrack->m_GUID);
1670 if (!strcmp(child.first_child().value(), "update")) {
1671 if (pExisting) {
1672 pExisting->SetName(pTrack->GetName());
1673 pExisting->m_TrackStartString = pTrack->m_TrackStartString;
1674 pExisting->m_TrackEndString = pTrack->m_TrackEndString;
1675 }
1676 }
1677
1678 else if (!strcmp(child.first_child().value(), "delete")) {
1679 if (pExisting) {
1680 evt_delete_track.Notify(std::make_shared<Track>(*pExisting), "");
1681 }
1682 }
1683
1684 else if (!strcmp(child.first_child().value(), "add")) {
1685 if (!pExisting) ::InsertTrack(pTrack, true);
1686 }
1687
1688 else
1689 delete pTrack;
1690 }
1691 }
1692
1693 else if (!strcmp(object.name(), "rte") && g_pRouteMan) {
1694 Route *pRoute = GPXLoadRoute1(object, false, false, false, 0, true);
1695
1696 if (pRoute) {
1697 pugi::xml_node xchild = object.child("extensions");
1698 pugi::xml_node child = xchild.child("opencpn:action");
1699
1700 if (!strcmp(child.first_child().value(), "add")) {
1701 ::UpdateRouteA(pRoute, this, this);
1702 }
1703
1704 else if (!strcmp(child.first_child().value(), "update")) {
1705 ::UpdateRouteA(pRoute, this, this);
1706 }
1707
1708 else if (!strcmp(child.first_child().value(), "delete")) {
1709 Route *pExisting = RouteExists(pRoute->m_GUID);
1710 if (pExisting) {
1711 m_bSkipChangeSetUpdate = true;
1712 evt_delete_route.Notify(std::make_shared<Route>(*pExisting), "");
1713 m_bSkipChangeSetUpdate = false;
1714 }
1715 }
1716
1717 else
1718 delete pRoute;
1719 }
1720 } else if (!strcmp(object.name(), "tkpt") && pWayPointMan) {
1721 TrackPoint *pWp = ::GPXLoadTrackPoint1(object);
1722
1723 // RoutePoint *pExisting = WaypointExists(
1724 // pWp->GetName(), pWp->m_lat, pWp->m_lon );
1725
1726 pugi::xml_node xchild = object.child("extensions");
1727 pugi::xml_node child = xchild.child("opencpn:action");
1728
1729 pugi::xml_node guid_child = xchild.child("opencpn:track_GUID");
1730 wxString track_GUID(guid_child.first_child().value(), wxConvUTF8);
1731
1732 Track *pExistingTrack = TrackExists(track_GUID);
1733
1734 if (!strcmp(child.first_child().value(), "add") && pExistingTrack && pWp) {
1735 pExistingTrack->AddPoint(pWp);
1736 pWp->m_GPXTrkSegNo = pExistingTrack->GetCurrentTrackSeg() + 1;
1737 } else
1738 delete pWp;
1739 }
1740
1741 object = object.next_sibling();
1742 }
1743 // Check to make sure we haven't loaded tracks with less than 2 points
1744 auto it = g_TrackList.begin();
1745 while (it != g_TrackList.end()) {
1746 Track *pTrack = *it;
1747 if (pTrack->GetnPoints() < 2) {
1748 auto to_erase = it;
1749 --it;
1750 g_TrackList.erase(to_erase);
1751 delete pTrack;
1752 }
1753 ++it;
1754 }
1755
1756 return true;
1757}
1758
1759
1760void NavObjectChanges::AddNewRoute(Route *pr) {
1761 // if( pr->m_bIsInLayer )
1762 // return true;
1763 if (!m_bSkipChangeSetUpdate) AddRoute(pr, "add");
1764}
1765
1766void NavObjectChanges::UpdateRoute(Route *pr) {
1767 // if( pr->m_bIsInLayer ) return true;
1768 if (!m_bSkipChangeSetUpdate) AddRoute(pr, "update");
1769}
1770
1771void NavObjectChanges::DeleteConfigRoute(Route *pr) {
1772 // if( pr->m_bIsInLayer )
1773 // return true;
1774 if (!m_bSkipChangeSetUpdate) AddRoute(pr, "delete");
1775}
1776
1777void NavObjectChanges::AddNewTrack(Track *pt) {
1778 if (!pt->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddTrack(pt, "add");
1779}
1780
1781void NavObjectChanges::UpdateTrack(Track *pt) {
1782 if (pt->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddTrack(pt, "update");
1783}
1784
1785void NavObjectChanges::DeleteConfigTrack(Track *pt) {
1786 if (!pt->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddTrack(pt, "delete");
1787}
1788
1789void NavObjectChanges::AddNewWayPoint(RoutePoint *pWP, int crm) {
1790 if (!pWP->m_bIsInLayer && pWP->m_bIsolatedMark && !m_bSkipChangeSetUpdate)
1791 AddWP(pWP, "add");
1792}
1793
1794void NavObjectChanges::UpdateWayPoint(RoutePoint *pWP) {
1795 if (!pWP->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddWP(pWP, "update");
1796}
1797
1798void NavObjectChanges::DeleteWayPoint(RoutePoint *pWP) {
1799 if (!pWP->m_bIsInLayer && !m_bSkipChangeSetUpdate) AddWP(pWP, "delete");
1800}
1801
1802void NavObjectChanges::AddNewTrackPoint(TrackPoint *pWP,
1803 const wxString &parent_GUID) {
1804 if (!m_bSkipChangeSetUpdate) AddTrackPoint(pWP, "add", parent_GUID);
1805}
1806
1807RoutePoint *WaypointExists(const wxString &name, double lat, double lon) {
1808 RoutePoint *pret = NULL;
1809 // if( g_bIsNewLayer ) return NULL;
1810 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
1811 while (node) {
1812 RoutePoint *pr = node->GetData();
1813
1814 // if( pr->m_bIsInLayer ) return NULL;
1815
1816 if (name == pr->GetName()) {
1817 if (fabs(lat - pr->m_lat) < 1.e-6 && fabs(lon - pr->m_lon) < 1.e-6) {
1818 pret = pr;
1819 break;
1820 }
1821 }
1822 node = node->GetNext();
1823 }
1824
1825 return pret;
1826}
1827
1828RoutePoint *WaypointExists(const wxString &guid) {
1829 wxRoutePointListNode *node = pWayPointMan->GetWaypointList()->GetFirst();
1830 while (node) {
1831 RoutePoint *pr = node->GetData();
1832
1833 // if( pr->m_bIsInLayer ) return NULL;
1834
1835 if (guid == pr->m_GUID) {
1836 return pr;
1837 }
1838 node = node->GetNext();
1839 }
1840
1841 return NULL;
1842}
1843
1844bool WptIsInRouteList(RoutePoint *pr) {
1845 bool IsInList = false;
1846
1847 wxRouteListNode *node1 = pRouteList->GetFirst();
1848 while (node1) {
1849 Route *pRoute = node1->GetData();
1850 RoutePointList *pRoutePointList = pRoute->pRoutePointList;
1851
1852 wxRoutePointListNode *node2 = pRoutePointList->GetFirst();
1853 RoutePoint *prp;
1854
1855 while (node2) {
1856 prp = node2->GetData();
1857
1858 if (pr->IsSame(prp)) {
1859 IsInList = true;
1860 break;
1861 }
1862
1863 node2 = node2->GetNext();
1864 }
1865 node1 = node1->GetNext();
1866 }
1867 return IsInList;
1868}
1869
1870Route *RouteExists(const wxString &guid) {
1871 wxRouteListNode *route_node = pRouteList->GetFirst();
1872
1873 while (route_node) {
1874 Route *proute = route_node->GetData();
1875
1876 if (guid == proute->m_GUID) return proute;
1877
1878 route_node = route_node->GetNext();
1879 }
1880 return NULL;
1881}
1882
1883Route *RouteExists(Route *pTentRoute) {
1884 wxRouteListNode *route_node = pRouteList->GetFirst();
1885 while (route_node) {
1886 Route *proute = route_node->GetData();
1887
1888 if (proute->IsEqualTo(pTentRoute)) return proute;
1889
1890 route_node = route_node->GetNext(); // next route
1891 }
1892 return NULL;
1893}
1894
1895Track *TrackExists(const wxString &guid) {
1896 for (Track* ptrack : g_TrackList) {
1897 if (guid == ptrack->m_GUID) return ptrack;
1898 }
1899 return NULL;
1900}
const void Notify()
Notify all listeners, no data supplied.
EventVar evt_delete_track
Notified when Routeman (?) should delete a track.
EventVar evt_delete_route
Notified when Routeman (?) should delete a Route*.
Definition: route.h:70
bool DeleteRoute(Route *pRoute, NavObjectChanges *nav_obj_changes)
Definition: routeman.cpp:726
Definition: select.h:51
Definition: track.h:79