1 #define _USE_MATH_DEFINES
2 #include "ClimbAnalyse.h"
5 double minS,
double maxdwnHM,
double minHM,
27 ClimbAnalyse::~ClimbAnalyse(){
28 if(
f != NULL)
f->~FibunacciHeap();
47 if(c->c->state != climbend)
70 float result = 0, hup, hdown;
71 for(
int i = 0; i < arraylength -1; i++){
74 for(
int j = i+1; j < arraylength; j++){
76 hup = hup + t[j].h - t[j-1].h;
78 hdown = hdown -t[j].h + t[j-1].h;
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));
88 double minS,
double maxdwnHM,
double minHM){
100 k->cd->
s->
from = NULL;
101 k->cd->
s->
via = NULL;
118 void ClimbAnalyse::init_climb(
climb* c,
KOO* k){
133 c->
state = climbstart;
156 if(tp != NULL && tp != tpstop){
184 tpl->t.h = t[tpc-1].h;
188 for(
int i = 1; i < tpc; i++){
190 tpl->next->prev = tpl;
193 tpl->t.d = t[i].d + doffset;
197 float dmax = t[tpc-1].d;
198 for(
int i = tpc-2; i >= 0; i--){
200 tpl->next->prev = tpl;
203 tpl->t.d = (dmax-t[i].d) + doffset;
210 float hmdown= 0, hmup = 0;
212 while(t->prev != NULL){
213 if(t->prev->t.h < t->t.h)
214 hmdown = hmdown - t->prev->t.h + t->t.h;
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
227 if(c->
state == outofuse)
238 climb* ct = c, *cfirst = NULL ,*clast = NULL;
241 if(clast == NULL && ct->
state == outofuse)
243 if(ct->
state == outofuse)
247 dautonom = dautonom + ct->
tend->t.d;
249 dautonom = dautonom + ct->
t->t.d;
250 if(ct->prev != c->
cst)
251 dautonom = dautonom - ct->prev->
t->t.d;
253 dautonom = dautonom - c->
tst->t.d;
257 if(( cfirst == NULL) ||
259 dautonom/(c->
tend->t.d-c->
tst->t.d) > 0.5))
275 float hmdown= 0, hmup = 0;
278 while(t->prev != NULL && t != c->prev->
t){
283 while(t2->prev != NULL){
285 if(t2->prev->t.h < t2->t.h)
286 hmdown = hmdown - t2->prev->
t.h + t2->t.h;
288 hmup = hmup + t2->prev->t.h - t2->t.h;
290 if(ccst->
t != NULL && t2->prev->t.d < ccst->
t->t.d)
293 if( (t->t.d-t2->prev->t.d) != 0 &&
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){
300 c->
Pmax = float(hmdown*hmdown/(t->t.d-t2->prev->t.d)/1000.);
303 c->
d = t->t.d-t2->prev->t.d;
306 c->
hstart = t2->prev->t.h;
353 c->
state = increasing;
355 c->
state = decreasing;
380 ct->
state = outofuse;
405 while(ct->next != NULL && ct->next != c){
408 if(ct->next != NULL){
409 ct->next = ct->next->next;
420 void ClimbAnalyse::count_climbs(
KOO* k){
472 for(
long i = climbcount-1; i >= 0; i--){
487 if(ct->via == c->
via)
489 ct->state = outofuse;
496 short ClimbAnalyse::check(
KOO* k){
499 if(k->cd->
s->
from != NULL){
506 return check(k->l)*check(k->r);
514 while(ct != c->c->
cst){
521 while(ct != c->c->
cst){
527 c->t =
new Track(narray,nc);
529 if(c->c->
cst->
t == NULL)
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);
540 result ->climbcount = 0;
543 result->climbcount++;
546 if(result->climbcount == 0){
561 result->climb[ci].dhcount =
climbpool[i].t->get_array_length();
563 result->climb[ci].KOOcount =
climbpool[i].t->get_KOOa_length();
565 result->climb[ci].
slope = result->climb[ci].
hmup/ result->climb[ci].
d / 10.;
568 result->climb[ci].midlat = k.
lat;
569 result->climb[ci].midlon = k.lon;
570 result->climb[ci].name =
climbpool[i].name;
575 for(
long i = 0; i < result->climbcount; i++){
577 for(
long j = 0; j < result->climbcount; j++)
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;
592 climblayer* ClimbAnalyse::load_ClimbLayer(
char* filename){
593 FILE*
f = fopen(filename,
"rb");
596 fread(&(c->climbcount),
sizeof(c->climbcount),1,f);
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);
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);
623 fread(&length,
sizeof(
int),1,f);
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';
630 c->climb[i].name = NULL;
637 void ClimbAnalyse::save_ClimbLayer(
char* projectname,
char* folder,
climblayer *c){
639 QString filename = QString(folder).append(projectname).append(
".bbl");
640 FILE* f = fopen(filename.toLocal8Bit().data(),
"wb");
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);
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);
665 if(c->climb[i].name != NULL)
666 length = strlen(c->climb[i].name);
667 fwrite(&length,
sizeof(
int),1,f);
669 fwrite(&(c->climb[i].name[0]),
sizeof(
char),length,f);
675 void ClimbAnalyse::create_MAP(
char* projectname,
char* folder,
HeightData* h,
678 double minlat=90,maxlat=-90,minlon=180,maxlon=-180;
679 for(
long i = climbcount-1; i >= 0; i--){
685 QString filename = QString(folder).append(projectname).append(
"climblist.txt");
690 void ClimbAnalyse::create_html(
char* projectname,
char* folder){
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");
704 unsigned int realclimbs =0;
708 if(
o->
isin(&kt,minlat,maxlat,minlon,maxlon))
714 f = fopen(path1.toLocal8Bit().data(),
"wb");
716 fnames = fopen(path4.toLocal8Bit().data(),
"w");
717 fwrite(&realclimbs,4,1,f);
718 int realindex = -1, length;
722 if(
o->
isin(&kt,minlat,maxlat,minlon,maxlon)){
732 sb = short(
climbpool[i].t->get_bend()*100);
742 QString filename = QString(path0).arg(realindex);
743 p.save_to_png(filename);
745 filename = QString(path2).arg(realindex);
751 fwrite(&(
climbpool[i].name[0]),
sizeof(
char),
753 fwrite(&newline,
sizeof(
char),1,fnames);
761 void ClimbAnalyse::create_list(
char* projectname,
char* folder){
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--){
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",
784 if(resident->prev->
home == aspirant->prev->
home){
786 if( (resident->
cst == aspirant->
cst && resident->
t->t.d <= aspirant->
t->t.d) ||
788 resident->
state == increasing &&
789 resident->
P > aspirant->
P)
798 nameaspirant::nameaspirant(
char* name){
799 this->name = QString().fromUtf8(name);
802 nameaspirant::nameaspirant(
char* name,
float d){
803 this->name = QString().fromUtf8(name);
808 if(this->name == o.name)
814 for(
long i = climbcount-1; i >= 0; i--){
817 QList<nameaspirant> wn;
820 QList<nameaspirant> pn;
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;
836 if(max>0.125 && !pn[maxi].name.isNull()){
838 name.append(pn[maxi].name);
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;
847 if(max>0.125 && !pn[maxi].name.isNull())
848 name.append(
" (").append(pn[maxi].name).append(
")");
852 qSort(wn.begin(),wn.end());
853 if(!wn[0].name.isEmpty()){
857 if(wn.length()>1 && !wn[1].name.isEmpty()
858 && wn[0].d + wn[1].d > 0.66)
859 wname.append(wn[0].name)
863 if(!wname.isEmpty()){
865 name.append(
", ").append(wname);
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(
"]");
877 climbpool[i].name =
new char[strlen(name.toUtf8().data())+1];
878 strcpy(
climbpool[i].name,name.toUtf8().data());
881 QString none =
"none";
882 climbpool[i].name =
new char[strlen(name.toUtf8().data())+1];
883 strcpy(
climbpool[i].name,name.toUtf8().data());
892 climb* c = c0, *clast;
895 if( i > -1) (*wn)[i].
d += c->
via->
d;
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;
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;
912 double fac,
Track* t,
bool validstart){
913 bool calcfromindex = fac < 0;
916 KOO ks = t->get_firstKOO();
917 KOO ke = t->get_lastKOO();
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);
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));
932 if(o->isin(pts->
k,latmin,latmax,lonmin,lonmax)){
933 if(calcfromindex) fac = 1.1*(1-exp(-sqrt(pts->
index/800)));
936 d = distance(ktt.
lat,ktt.lon,pts->
k->
lat,pts->
k->lon);
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));
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));
955 double minlon,
double maxlon){
957 this->maxlat = maxlat;
958 this->minlon = minlon;
959 this->maxlon = maxlon;
void sort_climbpool(long s, long e)
quicksort for collected climbs
double minlat
bounding rect, saved html data is limited to
void calc_climb(climb *c)
calcs P, Pmax, Prec, tst of a climb
KOO * home
cross, climb refers to
Neighbour * via
connection to reach this STRONG
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
Way * way
Neighbour lives uses this Way.
double height(double lon, double lat, void *hc, short mode)
returns height data
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)
void collect_climbs(KOO *k)
picks raw climbs from street net, to be selected (select_climbs())
float index
for summit ranking
climbpoolele * climbpool
container to store climbs when collect_climbs()
KOO * get_first_KOO()
returns root of node-AVL tree
container struct to hold data of a coordinate
short next_d(double lat, double lon, double *d)
searches for closest point on track to point (lat,lon)
climb * cst
start point as climb struct
short branches
count of branching chilf climbs
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
void get_brect(double *latmin, double *latmax, double *lonmin, double *lonmax)
return bounding rect of Track
double ** get_d_h_array_copy()
returns deep copy
short enough_active(climb *c)
checks climb, whether used roads are sufficently independend
routing container struct, connects cross via Way with each other
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
container struct for ClimbAnalyse
main container list climbanalyse
STRONG * s
memory for routing algorithms
climblayer * get_ClimbLayer()
qint64 id
id inherited from OSM data
trackpointlist * t
track profil so far, to trace back
char * name
OSM name of point
holds digital elevation model extracted from SRTM3 data
trackpointlist * tst
start point in track profil
official representation of Track in BTP3
climb * root
root of the whole climb tree
void save_to_png(QString filename)
save map as picture to hard disk
void * from
< pointer to STRONG or FibunacciHeap
plotting 2D-Data sets as the height profile of a track or poweranalysis data
void to_binary_KOO(char *filename)
save binary KOOa to file (website)
short crossunused(climb *c, KOO *k)
varifies, that climb has not used the cross at k before
void select_climbs()
selects collected climbs, if suffiently independed or difficult
climbstate state
current state at ClimbAnalyse
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
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
int tpc
count of trackpoint
Neighbour * neighbours
neigbours to link to other cross
BTP3 database, created from OpenStreetMap data.
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
trackpointlist * add(trackpointlist *tp, trackpoint *t, int tpc, readdirection rd)
adds an branch t to a axisting trackpointlist
float get_bend()
return serpentine index
Neighbour * via
last used link
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
float calc_P(trackpointlist *tp)
calcs climb difficulty with fixed climb end
trackpoint * tp
heighdata of this Neighbour
char * name
name ref owned by lines
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
osm data container list for point like data (summits, towns, ...)
void expand(climb *c)
makes this climb expand over all Neighbour relations