You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

waypt.cc 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. /*
  2. Perform various operations on waypoints.
  3. Copyright (C) 2002-2013 Robert Lipe, robertlipe+source@gpsbabel.org
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  15. */
  16. #include "defs.h"
  17. #include "cet_util.h"
  18. #include "grtcirc.h"
  19. #include "garmin_fs.h"
  20. #include "session.h"
  21. #include "src/core/logging.h"
  22. #include <QtCore/QDebug>
  23. #include <QtCore/QList>
  24. #include <stdio.h>
  25. #include <math.h>
  26. #if NEWQ
  27. QList<Waypoint*> waypt_list;
  28. queue waypt_head; // This is here solely to freak out the formats that are
  29. // looking into what should be a private members.
  30. #else
  31. queue waypt_head;
  32. #endif
  33. static unsigned int waypt_ct;
  34. static short_handle mkshort_handle;
  35. geocache_data Waypoint::empty_gc_data;
  36. static global_trait traits;
  37. const global_trait* get_traits(void)
  38. {
  39. return &traits;
  40. }
  41. void
  42. waypt_init(void)
  43. {
  44. mkshort_handle = mkshort_new_handle();
  45. #if NEWQ
  46. waypt_list.clear();
  47. #else
  48. QUEUE_INIT(&waypt_head);
  49. #endif
  50. }
  51. void update_common_traits(const Waypoint* wpt)
  52. {
  53. /* This is a bit tacky, but it allows a hint whether we've seen
  54. * this data or not in the life cycle of this run. Of course,
  55. * the caches could have been filtered out of existance and not
  56. * all waypoints may have this and a few other pitfalls, but it's
  57. * an easy and fast test here.
  58. */
  59. traits.trait_geocaches |= (wpt->gc_data->diff && wpt->gc_data->terr);
  60. traits.trait_heartrate |= wpt->heartrate > 0;
  61. traits.trait_cadence |= wpt->cadence > 0;
  62. traits.trait_power |= wpt->power > 0;
  63. traits.trait_depth |= WAYPT_HAS(wpt, depth);
  64. traits.trait_temperature |= WAYPT_HAS(wpt, temperature);
  65. }
  66. void
  67. waypt_add(Waypoint* wpt)
  68. {
  69. double lat_orig = wpt->latitude;
  70. double lon_orig = wpt->longitude;
  71. #if NEWQ
  72. waypt_list.append(wpt);
  73. #else
  74. ENQUEUE_TAIL(&waypt_head, &wpt->Q);
  75. waypt_ct++;
  76. #endif
  77. if (wpt->latitude < -90) {
  78. wpt->latitude += 180;
  79. } else if (wpt->latitude > +90) {
  80. wpt->latitude -= 180;
  81. }
  82. if (wpt->longitude < -180) {
  83. wpt->longitude += 360;
  84. } else if (wpt->longitude > +180) {
  85. wpt->longitude -= 360;
  86. }
  87. if ((wpt->latitude < -90) || (wpt->latitude > 90.0))
  88. Fatal() << wpt->session->name
  89. << "Invalid latitude" << lat_orig << "in waypoint"
  90. << wpt->shortname;
  91. if ((wpt->longitude < -180) || (wpt->longitude > 180.0))
  92. Fatal() << "Invalid longitude" << lon_orig << "in waypoint"
  93. << wpt->shortname;
  94. /*
  95. * Some input may not have one or more of these types so we
  96. * try to be sure that we have these fields even if just by
  97. * copying them from elsewhere.
  98. */
  99. // Note tests for isNull here as some formats intentionally set "".
  100. // This is kind of goofy, but it emulates the C string implementation.
  101. if (wpt->shortname.isNull()) {
  102. if (!wpt->description.isNull()) {
  103. wpt->shortname = wpt->description;
  104. } else if (!wpt->notes.isNull()) {
  105. wpt->shortname = wpt->notes;
  106. } else {
  107. QString n;
  108. n.sprintf("%03d", waypt_count());
  109. wpt->shortname = QString("WPT%1").arg(n);
  110. }
  111. }
  112. if (wpt->description.isEmpty()) {
  113. if (!wpt->notes.isNull()) {
  114. wpt->description = wpt->notes;
  115. } else {
  116. if (!wpt->shortname.isNull()) {
  117. wpt->description = wpt->shortname;
  118. }
  119. }
  120. }
  121. update_common_traits(wpt);
  122. }
  123. void
  124. waypt_del(Waypoint* wpt)
  125. {
  126. // the wpt must be on waypt_list, and is assumed unique.
  127. #if NEWQ
  128. waypt_list.removeOne(wpt);
  129. #else
  130. dequeue(&wpt->Q);
  131. waypt_ct--;
  132. #endif
  133. }
  134. unsigned int
  135. waypt_count(void)
  136. {
  137. #if NEWQ
  138. return waypt_list.size();
  139. #else
  140. return waypt_ct;
  141. #endif
  142. }
  143. void
  144. set_waypt_count(unsigned int nc)
  145. {
  146. waypt_ct = nc;
  147. }
  148. void
  149. waypt_disp(const Waypoint* wpt)
  150. {
  151. if (wpt->GetCreationTime().isValid()) {
  152. printf("%s ", qPrintable(wpt->creation_time.toString()));
  153. }
  154. printposn(wpt->latitude,1);
  155. printposn(wpt->longitude,0);
  156. if (!wpt->description.isEmpty()) {
  157. printf("%s/%s",
  158. global_opts.synthesize_shortnames ?
  159. qPrintable(mkshort(mkshort_handle, wpt->description)) :
  160. qPrintable(wpt->shortname),
  161. qPrintable(wpt->description));
  162. }
  163. if (wpt->altitude != unknown_alt) {
  164. printf(" %f", wpt->altitude);
  165. }
  166. printf("\n");
  167. }
  168. void
  169. waypt_status_disp(int total_ct, int myct)
  170. {
  171. fprintf(stdout, "%d/%d/%d\r", myct*100/total_ct, myct, total_ct);
  172. fflush(stdout);
  173. }
  174. void
  175. waypt_disp_all(waypt_cb cb)
  176. {
  177. waypt_disp_session(NULL, cb);
  178. }
  179. void
  180. waypt_disp_session(const session_t* se, waypt_cb cb)
  181. {
  182. int i = 0;
  183. #if NEWQ
  184. foreach(Waypoint* waypointp, waypt_list) {
  185. #else
  186. queue* elem, *tmp;
  187. Waypoint* waypointp;
  188. QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
  189. waypointp = (Waypoint*) elem;
  190. #endif
  191. if ((se == NULL) || (waypointp->session == se)) {
  192. if (global_opts.verbose_status) {
  193. i++;
  194. waypt_status_disp(waypt_count(), i);
  195. }
  196. (*cb)(waypointp);
  197. }
  198. }
  199. if (global_opts.verbose_status) {
  200. fprintf(stdout, "\r\n");
  201. }
  202. }
  203. void
  204. waypt_init_bounds(bounds* bounds)
  205. {
  206. /* Set data out of bounds so that even one waypoint will reset */
  207. bounds->max_lat = -9999;
  208. bounds->max_lon = -9999;
  209. bounds->min_lat = 9999;
  210. bounds->min_lon = 9999;
  211. bounds->max_alt = unknown_alt;
  212. bounds->min_alt = -unknown_alt;
  213. }
  214. int
  215. waypt_bounds_valid(bounds* bounds)
  216. {
  217. /* Returns true if bb has any 'real' data in it */
  218. return bounds->max_lat > -9999;
  219. }
  220. /*
  221. * Recompund bounding box based on new position point.
  222. */
  223. void
  224. waypt_add_to_bounds(bounds* bounds, const Waypoint* waypointp)
  225. {
  226. if (waypointp->latitude > bounds->max_lat) {
  227. bounds->max_lat = waypointp->latitude;
  228. }
  229. if (waypointp->longitude > bounds->max_lon) {
  230. bounds->max_lon = waypointp->longitude;
  231. }
  232. if (waypointp->latitude < bounds->min_lat) {
  233. bounds->min_lat = waypointp->latitude;
  234. }
  235. if (waypointp->longitude < bounds->min_lon) {
  236. bounds->min_lon = waypointp->longitude;
  237. }
  238. if (waypointp->altitude != unknown_alt) {
  239. if (waypointp->altitude < bounds->min_alt) {
  240. bounds->min_alt = waypointp->altitude;
  241. }
  242. if (waypointp->altitude > bounds->max_alt) {
  243. bounds->max_alt = waypointp->altitude;
  244. }
  245. }
  246. }
  247. /*
  248. * Makes another pass over the data to compute bounding
  249. * box data and populates bounding box information.
  250. */
  251. void
  252. waypt_compute_bounds(bounds* bounds)
  253. {
  254. waypt_init_bounds(bounds);
  255. #if NEWQ
  256. foreach(Waypoint* waypointp, waypt_list) {
  257. #else
  258. queue* elem, *tmp;
  259. Waypoint* waypointp;
  260. QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
  261. waypointp = (Waypoint*) elem;
  262. #endif
  263. waypt_add_to_bounds(bounds, waypointp);
  264. }
  265. }
  266. Waypoint*
  267. find_waypt_by_name(const QString& name)
  268. {
  269. #if NEWQ
  270. foreach(Waypoint* waypointp, waypt_list) {
  271. #else
  272. queue* elem, *tmp;
  273. Waypoint* waypointp;
  274. QUEUE_FOR_EACH(&waypt_head, elem, tmp) {
  275. waypointp = (Waypoint*) elem;
  276. #endif
  277. if (waypointp->shortname == name) {
  278. return waypointp;
  279. }
  280. }
  281. return NULL;
  282. }
  283. #if NEWQ
  284. void
  285. waypt_flush(queue* head)
  286. {
  287. // TODO: This is incorrect when head != &waypt_head
  288. // We need to pass in a QList<Waypoint*> instead of a queue* that we ignore!
  289. if (head != &waypt_head) {
  290. if (global_opts.debug_level >= 1) {
  291. warning("NEWQ version of waypt_flush is unimplemented for this list.\n");
  292. }
  293. } else {
  294. while (!waypt_list.isEmpty()) {
  295. delete waypt_list.takeFirst();
  296. }
  297. }
  298. }
  299. #else
  300. void
  301. waypt_flush(queue* head)
  302. {
  303. queue* elem, *tmp;
  304. QUEUE_FOR_EACH(head, elem, tmp) {
  305. Waypoint* q = (Waypoint*) dequeue(elem);
  306. delete q;
  307. if (head == &waypt_head) {
  308. waypt_ct--;
  309. }
  310. }
  311. }
  312. #endif
  313. void
  314. waypt_flush_all()
  315. {
  316. if (mkshort_handle) {
  317. mkshort_del_handle(&mkshort_handle);
  318. }
  319. #if NEWQ
  320. // TODO: eventually we shoud pass the list instead of the queue.
  321. waypt_flush(&waypt_head);
  322. #else
  323. waypt_flush(&waypt_head);
  324. #endif
  325. }
  326. void
  327. waypt_backup(signed int* count, queue** head_bak)
  328. {
  329. queue* elem, *tmp, *qbackup;
  330. Waypoint* wpt;
  331. int no = 0;
  332. qbackup = (queue*) xcalloc(1, sizeof(*qbackup));
  333. QUEUE_INIT(qbackup);
  334. #if NEWQ
  335. // Why does this code exist?
  336. //abort();
  337. #else
  338. QUEUE_MOVE(qbackup, &waypt_head);
  339. QUEUE_INIT(&waypt_head);
  340. #endif
  341. waypt_ct = 0;
  342. QUEUE_FOR_EACH(qbackup, elem, tmp) {
  343. wpt = (Waypoint*)elem;
  344. waypt_add(new Waypoint(*wpt));
  345. no++;
  346. }
  347. *head_bak = qbackup;
  348. *count = no;
  349. }
  350. void
  351. waypt_restore(signed int count, queue* head_bak)
  352. {
  353. if (head_bak == NULL) {
  354. return;
  355. }
  356. #if NEWQ
  357. //abort();
  358. #else
  359. waypt_flush(&waypt_head);
  360. QUEUE_INIT(&waypt_head);
  361. QUEUE_MOVE(&waypt_head, head_bak);
  362. #endif
  363. waypt_ct = count;
  364. xfree(head_bak);
  365. }
  366. void
  367. waypt_add_url(Waypoint* wpt, const QString& link, const QString& url_link_text)
  368. {
  369. wpt->url_link_list_.push_back(UrlLink(link, url_link_text));
  370. }
  371. void
  372. waypt_add_url(Waypoint* wpt, const QString& link, const QString& url_link_text, const QString& url_link_type)
  373. {
  374. wpt->url_link_list_.push_back(UrlLink(link, url_link_text, url_link_type));
  375. }
  376. double
  377. gcgeodist(const double lat1, const double lon1,
  378. const double lat2, const double lon2)
  379. {
  380. double res;
  381. res = radtometers(gcdist(RAD(lat1), RAD(lon1), RAD(lat2), RAD(lon2)));
  382. if (res < 0.1) {
  383. res = 0; /* calc. diffs on 32- and 64-bit hosts */
  384. }
  385. return res;
  386. }
  387. /*
  388. * returns full creation_time with parts of seconds in fractional portion
  389. */
  390. double
  391. waypt_time(const Waypoint* wpt)
  392. {
  393. if (!wpt->creation_time.isValid()) {
  394. return (double) 0;
  395. } else {
  396. return ((double)wpt->creation_time.toMSecsSinceEpoch()) / 1000.0;
  397. }
  398. }
  399. /*
  400. * Calculates the distance between points "A" and "B" including
  401. * special data (Garmin interstep links)
  402. * The result comes in meters.
  403. */
  404. double
  405. waypt_distance_ex(const Waypoint* A, const Waypoint* B)
  406. {
  407. double res = 0;
  408. garmin_fs_p gmsd;
  409. if ((A == NULL) || (B == NULL)) {
  410. return 0;
  411. }
  412. if ((gmsd = GMSD_FIND(A)) && (gmsd->ilinks != NULL)) {
  413. garmin_ilink_t* link = gmsd->ilinks;
  414. res = gcgeodist(A->latitude, A->longitude, link->lat, link->lon);
  415. while (link->next != NULL) {
  416. garmin_ilink_t* prev = link;
  417. link = link->next;
  418. res += gcgeodist(prev->lat, prev->lon, link->lat, link->lon);
  419. }
  420. res += gcgeodist(link->lat, link->lon, B->latitude, B->longitude);
  421. } else {
  422. res = gcgeodist(A->latitude, A->longitude, B->latitude, B->longitude);
  423. }
  424. return res;
  425. }
  426. double
  427. waypt_distance(const Waypoint* A, const Waypoint* B)
  428. {
  429. if ((A == NULL) || (B == NULL)) {
  430. return 0;
  431. } else {
  432. return gcgeodist(A->latitude, A->longitude, B->latitude, B->longitude);
  433. }
  434. }
  435. /*
  436. * Calculates the speed between points "A" and "B" including
  437. * special data (Garmin interstep links)
  438. * The result comes in meters per second and is always positive.
  439. */
  440. double
  441. waypt_speed_ex(const Waypoint* A, const Waypoint* B)
  442. {
  443. double dist, time;
  444. dist = waypt_distance_ex(A, B);
  445. if (dist == 0) {
  446. return 0;
  447. }
  448. time = fabs((double)A->creation_time.msecsTo(B->creation_time)) / 1000.0;
  449. if (time > 0) {
  450. return (dist / time);
  451. } else {
  452. return 0;
  453. }
  454. }
  455. /*
  456. * Calculates the speed between points "A" and "B"
  457. * the result comes in meters per second and is always positive
  458. */
  459. double
  460. waypt_speed(const Waypoint* A, const Waypoint* B)
  461. {
  462. double dist, time;
  463. dist = waypt_distance(A, B);
  464. if (dist == 0) {
  465. return 0;
  466. }
  467. time = fabs((double)A->creation_time.msecsTo(B->creation_time)) / 1000.0;
  468. if (time > 0) {
  469. return (dist / time);
  470. } else {
  471. return 0;
  472. }
  473. }
  474. /*
  475. * Calculates the vertical speed between points "A" and "B"
  476. * the result comes in meters per second and can be negative.
  477. */
  478. double
  479. waypt_vertical_speed(const Waypoint* A, const Waypoint* B)
  480. {
  481. double altitude, time;
  482. altitude = A->altitude - B->altitude;
  483. if (altitude == 0) {
  484. return 0;
  485. }
  486. time = fabs((double)A->creation_time.msecsTo(B->creation_time)) / 1000.0;
  487. if (time > 0) {
  488. return (altitude / time);
  489. } else {
  490. return 0;
  491. }
  492. }
  493. /*
  494. * Returns "Road Gradient" between A and B as a percentage of slope.
  495. * If there is no distance or either A or B have unknown altitude, return 0.
  496. */
  497. double
  498. waypt_gradient(const Waypoint* A, const Waypoint* B)
  499. {
  500. double dist, altitude, gradient;
  501. dist = waypt_distance(A, B);
  502. if (dist == 0) {
  503. return 0;
  504. }
  505. altitude = A->altitude - B->altitude;
  506. if (altitude == 0 ||
  507. A->altitude == unknown_alt || B->altitude == unknown_alt) {
  508. return 0;
  509. }
  510. gradient = (altitude / dist) * 100;
  511. return (gradient);
  512. }
  513. /*
  514. * Calculates "Course True" from A to B
  515. */
  516. double
  517. waypt_course(const Waypoint* A, const Waypoint* B)
  518. {
  519. if (A && B) {
  520. return heading_true_degrees(RAD(A->latitude), RAD(A->longitude), RAD(B->latitude), RAD(B->longitude));
  521. } else {
  522. return 0;
  523. }
  524. }
  525. Waypoint::Waypoint() :
  526. // Q(),
  527. latitude(0), // These should probably use some invalid data, but
  528. longitude(0), // it looks like we have code that relies on them being zero.
  529. altitude(unknown_alt),
  530. geoidheight(0),
  531. depth(0),
  532. proximity(0),
  533. route_priority(0),
  534. hdop(0),
  535. vdop(0),
  536. pdop(0),
  537. course(0),
  538. speed(0),
  539. fix(fix_unknown),
  540. sat(-1),
  541. heartrate(0),
  542. cadence(0),
  543. power(0),
  544. temperature(0),
  545. odometer_distance(0),
  546. gc_data(&Waypoint::empty_gc_data),
  547. fs(NULL),
  548. session(curr_session()),
  549. extra_data(NULL)
  550. {
  551. QUEUE_INIT(&Q);
  552. }
  553. Waypoint::~Waypoint()
  554. {
  555. if (gc_data != &Waypoint::empty_gc_data) {
  556. delete gc_data;
  557. }
  558. fs_chain_destroy(fs);
  559. }
  560. Waypoint::Waypoint(const Waypoint& other) :
  561. // Q(other.Q),
  562. latitude(other.latitude),
  563. longitude(other.longitude),
  564. altitude(other.altitude),
  565. geoidheight(other.geoidheight),
  566. depth(other.depth),
  567. proximity(other.proximity),
  568. shortname(other.shortname),
  569. description(other.description),
  570. notes(other.notes),
  571. url_link_list_(other.url_link_list_),
  572. wpt_flags(other.wpt_flags),
  573. icon_descr(other.icon_descr),
  574. creation_time(other.creation_time),
  575. route_priority(other.route_priority),
  576. hdop(other.hdop),
  577. vdop(other.vdop),
  578. pdop(other.pdop),
  579. course(other.course),
  580. speed(other.speed),
  581. fix(other.fix),
  582. sat(other.sat),
  583. heartrate(other.heartrate),
  584. cadence(other.cadence),
  585. power(other.power),
  586. temperature(other.temperature),
  587. odometer_distance(other.odometer_distance),
  588. gc_data(other.gc_data),
  589. fs(other.fs),
  590. session(other.session),
  591. extra_data(other.extra_data)
  592. {
  593. // deep copy geocache data unless it is the specail static empty_gc_data.
  594. if (other.gc_data != &Waypoint::empty_gc_data) {
  595. gc_data = new geocache_data(*other.gc_data);
  596. }
  597. /*
  598. * It's important that this duplicated waypoint not appear
  599. * on the master Q.
  600. */
  601. QUEUE_INIT(&Q);
  602. // deep copy fs chain data.
  603. fs = fs_chain_copy(other.fs);
  604. // note: session is not deep copied.
  605. // note: extra_data is not deep copied.
  606. }
  607. Waypoint& Waypoint::operator=(const Waypoint& other)
  608. {
  609. // the default assignment operator is not appropriate as we do deep copy of some members,
  610. // and we haven't bothered to write an appropriate one.
  611. // this is a dummy so the compiler can catch attempts to use the assignment operator.
  612. return *this;
  613. }
  614. bool
  615. Waypoint::HasUrlLink() const
  616. {
  617. return !url_link_list_.isEmpty();
  618. }
  619. const UrlLink&
  620. Waypoint::GetUrlLink() const
  621. {
  622. return url_link_list_[0];
  623. }
  624. const QList<UrlLink>
  625. Waypoint::GetUrlLinks() const
  626. {
  627. return url_link_list_;
  628. }
  629. void
  630. Waypoint::AddUrlLink(const UrlLink l)
  631. {
  632. url_link_list_.push_back(l);
  633. }
  634. QString
  635. Waypoint::CreationTimeXML() const
  636. {
  637. if (!creation_time.isValid()) {
  638. return NULL;
  639. }
  640. QDateTime dt = GetCreationTime().toUTC();
  641. // qDebug() << dt.toString("dd.MM.yyyy hh:mm:ss.zzz") << " CML " << microseconds;
  642. const char* format = "yyyy-MM-ddTHH:mm:ssZ";
  643. if (dt.time().msec()) {
  644. format = "yyyy-MM-ddTHH:mm:ss.zzzZ";
  645. }
  646. return dt.toString(format);
  647. }
  648. gpsbabel::DateTime
  649. Waypoint::GetCreationTime() const
  650. {
  651. return creation_time;
  652. }
  653. void
  654. Waypoint::SetCreationTime(gpsbabel::DateTime t)
  655. {
  656. creation_time = t;
  657. }
  658. void
  659. Waypoint::SetCreationTime(time_t t)
  660. {
  661. creation_time = QDateTime::fromTime_t(t);
  662. }
  663. void
  664. Waypoint::SetCreationTime(time_t t, int ms)
  665. {
  666. creation_time.setTime_t(t);
  667. creation_time = creation_time.addMSecs(ms);
  668. }
  669. geocache_data*
  670. Waypoint::AllocGCData()
  671. {
  672. if (gc_data == &Waypoint::empty_gc_data) {
  673. gc_data = new geocache_data;
  674. }
  675. return gc_data;
  676. }
  677. int
  678. Waypoint::EmptyGCData() const
  679. {
  680. return (gc_data == &Waypoint::empty_gc_data);
  681. }