]> git.street.me.uk Git - andy/viking.git/blame - src/viktrack.c
Refactoring: compute drawmode name by getting menu entry label
[andy/viking.git] / src / viktrack.c
CommitLineData
50a14534
EB
1/*
2 * viking -- GPS Data and Topo Analyzer, Explorer, and Manager
3 *
4 * Copyright (C) 2003-2005, Evan Battaglia <gtoevan@gmx.net>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <glib.h>
23#include <time.h>
9903c388 24#include <stdio.h>
bf35388d 25#include <stdlib.h>
ddc47a46 26#include <string.h>
bf35388d 27#include <math.h>
50a14534
EB
28#include "coords.h"
29#include "vikcoord.h"
30#include "viktrack.h"
31#include "globals.h"
ad0a8c2d 32#include "dems.h"
50a14534
EB
33
34VikTrack *vik_track_new()
35{
8c4f1350 36 VikTrack *tr = g_malloc0 ( sizeof ( VikTrack ) );
50a14534
EB
37 tr->ref_count = 1;
38 return tr;
39}
40
41void vik_track_set_comment_no_copy(VikTrack *tr, gchar *comment)
42{
43 if ( tr->comment )
44 g_free ( tr->comment );
45 tr->comment = comment;
46}
47
48
49void vik_track_set_comment(VikTrack *tr, const gchar *comment)
50{
51 if ( tr->comment )
52 g_free ( tr->comment );
53
54 if ( comment && comment[0] != '\0' )
55 tr->comment = g_strdup(comment);
56 else
57 tr->comment = NULL;
58}
59
60void vik_track_ref(VikTrack *tr)
61{
62 tr->ref_count++;
63}
64
65void vik_track_free(VikTrack *tr)
66{
67 if ( tr->ref_count-- > 1 )
68 return;
69
70 if ( tr->comment )
71 g_free ( tr->comment );
72 g_list_foreach ( tr->trackpoints, (GFunc) g_free, NULL );
73 g_list_free( tr->trackpoints );
74 g_free ( tr );
75}
76
77VikTrack *vik_track_copy ( const VikTrack *tr )
78{
79 VikTrack *new_tr = vik_track_new();
80 VikTrackpoint *new_tp;
81 GList *tp_iter = tr->trackpoints;
82 new_tr->visible = tr->visible;
83 new_tr->trackpoints = NULL;
84 while ( tp_iter )
85 {
86 new_tp = g_malloc ( sizeof ( VikTrackpoint ) );
87 *new_tp = *((VikTrackpoint *)(tp_iter->data));
88 new_tr->trackpoints = g_list_append ( new_tr->trackpoints, new_tp );
89 tp_iter = tp_iter->next;
90 }
91 vik_track_set_comment(new_tr,tr->comment);
92 return new_tr;
93}
94
95VikTrackpoint *vik_trackpoint_new()
96{
97 return g_malloc0(sizeof(VikTrackpoint));
98}
99
100void vik_trackpoint_free(VikTrackpoint *tp)
101{
102 g_free(tp);
103}
104
105VikTrackpoint *vik_trackpoint_copy(VikTrackpoint *tp)
106{
107 VikTrackpoint *rv = vik_trackpoint_new();
108 *rv = *tp;
109 return rv;
110}
111
112gdouble vik_track_get_length(const VikTrack *tr)
113{
114 gdouble len = 0.0;
115 if ( tr->trackpoints )
116 {
117 GList *iter = tr->trackpoints->next;
118 while (iter)
119 {
120 if ( ! VIK_TRACKPOINT(iter->data)->newsegment )
121 len += vik_coord_diff ( &(VIK_TRACKPOINT(iter->data)->coord),
122 &(VIK_TRACKPOINT(iter->prev->data)->coord) );
123 iter = iter->next;
124 }
125 }
126 return len;
127}
128
129gdouble vik_track_get_length_including_gaps(const VikTrack *tr)
130{
131 gdouble len = 0.0;
132 if ( tr->trackpoints )
133 {
134 GList *iter = tr->trackpoints->next;
135 while (iter)
136 {
137 len += vik_coord_diff ( &(VIK_TRACKPOINT(iter->data)->coord),
138 &(VIK_TRACKPOINT(iter->prev->data)->coord) );
139 iter = iter->next;
140 }
141 }
142 return len;
143}
144
145gulong vik_track_get_tp_count(const VikTrack *tr)
146{
147 gulong num = 0;
148 GList *iter = tr->trackpoints;
149 while ( iter )
150 {
151 num++;
152 iter = iter->next;
153 }
154 return num;
155}
156
157gulong vik_track_get_dup_point_count ( const VikTrack *tr )
158{
159 gulong num = 0;
160 GList *iter = tr->trackpoints;
161 while ( iter )
162 {
163 if ( iter->next && vik_coord_equals ( &(VIK_TRACKPOINT(iter->data)->coord),
164 &(VIK_TRACKPOINT(iter->next->data)->coord) ) )
165 num++;
166 iter = iter->next;
167 }
168 return num;
169}
170
171void vik_track_remove_dup_points ( VikTrack *tr )
172{
173 GList *iter = tr->trackpoints;
174 while ( iter )
175 {
176 if ( iter->next && vik_coord_equals ( &(VIK_TRACKPOINT(iter->data)->coord),
177 &(VIK_TRACKPOINT(iter->next->data)->coord) ) )
178 {
179 g_free ( iter->next->data );
180 tr->trackpoints = g_list_delete_link ( tr->trackpoints, iter->next );
181 }
182 else
183 iter = iter->next;
184 }
185}
186
187guint vik_track_get_segment_count(const VikTrack *tr)
188{
189 guint num = 1;
190 GList *iter = tr->trackpoints;
191 if ( !iter )
192 return 0;
193 while ( (iter = iter->next) )
194 {
195 if ( VIK_TRACKPOINT(iter->data)->newsegment )
196 num++;
197 }
198 return num;
199}
200
201VikTrack **vik_track_split_into_segments(VikTrack *t, guint *ret_len)
202{
203 VikTrack **rv;
204 VikTrack *tr;
205 guint i;
206 guint segs = vik_track_get_segment_count(t);
207 GList *iter;
208
209 if ( segs < 2 )
210 {
211 *ret_len = 0;
212 return NULL;
213 }
214
215 rv = g_malloc ( segs * sizeof(VikTrack *) );
216 tr = vik_track_copy ( t );
217 rv[0] = tr;
218 iter = tr->trackpoints;
219
220 i = 1;
221 while ( (iter = iter->next) )
222 {
223 if ( VIK_TRACKPOINT(iter->data)->newsegment )
224 {
225 iter->prev->next = NULL;
226 iter->prev = NULL;
227 rv[i] = vik_track_new();
228 if ( tr->comment )
229 vik_track_set_comment ( rv[i], tr->comment );
230 rv[i]->visible = tr->visible;
231 rv[i]->trackpoints = iter;
232 i++;
233 }
234 }
235 *ret_len = segs;
236 return rv;
237}
238
239void vik_track_reverse ( VikTrack *tr )
240{
241 GList *iter;
242 tr->trackpoints = g_list_reverse(tr->trackpoints);
243
244 /* fix 'newsegment' */
245 iter = g_list_last ( tr->trackpoints );
246 while ( iter )
247 {
248 if ( ! iter->next ) /* last segment, was first, cancel newsegment. */
249 VIK_TRACKPOINT(iter->data)->newsegment = FALSE;
250 if ( ! iter->prev ) /* first segment by convention has newsegment flag. */
251 VIK_TRACKPOINT(iter->data)->newsegment = TRUE;
252 else if ( VIK_TRACKPOINT(iter->data)->newsegment && iter->next )
253 {
254 VIK_TRACKPOINT(iter->next->data)->newsegment = TRUE;
255 VIK_TRACKPOINT(iter->data)->newsegment = FALSE;
256 }
257 iter = iter->prev;
258 }
259}
260
261gdouble vik_track_get_average_speed(const VikTrack *tr)
262{
263 gdouble len = 0.0;
264 guint32 time = 0;
265 if ( tr->trackpoints )
266 {
267 GList *iter = tr->trackpoints->next;
268 while (iter)
269 {
270 if ( VIK_TRACKPOINT(iter->data)->has_timestamp &&
271 VIK_TRACKPOINT(iter->prev->data)->has_timestamp &&
272 (! VIK_TRACKPOINT(iter->data)->newsegment) )
273 {
274 len += vik_coord_diff ( &(VIK_TRACKPOINT(iter->data)->coord),
275 &(VIK_TRACKPOINT(iter->prev->data)->coord) );
276 time += ABS(VIK_TRACKPOINT(iter->data)->timestamp - VIK_TRACKPOINT(iter->prev->data)->timestamp);
277 }
278 iter = iter->next;
279 }
280 }
281 return (time == 0) ? 0 : ABS(len/time);
282}
283
284gdouble vik_track_get_max_speed(const VikTrack *tr)
285{
286 gdouble maxspeed = 0.0, speed = 0.0;
287 if ( tr->trackpoints )
288 {
289 GList *iter = tr->trackpoints->next;
290 while (iter)
291 {
292 if ( VIK_TRACKPOINT(iter->data)->has_timestamp &&
293 VIK_TRACKPOINT(iter->prev->data)->has_timestamp &&
294 (! VIK_TRACKPOINT(iter->data)->newsegment) )
295 {
296 speed = vik_coord_diff ( &(VIK_TRACKPOINT(iter->data)->coord), &(VIK_TRACKPOINT(iter->prev->data)->coord) )
297 / ABS(VIK_TRACKPOINT(iter->data)->timestamp - VIK_TRACKPOINT(iter->prev->data)->timestamp);
298 if ( speed > maxspeed )
299 maxspeed = speed;
300 }
301 iter = iter->next;
302 }
303 }
304 return maxspeed;
305}
306
307void vik_track_convert ( VikTrack *tr, VikCoordMode dest_mode )
308{
309 GList *iter = tr->trackpoints;
310 while (iter)
311 {
312 vik_coord_convert ( &(VIK_TRACKPOINT(iter->data)->coord), dest_mode );
313 iter = iter->next;
314 }
315}
316
317/* I understood this when I wrote it ... maybe ... Basically it eats up the
318 * proper amounts of length on the track and averages elevation over that. */
319gdouble *vik_track_make_elevation_map ( const VikTrack *tr, guint16 num_chunks )
320{
321 gdouble *pts;
322 gdouble total_length, chunk_length, current_dist, current_area_under_curve, current_seg_length, dist_along_seg = 0.0;
323 gdouble altitude1, altitude2;
324 guint16 current_chunk;
325 gboolean ignore_it = FALSE;
326
327 GList *iter = tr->trackpoints;
328
4b31042b
QT
329 if (!iter->next) /* one-point track */
330 return NULL;
331
c79f0206
EB
332 { /* test if there's anything worth calculating */
333 gboolean okay = FALSE;
334 while ( iter )
335 {
336 if ( VIK_TRACKPOINT(iter->data)->altitude != VIK_DEFAULT_ALTITUDE ) {
337 okay = TRUE; break;
338 }
339 iter = iter->next;
340 }
341 if ( ! okay )
342 return NULL;
343 }
344
345
346
50a14534
EB
347 g_assert ( num_chunks < 16000 );
348
349 pts = g_malloc ( sizeof(gdouble) * num_chunks );
350
351 total_length = vik_track_get_length_including_gaps ( tr );
352 chunk_length = total_length / num_chunks;
353
354 current_dist = 0.0;
355 current_area_under_curve = 0;
356 current_chunk = 0;
357 current_seg_length = 0;
358
359 current_seg_length = vik_coord_diff ( &(VIK_TRACKPOINT(iter->data)->coord),
360 &(VIK_TRACKPOINT(iter->next->data)->coord) );
361 altitude1 = VIK_TRACKPOINT(iter->data)->altitude;
362 altitude2 = VIK_TRACKPOINT(iter->next->data)->altitude;
363 dist_along_seg = 0;
364
365 while ( current_chunk < num_chunks ) {
366
367 /* go along current seg */
368 if ( current_seg_length && (current_seg_length - dist_along_seg) > chunk_length ) {
369 dist_along_seg += chunk_length;
370
371 /* /
372 * pt2 *
373 * /x altitude = alt_at_pt_1 + alt_at_pt_2 / 2 = altitude1 + slope * dist_value_of_pt_inbetween_pt1_and_pt2
374 * /xx avg altitude = area under curve / chunk len
375 *pt1 *xxx avg altitude = altitude1 + (altitude2-altitude1)/(current_seg_length)*(dist_along_seg + (chunk_len/2))
376 * / xxx
377 * / xxx
378 **/
379
380 if ( ignore_it )
381 pts[current_chunk] = VIK_DEFAULT_ALTITUDE;
382 else
9903c388 383 pts[current_chunk] = altitude1 + (altitude2-altitude1)*((dist_along_seg - (chunk_length/2))/current_seg_length);
50a14534
EB
384
385 current_chunk++;
386 } else {
387 /* finish current seg */
388 if ( current_seg_length ) {
389 gdouble altitude_at_dist_along_seg = altitude1 + (altitude2-altitude1)/(current_seg_length)*dist_along_seg;
390 current_dist = current_seg_length - dist_along_seg;
391 current_area_under_curve = current_dist*(altitude_at_dist_along_seg + altitude2)*0.5;
392 } else { current_dist = current_area_under_curve = 0; } /* should only happen if first current_seg_length == 0 */
393
394 /* get intervening segs */
395 iter = iter->next;
396 while ( iter && iter->next ) {
397 current_seg_length = vik_coord_diff ( &(VIK_TRACKPOINT(iter->data)->coord),
398 &(VIK_TRACKPOINT(iter->next->data)->coord) );
399 altitude1 = VIK_TRACKPOINT(iter->data)->altitude;
400 altitude2 = VIK_TRACKPOINT(iter->next->data)->altitude;
401 ignore_it = VIK_TRACKPOINT(iter->next->data)->newsegment;
402
403 if ( chunk_length - current_dist >= current_seg_length ) {
404 current_dist += current_seg_length;
405 current_area_under_curve += current_seg_length * (altitude1+altitude2) * 0.5;
406 iter = iter->next;
407 } else {
408 break;
409 }
410 }
411
412 /* final seg */
413 dist_along_seg = chunk_length - current_dist;
9903c388 414 if ( ignore_it || !iter->next ) {
50a14534 415 pts[current_chunk] = current_area_under_curve / current_dist;
9903c388 416 }
50a14534
EB
417 else {
418 current_area_under_curve += dist_along_seg * (altitude1 + (altitude2 - altitude1)*dist_along_seg/current_seg_length);
419 pts[current_chunk] = current_area_under_curve / chunk_length;
420 }
421
422 current_dist = 0;
423 current_chunk++;
424 }
425 }
426
427 return pts;
428}
429
430
431void vik_track_get_total_elevation_gain(const VikTrack *tr, gdouble *up, gdouble *down)
432{
433 gdouble diff;
434 *up = *down = 0;
8c4f1350 435 if ( tr->trackpoints && VIK_TRACKPOINT(tr->trackpoints->data)->altitude != VIK_DEFAULT_ALTITUDE )
50a14534
EB
436 {
437 GList *iter = tr->trackpoints->next;
438 while (iter)
439 {
440 diff = VIK_TRACKPOINT(iter->data)->altitude - VIK_TRACKPOINT(iter->prev->data)->altitude;
441 if ( diff > 0 )
442 *up += diff;
443 else
444 *down -= diff;
445 iter = iter->next;
446 }
bf35388d
EB
447 } else
448 *up = *down = VIK_DEFAULT_ALTITUDE;
449}
450
451typedef struct {
452 double a, b, c, d;
453} spline_coeff_t;
454
455void compute_spline(int n, double *x, double *f, spline_coeff_t *p)
456{
457 double *h, *alpha, *B, *m;
458 int i;
ef4c2671
AF
459 int orig_n = n;
460 double new_x[3], new_f[3];
461
462 if (n==0) return;
463 if (n==1) {
464 new_x[0] = x[0];
465 new_f[0] = f[0];
466 new_x[1] = x[0]+0.00001;
467 new_f[1] = f[0];
468 x = new_x;
469 f = new_f;
470 n = 3;
471 }
472 if (n==2) {
473 new_x[0] = x[0];
474 new_f[0] = f[0];
475 new_x[1] = x[1];
476 new_f[1] = f[1];
477 new_x[2] = x[1] + x[1]-x[0];
478 new_f[2] = f[1] + f[1]-f[0];
479 x = new_x;
480 f = new_f;
481 n = 3;
482 }
bf35388d
EB
483
484 /* we're solving a linear system of equations of the form Ax = B.
485 * The matrix a is tridiagonal and consists of coefficients in
486 * the h[] and alpha[] arrays.
487 */
488
489 h = (double *)malloc(sizeof(double) * (n-1));
490 for (i=0; i<n-1; i++) {
491 h[i] = x[i+1]-x[i];
492 }
493
494 alpha = (double *)malloc(sizeof(double) * (n-2));
495 for (i=0; i<n-2; i++) {
496 alpha[i] = 2 * (h[i] + h[i+1]);
50a14534 497 }
bf35388d
EB
498
499 /* B[] is the vector on the right hand side of the equation */
500 B = (double *)malloc(sizeof(double) * (n-2));
501 for (i=0; i<n-2; i++) {
502 B[i] = 6 * ((f[i+2] - f[i+1])/h[i+1] - (f[i+1] - f[i])/h[i]);
503 }
504
505 /* Now solve the n-2 by n-2 system */
506 m = (double *)malloc(sizeof(double) * (n-2));
507 for (i=1; i<=n-3; i++) {
508 /*
509 d0 = alpha 0
510 a0 = h1
511 c0 = h1
512
513 di = di - (ai-1 / di-1) * ci-1
514 bi = bi - (ai-1 / di-1) * bi-1
515 ;
516 */
517 alpha[i] = alpha[i] - (h[i]/alpha[i-1]) * h[i];
518 B[i] = B[i] - (h[i]/alpha[i-1]) * B[i-1];
519 }
520 /* xn-3 = bn-3 / dn-3; */
521 m[n-3] = B[n-3]/alpha[n-3];
522 for (i=n-4; i>=0; i--) {
523 m[i] = (B[i]-h[i+1]*m[i+1])/alpha[i];
524 }
525
ef4c2671 526 for (i=0; i<orig_n-1; i++) {
bf35388d
EB
527 double mi, mi1;
528 mi = (i==(n-2)) ? 0 : m[i];
529 mi1 = (i==0) ? 0 : m[i-1];
530
531 p[i].a = f[i+1];
532 p[i].b = (f[i+1] - f[i]) / h[i] + h[i] * (2*mi + mi1) / 6;
533 p[i].c = mi/2;
534 p[i].d = (mi-mi1)/(6*h[i]);
535 }
536
537 free(alpha);
538 free(B);
539 free(h);
540 free(m);
50a14534 541}
25e44eac 542
bf35388d 543/* by Alex Foobarian */
25e44eac
AF
544gdouble *vik_track_make_speed_map ( const VikTrack *tr, guint16 num_chunks )
545{
bf35388d
EB
546 gdouble *v, *s, *t;
547 gdouble duration, chunk_dur, T, s_prev, s_now;
25e44eac 548 time_t t1, t2;
bf35388d
EB
549 int i, pt_count, numpts, spline;
550 GList *iter;
551 spline_coeff_t *p;
25e44eac 552
24d5c7e2
EB
553 if ( ! tr->trackpoints )
554 return NULL;
25e44eac 555
24d5c7e2 556 g_assert ( num_chunks < 16000 );
25e44eac 557
68fb2913 558#ifdef XXXXXXXXXXXXXXXXXX
7432fddf
AF
559 iter = tr->trackpoints;
560 while (iter) {
561
562 }
68fb2913 563#endif /*XXXXXXXXXXXXXXXXXX*/
7432fddf 564
25e44eac
AF
565 t1 = VIK_TRACKPOINT(tr->trackpoints->data)->timestamp;
566 t2 = VIK_TRACKPOINT(g_list_last(tr->trackpoints)->data)->timestamp;
567 duration = t2 - t1;
c79f0206
EB
568
569 if ( !t1 || !t2 || !duration )
570 return NULL;
571
25e44eac 572 if (duration < 0) {
7742da66 573 g_warning("negative duration: unsorted trackpoint timestamps?\n");
25e44eac
AF
574 return NULL;
575 }
bf35388d 576 pt_count = vik_track_get_tp_count(tr);
24d5c7e2 577
bf35388d 578 v = g_malloc ( sizeof(gdouble) * num_chunks );
25e44eac 579 chunk_dur = duration / num_chunks;
bf35388d
EB
580
581 s = g_malloc(sizeof(double) * pt_count);
582 t = g_malloc(sizeof(double) * pt_count);
583 p = g_malloc(sizeof(spline_coeff_t) * (pt_count-1));
584
585 iter = tr->trackpoints->next;
586 numpts = 0;
587 s[0] = 0;
588 t[0] = VIK_TRACKPOINT(iter->prev->data)->timestamp;
589 numpts++;
590 while (iter) {
591 s[numpts] = s[numpts-1] + vik_coord_diff ( &(VIK_TRACKPOINT(iter->prev->data)->coord), &(VIK_TRACKPOINT(iter->data)->coord) );
592 t[numpts] = VIK_TRACKPOINT(iter->data)->timestamp;
593 numpts++;
594 iter = iter->next;
25e44eac
AF
595 }
596
bf35388d
EB
597 compute_spline(numpts, t, s, p);
598
bf35388d
EB
599 /* the spline gives us distances at chunk_dur intervals. from these,
600 * we obtain average speed in each interval.
601 */
602 spline = 0;
603 T = t[spline];
604 s_prev =
605 p[spline].d * pow(T - t[spline+1], 3) +
606 p[spline].c * pow(T - t[spline+1], 2) +
607 p[spline].b * (T - t[spline+1]) +
608 p[spline].a;
609 for (i = 0; i < num_chunks; i++, T+=chunk_dur) {
610 while (T > t[spline+1]) {
611 spline++;
612 }
613 s_now =
614 p[spline].d * pow(T - t[spline+1], 3) +
615 p[spline].c * pow(T - t[spline+1], 2) +
616 p[spline].b * (T - t[spline+1]) +
617 p[spline].a;
618 v[i] = (s_now - s_prev) / chunk_dur;
619 s_prev = s_now;
620 /*
621 * old method of averages
622 v[i] = (s[spline+1]-s[spline])/(t[spline+1]-t[spline]);
623 */
624 }
625 g_free(s);
626 g_free(t);
627 g_free(p);
628 return v;
25e44eac 629}
24d5c7e2 630
bf35388d 631/* by Alex Foobarian */
e1e2f2c6 632VikTrackpoint *vik_track_get_closest_tp_by_percentage_dist ( VikTrack *tr, gdouble reldist )
24d5c7e2
EB
633{
634 gdouble dist = vik_track_get_length_including_gaps(tr) * reldist;
635 gdouble current_dist = 0.0;
636 gdouble current_inc = 0.0;
24d5c7e2
EB
637 if ( tr->trackpoints )
638 {
639 GList *iter = tr->trackpoints->next;
ecb51018 640 GList *last_iter = NULL;
24d5c7e2
EB
641 while (iter)
642 {
643 current_inc = vik_coord_diff ( &(VIK_TRACKPOINT(iter->data)->coord),
644 &(VIK_TRACKPOINT(iter->prev->data)->coord) );
645 current_dist += current_inc;
646 if ( current_dist >= dist )
647 break;
ecb51018 648 last_iter = iter;
24d5c7e2
EB
649 iter = iter->next;
650 }
ecb51018
QT
651 if (!iter) /* passing the end the track */
652 return (last_iter ? last_iter->data : NULL);
24d5c7e2
EB
653 /* we've gone past the dist already, was prev trackpoint closer? */
654 /* should do a vik_coord_average_weighted() thingy. */
655 if ( iter->prev && abs(current_dist-current_inc-dist) < abs(current_dist-dist) )
656 iter = iter->prev;
657
e1e2f2c6 658 return VIK_TRACKPOINT(iter->data);
24d5c7e2
EB
659
660 }
661 return NULL;
662}
b42a25ba
EB
663
664gboolean vik_track_get_minmax_alt ( const VikTrack *tr, gdouble *min_alt, gdouble *max_alt )
665{
666 *min_alt = 25000;
667 *max_alt = -5000;
668 if ( tr && tr->trackpoints && tr->trackpoints->data && (VIK_TRACKPOINT(tr->trackpoints->data)->altitude != VIK_DEFAULT_ALTITUDE) ) {
669 GList *iter = tr->trackpoints->next;
670 gdouble tmp_alt;
671 while (iter)
672 {
673 tmp_alt = VIK_TRACKPOINT(iter->data)->altitude;
674 if ( tmp_alt > *max_alt )
675 *max_alt = tmp_alt;
676 if ( tmp_alt < *min_alt )
677 *min_alt = tmp_alt;
678 iter = iter->next;
679 }
680 return TRUE;
681 }
682 return FALSE;
683}
ddc47a46
AF
684
685void vik_track_marshall ( VikTrack *tr, guint8 **data, guint *datalen)
686{
687 GList *tps;
688 GByteArray *b = g_byte_array_new();
689 guint len;
690 guint intp, ntp;
691
692 g_byte_array_append(b, (guint8 *)tr, sizeof(*tr));
693
694 /* we'll fill out number of trackpoints later */
695 intp = b->len;
696 g_byte_array_append(b, (guint8 *)&len, sizeof(len));
697
698 tps = tr->trackpoints;
699 ntp = 0;
700 while (tps) {
701 g_byte_array_append(b, (guint8 *)tps->data, sizeof(VikTrackpoint));
702 tps = tps->next;
703 ntp++;
704 }
705 *(guint *)(b->data + intp) = ntp;
706
707 len = (tr->comment) ? strlen(tr->comment)+1 : 0;
708 g_byte_array_append(b, (guint8 *)&len, sizeof(len));
709 if (tr->comment) g_byte_array_append(b, (guint8 *)tr->comment, len);
710
711 *data = b->data;
712 *datalen = b->len;
713 g_byte_array_free(b, FALSE);
714}
715
716VikTrack *vik_track_unmarshall (guint8 *data, guint datalen)
717{
718 guint len;
719 VikTrack *new_tr = vik_track_new();
720 VikTrackpoint *new_tp;
721 guint ntp;
722 gint i;
723
724 /* only the visibility is needed */
725 new_tr->visible = ((VikTrack *)data)->visible;
726 data += sizeof(*new_tr);
727
728 ntp = *(guint *)data;
729 data += sizeof(ntp);
730
731 for (i=0; i<ntp; i++) {
732 new_tp = vik_trackpoint_new();
733 memcpy(new_tp, data, sizeof(*new_tp));
734 data += sizeof(*new_tp);
735 new_tr->trackpoints = g_list_append(new_tr->trackpoints, new_tp);
736 }
737
738 len = *(guint *)data;
739 data += sizeof(len);
740 if (len) {
741 new_tr->comment = g_strdup((gchar *)data);
742 }
743 return new_tr;
744}
ad0a8c2d 745
55906514 746void vik_track_apply_dem_data ( VikTrack *tr )
ad0a8c2d
EB
747{
748 GList *tp_iter;
749 gint16 elev;
ad0a8c2d
EB
750 tp_iter = tr->trackpoints;
751 while ( tp_iter ) {
752 /* TODO: of the 4 possible choices we have for choosing an elevation
753 * (trackpoint in between samples), choose the one with the least elevation change
754 * as the last */
55906514 755 elev = a_dems_get_elev_by_coord ( &(VIK_TRACKPOINT(tp_iter->data)->coord) );
ad0a8c2d
EB
756 if ( elev != VIK_DEM_INVALID_ELEVATION )
757 VIK_TRACKPOINT(tp_iter->data)->altitude = elev;
758 tp_iter = tp_iter->next;
759 }
760}