\( \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
ClimbAnalyse.cpp
1 #define _USE_MATH_DEFINES
2 #include "ClimbAnalyse.h"
3 
4 ClimbAnalyse::ClimbAnalyse(OSM* O,short mintype, short maxtype, double minP,
5  double minS, double maxdwnHM, double minHM,
6  HeightData* h){
7  this->o = O;
8  this->h = h;
9  set_parameters(mintype, maxtype, minP, minS, maxdwnHM, minHM);
10  f = new FibunacciHeap<CAfib>;
11  cp = NULL;
12  climbpool = NULL;
13  climbcount = 0;
14  minlat = -90;
15  maxlat = 90;
16  minlon = -180;
17  maxlon = 180;
18  analyse();
19 }
21  f = NULL;
22  cp = NULL;
23  climbpool = NULL;
24  climbcount = 0;
25 }
26 
27 ClimbAnalyse::~ClimbAnalyse(){
28  if(f != NULL) f->~FibunacciHeap();
29  for(long i = 0; i < climbcount; i++){
30  free_tpl(climbpool[i].c->t->prev,climbpool[i].c->prev->t);
31  }
32  for(long i = 0; i < climbcount; i++){
33  if(climbpool[i].t != NULL)climbpool[i].t->~Track();
34  if(climbpool[i].c->t != NULL) free(climbpool[i].c->t);
35  }
36  if(climbpool != NULL)
37  free(climbpool);
38 }
42  CAfib* c = f->extmin();
43  while(c != NULL){
44  if(all_active(c->c))
45  expand(c->c);
46  else{
47  if(c->c->state != climbend)
48  del_climb(c->c);
49  }
50  free(c);
51  c = (CAfib*) f->extmin();
52  }
53  climbcount = 0;
54  count_climbs(o->get_first_KOO());
55  if(climbcount > 0){
56  //QMessageBox(QMessageBox::NoIcon,"climbcount",QString("%1").arg(climbcount)).exec();
57  climbpool = (climbpoolele*)malloc(climbcount*sizeof(climbpoolele));
58  climbcount = 0;
60  if(climbcount > 0){
61  sort_climbpool(0,climbcount-1);
62  select_climbs();
63  create_names();
64  }
65  }
66  else
67  climbpool = NULL;
68 }
69 float ClimbAnalyse::calc_P(trackpoint* t,int arraylength){
70  float result = 0, hup, hdown;
71  for(int i = 0; i < arraylength -1; i++){
72  hup = 0;
73  hdown = 0;
74  for(int j = i+1; j < arraylength; j++){
75  if(t[j].h > t[j-1].h)
76  hup = hup + t[j].h - t[j-1].h;
77  else
78  hdown = hdown -t[j].h + t[j-1].h;
79  if( hup*maxdwnHM > hdown
80  && hup / 1000. / (t[j].d - t[i].d) > minSlope
81  && hup*hup / 1000. / (t[j].d - t[i].d) > result)
82  result = float(hup*hup / 1000. / (t[j].d - t[i].d));
83  }
84  }
85  return result;
86 }
87 void ClimbAnalyse::set_parameters(short mintype, short maxtype, double minP,
88  double minS, double maxdwnHM, double minHM){
89  this->mintype = mintype;
90  this->maxtype = maxtype;
91  this->minP = minP;
92  this->minSlope = minS;
93  this->maxdwnHM = maxdwnHM;
94  this->minHM = minHM;
95  autonomP = 10;
96 }
98  if(k!= NULL){
99  if(k->cd != NULL){
100  k->cd->s->from = NULL;
101  k->cd->s->via = NULL;
102  }
103  reset_STRONG(k->r);
104  reset_STRONG(k->l);
105  }
106 }
108  if(k != NULL){
109  if(k->cd != NULL){
110  climb* c = (climb*)malloc(sizeof(climb));
111  init_climb(c, k);
112  expand(c);
113  }
114  init_fib(k->l);
115  init_fib(k->r);
116  }
117 }
118 void ClimbAnalyse::init_climb(climb* c, KOO* k){
119  c->branches = 0;
120  c->cst = NULL;
121  c->d = 0;
122  c->hend = 0;
123  c->hmdown = 0;
124  c->hmup = 0;
125  c->home = k;
126  c->hstart = 0;
127  c->next = NULL;
128  c->P = 0;
129  c->Pmax = 0;
130  c->Prec = 0;
131  c->prev = NULL;
132  c->root = c;
133  c->state = climbstart;
134  c->t = NULL;
135  c->tend = NULL;
136  c->tst = NULL;
137  c->via = NULL;
138 }
140  Neighbour* n = c->home->cd->neighbours;
141  trackpointlist* t;
142 
143  while(n != NULL){
144  if(n->way->type <= maxtype && n->way->type >= mintype &&
145  crossunused(c,n->nb)){
146  t = add(c->t,n->tp,n->tpc,n->rd);
147  if(!storeif_climb(n,t,c))
148  free_tpl(t,c->t);
149  else
150  c->branches++;
151  }
152  n = n->next;
153  }
154 }
156  if(tp != NULL && tp != tpstop){
157  free_tpl(tp->prev,tpstop);
158  free(tp);
159  }
160  else{
161  if(tp != NULL){
162  tp->next = NULL;
163  }
164  }
165 }
167  readdirection rd){
168  trackpointlist *tpl;
169  float doffset;
170  if(tp != NULL){
171  // append to existing list
172  doffset = tp->t.d;
173  tpl = tp;
174  }
175  else{
176  // created new list
177  doffset = 0;
178  tpl = (trackpointlist*)malloc(sizeof(trackpointlist));
179  tpl->prev = NULL;
180  tpl->t.d = 0;
181  if(rd == fw)
182  tpl->t.h = t[0].h;
183  else
184  tpl->t.h = t[tpc-1].h;
185  }
186  // read and insert
187  if(rd == fw){
188  for(int i = 1; i < tpc; i++){
189  tpl->next = (trackpointlist*)malloc(sizeof(trackpointlist));
190  tpl->next->prev = tpl;
191  tpl = tpl->next;
192  tpl->t.h = t[i].h;
193  tpl->t.d = t[i].d + doffset;
194  }
195  }
196  else{
197  float dmax = t[tpc-1].d;
198  for(int i = tpc-2; i >= 0; i--){
199  tpl->next = (trackpointlist*)malloc(sizeof(trackpointlist));
200  tpl->next->prev = tpl;
201  tpl = tpl->next;
202  tpl->t.h = t[i].h;
203  tpl->t.d = (dmax-t[i].d) + doffset;
204  }
205  }
206  tpl->next = NULL;
207  return tpl;
208 }
210  float hmdown= 0, hmup = 0;
211  trackpointlist* t = tp;
212  while(t->prev != NULL){
213  if(t->prev->t.h < t->t.h)
214  hmdown = hmdown - t->prev->t.h + t->t.h;
215  else
216  hmup = hmup + t->prev->t.h - t->t.h;
217  if( hmdown*hmdown/(tp->t.d-t->prev->t.d)/1000.> minP
218  &&hmdown/(tp->t.d-t->prev->t.d)/1000. > minSlope
219  &&hmdown*maxdwnHM > hmup)
220  return 1;
221  t = t->prev;
222  }
223  return 0;
224 }
226  climb* ct = c->prev;
227  if(c->state == outofuse)
228  return 0;
229  while(ct != NULL){
230  if(ct->state == outofuse || c->home == ct->home){
231  return 0;
232  }
233  ct =ct->prev;
234  }
235  return 1;
236 }
238  climb* ct = c, *cfirst = NULL ,*clast = NULL;
239  float dautonom = 0;
240  while(ct != c->cst){
241  if(clast == NULL && ct->state == outofuse)
242  clast = ct;
243  if(ct->state == outofuse)
244  cfirst = ct;
245  else{
246  if(ct == c)
247  dautonom = dautonom + ct->tend->t.d;
248  else
249  dautonom = dautonom + ct->t->t.d;
250  if(ct->prev != c->cst)
251  dautonom = dautonom - ct->prev->t->t.d;
252  else
253  dautonom = dautonom - c->tst->t.d;
254  }
255  ct =ct->prev;
256  }
257  if(( cfirst == NULL) ||
258  ((c->Pmax - clast->P > autonomP || cfirst->prev->Pmax > autonomP) &&
259  dautonom/(c->tend->t.d-c->tst->t.d) > 0.5))
260  return 1;
261  else
262  return 0;
263 }
265  c->Prec = c->prev->Prec;
266  c->cst = c->prev->cst;
267  c->P = 0;
268  c->Pmax = 0;
269  c->d = 0;
270  c->hend = 0;
271  c->hstart = 0;
272  c->hmup = 0;
273  c->hmdown = 0;
274 
275  float hmdown= 0, hmup = 0;
276  trackpointlist* t = c->t, *t2;
277  climb* ccst = c;
278  while(t->prev != NULL && t != c->prev->t){
279  t2 = t;
280  hmdown = 0;
281  hmup = 0;
282  ccst = c;
283  while(t2->prev != NULL){
284  // refresh height meters
285  if(t2->prev->t.h < t2->t.h)
286  hmdown = hmdown - t2->prev->t.h + t2->t.h;
287  else
288  hmup = hmup + t2->prev->t.h - t2->t.h;
289  // posibly refhresh climb start
290  if(ccst->t != NULL && t2->prev->t.d < ccst->t->t.d)
291  ccst = ccst->prev;
292  // calc climb
293  if( (t->t.d-t2->prev->t.d) != 0 &&
294  //(c->Prec < minP || hmdown > minHM) &&
295  hmup < maxdwnHM*hmdown &&
296  hmdown/(t->t.d-t2->prev->t.d)/1000.> minSlope &&
297  hmdown/(t->t.d-t2->prev->t.d)/1000.< 0.35 &&
298  hmdown*hmdown/(t->t.d-t2->prev->t.d)/1000.> c->Pmax){
299  // climb definitions are matched
300  c->Pmax = float(hmdown*hmdown/(t->t.d-t2->prev->t.d)/1000.);
301  c->tst = t2->prev;
302  c->tend = t;
303  c->d = t->t.d-t2->prev->t.d;
304  c->cst = ccst;
305  c->hend = t->t.h;
306  c->hstart = t2->prev->t.h;
307  c->hmup = hmdown;
308  c->hmdown = hmup;
309  if(t == c->t){
310  // climb end exactly at cross
311  c->P = c->Pmax;
312  }
313  if(c->Pmax > c->Prec)
314  c->Prec = c->Pmax;
315  }
316  t2 = t2->prev;
317  }
318  t = t->prev;
319  }
320 }
322 
323  climb* c = (climb*)malloc(sizeof(climb));
324  c->branches = 0;
325  c->home = n->nb;
326  c->prev = from;
327  c->t = tp;
328  c->via = n;
329  c->state = failure;
330  calc_climb(c);
331 
332  short keep, expand;
333  // check whether climbs could exist on itseld
334  if(c->P == 0){
335  // climb cannot further expand as it breaks clibm definiton
336  if(c->Pmax > minP){
337  // but somewhere within the climb it reached climb state
338  keep = 1;
339  expand = 0;
340  c->state = climbend;
341  }
342  else{
343  // never reached climb state
344  keep = 0;
345  expand = 0;
346  }
347  }
348  else{
349  // climb matches climb definitions
350  keep = 1;
351  expand = 1;
352  if(c->P == c->Prec)
353  c->state = increasing;
354  else
355  c->state = decreasing;
356  }
357 
358  if(expand){
359  // climb is supposed to expand, but has to fight existing climbs
360  climb* ct = (climb*)(n->nb->cd->s->from);
361  while(ct != NULL){
362  if(looses(ct,c)){
363  ct = NULL;
364  keep = expand = 0;
365  c->state = outofuse;
366  }
367  else
368  ct = ct->next;
369  }
370  }
371 
372  if(keep){
373  c->next = (climb*) c->home->cd->s->from;
374  c->home->cd->s->from = c;
375  CAfib* cfib = (CAfib*) f->ins(c->t->t.h);
376  cfib->c = c;
377  climb* ct = c->next;
378  while(ct != NULL){
379  if(looses(c,ct))
380  ct->state = outofuse;
381  ct = ct->next;
382  }
383  return 1;
384  }
385  else{
386  free(c);
387  return 0;
388  }
389 }
391  while(c != NULL){
392  if(c->home == k)
393  return 0;
394  c = c->prev;
395  }
396  return 1;
397 }
399  // delete only directly after extract_min() from FibunacciHeap, but bot due
400  // to expanding climbs. Expanding climbs only set other climbs
401  // c->state = outofuse
402  if(c != NULL && c->branches == 0){
403  climb dummy; dummy.next = (climb*)c->home->cd->s->from;
404  climb* ct = &dummy;
405  while(ct->next != NULL && ct->next != c){
406  ct = ct->next;
407  }
408  if(ct->next != NULL){
409  ct->next = ct->next->next;
410  c->home->cd->s->from = dummy.next;
411  if(c->prev != NULL){ //delete as far as possible
412  free_tpl(c->t,c->prev->t);
413  c->prev->branches--;
414  del_climb(c->prev); //automatically del if only 2 branches
415  }
416  }
417  free(c);
418  }
419 }
420 void ClimbAnalyse::count_climbs(KOO* k){
421  if(k!= NULL){
422  if(k->cd != NULL){
423  climb* c = (climb*)(k->cd->s->from);
424  while(c != NULL){
425  if(c->Pmax == c->Prec){
426  climbcount++;
427  }
428  c = c->next;
429  }
430  }
431  count_climbs(k->l);
432  count_climbs(k->r);
433  }
434 }
436  if(k!= NULL){
437  if(k->cd != NULL){
438  climb* c = (climb*)(k->cd->s->from);
439  while(c!= NULL){
440  if(c->Pmax == c->Prec &&
441  c->hmup > minHM){
442  climbpool[climbcount].c = c;
443  climbpool[climbcount].P = c->Pmax;
444  climbcount++;
445  }
446  c = c->next;
447  }
448  }
449  collect_climbs(k->l);
450  collect_climbs(k->r);
451  }
452 }
453 void ClimbAnalyse::sort_climbpool(long s, long e){
454  long l = s, r = e;
455  climbpoolele c;
456  float p = climbpool[(s+e)/2].P;
457  do{
458  while(climbpool[l].P < p) l++;
459  while(climbpool[r].P > p) r--;
460  if(l<=r){
461  c = climbpool[l];
462  climbpool[l] = climbpool[r];
463  climbpool[r] = c;
464  l++;
465  r--;
466  }
467  }while(l <= r);
468  if(s < r) sort_climbpool(s,r);
469  if(l < e) sort_climbpool(l,e);
470 }
472  for(long i = climbcount-1; i >= 0; i--){
473  if(!enough_active(climbpool[i].c)){
474  climbpool[i].P = 0;
475  climbpool[i].t = NULL;
476  }
477  else{
479  }
480  climbpool[i].name = NULL;
481  climb* c = climbpool[i].c, *ct;
482  while(c != climbpool[i].c->cst){
483  // all climbs which belong to the pure climb
484  ct = (climb*) c->home->cd->s->from;
485  while(ct != NULL){
486  // climbs which us this cross ...
487  if(ct->via == c->via)
488  // ... and this Neighbour relation
489  ct->state = outofuse;
490  ct = ct->next;
491  }
492  c = c->prev;
493  }
494  }
495 }
496 short ClimbAnalyse::check(KOO* k){
497  if(k != NULL){
498  if(k->cd != NULL){
499  if(k->cd->s->from != NULL){
500  climb* c = (climb*)k->cd->s->from;
501  while(c != NULL){
502  c = c->next;
503  }
504  }
505  }
506  return check(k->l)*check(k->r);
507  }
508  else
509  return 1;
510 }
512  climb* ct = c->c;
513  int nc = 0;
514  while(ct != c->c->cst){
515  ct = ct->prev;
516  nc++;
517  }
518  Neighbour** narray = (Neighbour**)malloc(nc*sizeof(Neighbour*));
519  int i = nc;
520  ct = c->c;
521  while(ct != c->c->cst){
522  i--;
523  narray[i] = ct->via;
524  ct = ct->prev;
525  }
526 
527  c->t = new Track(narray,nc);
528  float d0;
529  if(c->c->cst->t == NULL)
530  d0 = 0;
531  else
532  d0 = c->c->cst->t->t.d;
533  c->t->trim_right(c->c->tend->t.d - d0);
534  c->t->trim_left (c->c->tst->t.d - d0);
535 }
537  if(climbcount > 0 && climbpool != NULL){
538  climblayer* result = (climblayer*)malloc(sizeof(climblayer));
539  // count valid climbs
540  result ->climbcount = 0;
541  for(long i = 0; i < climbcount; i++)
542  if(climbpool[i].P >= minP)
543  result->climbcount++;
544  result->climb = (climblayerelement*)malloc(result->climbcount*sizeof(climblayerelement));
545 
546  if(result->climbcount == 0){
547  free(result);
548  return NULL;
549  }
550 
551  // extract valid climbs an note them
552  long ci = 0;
553  for(long i = 0; i < climbcount; i++){
554  if(climbpool[i].P >= minP){
555  result->climb[ci].P = climbpool[i].P;
556  result->climb[ci].hstart = climbpool[i].c->hstart;
557  result->climb[ci].hend = climbpool[i].c->hend;
558  result->climb[ci].hmdown = climbpool[i].c->hmdown;
559  result->climb[ci].hmup = climbpool[i].c->hmup;
560  result->climb[ci].d = climbpool[i].c->d;
561  result->climb[ci].dhcount = climbpool[i].t->get_array_length();
562  result->climb[ci].dharray = climbpool[i].t->get_d_h_array_copy();
563  result->climb[ci].KOOcount = climbpool[i].t->get_KOOa_length();
564  result->climb[ci].KOOarray = climbpool[i].t->get_KOOa_copy();
565  result->climb[ci].slope = result->climb[ci].hmup/ result->climb[ci].d / 10.;
566  result->climb[ci].bend = climbpool[i].t->get_bend()/climbpool[i].c->d;
567  KOO k; climbpool[i].t->extract_KOO(&k,climbpool[i].c->d/2.);
568  result->climb[ci].midlat = k.lat;
569  result->climb[ci].midlon = k.lon;
570  result->climb[ci].name = climbpool[i].name;
571  ci++;
572  }
573  }
574  // make local ranking of climbs
575  for(long i = 0; i < result->climbcount; i++){
576  float m = 0;
577  for(long j = 0; j < result->climbcount; j++)
578  m = qMax(m,
579  float(result->climb[j].P
580  * exp(-distance(result->climb[i].midlat,
581  result->climb[i].midlon,
582  result->climb[j].midlat,
583  result->climb[j].midlon)/30)));
584  result->climb[i].LocRank = result->climb[i].P / m;
585  }
586 
587  return result;
588  }
589  else
590  return NULL;
591 }
592 climblayer* ClimbAnalyse::load_ClimbLayer(char* filename){
593  FILE* f = fopen(filename,"rb");
594  if(f != NULL){
595  climblayer* c = (climblayer*)malloc(sizeof(climblayer));
596  fread(&(c->climbcount),sizeof(c->climbcount),1,f);
597  c->climb = (climblayerelement*)malloc(c->climbcount*sizeof(climblayerelement));
598  for(long i = 0; i < c->climbcount; i++){
599  fread(&(c->climb[i].d ),sizeof(c->climb[i].d ),1,f);
600  fread(&(c->climb[i].dhcount ),sizeof(c->climb[i].dhcount ),1,f);
601  fread(&(c->climb[i].hend ),sizeof(c->climb[i].hend ),1,f);
602  fread(&(c->climb[i].hmdown ),sizeof(c->climb[i].hmdown ),1,f);
603  fread(&(c->climb[i].hmup ),sizeof(c->climb[i].hmup ),1,f);
604  fread(&(c->climb[i].hstart ),sizeof(c->climb[i].hstart ),1,f);
605  fread(&(c->climb[i].KOOcount ),sizeof(c->climb[i].KOOcount),1,f);
606  fread(&(c->climb[i].P ),sizeof(c->climb[i].P ),1,f);
607  fread(&(c->climb[i].slope ),sizeof(c->climb[i].slope ),1,f);
608  fread(&(c->climb[i].bend ),sizeof(c->climb[i].bend ),1,f);
609  fread(&(c->climb[i].midlat ),sizeof(c->climb[i].midlat ),1,f);
610  fread(&(c->climb[i].midlon ),sizeof(c->climb[i].midlon ),1,f);
611  fread(&(c->climb[i].LocRank ),sizeof(c->climb[i].LocRank ),1,f);
612  c->climb[i].dharray = new double*[2];
613  c->climb[i].dharray[0] = new double[c->climb[i].dhcount];
614  c->climb[i].dharray[1] = new double[c->climb[i].dhcount];
615  fread(c->climb[i].dharray[0],sizeof(double),c->climb[i].dhcount,f);
616  fread(c->climb[i].dharray[1],sizeof(double),c->climb[i].dhcount,f);
617  c->climb[i].KOOarray = new double*[2];
618  c->climb[i].KOOarray[0] = new double[c->climb[i].KOOcount];
619  c->climb[i].KOOarray[1] = new double[c->climb[i].KOOcount];
620  fread(c->climb[i].KOOarray[0],sizeof(double),c->climb[i].KOOcount,f);
621  fread(c->climb[i].KOOarray[1],sizeof(double),c->climb[i].KOOcount,f);
622  int length;
623  fread(&length,sizeof(int),1,f);
624  if(length > 0){
625  c->climb[i].name = new char[length+1];
626  fread(&(c->climb[i].name[0]),sizeof(char),length,f);
627  c->climb[i].name[length] = '\0';
628  }
629  else
630  c->climb[i].name = NULL;
631  }
632  return c;
633  }
634  else
635  return NULL;
636 }
637 void ClimbAnalyse::save_ClimbLayer(char* projectname, char* folder,climblayer *c){
638  if(c != NULL){
639  QString filename = QString(folder).append(projectname).append(".bbl");
640  FILE* f = fopen(filename.toLocal8Bit().data(),"wb");
641  if(f != NULL){
642  fwrite(&(c->climbcount),sizeof(c->climbcount),1,f);
643  for(long i = 0; i < c->climbcount; i++){
644  fwrite(&(c->climb[i].d ),sizeof(c->climb[i].d ),1,f);
645  fwrite(&(c->climb[i].dhcount ),sizeof(c->climb[i].dhcount ),1,f);
646  fwrite(&(c->climb[i].hend ),sizeof(c->climb[i].hend ),1,f);
647  fwrite(&(c->climb[i].hmdown ),sizeof(c->climb[i].hmdown ),1,f);
648  fwrite(&(c->climb[i].hmup ),sizeof(c->climb[i].hmup ),1,f);
649  fwrite(&(c->climb[i].hstart ),sizeof(c->climb[i].hstart ),1,f);
650  fwrite(&(c->climb[i].KOOcount),sizeof(c->climb[i].KOOcount),1,f);
651  fwrite(&(c->climb[i].P ),sizeof(c->climb[i].P ),1,f);
652  fwrite(&(c->climb[i].slope ),sizeof(c->climb[i].slope ),1,f);
653  fwrite(&(c->climb[i].bend ),sizeof(c->climb[i].bend ),1,f);
654  fwrite(&(c->climb[i].midlat ),sizeof(c->climb[i].midlat ),1,f);
655  fwrite(&(c->climb[i].midlon ),sizeof(c->climb[i].midlon ),1,f);
656  fwrite(&(c->climb[i].LocRank ),sizeof(c->climb[i].LocRank ),1,f);
657  //if(c->climb[i].dhcount == 0 || i == 2390)
658  // QMessageBox().exec();
659  fwrite(c->climb[i].dharray[0],sizeof(double),c->climb[i].dhcount,f);
660  fwrite(c->climb[i].dharray[1],sizeof(double),c->climb[i].dhcount,f);
661  fwrite(c->climb[i].KOOarray[0],sizeof(double),c->climb[i].KOOcount,f);
662  fwrite(c->climb[i].KOOarray[1],sizeof(double),c->climb[i].KOOcount,f);
663 
664  int length = 0;
665  if(c->climb[i].name != NULL)
666  length = strlen(c->climb[i].name);
667  fwrite(&length,sizeof(int),1,f);
668  if(length > 0)
669  fwrite(&(c->climb[i].name[0]),sizeof(char),length,f);
670  }
671  fclose(f);
672  }
673  }
674 }
675 void ClimbAnalyse::create_MAP(char* projectname, char* folder, HeightData* h,
676  double size){
677  if(climbcount > 0){
678  double minlat=90,maxlat=-90,minlon=180,maxlon=-180;
679  for(long i = climbcount-1; i >= 0; i--){
680  if(climbpool[i].P >= minP){
681  climbpool[i].t->adapt_brect(&minlat,&maxlat,&minlon,&maxlon);
682  }
683  }
684  MAP* mt = new MAP(h,o);
685  QString filename = QString(folder).append(projectname).append("climblist.txt");
686  mt->save_to_png(filename.toLocal8Bit().data());
687  mt->~MAP();
688  }
689 }
690 void ClimbAnalyse::create_html(char* projectname, char* folder){
691  if(climbcount > 0){
692  //QMessageBox(QMessageBox::NoIcon,"",QString("%1").arg(folder)).exec();
693  plot2D p;
694  p.set_size(450,300);
695  QString path0 = QString(folder).append("/").append(projectname).append("-%1.png");
696  QString path1 = QString(folder).append("/").append(projectname).append("-BinaryList.src");
697  QString path2 = QString(folder).append("/").append(projectname).append("-%1.trk");
698  QString path4 = QString(folder).append("/").append(projectname).append("-names.txt");
699  ushort usb;
700  short sb;
701  float fb;
702  KOO kt;
703  char newline = '\n';
704  unsigned int realclimbs =0;
705  for(int i = 0; i < climbcount; i++){
706  if(climbpool[i].P >= minP){
707  climbpool[i].t->extract_KOO(&kt,climbpool[i].c->d / 2.);
708  if(o->isin(&kt,minlat,maxlat,minlon,maxlon))
709  realclimbs++;
710  }
711  }
712  if(realclimbs>0){
713  FILE* f;
714  f = fopen(path1.toLocal8Bit().data(),"wb");
715  FILE* fnames;
716  fnames = fopen(path4.toLocal8Bit().data(),"w");
717  fwrite(&realclimbs,4,1,f);
718  int realindex = -1, length;
719  for(int i = 0; i < climbcount; i++)
720  if(climbpool[i].P >= minP){
721  climbpool[i].t->extract_KOO(&kt,climbpool[i].c->d / 2.);
722  if(o->isin(&kt,minlat,maxlat,minlon,maxlon)){
723  /*Binaere Daten schreiben*/
724  usb = ushort(climbpool[i].c->d*1000);
725  fwrite(&usb,2,1,f);
726  sb = short(climbpool[i].c->hstart*10);
727  fwrite(&sb,2,1,f);
728  sb = short(climbpool[i].c->hend*10);
729  fwrite(&sb,2,1,f);
730  sb = short(climbpool[i].c->hmdown*10);
731  fwrite(&sb,2,1,f);
732  sb = short(climbpool[i].t->get_bend()*100);
733  fwrite(&sb,2,1,f);
734  fb = float(kt.lon);
735  fwrite(&fb,4,1,f);
736  fb = float(kt.lat);
737  fwrite(&fb,4,1,f);
738  /*png-Datei erzeugen*/
739  realindex++;
740  p.set_data(climbpool[i].t->get_d_h_array(),
741  climbpool[i].t->get_array_length());
742  QString filename = QString(path0).arg(realindex);
743  p.save_to_png(filename);
744  /*track erzeugen*/
745  filename = QString(path2).arg(realindex);
746  climbpool[i].t->to_binary_KOO(filename.toLocal8Bit()
747  .data());
748  /*write names file*/
749  length = strlen(climbpool[i].name);
750  if(length > 0)
751  fwrite(&(climbpool[i].name[0]),sizeof(char),
752  length,fnames);
753  fwrite(&newline,sizeof(char),1,fnames);
754  }
755  }
756  fclose(f);
757  fclose(fnames);
758  }
759  }
760 }
761 void ClimbAnalyse::create_list(char* projectname, char* folder){
762  if(climbcount > 0){
763  QString filename = QString(folder).append("\\").append(projectname).append("climblist.txt");
764  FILE* f = fopen(filename.toLocal8Bit().data(),"w");
765  for(long i = climbcount; i >= 0; i--){
766  if(climbpool[i].P > minP)
767  fprintf(f,"%5.1f P\t %4.1f %% \t %.2f km\t %6.1f m\t %6.1f m\t %6.1f m\t %6.1f m\t %6.1f serpentine/km\t%s\t Start-id: %12li\t End-id:%12li \n",
768  climbpool[i].P,
769  climbpool[i].c->hmup/climbpool[i].c->d/10,
770  climbpool[i].c->d,
771  climbpool[i].c->hmup,
772  climbpool[i].c->hmdown,
773  climbpool[i].c->hstart,
774  climbpool[i].c->hend,
775  climbpool[i].t->get_bend()/climbpool[i].c->d,
776  climbpool[i].name,
777  climbpool[i].c->cst->home->id,
778  climbpool[i].c->home->id);
779  }
780  fclose(f);
781  }
782 }
783 short ClimbAnalyse::looses(climb* resident, climb* aspirant){
784  if(resident->prev->home == aspirant->prev->home){
785  // climbs do not only meet each other, but already share a road
786  if( (resident->cst == aspirant->cst && resident->t->t.d <= aspirant->t->t.d) ||
787  (aspirant->P < autonomP &&
788  resident->state == increasing &&
789  resident->P > aspirant->P)
790  )
791  return 1;
792  else
793  return 0;
794  }
795  else
796  return 0;
797 }
798 nameaspirant::nameaspirant(char* name){
799  this->name = QString().fromUtf8(name);
800  d = e = s = 0;
801 }
802 nameaspirant::nameaspirant(char* name, float d){
803  this->name = QString().fromUtf8(name);
804  this->d = d;
805  e = s = 0;
806 }
807 bool nameaspirant::operator ==(nameaspirant o){
808  if(this->name == o.name)
809  return true;
810  else
811  return false;
812 }
814  for(long i = climbcount-1; i >= 0; i--){
815  if(climbpool[i].P >= minP){
816  // determine street names
817  QList<nameaspirant> wn;
818  eval_Way_names(&wn,climbpool[i].c);
819  // determine point names
820  QList<nameaspirant> pn;
821  eval_point_names(&pn,o->village,1.0,climbpool[i].t,true);
822  eval_point_names(&pn,o->town,1.0,climbpool[i].t,true);
823  eval_point_names(&pn,o->locality,1.0,climbpool[i].t,true);
824  eval_point_names(&pn,o->col,1.2,climbpool[i].t,true);
825  eval_point_names(&pn,o->peak,-1,climbpool[i].t,false);
826  QString name;
827  bool foundname = 0;
828  // 1. check end point
829  double max = 0;
830  int maxi = -1;
831  for(int i = 0; i < pn.length(); i++)
832  if(max < (pn[i].e-pn[i].s)*pn[i].d > max){
833  max = (pn[i].e-pn[i].s)*pn[i].d;
834  maxi = i;
835  }
836  if(max>0.125 && !pn[maxi].name.isNull()){
837  foundname = 1;
838  name.append(pn[maxi].name);
839  // 2. check start point
840  max = 0;
841  maxi = -1;
842  for(int i = 0; i < pn.length(); i++)
843  if(max < (-pn[i].e+pn[i].s)*pn[i].d > max){
844  max = (-pn[i].e+pn[i].s)*pn[i].d;
845  maxi = i;
846  }
847  if(max>0.125 && !pn[maxi].name.isNull())
848  name.append(" (").append(pn[maxi].name).append(")");
849  }
850  // 3. check way name
851  QString wname;
852  qSort(wn.begin(),wn.end());
853  if(!wn[0].name.isEmpty()){
854  if(wn[0].d > 0.5)
855  wname = wn[0].name;
856  else
857  if(wn.length()>1 && !wn[1].name.isEmpty()
858  && wn[0].d + wn[1].d > 0.66)
859  wname.append(wn[0].name)
860  .append(", ")
861  .append(wn[1].name);
862  }
863  if(!wname.isEmpty()){
864  if(foundname)
865  name.append(", ").append(wname);
866  else
867  name = wname;
868  }
869  // 4. if way name at maximum, add closest point
870  if(!foundname && pn.length() > 0){
871  qSort(pn.begin(),pn.end());
872  if(!pn[0].name.isEmpty() && pn[0].d > 0.5)
873  name.append(" [").append(pn[0].name).append("]");
874  }
875  // copy to data
876  if(!name.isEmpty()){
877  climbpool[i].name = new char[strlen(name.toUtf8().data())+1];
878  strcpy(climbpool[i].name,name.toUtf8().data());
879  }
880  else{
881  QString none = "none";
882  climbpool[i].name = new char[strlen(name.toUtf8().data())+1];
883  strcpy(climbpool[i].name,name.toUtf8().data());
884  }
885  }
886  else
887  climbpool[i].name = NULL;
888 
889  }
890 }
891 void ClimbAnalyse::eval_Way_names(QList<nameaspirant> *wn, climb* c0){
892  climb* c = c0, *clast;
893  while(c != c0->cst){
894  int i = wn->indexOf(c->via->way->name);
895  if( i > -1) (*wn)[i].d += c->via->d;
896  else wn->append(nameaspirant(c->via->way->name,
897  c->via->d));
898  clast = c;
899  c = c->prev;
900  }
901  int is = wn->indexOf(c0->via->way->name);
902  int ie = wn->indexOf(clast->via->way->name);
903  (*wn)[is].d -= c0->t ->t.d - c0->tend ->t.d;
904  if(c0->cst->t != NULL)
905  (*wn)[ie].d -= c0->tst->t.d - c0->cst->t->t.d;
906  else
907  (*wn)[ie].d -= c0->tst->t.d;
908  for(int i = 0; i < wn->length(); i++)
909  (*wn)[i].d = (*wn)[i].d / c0->d;
910 }
911 void ClimbAnalyse::eval_point_names(QList<nameaspirant> *pn, points **p,
912  double fac, Track* t, bool validstart){
913  bool calcfromindex = fac < 0;
914  points* pts = *p;
915  double d,h0;
916  KOO ks = t->get_firstKOO();
917  KOO ke = t->get_lastKOO();
918  KOO ktt;
919  float hs = h->height(ks.lon,ks.lat,NULL,0);
920  float he = h->height(ke.lon,ke.lat,NULL,0);
921  float dlimit = distance(ks.lat,ks.lon,ke.lat,ke.lon);
922  float dh = he-hs;
923  double latmin,latmax,lonmin,lonmax;
924  t->get_brect(&latmin,&latmax,&lonmin,&lonmax);
925  double dd = sqrt((latmax-latmin)*(latmax-latmin)+
926  (lonmax-lonmin)*(lonmax-lonmin));
927  latmin -= dd;
928  latmax += dd;
929  lonmin -= dd;
930  lonmax += dd;
931  while(pts != NULL){
932  if(o->isin(pts->k,latmin,latmax,lonmin,lonmax)){
933  if(calcfromindex) fac = 1.1*(1-exp(-sqrt(pts->index/800)));
934  t->next_d(pts->k->lat,pts->k->lon,&d);
935  t->extract_KOO(&ktt,d);
936  d = distance(ktt.lat,ktt.lon,pts->k->lat,pts->k->lon);
937  h0 = h->height(pts->k->lon,pts->k->lat,NULL,0);
938  if(d<dlimit){
939  pn->append(nameaspirant(pts->name,(1-d/dlimit)*fac));
940  pn->last().e = qMax(0.,
941  (1-distance(ke.lat,ke.lon,pts->k->lat,pts->k->lon)
942  /dlimit)*(1-qAbs(h0-he)/dh));
943  if(validstart)
944  pn->last().s = qMax(0.,
945  (1-distance(ks.lat,ks.lon,pts->k->lat,pts->k->lon)
946  /dlimit)*(1-qAbs(hs-h0)/dh));
947  else
948  pn->last().s = 0;
949  }
950  }
951  pts = pts->next;
952  }
953 }
954 void ClimbAnalyse::set_brect(double minlat, double maxlat,
955  double minlon, double maxlon){
956  this->minlat = minlat;
957  this->maxlat = maxlat;
958  this->minlon = minlon;
959  this->maxlon = maxlon;
960 }
void sort_climbpool(long s, long e)
quicksort for collected climbs
float d
Definition: DataTyps.h:389
double minlat
bounding rect, saved html data is limited to
Definition: ClimbAnalyse.h:145
void calc_climb(climb *c)
calcs P, Pmax, Prec, tst of a climb
KOO * home
cross, climb refers to
Definition: DataTyps.h:383
Neighbour * via
connection to reach this STRONG
Definition: DataTyps.h:258
void create_names()
create names from OSM data
void create_climb_Track(climbpoolele *c)
trace back climb to start and creates Track instance from it
HeightData * h
Definition: ClimbAnalyse.h:143
Way * way
Neighbour lives uses this Way.
Definition: DataTyps.h:53
float Prec
Definition: DataTyps.h:389
double height(double lon, double lat, void *hc, short mode)
returns height data
Definition: HeightData.cpp:418
void set_parameters(short mintype, short maxtype, double minP, double minSlope, double maxdwnHM, double minHM)
set the definitons of the climb
short isin(lines *l, double minlat, double maxlat, double minlon, double maxlon)
Definition: osm.cpp:670
void collect_climbs(KOO *k)
picks raw climbs from street net, to be selected (select_climbs())
float index
for summit ranking
Definition: DataTyps.h:139
climbpoolele * climbpool
container to store climbs when collect_climbs()
Definition: ClimbAnalyse.h:87
KOO * get_first_KOO()
returns root of node-AVL tree
Definition: osm.cpp:1692
container struct to hold data of a coordinate
Definition: DataTyps.h:82
float hmup
Definition: DataTyps.h:389
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
long int climbcount
Definition: ClimbAnalyse.h:85
climb * cst
start point as climb struct
Definition: DataTyps.h:392
*short maxtype
Definition: ClimbAnalyse.h:77
KOO * nb
Definition: DataTyps.h:54
short branches
count of branching chilf climbs
Definition: DataTyps.h:382
short all_active(climb *c)
checks, whether used road are still avaiable in select_climbs()
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 enough_active(climb *c)
checks climb, whether used roads are sufficently independend
routing container struct, connects cross via Way with each other
Definition: DataTyps.h:47
void reset_STRONG(KOO *k)
preparing cross to be inserted into f
void free_tpl(trackpointlist *tp, trackpointlist *tpstop)
deletes a trackpointlist down to tpstop
Neighbour * next
next Neighbour, set to NULL if last
Definition: DataTyps.h:63
container struct for ClimbAnalyse
Definition: DataTyps.h:380
main container list climbanalyse
Definition: DataTyps.h:162
KOO * k
reference to KOO
Definition: DataTyps.h:138
void init_fib(KOO *k)
STRONG * s
memory for routing algorithms
Definition: DataTyps.h:75
climblayer * get_ClimbLayer()
double maxdwnHM
Definition: ClimbAnalyse.h:80
qint64 id
id inherited from OSM data
Definition: DataTyps.h:83
float Pmax
Definition: DataTyps.h:389
climb * cp
Definition: ClimbAnalyse.h:89
trackpointlist * t
track profil so far, to trace back
Definition: DataTyps.h:384
char * name
OSM name of point
Definition: DataTyps.h:140
holds digital elevation model extracted from SRTM3 data
Definition: HeightData.h:26
trackpointlist * tst
start point in track profil
Definition: DataTyps.h:385
official representation of Track in BTP3
Definition: track.h:14
readdirection rd
Definition: DataTyps.h:52
double minHM
Definition: ClimbAnalyse.h:80
char type
classification
Definition: DataTyps.h:129
double autonomP
Definition: ClimbAnalyse.h:80
climb * root
root of the whole climb tree
Definition: DataTyps.h:393
float hend
Definition: DataTyps.h:389
void save_to_png(QString filename)
save map as picture to hard disk
Definition: MAP.cpp:1197
void * from
&lt; pointer to STRONG or FibunacciHeap
Definition: DataTyps.h:257
plotting 2D-Data sets as the height profile of a track or poweranalysis data
Definition: plot2D.h:20
float P
Definition: DataTyps.h:389
void to_binary_KOO(char *filename)
save binary KOOa to file (website)
Definition: track.cpp:848
short crossunused(climb *c, KOO *k)
varifies, that climb has not used the cross at k before
float hmdown
Definition: DataTyps.h:389
void select_climbs()
selects collected climbs, if suffiently independed or difficult
climbstate state
current state at ClimbAnalyse
Definition: DataTyps.h:381
float d
distance
Definition: DataTyps.h:58
void del_climb(climb *c)
deletes the whole climb recursivly
void set_brect(double minlat, double maxlat, double minlon, double maxlon)
restrict saved data to a rectangular area
void adapt_brect(double *latmin, double *latmax, double *lonmin, double *lonmax)
increases rect to contain track, if necessary
Definition: track.cpp:687
trackpointlist * tend
Definition: DataTyps.h:386
void eval_point_names(QList< nameaspirant > *pn, points **p, double fac, Track *t, bool validstart)
create climb name aspirant list from summits and other point data
short is_climb(trackpointlist *tp)
checks whether the list represents a climb
void set_data(double **dataxy, int count)
setting one dataset and repaint plot
Definition: plot2D.cpp:475
int tpc
count of trackpoint
Definition: DataTyps.h:60
Neighbour * neighbours
neigbours to link to other cross
Definition: DataTyps.h:74
BTP3 database, created from OpenStreetMap data.
Definition: osm.h:34
short storeif_climb(Neighbour *n, trackpointlist *tp, climb *from)
checks for existing climbs at cross and executes looses()
FibunacciHeap< CAfib > * f
priority queue to store active cross sorted by height
Definition: ClimbAnalyse.h:84
trackpointlist * add(trackpointlist *tp, trackpoint *t, int tpc, readdirection rd)
adds an branch t to a axisting trackpointlist
float hstart
Definition: DataTyps.h:389
float get_bend()
return serpentine index
Definition: track.cpp:819
Neighbour * via
last used link
Definition: DataTyps.h:394
void eval_Way_names(QList< nameaspirant > *wn, climb *c0)
create climb name aspirant list according to street names
container struct for Track to hold distance and height data
Definition: DataTyps.h:33
float calc_P(trackpointlist *tp)
calcs climb difficulty with fixed climb end
trackpoint * tp
heighdata of this Neighbour
Definition: DataTyps.h:62
char * name
name ref owned by lines
Definition: DataTyps.h:130
short looses(climb *resident, climb *aspirant)
determines, whether a new climb can stop an existing or vice versa
double ** get_KOOa_copy()
returns deep copy
Definition: track.cpp:219
osm data container list for point like data (summits, towns, ...)
Definition: DataTyps.h:137
*short mintype
Definition: ClimbAnalyse.h:77
void expand(climb *c)
makes this climb expand over all Neighbour relations
double minSlope
Definition: ClimbAnalyse.h:80
generating maps
Definition: MAP.h:24