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.

route.cc 14KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. /*
  2. Copyright (C) 2002-2010 Robert Lipe, robertlipe+source@gpsbabel.org
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
  14. */
  15. #include <stdio.h>
  16. #include "defs.h"
  17. #include "grtcirc.h"
  18. #include "session.h"
  19. static queue my_route_head;
  20. static queue my_track_head;
  21. static int rte_head_ct;
  22. static int rte_waypts;
  23. static int trk_head_ct;
  24. static int trk_waypts;
  25. extern void update_common_traits(const Waypoint* wpt);
  26. void
  27. route_init(void)
  28. {
  29. QUEUE_INIT(&my_route_head);
  30. QUEUE_INIT(&my_track_head);
  31. }
  32. unsigned int
  33. route_waypt_count(void)
  34. {
  35. /* total wapoint count -- all routes */
  36. return rte_waypts;
  37. }
  38. unsigned int
  39. route_count(void)
  40. {
  41. return rte_head_ct; /* total # of routes */
  42. }
  43. unsigned int
  44. track_waypt_count(void)
  45. {
  46. /* totaly waypoint count -- all tracks */
  47. return trk_waypts;
  48. }
  49. unsigned int
  50. track_count(void)
  51. {
  52. return trk_head_ct; /* total # of tracks */
  53. }
  54. route_head*
  55. route_head_alloc(void)
  56. {
  57. route_head* rte_head = new route_head;
  58. return rte_head;
  59. }
  60. static void
  61. any_route_free(route_head* rte)
  62. {
  63. delete rte;
  64. rte = NULL;
  65. }
  66. static void
  67. any_route_add_head(route_head* rte, queue* head)
  68. {
  69. ENQUEUE_TAIL(head, &rte->Q);
  70. }
  71. static void
  72. any_route_del_head(route_head* rte)
  73. {
  74. dequeue(&rte->Q);
  75. any_route_free(rte);
  76. }
  77. void
  78. route_add_head(route_head* rte)
  79. {
  80. any_route_add_head(rte, &my_route_head);
  81. rte_head_ct++;
  82. }
  83. void
  84. route_del_head(route_head* rte)
  85. {
  86. rte_waypts -= rte->rte_waypt_ct;
  87. any_route_del_head(rte);
  88. rte_head_ct--;
  89. }
  90. void
  91. track_add_head(route_head* rte)
  92. {
  93. any_route_add_head(rte, &my_track_head);
  94. trk_head_ct++;
  95. }
  96. void
  97. track_del_head(route_head* rte)
  98. {
  99. trk_waypts -= rte->rte_waypt_ct;
  100. any_route_del_head(rte);
  101. trk_head_ct--;
  102. }
  103. void
  104. track_insert_head(route_head* rte, route_head* predecessor)
  105. {
  106. ENQUEUE_AFTER(&predecessor->Q, &rte->Q);
  107. trk_head_ct++;
  108. }
  109. static
  110. route_head*
  111. common_route_by_name(queue* routes, const char* name)
  112. {
  113. queue* elem, *tmp;
  114. route_head* rte;
  115. QUEUE_FOR_EACH(routes, elem, tmp) {
  116. rte = (route_head*) elem;
  117. if (rte->rte_name == name) {
  118. return rte;
  119. }
  120. }
  121. return NULL;
  122. }
  123. route_head*
  124. route_find_route_by_name(const char* name)
  125. {
  126. return common_route_by_name(&my_route_head, name);
  127. }
  128. route_head*
  129. route_find_track_by_name(const char* name)
  130. {
  131. return common_route_by_name(&my_track_head, name);
  132. }
  133. static void
  134. any_route_add_wpt(route_head* rte, Waypoint* wpt, int* ct, int synth, const QString& namepart, int number_digits)
  135. {
  136. ENQUEUE_TAIL(&rte->waypoint_list, &wpt->Q);
  137. rte->rte_waypt_ct++; /* waypoints in this route */
  138. if (ct) {
  139. (*ct)++;
  140. }
  141. if (synth && wpt->shortname.isEmpty()) {
  142. wpt->shortname = QString().sprintf("%s%0*d", CSTRc(namepart), number_digits, *ct);
  143. wpt->wpt_flags.shortname_is_synthetic = 1;
  144. }
  145. update_common_traits(wpt);
  146. }
  147. void
  148. route_add_wpt_named(route_head* rte, Waypoint* wpt, const QString& namepart, int number_digits)
  149. {
  150. // First point in a route is always a new segment.
  151. // This improves compatibility when reading from
  152. // segment-unaware formats.
  153. if (QUEUE_EMPTY(&rte->waypoint_list)) {
  154. wpt->wpt_flags.new_trkseg = 1;
  155. }
  156. any_route_add_wpt(rte, wpt, &rte_waypts, 1, namepart, number_digits);
  157. }
  158. void
  159. route_add_wpt(route_head* rte, Waypoint* wpt)
  160. {
  161. const char RPT[] = "RPT";
  162. route_add_wpt_named(rte, wpt, RPT, 3);
  163. }
  164. void
  165. track_add_wpt_named(route_head* rte, Waypoint* wpt, const QString& namepart, int number_digits)
  166. {
  167. // First point in a track is always a new segment.
  168. // This improves compatibility when reading from
  169. // segment-unaware formats.
  170. if (QUEUE_EMPTY(&rte->waypoint_list)) {
  171. wpt->wpt_flags.new_trkseg = 1;
  172. }
  173. any_route_add_wpt(rte, wpt, &trk_waypts, 0, namepart, number_digits);
  174. }
  175. void
  176. track_add_wpt(route_head* rte, Waypoint* wpt)
  177. {
  178. const char RPT[] = "RPT";
  179. track_add_wpt_named(rte, wpt, RPT, 3);
  180. }
  181. Waypoint*
  182. route_find_waypt_by_name(route_head* rh, const char* name)
  183. {
  184. queue* elem, *tmp;
  185. QUEUE_FOR_EACH(&rh->waypoint_list, elem, tmp) {
  186. Waypoint* waypointp = (Waypoint*) elem;
  187. if (waypointp->shortname == name) {
  188. return waypointp;
  189. }
  190. }
  191. return NULL;
  192. }
  193. static void
  194. any_route_del_wpt(route_head* rte, Waypoint* wpt, int* ct)
  195. {
  196. if (wpt->wpt_flags.new_trkseg && wpt != (Waypoint*)QUEUE_LAST(&rte->waypoint_list)) {
  197. Waypoint* wpt_next = (Waypoint*)QUEUE_NEXT(&wpt->Q);
  198. wpt_next->wpt_flags.new_trkseg = 1;
  199. }
  200. wpt->wpt_flags.new_trkseg = 0;
  201. dequeue(&wpt->Q);
  202. rte->rte_waypt_ct--;
  203. if (ct) {
  204. (*ct)--;
  205. }
  206. }
  207. void
  208. route_del_wpt(route_head* rte, Waypoint* wpt)
  209. {
  210. any_route_del_wpt(rte, wpt, &rte_waypts);
  211. }
  212. void
  213. track_del_wpt(route_head* rte, Waypoint* wpt)
  214. {
  215. any_route_del_wpt(rte, wpt, &trk_waypts);
  216. }
  217. void
  218. route_disp(const route_head* rh, waypt_cb cb)
  219. {
  220. queue* elem, *tmp;
  221. if (!cb) {
  222. return;
  223. }
  224. QUEUE_FOR_EACH(&rh->waypoint_list, elem, tmp) {
  225. Waypoint* waypointp;
  226. waypointp = (Waypoint*) elem;
  227. (*cb)(waypointp);
  228. }
  229. }
  230. void
  231. route_reverse(const route_head* rte_hd)
  232. {
  233. /* Cast away const-ness */
  234. route_head* rh = (route_head*) rte_hd;
  235. queue* elem, *tmp;
  236. QUEUE_FOR_EACH(&rh->waypoint_list, elem, tmp) {
  237. ENQUEUE_HEAD(&rh->waypoint_list, dequeue(elem));
  238. }
  239. }
  240. static void
  241. common_disp_all(queue* qh, route_hdr rh, route_trl rt, waypt_cb wc)
  242. {
  243. queue* elem, *tmp;
  244. QUEUE_FOR_EACH(qh, elem, tmp) {
  245. const route_head* rhp;
  246. rhp = (route_head*) elem;
  247. if (rh) {
  248. (*rh)(rhp);
  249. }
  250. route_disp(rhp, wc);
  251. if (rt) {
  252. (*rt)(rhp);
  253. }
  254. }
  255. }
  256. static void
  257. common_disp_session(const session_t* se, queue* qh, route_hdr rh, route_trl rt, waypt_cb wc)
  258. {
  259. queue* elem, *tmp;
  260. QUEUE_FOR_EACH(qh, elem, tmp) {
  261. const route_head* rhp;
  262. rhp = (route_head*) elem;
  263. if (rhp->session == se) {
  264. if (rh) {
  265. (*rh)(rhp);
  266. }
  267. route_disp(rhp, wc);
  268. if (rt) {
  269. (*rt)(rhp);
  270. }
  271. }
  272. }
  273. }
  274. void
  275. route_disp_all(route_hdr rh, route_trl rt, waypt_cb wc)
  276. {
  277. common_disp_all(&my_route_head, rh, rt, wc);
  278. }
  279. void
  280. route_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc)
  281. {
  282. common_disp_session(se, &my_route_head, rh, rt, wc);
  283. }
  284. void
  285. track_disp_all(route_hdr rh, route_trl rt, waypt_cb wc)
  286. {
  287. common_disp_all(&my_track_head, rh, rt, wc);
  288. }
  289. void
  290. track_disp_session(const session_t* se, route_hdr rh, route_trl rt, waypt_cb wc)
  291. {
  292. common_disp_session(se, &my_track_head, rh, rt, wc);
  293. }
  294. static void
  295. route_flush_q(queue* head)
  296. {
  297. queue* elem, *tmp;
  298. queue* q;
  299. QUEUE_FOR_EACH(head, elem, tmp) {
  300. q = dequeue(elem);
  301. any_route_free((route_head*) q);
  302. }
  303. }
  304. void
  305. route_flush_all_routes(void)
  306. {
  307. route_flush_q(&my_route_head);
  308. rte_head_ct = 0;
  309. rte_waypts = 0;
  310. }
  311. void
  312. route_flush_all_tracks(void)
  313. {
  314. route_flush_q(&my_track_head);
  315. trk_head_ct = 0;
  316. trk_waypts = 0;
  317. }
  318. void
  319. route_flush_all()
  320. {
  321. route_flush_all_tracks();
  322. route_flush_all_routes();
  323. }
  324. void
  325. route_flush(queue* head)
  326. {
  327. queue* elem, *tmp;
  328. queue* q;
  329. QUEUE_FOR_EACH(head, elem, tmp) {
  330. q = dequeue(elem);
  331. any_route_free((route_head*)q);
  332. }
  333. }
  334. void
  335. route_copy(int* dst_count, int* dst_wpt_count, queue** dst, queue* src)
  336. {
  337. queue* elem, *tmp, *elem2, *tmp2;
  338. route_head* rte_new;
  339. int junk;
  340. if (!dst_wpt_count) {
  341. dst_wpt_count = &junk;
  342. }
  343. if (!*dst) {
  344. *dst = (queue*)xcalloc(1, sizeof(queue));
  345. QUEUE_INIT(*dst);
  346. *dst_count = 0;
  347. *dst_wpt_count = 0;
  348. }
  349. const char RPT[] = "RPT";
  350. QUEUE_FOR_EACH(src, elem, tmp) {
  351. route_head* rte_old = (route_head*)elem;
  352. rte_new = route_head_alloc();
  353. rte_new->rte_name = rte_old->rte_name;
  354. rte_new->rte_desc = rte_old->rte_desc;
  355. rte_new->rte_url = rte_old->rte_url;
  356. rte_new->fs = fs_chain_copy(rte_old->fs);
  357. rte_new->rte_num = rte_old->rte_num;
  358. any_route_add_head(rte_new, *dst);
  359. QUEUE_FOR_EACH(&rte_old->waypoint_list, elem2, tmp2) {
  360. any_route_add_wpt(rte_new, new Waypoint(*(Waypoint*)elem2), dst_wpt_count, 0, RPT, 3);
  361. }
  362. (*dst_count)++;
  363. }
  364. }
  365. void
  366. route_append(queue* src)
  367. {
  368. queue* dst = &my_route_head;
  369. route_copy(&rte_head_ct, &rte_waypts, &dst, src);
  370. }
  371. void
  372. track_append(queue* src)
  373. {
  374. queue* dst = &my_track_head;
  375. route_copy(&trk_head_ct, &trk_waypts, &dst, src);
  376. }
  377. void
  378. route_backup(signed int* count, queue** head_bak)
  379. {
  380. route_copy(count, NULL, head_bak, &my_route_head);
  381. }
  382. static void
  383. route_restore_hdr(const route_head* rte)
  384. {
  385. (void)rte;
  386. rte_head_ct++;
  387. }
  388. static void
  389. track_restore_hdr(const route_head* trk)
  390. {
  391. (void)trk;
  392. trk_head_ct++;
  393. }
  394. static void
  395. route_restore_tlr(const route_head* rte)
  396. {
  397. (void)rte;
  398. }
  399. static void
  400. route_restore_wpt(const Waypoint* wpt)
  401. {
  402. (void)wpt;
  403. rte_waypts++;
  404. }
  405. static void
  406. track_restore_wpt(const Waypoint* wpt)
  407. {
  408. (void)wpt;
  409. trk_waypts++;
  410. }
  411. static void
  412. common_restore_finish(void)
  413. {
  414. rte_head_ct = 0;
  415. trk_head_ct = 0;
  416. rte_waypts = 0;
  417. trk_waypts = 0;
  418. route_disp_all(route_restore_hdr, route_restore_tlr, route_restore_wpt);
  419. track_disp_all(track_restore_hdr, route_restore_tlr, track_restore_wpt);
  420. }
  421. void
  422. route_restore(queue* head_bak)
  423. {
  424. if (head_bak == NULL) {
  425. return;
  426. }
  427. route_flush_q(&my_route_head);
  428. QUEUE_INIT(&my_route_head);
  429. QUEUE_MOVE(&my_route_head, head_bak);
  430. common_restore_finish();
  431. }
  432. void
  433. track_backup(signed int* count, queue** head_bak)
  434. {
  435. route_copy(count, NULL, head_bak, &my_track_head);
  436. }
  437. void
  438. track_restore(queue* head_bak)
  439. {
  440. if (head_bak == NULL) {
  441. return;
  442. }
  443. route_flush_q(&my_track_head);
  444. QUEUE_INIT(&my_track_head);
  445. QUEUE_MOVE(&my_track_head, head_bak);
  446. common_restore_finish();
  447. }
  448. /*
  449. * Move the entire track queue onto the route queue making no attempt
  450. * at all to "fix" anything in the process.
  451. */
  452. void
  453. routes_to_tracks(void)
  454. {
  455. queue* elem, *tmp;
  456. QUEUE_FOR_EACH(&my_route_head, elem, tmp) {
  457. route_head* trk = (route_head*) elem;
  458. dequeue(&trk->Q);
  459. ENQUEUE_TAIL(&my_track_head, &trk->Q);
  460. }
  461. }
  462. /*
  463. * Same, but in opposite direction.
  464. */
  465. void
  466. tracks_to_routes(void)
  467. {
  468. queue* elem, *tmp;
  469. QUEUE_FOR_EACH(&my_track_head, elem, tmp) {
  470. route_head* trk = (route_head*) elem;
  471. dequeue(&trk->Q);
  472. ENQUEUE_TAIL(&my_route_head, &trk->Q);
  473. }
  474. }
  475. /*
  476. * This really makes more sense for tracks than routes.
  477. * Run over all the trackpoints, computing heading (course), speed, and
  478. * and so on.
  479. *
  480. * If trkdatap is non-null upon entry, a pointer to an allocated collection
  481. * (hopefully interesting) statistics about the track will be placed there.
  482. */
  483. void track_recompute(const route_head* trk, computed_trkdata** trkdatap)
  484. {
  485. Waypoint first;
  486. Waypoint* thisw;
  487. Waypoint* prev = &first;
  488. queue* elem, *tmp;
  489. int tkpt = 0;
  490. int pts_hrt = 0;
  491. double tot_hrt = 0.0;
  492. int pts_cad = 0;
  493. double tot_cad = 0.0;
  494. computed_trkdata* tdata = (computed_trkdata*)xcalloc(1, sizeof(computed_trkdata));
  495. if (trkdatap) {
  496. *trkdatap = tdata;
  497. }
  498. // first.latitude = 0;
  499. // first.longitude = 0;
  500. // first.creation_time = 0;
  501. tdata->min_hrt = 9999;
  502. tdata->min_alt = -unknown_alt;
  503. tdata->max_alt = unknown_alt;
  504. QUEUE_FOR_EACH((queue*)&trk->waypoint_list, elem, tmp) {
  505. double tlat, tlon, plat, plon, dist;
  506. thisw = (Waypoint*)elem;
  507. /*
  508. * gcdist and heading want radians, not degrees.
  509. */
  510. tlat = RAD(thisw->latitude);
  511. tlon = RAD(thisw->longitude);
  512. plat = RAD(prev->latitude);
  513. plon = RAD(prev->longitude);
  514. WAYPT_SET(thisw, course, heading_true_degrees(plat, plon,
  515. tlat, tlon));
  516. dist = radtometers(gcdist(plat, plon, tlat, tlon));
  517. /*
  518. * Avoid that 6300 mile jump as we move from 0,0.
  519. */
  520. if (plat && plon) {
  521. tdata->distance_meters += dist;
  522. }
  523. /*
  524. * If we've moved as much as a meter,
  525. * conditionally recompute speeds.
  526. */
  527. if (!WAYPT_HAS(thisw, speed) && (dist > 1)) {
  528. // Only recompute speed if the waypoint
  529. // didn't already have a speed
  530. if (thisw->GetCreationTime().isValid() &&
  531. prev->GetCreationTime().isValid() &&
  532. thisw->GetCreationTime() > prev->GetCreationTime()) {
  533. double timed =
  534. prev->GetCreationTime().msecsTo(thisw->GetCreationTime()) / 1000.0;
  535. WAYPT_SET(thisw, speed, dist / timed);
  536. }
  537. }
  538. if (WAYPT_HAS(thisw, speed)) {
  539. if (thisw->speed > tdata->max_spd) {
  540. tdata->max_spd = thisw->speed;
  541. }
  542. if (thisw->speed < tdata->min_spd) {
  543. tdata->min_spd = thisw->speed;
  544. }
  545. }
  546. if (thisw->altitude != unknown_alt) {
  547. if (thisw->altitude < tdata->min_alt) {
  548. tdata->min_alt = thisw->altitude;
  549. }
  550. if (thisw->altitude > tdata->max_alt) {
  551. tdata->max_alt = thisw->altitude;
  552. }
  553. }
  554. if (thisw->heartrate > 0) {
  555. pts_hrt++;
  556. tot_hrt += (float) thisw->heartrate;
  557. }
  558. if ((thisw->heartrate > 0) && (thisw->heartrate < tdata->min_hrt)) {
  559. tdata->min_hrt = (int) thisw->heartrate;
  560. }
  561. if ((thisw->heartrate > 0) && (thisw->heartrate > tdata->max_hrt)) {
  562. tdata->max_hrt = (int) thisw->heartrate;
  563. }
  564. if (thisw->cadence > 0) {
  565. pts_cad++;
  566. tot_cad += (float) thisw->cadence;
  567. }
  568. if ((thisw->cadence > 0) && (thisw->cadence > tdata->max_cad)) {
  569. tdata->max_cad = (int) thisw->cadence;
  570. }
  571. if (thisw->GetCreationTime().isValid() && (thisw->GetCreationTime().toTime_t() < tdata->start)) {
  572. tdata->start = thisw->GetCreationTime().toTime_t();
  573. }
  574. if (thisw->creation_time.toTime_t() > tdata->end) {
  575. tdata->end = thisw->GetCreationTime().toTime_t();
  576. if (tdata->start == 0) {
  577. tdata->start = tdata->end;
  578. }
  579. }
  580. prev = thisw;
  581. if (thisw->shortname.isEmpty()) {
  582. thisw->shortname = QString("%1-%2").arg(trk->rte_name).arg(tkpt);
  583. }
  584. tkpt++;
  585. }
  586. if (pts_hrt > 0) {
  587. tdata->avg_hrt = tot_hrt / (float) pts_hrt;
  588. }
  589. if (pts_cad > 0) {
  590. tdata->avg_cad = tot_cad / (float) pts_cad;
  591. }
  592. if (!trkdatap) {
  593. xfree(tdata);
  594. }
  595. }
  596. route_head::route_head() :
  597. rte_num(0),
  598. rte_waypt_ct(0),
  599. fs(NULL),
  600. cet_converted(0),
  601. // line_color(),
  602. line_width(-1),
  603. session(curr_session())
  604. {
  605. QUEUE_INIT(&Q);
  606. QUEUE_INIT(&waypoint_list);
  607. };
  608. route_head::~route_head()
  609. {
  610. waypt_flush(&waypoint_list);
  611. if (fs) {
  612. fs_chain_destroy(fs);
  613. }
  614. }