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