\( \def\bold#1{\bf #1} \newcommand{\d}{\mathrm{d}} \) BTP: Manual and Source Code Documentation

Power Uphill

bike mass [kg]
body mass [kg]
altitude gain [m]
climb length [km]
gradient [%]
time [s]
speed [km/h]
power [W]
power/mass [W/kg]
climbrate [m/min]

average power on climb stage

BTP  3.0
Routing/ClimbAnalysis/PowerCalculation
track.cpp
1 #define _USE_MATH_DEFINES
2 #include "Track.h"
3 
4 Track::Track(){
5  tpl = NULL;
6  kl = NULL;
7  kc = 0;
8  tc = 0;
9  d_h_array = NULL;
10  KOOpool = NULL;
11  keep_lists = 0;
12 }
13 Track::Track(double** KOOarray, int count){
14  KOOa = NULL;
15  KOOpool = NULL;
16  kl = new KOOlist[count];
17  for(int i = 0; i < count; i++)
18  kl[i].k = add_to_KOOpool(KOOarray[0][i],KOOarray[1][i]);
19  kl[0].d = 0;
20  for(int i = 1; i < count; i++)
21  kl[i].d = distance(KOOarray[0][i],KOOarray[1][i],
22  KOOarray[0][i-1],KOOarray[1][i-1])
23  + kl[i-1].d;
24 
25  tc = 0;
26  kc = count;
27  keep_lists = 0;
28  d_h_array = NULL;
29  tpl = NULL;
30 }
31 Track::Track(trackpoint* tpl,int tc, KOOlist* kl, int kc){
32  this->tc = this->kc = 0;
33  this->tpl = NULL;
34  this->kl = NULL;
35  add(tpl,tc,kl,kc);
36  d_h_array = NULL;
37  KOOa = NULL;
38  KOOpool = NULL;
39  keep_lists = 1;
40  reset_markers();
41 }
42 Track::Track(double *d,double *h,double *lat,double *lon,int count){
43  kl = new KOOlist[count];
44  kc = count;
45  tpl = new trackpoint[count];
46  tc = count;
47  for(int i = 0; i < count; i++){
48  kl[i].k->lat = lat[i];
49  kl[i].k->lon = lon[i];
50  kl[i].tpi = i;
51  kl[i].d = d[i];
52  tpl[i].d = d[i];
53  tpl[i].h = h[i];
54  }
55  KOOa = NULL;
56  d_h_array = NULL;
57  KOOpool = NULL;
58  keep_lists = 0;
59 }
60 
61 Track::Track(Neighbour** narray, int nc){
62  /*calc list lengths*/
63  tc = kc = 1;
64  for(int i = 0; i < nc; i++){
65  kc += narray[i]->nodec -1;
66  tc += narray[i]->tpc -1;
67  }
68 
69  tpl = new trackpoint[tc];
70  kl = new KOOlist[kc];
71  /*Listen initialisieren*/
72  if(narray[0]->rd == fw){
73  tpl[0] = narray[0]->tp[0];
74  kl[0].k = narray[0]->node[0];
75  }
76  else{
77  tpl[0] = narray[0]->tp[narray[0]->tpc-1];
78  tpl[0].d = 0;
79  kl[0].k = narray[0]->node[narray[0]->nodec-1];
80  }
81 
82  int cik = 0, cit = 0;
83  kl[0].d = 0;
84  kl[0].tpi = 0;
85  float d0 = 0;
86  /*Rekonstruktion starten*/
87  for(int i = 0; i < nc; i++){
88  if(narray[i]->rd == fw){
89  d0 = kl[cik].d;
90  for(int j = 1; j < narray[i]->nodec; j++){
91  kl[cik+j].k = narray[i]->node[j];
92  kl[cik+j].d = kl[cik+j-1].d
93  + distance(kl[cik+j ].k->lat,kl[cik+j ].k->lon,
94  kl[cik+j-1].k->lat,kl[cik+j-1].k->lon);
95  kl[cik+j].tpi = -1;;
96  }
97  for(int j = 1; j < narray[i]->tpc; j++){
98  tpl[cit+j].h = narray[i]->tp[j].h;
99  tpl[cit+j].d = narray[i]->tp[j].d + d0;
100  }
101  cik += narray[i]->nodec-1;
102  cit += narray[i]->tpc-1;
103  }
104  else{
105  d0 = kl[cik].d + narray[i]->tp[narray[i]->tpc-1].d;
106  cik += narray[i]->nodec-1;
107  cit += narray[i]->tpc-1;
108  for(int j = narray[i]->nodec-2; j >= 0; j--){
109  kl[cik-j].k = narray[i]->node[j];
110  kl[cik-j].d = kl[cik-j-1].d
111  + distance(kl[cik-j ].k->lat,kl[cik-j ].k->lon,
112  kl[cik-j-1].k->lat,kl[cik-j-1].k->lon);
113  kl[cik-j].tpi = -1;
114  }
115  for(int j = narray[i]->tpc-2; j >= 0; j--){
116  tpl[cit-j].h = narray[i]->tp[j].h;
117  tpl[cit-j].d = d0 - narray[i]->tp[j].d;
118  }
119  }
120  kl[cik].tpi = cit;
121  kl[cik].d = tpl[cit].d;
122  }
123  d_h_array = NULL;
124  KOOa = NULL;
125  KOOpool = NULL;
126  keep_lists = 1;
127  reset_markers();
128 }
129 Track::Track(Track* tracktocopy){
130  tpl = NULL;
131  kl = NULL;
132  tc = kc = 0;
133  KOOa = NULL;
134  d_h_array = NULL;
135  KOOpool = NULL;
136  keep_lists = 0;
137  if(tracktocopy != NULL)
138  add(tracktocopy);
139 }
140 Track::~Track(){
141  if(d_h_array != NULL){
142  delete d_h_array[1];
143  delete d_h_array[0];
144  delete d_h_array;
145  }
146  free_KOOpool(KOOpool);
147  if(!keep_lists)
148  delete_complete();
149 }
150 void Track::add(trackpoint* tpl,int tc, KOOlist* kl, int kc){
151  /*an KOOlist anhaengen*/
152  if(this->kl == NULL){
153  this->kl = new KOOlist[kc];
154  memcpy(&(this->kl[0]),kl,kc*sizeof(KOOlist));
155  this->kc = kc;
156  }
157  else{
158  int newkc = this->kc + kc -1;
159  KOOlist* newkl = new KOOlist[newkc];
160  memcpy(&(newkl[0]),this->kl,this->kc*sizeof(KOOlist));
161  memcpy(&(newkl[this->kc]),&(kl[1]),(kc-1)*sizeof(KOOlist));
162  for(int i = 0; i < kc-1; i++){
163  newkl[i+this->kc].d += this->kl[this->kc-1].d;
164  if(newkl[i+this->kc].tpi >= 0)
165  newkl[i+this->kc].tpi += this->tc - 1;
166  }
167  delete this->kl;
168  this->kl = newkl;
169  this->kc = newkc;
170  }
171  /*an Trackpoointlist anhaengen*/
172  if(this->tpl == NULL){
173  this->tpl = new trackpoint[tc];
174  memcpy(&(this->tpl[0]),tpl,tc*sizeof(trackpoint));
175  this->tc = tc;
176  }
177  else{
178  int newtc = this->tc + tc -1;
179  trackpoint* newtpl = new trackpoint[newtc];
180  memcpy(&(newtpl[0]),this->tpl,this->tc*sizeof(trackpoint));
181  memcpy(&(newtpl[this->tc]),&(tpl[1]),(tc-1)*sizeof(trackpoint));
182  for(int i = 0; i < tc-1; i++)
183  newtpl[this->tc+i].d += this->tpl[this->tc-1].d;
184  delete this->tpl;
185  this->tpl = newtpl;
186  this->tc = newtc;
187  }
188 }
189 void Track::get_data_ref(trackpoint** tpl,int* tc, KOOlist** kl, int* kc){
190  if(tpl != NULL) *tpl = this->tpl;
191  if(tc != NULL) *tc = this->tc;
192  if(kl != NULL) *kl = this->kl;
193  if(kc != NULL) *kc = this->kc;
194 }
195 void Track::add(Track* t2){
196  if(t2 != NULL && t2->notNULL()){
197  int atc,akc;
198  KOOlist* akl;
199  trackpoint* atpl;
200  t2->get_data_ref(&atpl,&atc,&akl,&akc);
201  add(atpl,atc,akl,akc);
202  }
203 }
206  return d_h_array;
207 }
210  double** result = d_h_array;
211  d_h_array = NULL;
212  return result;
213 }
214 
215 double** Track::get_KOOa(){
216  refresh_KOOa();
217  return KOOa;
218 }
220  refresh_KOOa();
221  double** result = KOOa;
222  KOOa = NULL;
223  return result;
224 }
226  if(tpl != NULL){
227  /*Alte Daten löschen*/
228  if(d_h_array != NULL){
229  delete d_h_array[0];
230  delete d_h_array[1];
231  delete d_h_array;
232  }
233  /*Neues Array erzeugen*/
234  d_h_array = new double*[2];
235  d_h_array[0] = new double[tc];
236  d_h_array[1] = new double[tc];
237  for(long int j = 0; j < tc; j++){
238  d_h_array[0][j] = tpl[j].d;
239  d_h_array[1][j] = tpl[j].h;
240  }
241  }
242  else
243  d_h_array = NULL;
244 }
246  if(kl != NULL){
247  /*Alte Daten löschen*/
248  if(KOOa != NULL){
249  delete KOOa[0];
250  delete KOOa[1];
251  delete KOOa;
252  }
253 
254  /*Neues Array erzeugen*/
255  KOOa = new double*[2];
256  KOOa[0] = new double[kc];
257  KOOa[1] = new double[kc];
258  for(long int j = 0; j < kc; j++){
259  KOOa[0][j] = kl[j].k->lat;
260  KOOa[1][j] = kl[j].k->lon;
261  }
262  }
263  else
264  KOOa = NULL;
265 
266 }
267 long int Track::get_array_length(){
268  return tc;
269 }
270 long int Track::get_KOOa_length(){
271  return kc;
272 }
274  if(tpl != NULL){
275  float result = 0;
276  for(int i = 1; i < tc; i++)
277  if(tpl[i].h - tpl[i-1].h > 0)
278  result += tpl[i].h - tpl[i-1].h;
279  return result;
280  }
281  else
282  return 0;
283 }
284 float Track::get_height_meters(float dmin, float dmax){
285  if(tpl != NULL){
286  int ll = 0, lr = tc-1;
287  while(ll+1 < lr && tpl[ll].d != tpl[lr].d){
288  if(tpl[(ll+lr)/2].d > dmin)
289  lr = (ll+lr)/2;
290  else
291  ll = (ll+lr)/2;
292  }
293  int rl = 0, rr = tc-1;
294  while(rl+1 < rr && tpl[rl].d != tpl[rr].d){
295  if(tpl[(rl+rr)/2].d > dmax)
296  rr = (rl+rr)/2;
297  else
298  rl = (rl+rr)/2;
299  }
300 
301  if(tpl[ll].d == tpl[lr].d || tpl[rl].d == tpl[rr].d)
302  return 0.;
303  else{
304  float result = 0;
305  for(int i = ll; i < rr; i++)
306  if(tpl[i+1].h - tpl[i].h > 0)
307  result += tpl[i+1].h - tpl[i].h;
308  if(tpl[lr].h > tpl[ll].h)
309  result -= (tpl[lr].h - tpl[ll].h)
310  * (dmin-tpl[ll].d)/(tpl[lr].d-tpl[ll].d);
311  if(tpl[rr].h > tpl[rl].h)
312  result -= (tpl[rr].h - tpl[rl].h)
313  * (tpl[rr].d-dmax)/(tpl[rr].d-tpl[rl].d);
314  return result;
315  }
316  }
317  else
318  return 0.;
319 }
321  if(kl != NULL)
322  return kl[kc-1].d;
323  else
324  return 0.;
325 }
326 KOO* Track::get_last_KOO(){
327  if(kl != NULL)
328  return kl[kc-1].k;
329  else
330  return NULL;
331 }
332 KOO* Track::add_to_KOOpool(double lat, double lon){
333  KOO* k;
334  if(KOOpool == NULL){
335  k = new KOO;
336  KOOpool = k;
337  }
338  else{
339  KOOpool->prev->r = new KOO;
340  k = KOOpool->prev->r;
341  k->prev = KOOpool->prev;
342  }
343  k->lat = lat;
344  k->lon = lon;
345  k->r = NULL;
346  k->l = NULL;
347  k->cd = NULL;
348  KOOpool->prev = k;
349  return k;
350 }
351 void Track::free_KOOpool(KOO* k){
352  if(k != NULL){
353  free_KOOpool(k->l);
354  free_KOOpool(k->r);
355  delete k;
356  }
357 }
358 short Track::extract_KOO(KOO* k, double d){
359  if(kc > 0){
360  int l = 0, r = kc-1;
361  while(l+1 < r && kl[l].d != kl[r].d){
362  if(kl[(l+r)/2].d > d)
363  r = (l+r)/2;
364  else
365  l = (l+r)/2;
366  }
367  if(kl[l].d == kl[r].d)
368  return 0;
369  else{
370  double dd = kl[r].d-kl[l].d;
371  k->lat = kl[r].k->lat*(d-kl[l].d)/dd + kl[l].k->lat*(kl[r].d-d)/dd;
372  k->lon = kl[r].k->lon*(d-kl[l].d)/dd + kl[l].k->lon*(kl[r].d-d)/dd;
373  return 1;
374  }
375  }
376  else
377  return 0;
378 }
379 short Track::extract_h(double d, double* h){
380  if(tc > 0){
381  int l = 0, r = tc-1;
382  while(l+1 < r && tpl[l].d != tpl[r].d){
383  if(tpl[(l+r)/2].d > d)
384  r = (l+r)/2;
385  else
386  l = (l+r)/2;
387  }
388 
389  if(tpl[l].d == tpl[r].d)
390  return 0;
391  else{
392  double dd = tpl[l].d-tpl[r].d;
393  *h = tpl[r].h*(tpl[l].d-d)/dd + tpl[l].h*(d-tpl[r].d)/dd;
394  return 1;
395  }
396  }
397  else
398  return 0;
399 }
400 short Track::extract_azimtut(double d, double* azimut){
401  if(kc > 0){
402  int l = 0, r = kc-1;
403  while(l+1 < r && kl[l].d != kl[r].d){
404  if(kl[(l+r)/2].d > d)
405  r = (l+r)/2;
406  else
407  l = (l+r)/2;
408  }
409  if(kl[l].d == kl[r].d)
410  return 0;
411  else{
412  *azimut = atan2((kl[r].k->lon-kl[l].k->lon)
413  *cos((kl[r].k->lat+kl[l].k->lat)/360.*M_PI),
414  kl[r].k->lat-kl[l].k->lat);
415  return 1;
416  }
417  }
418  else
419  return 0;
420 
421 }
422 
423 short Track::next_d(double lat, double lon, double* d){
424  if(kl != NULL){
425  double dmin = distance(lat,lon,kl[0].k->lat,kl[0].k->lon), a,b,c,h;
426  *d = 0;
427  a = dmin;
428  for(int i = 1; i < kc; i++){
429  b = a;
430  a = distance( lat, lon,kl[i].k->lat,kl[i].k->lon);
431  c = kl[i].d - kl[i-1].d;
432  if(a*a + c*c <= b*b){
433  /*Punkt steht hinter kl[i].k*/
434  if(a < dmin){
435  dmin = a;
436  *d = kl[i].d;
437  }
438  }
439  else{
440  if(b*b + c*c <= a*a){
441  /*Punkt steht vor kl[i-1].k*/
442  if(b < dmin){
443  dmin = b;
444  *d = kl[i-1].d;
445  }
446  }
447  else{
448  /*Punkt steht über Strecke*/
449  h = sqrt((4*a*a*b*b-(c*c-a*a-b*b)*(c*c-a*a-b*b))/(4*c*c));
450  if( h < dmin){
451  dmin = h;
452  *d = kl[i-1].d + sqrt(b*b-h*h);
453  }
454  }
455  }
456  }
457  return 1;
458  }
459  else
460  return 0;
461 }
462 void Track::delete_cross(int nr){
463  if(kl != NULL){
464  int c = 0;
465  int ci = kc-1;
466  while(ci >= 0 && (c < nr || kl[ci].k->cd == NULL)){
467  if(kl[ci].k->cd != NULL && kl[ci].tpi >= 0)
468  c++;
469  ci--;
470  }
471  trim_right(ci,kl[ci].tpi);
472  }
473 
474 }
476  short ci = -1;
477 
478  for(int i = kc-1; i >= 0; i--)
479  if(kl[i].k == k){
480  ci = i;
481  i = -1;
482  }
483  if(ci == 0){
484  // Track is totaly lost
485  delete tpl;
486  delete kl;
487  kc = 0;
488  tc = 0;
489  tpl = NULL;
490  kl = NULL;
491  }
492 
493  if(ci > 0){
494  kc = ci + 1;
495  tc = kl[ci].tpi+1;
496  realloc(kl,kc*sizeof(KOOlist));
497  realloc(tpl,tc*sizeof(trackpoint));
498  kl[ci].marked = 1;
499  }
500 }
502  if(kl != NULL){
503  delete kl;
504  kl = NULL;
505  kc = 0;
506  }
507  if(tpl != NULL){
508  delete tpl;
509  tpl = NULL;
510  tc = 0;
511  }
512 }
514  if(kl != NULL)
515  return 1;
516  else
517  return 0;
518 }
519 short Track::near_check(double lat, double lon, double limit){
520  if(kl != NULL){
521  limit = limit*limit;
522  int ci = 0;
523  double lonc = cos(kl[ci].k->lat/180*M_PI)*cos(kl[ci].k->lat/180*M_PI);
524  while(ci < kc
525  &&(kl[ci].k->lat-lat)*(kl[ci].k->lat-lat)
526  +(kl[ci].k->lon-lon)*(kl[ci].k->lon-lon)*lonc >limit
527  )
528  ci++;
529  if(ci < kc)
530  return 1;
531  else
532  return 0;
533  }
534  else
535  return 0;
536 }
537 void Track::trim_right(float d){
538  if(d < kl[kc-1].d && d < tpl[tc-1].d){
539  double h;
540  extract_h(d,&h);
541  KOO* k = add_to_KOOpool(0,0);
542  extract_KOO(k,d);
543  int kci = kc-1;
544  while(kci > 0 && kl[kci].d > d)
545  kci--;
546  kci++;
547  kl[kci].k = k;
548  kl[kci].d = d;
549  kl[kci].marked = 1;
550 
551  int tci = tc-1;
552  while(tci > 0 && tpl[tci].d > d)
553  tci--;
554  tci++;
555  tpl[tci].d = d;
556  tpl[tci].h = h;
557 
558  trim_right(kci,tci);
559  }
560 }
561 void Track::trim_left(float d){
562  if(d > kl[0].d && d > tpl[0].d){
563  double h;
564  extract_h(d,&h);
565  KOO* k = add_to_KOOpool(0,0);
566  extract_KOO(k,d);
567  int kci = 0;
568  while(kci < kc && kl[kci].d < d)
569  kci++;
570  kci--;
571  kl[kci].k = k;
572  kl[kci].d = d;
573  kl[kci].marked = 1;
574 
575 
576  int tci = 0;
577  while(tci < tc && tpl[tci].d < d)
578  tci++;
579  tci--;
580  tpl[tci].d = d;
581  tpl[tci].h = h;
582 
583  trim_left(kci,tci);
584  }
585 }
586 void Track::trim_left(KOO* k){
587  if(k != kl[0].k){
588  int kci = -1;
589  for(int i = 0; i < kc; i++)
590  if(kl[i].k == k){
591  kci = i;
592  i = kc;
593  }
594  int tci = kl[kci].tpi;
595 
596  trim_left(kci,tci);
597  }
598 }
599 void Track::trim_right(KOO* k){
600  if(k != kl[kc-1].k){
601  int kci = -1;
602  for(int i = kc-1; i >= 0; i--)
603  if(kl[i].k == k){
604  kci = i;
605  i = -1;
606  }
607  int tci = kl[kci].tpi;
608  trim_right(kci,tci);
609  }
610 }
611 void Track::trim_left(int kci, int tci){
612  if(kci == kc-1 || tci == tc-1)
613  delete_complete();
614  else{
615  kc -= kci;
616  KOOlist* newkl = new KOOlist[kc];
617  memcpy(&(newkl[0]),&(kl[kci]),kc*sizeof(KOOlist));
618  delete kl;
619  kl = newkl;
620 
621  tc -= tci;
622  trackpoint* newtpl = new trackpoint[tc];
623  memcpy(&(newtpl[0]),&(tpl[tci]),tc*sizeof(trackpoint));
624  delete tpl;
625  tpl = newtpl;
626 
627  for(int i = kc - 1; i >= 0; i--){
628  kl[i].d -= kl[0].d;
629  if(kl[i].tpi >= 0)
630  kl[i].tpi -= tci;
631  }
632 
633  for(int i = tc - 1; i >= 0; i--)
634  tpl[i].d -= tpl[0].d;
635 
636  if(kl[0].k->cd != NULL)
637  kl[0].marked = 1;
638  else
639  kl[0].marked = 0;
640  }
641 }
642 void Track::trim_right(int kci, int tci){
643  if(kci == 0 || tci == 0)
644  delete_complete();
645  else{
646  kc = kci + 1;
647  KOOlist* newkl = new KOOlist[kc];
648  memcpy(&(newkl[0]),kl,kc*sizeof(KOOlist));
649  delete kl;
650  kl = newkl;
651 
652  tc = tci + 1;
653  trackpoint* newtpl = new trackpoint[tc];
654  memcpy(&(newtpl[0]),tpl,tc*sizeof(trackpoint));
655  delete tpl;
656  tpl = newtpl;
657 
658  kl[kc-1].tpi = tci;
659 
660  if(kl[kc-1].k->cd != NULL)
661  kl[kc-1].marked = 1;
662  else
663  kl[kc-1].marked = 0;
664  }
665 
666 }
667 void Track::invert(){
668  if(kl != NULL){
669  KOOlist* newkl = new KOOlist[kc];
670  for(int i = 0; i < kc; i++){
671  newkl[i] = kl[kc-1-i];
672  newkl[i].d = kl[kc-1].d-newkl[i].d;
673  if(newkl[i].tpi >= 0)
674  newkl[i].tpi = tc - 1 - newkl[i].tpi;
675  }
676  delete kl;
677  kl = newkl;
678  trackpoint* newtpl = new trackpoint[tc];
679  for(int i = 0; i < tc; i++){
680  newtpl[i].h = tpl[tc-1-i].h;
681  newtpl[i].d = tpl[tc-1].d - tpl[tc-1-i].d;
682  }
683  delete tpl;
684  tpl = newtpl;
685  }
686 }
687 void Track::adapt_brect(double* latmin, double* latmax,
688  double* lonmin, double* lonmax){
689  if(kl != NULL)
690  for(int i = 0; i < kc; i++){
691  if(kl[i].k->lat > *latmax) *latmax = kl[i].k->lat;
692  if(kl[i].k->lat < *latmin) *latmin = kl[i].k->lat;
693  if(kl[i].k->lon > *lonmax) *lonmax = kl[i].k->lon;
694  if(kl[i].k->lon < *lonmin) *lonmin = kl[i].k->lon;
695  }
696 }
697 void Track::get_brect(double* latmin, double* latmax,
698  double* lonmin, double* lonmax){
699  *latmax = -90;
700  *latmin = 90;
701  *lonmax = -180;
702  *lonmin = 180;
703  adapt_brect(latmin,latmax,lonmin,lonmax);
704 }
705 int Track::owns(KOO* k){
706  for(int i = 0; i < kc; i++)
707  if(kl[i].k == k)
708  return 1;
709  return 0;
710 }
712  if(kl != NULL){
713  for(int i = 0; i < kc; i++)
714  kl[i].marked = 0;
715  kl[0].marked = kl[kc-1].marked = 1;
716  }
717 }
719  if(kl != NULL){
720  int ci = 0;
721  while(kl[ci].k != k && ci < kc)
722  ci++;
723  /*falls gefunden umschalten*/
724  if(ci < kc-1 && ci > 0){
725  if(kl[ci].marked == 0)
726  kl[ci].marked = 1;
727  else
728  kl[ci].marked = 0;
729  return 1;
730  }
731  else
732  return 0;
733  }
734  return 0;
735 }
736 void Track::get_anchors(float d, KOO** kfrom, KOO** kto){
737  *kfrom = NULL;
738  *kto = NULL;
739  if(kl != NULL){
740  if(d <= 0)
741  *kto = kl[0].k;
742  if(d >= kl->prev->d)
743  *kfrom = kl[kc-1].k;
744  if(d > 0 && d < kl[kc-1].d){
745  int ci = 1;
746  while(kl[ci].d < d || kl[ci].marked == 0){
747  if(kl[ci].marked) *kfrom = kl[ci].k;
748  ci++;
749  }
750  *kto = kl[ci].k;
751  }
752  }
753 }
754 short Track::found_anchors(double clickedlat, double clickedlon,
755  float maxd, KOO** kfrom, KOO** kto){
756  /*naechsten Anker raussuchen*/
757  float dmax = maxd;
758  int clicki = -1;
759  for(int i = 0; i < kc; i++)
760  if( kl[i].marked
761  && distance(clickedlat,clickedlon,
762  kl[i].k->lat,kl[i].k->lon) < dmax){
763  /*ein Anker innerhalb der Maximaldistanz dmax wurde gefunden*/
764  clicki = i;
765  dmax = distance(clickedlat,clickedlon,
766  kl[i].k->lat,kl[i].k->lon);
767  }
768 
769  if(clicki >= 0){
770  kl[clicki].marked = 0;
771  /*ein Anker wurde gefunden*/
772  /*suche nachfolgenden Anker*/
773  int ci = clicki;
774  while(ci < kc-1 && !kl[ci].marked)
775  ci++;
776  if(ci != clicki)
777  *kto = kl[ci].k;
778  else
779  *kto = NULL;
780  /*suche vorhergehenden Anker*/
781  ci = clicki;
782  while(ci > 0 && !kl[ci].marked)
783  ci--;
784  if(ci != clicki)
785  *kfrom = kl[ci].k;
786  else
787  *kfrom = NULL;
788  kl[clicki].marked = 1;
789  return 1;
790  }
791  else
792  return 0;
793 }
794 short Track::next_cross(double clickedlat, double clickedlon,
795  KOO** kdot, float maxd){
796  *kdot = NULL;
797  short marked;
798  /*naechsten Anker raussuchen*/
799  float dmax = maxd;
800  for(int i = 0; i < kc; i++)
801  if( kl[i].k->status == 2
802  && distance(clickedlat,clickedlon,
803  kl[i].k->lat,kl[i].k->lon) < dmax){
804  /*ein Anker innerhalb der Maximaldistanz dmax wurde gefunden*/
805  *kdot = kl[i].k;
806  if(kl[i].marked) marked = 1;
807  else marked = 0;
808  dmax = distance(clickedlat,clickedlon,
809  kl[i].k->lat,kl[i].k->lon);
810  }
811 
812  if(*kdot != NULL){
813  if(marked) return 2;
814  else return 1;
815  }
816  else
817  return 0;
818 }
820  if(kl != NULL){
821  float cbend = 0;
822  float ang1, ang2, tbend;
823  float d = 0;
824  float result = 0;
825  for(int i = 0; i < kc-2; i++){
826  d = d + distance(kl[i].k->lat,kl[i].k->lon,kl[i+1].k->lat,kl[i+1].k->lon);
827  ang1 = atan2(kl[i+1].k->lat-kl[i].k->lat,
828  kl[i+1].k->lon-kl[i].k->lon);
829  ang2 = atan2(kl[i+2].k->lat-kl[i+1].k->lat,
830  kl[i+2].k->lon-kl[i+1].k->lon);
831  tbend = ang2 - ang1;
832  if(tbend < -M_PI) tbend = tbend + 2*M_PI;
833  if(tbend > M_PI) tbend = tbend - 2*M_PI;
834  if(tbend *cbend < 0){
835  result = result + cbend*cbend/M_PI/M_PI;
836  cbend = tbend;
837  }
838  else{
839  cbend = cbend + tbend;
840  }
841  }
842  result = result + cbend*cbend/M_PI/M_PI;
843  return result;
844  }
845  else
846  return 0;
847 }
848 void Track::to_binary_KOO(char* filename){
849  FILE* f = fopen(filename,"wb");
850  fwrite(&kc,sizeof(kc),1,f);
851  float floatbuf;
852  for(int i = 0; i < kc; i++){
853  floatbuf = float(kl[i].k->lat);
854  fwrite(&(floatbuf),sizeof(float),1,f);
855  floatbuf = float(kl[i].k->lon);
856  fwrite(&(floatbuf),sizeof(float),1,f);
857  }
858  fclose(f);
859 }
860 void Track::to_gpx(char* filename){
861  FILE* f = fopen(filename,"w");
862  fprintf(f,"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
863  fprintf(f,"<gpx \nversion=\"1.0\" creator=\"GPSBabel - http://www.gpsbabel.org\"");
864  fprintf(f,"\nxmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"");
865  fprintf(f,"\nxmlns=\"http://www.topografix.com/GPX/1/0\"");
866  fprintf(f,"\nxsi:schemaLocation=\"http://www.topografix.com/GPX/1/0 http://www.topografix.com/GPX/1/0/gpx.xsd\">");
867  fprintf(f,"\n<time>2010-03-14T06:49:54Z</time>\n");
868  double minlat,minlon, maxlat, maxlon;
869  get_brect(&minlat,&maxlat,&minlon,&maxlon);
870  fprintf(f,"<bounds minlat=\"");
871  fprintf(f,"%f\" minlon =\"%f\" maxlat=\"%f\" maxlon=\"%f\" />"
872  ,minlat,minlon,maxlat,maxlon);
873 
874  fprintf(f,"<trkseg>\n");
875  for(int i = 0; i < kc; i++)
876  fprintf(f,"\n<trkpt lat=\"%f\" lon=\"%f\">\n<ele>0.000000</ele>\n</trkpt>"
877  ,kl[i].k->lat,kl[i].k->lon);
878 
879  fprintf(f,"</trkseg>\n");
880  fprintf(f,"</trk>\n</gpx>");
881  fclose(f);
882 }
883 KOO Track::get_firstKOO(){
884  if(kl != NULL)
885  return *(kl[0].k);
886  else{
887  KOO k; k.lat = 0; k.lon = 0;
888  return k;
889  }
890 }
891 
892 KOO Track::get_lastKOO(){
893  if(kl != NULL)
894  return *(kl[kc-1].k);
895  else{
896  KOO k; k.lat = 0; k.lon = 0;
897  return k;
898  }
899 }
void reset_markers()
set markers to zero
Definition: track.cpp:711
trackpoint * tpl
Definition: track.h:94
KOOlist * kl
KOO data array.
Definition: track.h:97
container struct to hold data of a coordinate
Definition: DataTyps.h:82
void refresh_KOOa()
refreshs KOOa
Definition: track.cpp:245
KOO ** node
reference to KOO (of way)
Definition: DataTyps.h:61
char status
state of the KOO when used by different classes
Definition: DataTyps.h:100
double lat
Definition: DataTyps.h:86
short next_d(double lat, double lon, double *d)
searches for closest point on track to point (lat,lon)
Definition: track.cpp:423
double ** get_d_h_array()
returns reference
Definition: track.cpp:204
short notNULL()
is track empty or not
Definition: track.cpp:513
void delete_complete()
Definition: track.cpp:501
float get_height_meters()
Definition: track.cpp:273
short extract_KOO(KOO *k, double d)
creates KOO refering distance point d
Definition: track.cpp:358
void get_brect(double *latmin, double *latmax, double *lonmin, double *lonmax)
return bounding rect of Track
Definition: track.cpp:697
double ** get_d_h_array_copy()
returns deep copy
Definition: track.cpp:208
short next_cross(double clickedlat, double clickedlon, KOO **kdot, float maxd)
stores cross in kdot which is closest to (clickedlat,clickedlon)
Definition: track.cpp:794
int tpi
index of related element in synchronized trackpoint array
Definition: DataTyps.h:180
void delete_cross(int nr)
deletes last nr cross of Track
Definition: track.cpp:462
routing container struct, connects cross via Way with each other
Definition: DataTyps.h:47
int kc
array length if kl
Definition: track.h:98
short extract_h(double d, double *h)
creates double for height refering distance point d
Definition: track.cpp:379
void delete_to_cross(KOO *k)
deletes cross after k
Definition: track.cpp:475
double ** get_KOOa()
returns reference
Definition: track.cpp:215
int nodec
count of used KOO in way
Definition: DataTyps.h:59
double ** d_h_array
distance height output, d:0, h:1
Definition: track.h:102
int tc
Definition: track.h:99
official representation of Track in BTP3
Definition: track.h:14
void to_gpx(char *filename)
save to gpx file
Definition: track.cpp:860
double get_length()
returns Track length [km]
Definition: track.cpp:320
double ** KOOa
coordinate output, lat:0, lon:1
Definition: track.h:103
short near_check(double lat, double lon, double limit)
check if point (lat,lon) is closer to track then limit
Definition: track.cpp:519
void to_binary_KOO(char *filename)
save binary KOOa to file (website)
Definition: track.cpp:848
short toggle_marker(KOO *k)
a KOO of the track can be marked or not, used for drag&amp;drop routing
Definition: track.cpp:718
void adapt_brect(double *latmin, double *latmax, double *lonmin, double *lonmax)
increases rect to contain track, if necessary
Definition: track.cpp:687
int tpc
count of trackpoint
Definition: DataTyps.h:60
float d
current distance, synchronized to trackpoint array
Definition: DataTyps.h:176
KOO * KOOpool
stores dynamically allocated KOO if public a function requires that
Definition: track.h:93
void refresh_d_h_array()
refreshs d_h_array
Definition: track.cpp:225
short keep_lists
destructor instruction, kl might be used outside this class
Definition: track.h:101
KOO * k
reference to KOO data
Definition: DataTyps.h:173
float get_bend()
return serpentine index
Definition: track.cpp:819
container struct for Track to hold distance and height data
Definition: DataTyps.h:33
KOO * prev
AVL tree pointers.
Definition: DataTyps.h:85
short marked
labels elements for drag-drop-routing:
Definition: DataTyps.h:178
trackpoint * tp
heighdata of this Neighbour
Definition: DataTyps.h:62
double ** get_KOOa_copy()
returns deep copy
Definition: track.cpp:219
main container for Track, WayHeight and ClimbAnalyse
Definition: DataTyps.h:172
short extract_azimtut(double d, double *azimut)
extract way direction at distance point d
Definition: track.cpp:400
void get_anchors(float d, KOO **kfrom, KOO **kto)
check if k is an element of Track
Definition: track.cpp:736