\( \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
MAP.cpp
1 #include "MAP.h"
2 
4  this->hd = h;
5  this->o = o;
6  width = oldwidth = 0;
7  height = oldheight = 0;
8  minlat0 = 50;
9  minlon0 = 12;
10  maxlat0 = 51;
11  maxlon0 = 14;
12  lowcontour = 10;
13  highcontour = 50;
14  cmap = new QPixmap;
15  hc = NULL;
16  cd = NULL;
17  lineos = 0;
18  h = NULL;
19  wxxold = 0;
20  wyyold = 0;
21  drawcontour = 1;
22  HP[0].setX( 0); HP[0].setY(-3);
23  HP[1].setX(-2); HP[1].setY(-2);
24  HP[2].setX(-1); HP[2].setY(-2);
25  HP[3].setX(0); HP[3].setY(-2);
26  HP[4].setX(1); HP[4].setY(-2);
27  HP[5].setX(2); HP[5].setY(-2);
28  HP[6].setX(-2); HP[6].setY(-1);
29  HP[7].setX(-1); HP[7].setY(-1);
30  HP[8].setX(0); HP[8].setY(-1);
31  HP[9].setX(1); HP[9].setY(-1);
32  HP[10].setX(2); HP[10].setY(-1);
33  HP[11].setX(-3); HP[11].setY(0);
34  HP[12].setX(-2); HP[12].setY(0);
35  HP[13].setX(-1); HP[13].setY(0);
36  HP[14].setX(1); HP[14].setY(0);
37  HP[15].setX(2); HP[15].setY(0);
38  HP[16].setX(3); HP[16].setY(0);
39  HP[17].setX(-2); HP[17].setY(1);
40  HP[18].setX(-1); HP[18].setY(1);
41  HP[19].setX(0); HP[19].setY(1);
42  HP[20].setX(1); HP[20].setY(1);
43  HP[21].setX(2); HP[21].setY(1);
44  HP[22].setX(-2); HP[22].setY(2);
45  HP[23].setX(-1); HP[23].setY(2);
46  HP[24].setX(0); HP[24].setY(2);
47  HP[25].setX(1); HP[25].setY(2);
48  HP[26].setX(2); HP[26].setY(2);
49  HP[27].setX(0); HP[27].setY(3);
50  MS0.minlat = 50;
51  MS0.minlon = 13;
52  MS0.maxlat = 51;
53  MS0.maxlon = 14.5;
54  MS0.roadcolor[0] = QColor(0,0,0).rgba();
55  MS0.roadcolor[1] = QColor(0,0,0).rgba();
56  MS0.roadcolor[2] = QColor(0,0,0).rgba();
57  MS0.roadcolor[3] = QColor(0,0,0).rgba();
58  MS0.roadcolor[4] = QColor(0,0,0).rgba();
59  MS0.roadcolor[5] = QColor(0,0,0).rgba();
60  MS0.roadwidth[0] = 6.;
61  MS0.roadwidth[1] = 4.;
62  MS0.roadwidth[2] = 3.;
63  MS0.roadwidth[3] = 2.;
64  MS0.roadwidth[4] = 1.;
65  MS0.roadwidth[5] = 0.5;
66  MS0.summitcolor = QColor(100,15,0).rgba();
67  MS0.summitsize = 12;
68  MS0.pointsize[0] = 35;
69  MS0.pointsize[1] = 25;
70  MS0.pointsize[2] = 15;
71  MS0.pointsize[3] = 8;
72  MS0.pointcolor[0] = QColor(1,1,1).rgba();
73  MS0.pointcolor[1] = QColor(1,1,1).rgba();
74  MS0.pointcolor[2] = QColor(1,1,1).rgba();
75  MS0.pointcolor[3] = QColor(1,1,1).rgba();
76  MS0.drawcontour = 1;
77  MS0.drawsummit = 1;
78  MS0.drawpoints = 1;
79  MS0.drawwood = 1;
80  MS0.drawstreetcontour = 1;
81  MS0.woodcolor = QColor(0,200,0,50).rgba();
82  MS0.drawater = 1;
83  MS0.watercolor = QColor(0,0,200,100).rgba();
84  MS0.drawscale = 1;
85  MS0.drawstreetlabel = 1;
86  MS0.heightcolor[0] = QColor(228,255,206).rgba();
87  MS0.heightcolor[1] = QColor(215,255,127).rgba();
88  MS0.heightcolor[2] = QColor(255,249,125).rgba();
89  MS0.heightcolor[3] = QColor(197,128, 98).rgba();
90  MS0.heightcolor[4] = QColor(220,220,220).rgba();
91  MS0.heights[0] = 0;
92  MS0.heights[1] = 300;
93  MS0.heights[2] = 600;
94  MS0.heights[3] = 900;
95  MS0.heights[4] = 1200;
96  MS0.sun.I = 5;
97  MS0.sun.azimut = -135;
98  MS0.sun.elevation = 45;
99  MS0.sun.cphi = cos(-MS0.sun.azimut/180.*M_PI);
100  MS0.sun.sphi = sin(-MS0.sun.azimut/180.*M_PI);
101  MS0.sun.ctheta = cos((90-MS0.sun.elevation)/180.*M_PI);
102  MS0.sun.stheta = sin((90-MS0.sun.elevation)/180.*M_PI);
103  MS = &MS0;
104 }
105 MAP::~MAP(void){
106  if (hc != NULL){
107  for(int wx = 0; wx < width+2; wx++){
108  delete(hc[wx]);
109  delete(dhdx[wx]);
110  delete(dhdy[wx]);
111  delete(t[wx]);
112  }
113  delete(hc);
114  delete dhdx;
115  delete dhdy;
116  delete(t);
117  }
118  if(cd != NULL)
119  delete cd;
120  delete cmap;
121 }
123  this->MS = MS;
124 }
125 
126 void MAP::resize(int width, int height){
127  oldwidth = this->width;
128  this->width = width;
129  oldheight = this->height;
130  this->height = height;
131 }
132 void MAP::set_borders(double latmin0, double latmax0,
133  double lonmin0, double lonmax0){
134  minlat = minlat0 = latmin0;
135  maxlat = maxlat0 = latmax0;
136  minlon = minlon0 = lonmin0;
137  maxlon = maxlon0 = lonmax0;
138 }
139 QPixmap* MAP::get_Map(){
140  return cmap;
141 }
143  double middle;
144  /*double q = distance(minlat0,minlon0,maxlat0,minlon0)
145  /distance((minlat0+maxlat0)/2.,minlon0,(minlat0+maxlat0)/2.,maxlon0);
146 
147  if( q > 1.0 * height/width){
148  // specified Area too wide
149  middle = (minlon+maxlon)/2.;
150  minlon = middle - ((middle-minlon0)*width*q/height);
151  maxlon = middle + ((maxlon0-middle)*width*q/height);
152  }
153  else{
154  // specified Area too high
155  middle = (minlat+maxlat)/2;
156  maxlat = middle + ((maxlat0-middle)/width/q*height);
157  minlat = middle - ((middle-minlat0)/width/q*height);
158  }
159  */mmaxlat = lattomercator(maxlat0);
160  mminlat = lattomercator(minlat0);
161  double q = (mminlat-mmaxlat)/(minlon0-maxlon0);
162  if( q > 1.0 * height/width){
163  // specified Area too wide
164  middle = (minlon+maxlon)/2.;
165  minlon = middle - ((middle-minlon0)*width*q/height);
166  maxlon = middle + ((maxlon0-middle)*width*q/height);
167  }
168  else{
169  // specified Area too high
170  middle = (mminlat+mmaxlat)/2;
171  mmaxlat = middle + ((mmaxlat-middle)/width/q*height);
172  mminlat = middle - ((middle-mminlat)/width/q*height);
173  maxlat = mercatortolat(mmaxlat);
174  minlat = mercatortolat(mminlat);
175  }
176  //scaling factors for SRTM3 data cell
177  //(meters per elemenary cell, px per elementary cell
178  middle = (minlat+maxlat)/2;
179  mperlat = float(distance(minlat,minlon,maxlat,minlon)/(maxlat-minlat)*1000/1200);
180  mperlon = float(distance(middle,minlon,middle,maxlon)/(maxlon-minlon)*1000/1200);
181  pxperlat = float(height/(maxlat-minlat)/1200.);
182  pxperlon = float(width/(maxlon-minlon)/1200.);
183  /*zoom in meter/pixel*/
184  zoom = distance((minlat+maxlat)/2,minlon,(minlat+maxlat)/2,maxlon)*1000/width;
185 
186  /*countour step size for the current zoom*/
187  int zoomint = int(zoom);
188  switch(zoomint > 50 ? 4 : zoomint > 30 ? 3:
189  zoomint > 15 ? 2:zoomint <= 15 ? 1:zoomint){
190  case 4: lowcontour = 100; highcontour = 10000; break;
191  case 3: lowcontour = 50; highcontour = 250; break;
192  case 2: lowcontour = 20; highcontour = 100; break;
193  case 1: lowcontour = 10; highcontour = 50; break;
194  }
195  /*recreate picture memory if neccesary*/
196  lineos = 3*width % 4;
197  if(lineos > 0) lineos = 4 - lineos;
198  if((width != oldwidth || height != oldheight)
199  && width != 0 && height != 0){
200  /*delete picture memory an recreate*/
201  if (hc != NULL){
202  for(int wx = 0; wx < oldwidth+2; wx++){
203  delete(hc[wx]);
204  delete(dhdx[wx]);
205  delete(dhdy[wx]);
206  delete(t[wx]);
207  }
208  delete(hc);
209  delete dhdx;
210  delete dhdy;
211  delete(t);
212  }
213  hc= new double*[width+2];
214  dhdx= new double*[width+2];
215  dhdy= new double*[width+2];
216  t = new char*[width+2];
217  for(int wx = 0; wx < width+2; wx++){
218  hc[wx] = new double[height+2];
219  dhdx[wx] = new double[height+2];
220  dhdy[wx] = new double[height+2];
221  t[wx] = new char[height+2];
222  }
223 
224  /*delete and recreate colourdate of every single px*/
225  if(cd != NULL)
226  delete cd;
227  cd = new unsigned char[(3*width+lineos)*height];
228  }
229 }
230 void MAP::SRTM3toMAP(short getcmap){
231  // first extend heighdata area by 1 screen px in every direction
232  double minlatex = mercatortolat(mminlat - (mmaxlat-mminlat)/height);
233  double maxlatex = mercatortolat(mmaxlat + (mmaxlat-mminlat)/height);
234  double minlonex = minlon - (maxlon - minlon)/width;
235  double maxlonex = maxlon + (maxlon - minlon)/width;
236 
237  hd->set_rect(minlatex,maxlatex,minlonex,maxlonex);
238  if(pxperlat < 1)
239  /*map show big area*/
240  //hd->interpolate_linear(width,height,0,hc,dhdx,dhdy);
241  hd->interpolate_linear_mercator(width+2,height+2,0,hc,dhdx,dhdy);
242  else
243  /*map shows small area, detailed presentation necessary*/
244  //hd->interpolate_bicubic_conv3(width,height,0,hc,dhdx,dhdy);
246  add_DEM();
247  if(MS->drawcontour)
248  add_contour();
249  if(getcmap){
250  QImage img(cd,width,height,QImage::Format_RGB888);
251  delete cmap;
252  cmap = new QPixmap(width,height);
253  cmap->convertFromImage(img);
254  }
255 }
257  for(int k = 0; k < width; k++)
258  for(int l = 0; l < height; l++){
259  htocolorfast(&(cd[l*(3*width+lineos)+k*3]),
260  hc[k+1][l+1],
261  dhdx[k+1][l+1]/mperlon,
262  dhdy[k+1][l+1]/mperlat);
263  }
264 }
266  if(drawcontour){
267  /*set important constants for calculation*/
268  double dI[4], f0l, f0h, fnl, fnh;
269  int dx[4]={+1,+1,+1,0};
270  int dy[4]={-1,0,+1,+1};
271  double I[4]={-0.2,-0.4,-0.2,-0.4};
272  int dd[4]={-1,0,1,2};
273  /*for every single px do ...*/
274  for(int x = 0; x < width; x++)
275  for(int y = 0; y < height; y++){
276  f0l = floor(hc[x+1][y+1]/lowcontour);
277  f0h = floor(hc[x+1][y+1]/highcontour);
278  /*... inspect all four neighbour px*/
279  for(int i = 0; i < 4; i++){
280  /*try small contour step first*/
281  fnl = floor(hc[x+1+dx[i]][y+1+dy[i]]/lowcontour);
282  if(f0l != fnl){
283  fnh = floor(hc[x+1+dx[i]][y+1+dy[i]]/highcontour);
284  if(f0h != fnh){
285  /*draw fat line*/
286  fnh=max(fnh,f0h);
287  dI[1] = qAbs(hc[x+1 ][y+1 ] - fnh*highcontour)
288  /qAbs(hc[x+1+dx[i]][y+1+dy[i]] - hc[x+1][y+1]);
289  dI[2] = 1. - dI[1];
290  dI[0] = dI[1] + 1;
291  dI[3] = dI[2] + 1;
292  for(int j = 0; j < 4; j++){
293  if(dI[j] < 0.5) dI[j] = 1.;
294  else dI[j] = qMax(0.,1.5-dI[j]);
295  change_intensity(x+dx[i]*dd[j],y+dy[i]*dd[j],I[i]*dI[j]);
296  }
297  }
298  else{
299  /*draw thin line*/
300  fnl=max(fnl,f0l);
301  change_intensity(x ,y ,I[i]
302  *qAbs(hc[x+1+dx[i]][y+1+dy[i]] - fnl*lowcontour)
303  /qAbs(hc[x+1+dx[i]][y+1+dy[i]] - hc[x+1][y+1]));
304  change_intensity(x+dx[i],y+dy[i],I[i]
305  *qAbs(hc[x+1 ][y+1 ] - fnl*lowcontour)
306  /qAbs(hc[x+1+dx[i]][y+1+dy[i]] - hc[x+1][y+1]));
307  }
308  }
309  }
310  }
311  }
312 }
313 inline void MAP::htocolorfast(unsigned char* cd,float h,float dxf,float dyf){
314  int i = 0;
315  while(h > MS->heights[i+1] && i < 3)
316  i++;
317  float l = qMax(0.,
318  qMin(1.,
319  (MS->heights[i+1]-h)/(MS->heights[i+1]-MS->heights[i])));
320  float r = 1-l;
321 
322  float I = MS->sun.I*((-(dxf*MS->sun.sphi+dyf*MS->sun.cphi)*MS->sun.stheta
323  +MS->sun.ctheta)
324  /sqrt(1+dxf*dxf+dyf*dyf)-MS->sun.ctheta);
325  if(I>0){
326  cd[0] = qMin(uchar(255),
327  uchar((qRed (MS->heightcolor[i])*l+qRed (MS->heightcolor[i+1])*r)/(I+1)
328  + I/(I+1)*255.));
329  cd[1] = qMin(uchar(255),
330  uchar((qGreen(MS->heightcolor[i])*l+qGreen(MS->heightcolor[i+1])*r)/(I+1)
331  + I/(I+1)*255.));
332  cd[2] = qMin(uchar(255),
333  uchar((qBlue (MS->heightcolor[i])*l+qBlue (MS->heightcolor[i+1])*r)/(I+1)
334  + I/(I+1)*255.));
335  }
336  else{
337  cd[0] = uchar((qRed (MS->heightcolor[i])*l+qRed (MS->heightcolor[i+1])*r)/(-I+1));
338  cd[1] = uchar((qGreen(MS->heightcolor[i])*l+qGreen(MS->heightcolor[i+1])*r)/(-I+1));
339  cd[2] = uchar((qBlue (MS->heightcolor[i])*l+qBlue (MS->heightcolor[i+1])*r)/(-I+1));
340  }
341 }
342 void MAP::change_intensity(int x, int y, double dI){
343  if( x >= 0 && x < width && y >= 0 && y < height){
344  unsigned char* c = &(cd[y*(3*width+lineos)+x*3]);
345  if(dI>0){
346  c[0] = c[0]/(1+dI)+255*dI/1+dI;
347  c[1] = c[1]/(1+dI)+255*dI/1+dI;
348  c[2] = c[2]/(1+dI)+255*dI/1+dI;
349  }
350  else{
351  c[0] = c[0]/(1-dI);
352  c[1] = c[1]/(1-dI);
353  c[2] = c[2]/(1-dI);
354  }
355  }
356 }
357 double MAP::getminlat(){
358  return minlat;
359 }
360 double MAP::getminlon(){
361  return minlon;
362 }
363 double MAP::getmaxlat(){
364  return maxlat;
365 }
366 double MAP::getmaxlon(){
367  return maxlon;
368 }
369 int MAP::getwidth(){
370  return width;
371 }
372 int MAP::getheight(){
373  return height;
374 }
375 double MAP::y_to_lat(int y){
376  //return maxlat-(maxlat-minlat)/height*(0.5 + y);
377  return mercatortolat(mmaxlat-(mmaxlat-mminlat)/height*(0.5 + y));
378 }
379 double MAP::x_to_lon(int x){
380  return minlon+(maxlon-minlon)/width*(0.5 + x);
381 }
382 double MAP::lat_to_y(double lat){
383  //return (maxlat-lat)/(maxlat-minlat)*height;
384  return (mmaxlat-lattomercator(lat))/(mmaxlat-mminlat)*height;
385 }
386 double MAP::lon_to_x(double lon){
387  return (lon-minlon)/(maxlon-minlon)*width;
388 }
389 double MAP::xy_to_height(int x, int y){
390  if(x>=0 && x < width && y >= 0 && y < height)
391  return hc[x][y];
392  else
393  return 0;
394 }
395 inline float MAP::lattoy(double lat){
396  //return (maxlat-lat)/(maxlat-minlat)*height;
397  return (mmaxlat-lattomercator(lat))/(mmaxlat-mminlat)*height;
398 }
399 inline float MAP::lontox(double lon){
400  return (lon-minlon)/(maxlon-minlon)*width;
401 }
402 float MAP::get_mperlon(){
403  return mperlon;
404 }
405 float MAP::get_mperlat(){
406  return mperlat;
407 }
408 void MAP::OSMtoMAP(short getcmap,short drawroads, short drawnature , short drawpoints){
409  if(o->get_status() >= 3){
410  reset_Template();
411  if(drawnature && MS->drawwood) facetoTemplate(o->wood,1);
412  if(drawnature && MS->drawater) facetoTemplate(o->water,10);
413  if(drawnature && (MS->drawwood||MS->drawater))
414  TemplatetoColorData();
415  if(getcmap){
416  delete cmap;
417  cmap = new QPixmap(width,height);
418  cmap->fill(Qt::red);
419  }
420  QPainter p(cmap);
421  if(getcmap){
422  QImage img(cd,width,height,QImage::Format_RGB888);
423  p.drawImage(0,0,img);
424  }
425  p.setRenderHint(QPainter::Antialiasing);
426  p.setRenderHint(QPainter::TextAntialiasing);
427 
428  if(drawnature && MS->drawater){
429  linetomap(o,&p,o->creek, QColor(0,0,255,100), zoomsize(1 ),1);
430  linetomap(o,&p,o->river, QColor(0,0,255,100), zoomsize(4 ),1);
431  }
432 
433  if(drawroads){
434  linetomap(o,&p,o->track2, QColor(MS->roadcolor[4]),zoomsize(MS->roadwidth[4]),1);
435  linetomap(o,&p,o->track, QColor(MS->roadcolor[3]),zoomsize(MS->roadwidth[3]),1);
436  linetomap(o,&p,o->secondary,QColor(MS->roadcolor[2]),zoomsize(MS->roadwidth[2]),1);
437  linetomap(o,&p,o->primary, QColor(MS->roadcolor[1]),zoomsize(MS->roadwidth[1]),1);
438  linetomap(o,&p,o->highway, QColor(MS->roadcolor[0]),zoomsize(MS->roadwidth[0]),1);
439  }
440 
441  reset_Template(); // enables space checking for labels
442 
443  if(drawpoints && MS->drawpoints){
444  pointtomap(o,&p,o->metropolis, QColor(MS->pointcolor[0]),zoomsize(MS->pointsize[0]));
445  pointtomap(o,&p,o->city, QColor(MS->pointcolor[1]),zoomsize(MS->pointsize[1]));
446  }
447  if(drawpoints && MS->drawsummit)
448  peaktomap(o,&p,o->peak,0,1e10, QColor(MS->summitcolor), zoomsize(MS->summitsize));
449  if(MS->drawater)
450  rivernametomap(o,&p,o->river, QColor(0,0,60,255), zoomsize(8 ));
451  if(drawpoints && MS->drawpoints)
452  pointtomap(o,&p,o->town, QColor(MS->pointcolor[2]),zoomsize(MS->pointsize[2]));
453  if(MS->drawater)
454  waternametomap(o,&p,o->water, QColor(0,0,60,255), zoomsize(8 ));
455  if(MS->drawater)
456  pointtomap(o,&p,o->village, QColor(MS->pointcolor[3]),zoomsize(MS->pointsize[3]));
457  if(MS->drawstreetlabel){
458  streetnametomap(o,&p,o->primary,QColor(200,200,200),zoomsize(8 ));
459  streetnametomap(o,&p,o->highway,QColor(200,200,200),zoomsize(8 ));
460  }
461  if(MS->drawscale)
462  add_scale(&p);
463  }
464 }
465 void MAP::linetomap(OSM* o, QPainter *p, lines** ll,QColor color,
466  float linewidth, float minlinewidth){
467  if(linewidth >= minlinewidth){
468  QPoint* pts;
469  lines* l = *ll;
470  if(MS->drawstreetcontour)
471  p->setPen(QPen(color,linewidth,Qt::SolidLine,Qt::RoundCap,Qt::RoundJoin));
472  else
473  p->setPen(QPen(color,linewidth));
474  while(l != NULL){
475  if(o->isin(l,minlat,maxlat,minlon,maxlon)){
476  pts = new QPoint[l->way->nodec];
477  for(int i = 0; i < l->way->nodec;i++){
478  pts[i].setX(lontox(l->way->node[i]->lon));
479  pts[i].setY(lattoy(l->way->node[i]->lat));
480  }
481  p->drawPolyline(pts,l->way->nodec);
482  delete pts;
483  }
484  l = l->next;
485  }
486  }
487 }
488 void MAP::facetoTemplate(lines** ff, char val){
489  lines* f = *ff;
490  while(f != NULL){
491  if(o->isin(f,minlat,maxlat,minlon,maxlon)){
492  linestoTemplate(f,val);
493  }
494  f = f->next;
495  }
496 }
497 void MAP::pointtomap(OSM* o, QPainter *p, points** pp,QColor color,float size){
498  if(size>8){
499  QColor btext(color);
500  QColor blight(color.red()*0.1+220,
501  color.green()*0.1+220,
502  color.blue()*0.1+200,
503  20);
504  p->setFont(QFont("Arial",size, QFont::Bold, false));
505  QFontMetricsF fm(p->font());
506  QRectF R;
507  R.setHeight(fm.height());
508  float yoffset = fm.ascent()-fm.strikeOutPos();
509  float yso = fm.strikeOutPos();
510  int x,y;
511  points* pts = *pp;
512  while(pts != NULL){
513  if(o->isin(pts,minlat,maxlat,minlon,maxlon)){
514  x = lontox(pts->k->lon);
515  y = lattoy(pts->k->lat);
516  QString w = QString().fromUtf8(pts->name);
517  R.setWidth(fm.width(w));
518  R.moveTo(x-R.width()/2,y-yoffset);
519  if(check_TemplateSpace(R)){
520  Draw_lighted_text(p,&w,QPointF(R.left(),y+yso),&blight,&btext);
522  }
523  }
524  pts = pts->next;
525  }
526  }
527 }
528 void MAP::peaktomap(OSM* o, QPainter *p, points** pp, float min, float max,
529  QColor color,float size){
530  QBrush btext(color);
531  QBrush blight(QColor(color.red()*0.2+204,
532  color.green()*0.2+204,
533  color.blue()*0.2+204,
534  140));
535  QRectF R;
536  points* pts = *pp;
537  QPointF alignto[3];
538  float size0 = size;
539  int x,y;
540  while(pts != NULL && pts->index >= min){
541  if(pts->index < max &&
542  o->isin(pts,minlat,maxlat,minlon,maxlon)){
543  /*Schriftgroesse auf Berge mit Index 20 normieren, falls zu klein
544  nicht zeichnen*/
545  size = size0 * sqrt(pts->index/1500);
546  if(size > 8){
547  p->setFont(QFont("Arial",size, QFont::Bold, false));
548  x = lontox(pts->k->lon);
549  y = lattoy(pts->k->lat);
550  float size05 = size * 0.5;
551  float frc = 0.3;
552  QString w = QString().fromUtf8(pts->name);
553  QPointF p1(x ,y-size05*1.2);
554  QPointF p2(x+size05*0.866,y+size05*0.5);
555  QPointF p3(x-size05*0.866,y+size05*0.5);
556  QPointF d1(frc*size05,0);
557  QPointF d2(-frc*size05*0.5,frc*size05*0.866);
558  QPointF d3(-frc*size05*0.5,-frc*size05*0.866);
559  QPainterPath Triang;
560  Triang.moveTo(p1);
561  Triang.cubicTo(p1+d1,p2-d2,p2);
562  Triang.cubicTo(p2+d2,p3-d3,p3);
563  Triang.cubicTo(p3+d3,p1-d1,p1);
564  alignto[0].setX(x-5*size); alignto[0].setY(y+1*size);
565  alignto[1].setX(x); alignto[1].setY(y-1.5*size);
566  alignto[2].setX(x+5*size); alignto[2].setY(y+1*size);
567  R = Triang.boundingRect();
568  if(check_TemplateSpace(R))
569  if(Draw_aligned_text(p,&(alignto[0]),3,&w,p1,&blight,&btext)){
570  p->setPen(Qt::NoPen);
571  Draw_lighted_Path(p,&Triang,&blight,&btext);
573  }
574  }
575  }
576  pts = pts->next;
577  }
578 }
579 void MAP::waternametomap(OSM* o, QPainter *p, lines** pp,QColor color,float size){
580  if(size > 8){
581  color.setAlpha(255);
582  QColor btext(color.darker(200));
583  QColor blight(color.red()*0.1+220,
584  color.green()*0.1+220,
585  color.blue()*0.1+220,
586  20);
587  p->setFont(QFont("Arial",size, QFont::Bold, false));
588  QFontMetricsF fm(p->font());
589  QRectF R;
590  R.setHeight(fm.height());
591  float yoffset = fm.ascent()-fm.strikeOutPos();
592  float yso = fm.strikeOutPos();
593  int x,y;
594  lines* pts = *pp;
595 
596  while(pts != NULL){
597  if( pts->name != NULL
598  && o->isin(pts,minlat,maxlat,minlon,maxlon)
599  && (pts->way->maxlon - pts->way->minlon)*
600  (pts->way->maxlat - pts->way->minlat)*mperlat*1200*mperlon*1200
601  > 1000*zoom*zoom){
602  x = lontox((pts->way->maxlon+pts->way->minlon)/2);
603  y = lattoy((pts->way->maxlat+pts->way->minlat)/2);
604  QString w = QString().fromUtf8(pts->name);
605  R.setWidth(fm.width(w));
606  R.moveTo(x-R.width()/2,y-yoffset);
607  if(check_TemplateSpace(R)){
608  Draw_lighted_text(p,&w,QPointF(R.left(),y+yso),&blight,&btext);
610  }
611  }
612  pts = pts->next;
613  }
614  }
615 }
616 void MAP::streetnametomap(OSM* o, QPainter *p, lines** pp,QColor color,float size){
617  QColor btext(color);
618  p->setBrush(QBrush(QColor(50,50,50,150)));
619  p->setFont(QFont("Arial",size, QFont::Bold, false));
620  QFontMetricsF fm(p->font());
621  QRectF R;
622  float yoffset = fm.ascent()-fm.strikeOutPos();
623  float yso = fm.strikeOutPos();
624  int x,y,fwidth;
625  lines* pts = *pp;
626 
627  while(pts != NULL){
628  if(pts->name != NULL){
629  x = lontox(pts->way->node[pts->way->nodec/2]->lon);
630  y = lattoy(pts->way->node[pts->way->nodec/2]->lat);
631  QString w = QString().fromUtf8(pts->name);
632  R.setHeight(fm.height());
633  fwidth = fm.width(w);
634  R.setWidth(fwidth*1.2);
635  R.moveTo(x-R.width()/2,y-yoffset);
636  if(check_TemplateSpace(R)){
637  p->setPen(QColor(0,0,0));
638  p->drawRoundRect(R,25,25);
639  p->setPen(btext);
640  p->drawText(x-fwidth/2,y+yso,w);
641  /*bevor Templatespace setzen, Rechteck aufblähen, da sonst
642  zuviele weitere Beschriftungen eingefuegt werden. Beachte:
643  Die StraĂŸen sind die letzen Beschriftungen in der Karte*/
644  R.adjust(-2*R.width(),-2*R.height(),2*R.width(),2*R.height());
646  }
647  }
648  pts = pts->next;
649  }
650 }
651 void MAP::rivernametomap(OSM* o, QPainter *p, lines** pp,QColor color,float size){
652  if(size > 8){
653  int i,j;
654  color.setAlpha(255);
655  QBrush btext(color.darker(200));
656  QBrush blight(QColor(color.red()*0.2+204,
657  color.green()*0.2+204,
658  color.blue()*0.2+204,
659  140));
660  p->setFont(QFont("Arial",size,QFont::Bold));
661  QFontMetricsF fm(p->font());
662  QPointF P(0.,0.);
663  lines* pts = *pp;
664  QPointF path[1000];
665  float d;
666  QRectF brect;
667  while(pts != NULL){
668  if( pts->name != NULL
669  && o->isin(pts,minlat,maxlat,minlon,maxlon)){
670  // river lies within map and has a name
671  QString w = QString().fromUtf8(pts->name);
672  brect = fm.boundingRect(w);
673  if(
674  sqrt( (pts->way->maxlon - pts->way->minlon)*
675  (pts->way->maxlon - pts->way->minlon)*mperlon*1200*mperlon*1200
676  +(pts->way->maxlat - pts->way->minlat)*
677  (pts->way->maxlat - pts->way->minlat)*mperlon*1200*mperlon*1200)
678  > brect.width()*2*zoom){
679  // river is long enough to be labeled
680  path[0].setX(lontox(pts->way->node[0]->lon));
681  path[0].setY(lattoy(pts->way->node[0]->lat));
682  i = 1;
683  j = 0;
684  d = 0;
685  do{ path[i].setX(lontox(pts->way->node[i]->lon));
686  path[i].setY(lattoy(pts->way->node[i]->lat));
687  d = d+ sqrt((path[i-1].x()-path[i].x())*(path[i-1].x()-path[i].x())
688  +(path[i-1].y()-path[i].y())*(path[i-1].y()-path[i].y()));
689  if(d < brect.width()*1.5) j = i;
690  i++;
691  }while(d < brect.width()*3 && i < pts->way->nodec);
692  if(i != pts->way->nodec){
693  i--;
694  P = path[j];
695  Draw_aligned_text(p,&(path[0]),i,&w,P,&blight,&btext);
696  }
697  }
698  }
699  pts = pts->next;
700  }
701  }
702 }
703 void MAP::add_scale(QPainter *p){
704  QColor b(0,0,0);
705  QColor w(255,255,255,120);
706  QColor wt(255,255,255,20);
707  p->setFont(QFont("Arial",10, QFont::Bold, false));
708  QFontMetricsF fm(p->font());
709  float sd = width/3*zoom/1000;
710  float dsd = float(upperscale(sd/8));
711  int x0 = width/3*2-20;
712  int y0 = height - 20;
713  int width0 = int(floor(dsd*1000/zoom));
714  QRectF R;
715  QPointF P;
716  p->setPen(Qt::NoPen);
717  for(int i = 0; i < sd/dsd-1; i++)
718  if(i % 2 == 0){
719  p->setBrush(w);
720  p->drawRect(x0+i*width0,y0,width0,10);
721  }
722  else{
723  p->setBrush(b);
724  p->drawRect(x0+i*width0,y0,width0,10);
725  }
726 
727  P.setY(0);
728  for(int i = 0; i < sd/dsd; i++){
729  P.setX(x0+i*width0);
730  QString label = QString("%1 km").arg(i*dsd,0,'f',1);
731  R = fm.boundingRect(label);
732  R.translate(x0+i*width0-R.width()/2,y0-5-fm.descent());
733  Draw_lighted_text(p,&label,R.bottomLeft(),&wt,&b);
734  }
735 }
736 void MAP::Draw_lighted_text(QPainter *p, QString* w, QPointF P,
737  QColor* lightcolor, QColor* textcolor){
738  p->setPen(*lightcolor);
739  for(int i = 0; i < 28; i++)
740  p->drawText(P+HP[i],*w);
741  p->setPen(*textcolor);
742  p->drawText(P,*w);
743 }
744 int MAP::Draw_lighted_text(QPainter* p, KOO *k, QString* w,
745  QColor* lightcolor, QColor* textcolor){
746  float x = lontox(k->lon);
747  float y = lattoy(k->lat);
748  QFontMetricsF fm(p->font());
749  QRectF R;
750  R.setHeight(fm.height());
751  float yoffset = fm.ascent()-fm.strikeOutPos();
752  float yso = fm.strikeOutPos();
753  R.setWidth(fm.width(*w));
754  R.moveTo(x-R.width()/2,y-yoffset);
755  if(check_TemplateSpace(R)){
757  Draw_lighted_text(p,w,QPointF(R.left(),y+yso),lightcolor,textcolor);
758  return 1;
759  }
760  else
761  return 0;
762 }
763 
764 float MAP::zoomsize(float size){
765  return size * sqrt(40/zoom);
766 }
767 void MAP::linestoTemplate(lines* f,char val){
768 /*Edge-flag-Algorithmus*/
769  if(f->way->node[0]== f->way->node[f->way->nodec-1]){
770  /*falls eine geschlossene Kurve voliegt*/
771  int i,j,ymin,ymax,xmin;
772  float dxdy;
773  templatepoint* p = new templatepoint[f->way->nodec];
774 
775  /*Koordinaten berechnen*/
776  for(i = 0; i < f->way->nodec; i++){
777  p[i].x = lontox(f->way->node[i]->lon);
778  p[i].y = lattoy(f->way->node[i]->lat);
779  }
780 
781  /*Schablone setzen*/
782  for(i = 0; i < f->way->nodec-1; i++){
783  if(p[i+1].y != p[i].y){
784  /*fallsPolygonteil beitrag liefert*/
785  if(p[i+1].y > p[i].y){
786  ymin = p[i].y;
787  ymax = p[i+1].y;
788  dxdy = float(1.*(p[i+1].x - p[i].x)/(ymax - ymin));
789  xmin = p[i].x;
790  }
791  else{
792  ymin = p[i+1].y;
793  ymax = p[i].y;
794  xmin = p[i+1].x;
795  dxdy = float(1.*(p[i].x - p[i+1].x)/(ymax - ymin));
796  }
797  for(j = ymin; j < ymax; j++)
798  set(xmin+int((j-ymin)*dxdy),j,val);
799  }
800  }
801  delete p;
802  }
803 }
804 void MAP::TemplatetoColorData(){
805  int x , y;
806  int wor = qRed(MS->woodcolor);
807  int wog = qGreen(MS->woodcolor);
808  int wob = qBlue(MS->woodcolor);
809  float woa = 1.*qAlpha(MS->woodcolor)/255.;
810  int war = qRed(MS->watercolor);
811  int wag = qGreen(MS->watercolor);
812  int wab = qBlue(MS->watercolor);
813  float waa = 1.*qAlpha(MS->watercolor)/255.;
814 
815  short wood ,water;
816  for(y = 0; y < height; y++){
817  wood = water = 0;
818  for(x = 0; x < width; x++){
819  if(t[x][y] %10 == 1){
820  if(wood) wood = 0;
821  else wood = 1;
822  }
823  if(t[x][y] >= 10){
824  if(water) water = 0;
825  else water = 1;
826  }
827  if(water == 1){
828  cd[y *(3*width+lineos)+x*3+0] = uchar(cd[y *(3*width+lineos)+x*3+0]*(1-waa)+waa*war);
829  cd[y *(3*width+lineos)+x*3+1] = uchar(cd[y *(3*width+lineos)+x*3+1]*(1-waa)+waa*wag);
830  cd[y *(3*width+lineos)+x*3+2] = uchar(cd[y *(3*width+lineos)+x*3+2]*(1-waa)+waa*wab);
831  }
832  else
833  if(wood == 1){
834  cd[y *(3*width+lineos)+x*3+0] = uchar(cd[y *(3*width+lineos)+x*3+0]*(1-woa)+woa*wor);
835  cd[y *(3*width+lineos)+x*3+1] = uchar(cd[y *(3*width+lineos)+x*3+1]*(1-woa)+woa*wog);
836  cd[y *(3*width+lineos)+x*3+2] = uchar(cd[y *(3*width+lineos)+x*3+2]*(1-woa)+woa*wob);
837  }
838  }
839  }
840 }
841 inline void MAP::set(int x, int y,char val){
842  if(y >= 0 && x < width && y < height){
843  if(x < 0)
844  x = 0;
845  if(val == 10){
846  // water
847  if(t[x][y] >= 10)
848  t[x][y] -= 10;
849  else
850  t[x][y] += 10;
851  }
852  else{
853  // wood
854  if(t[x][y] % 10 == 1)
855  t[x][y] -= 1;
856  else
857  t[x][y] += 1;
858  }
859  }
860 }
861 
863  int i,j;
864  for(i = 0; i < width; i++)
865  for(j = 0; j < height; j++)
866  t[i][j] = 0;
867 }
868 short MAP::check_TemplateSpace(QRectF R){
869  if(R.height() == 0 || R.width() == 0)
870  return 1;
871  short result = 1;
872  int x,y,xmin,xmax,ymin,ymax;
873  if(R.bottom() >= height)ymax = height;
874  else ymax = int(R.bottom()+1);
875  if(R.top() < 0) ymin = 0;
876  else ymin = int(R.top());
877  if(R.right() >= width) xmax = width;
878  else xmax = int(R.right()+1);
879  if(R.left() < 0) xmin = 0;
880  else xmin = int(R.left());
881  for(y = ymin ; y < ymax; y++)
882  for(x = xmin ; x < xmax; x++)
883  if (t[x][y] > 0){
884  y = ymax;
885  x = xmax;
886  result = 0;
887  }
888  return result;
889 }
890 void MAP::set_TemplateSpace(QRectF R){
891  if(R.height() == 0 || R.width() == 0)
892  return;
893  int x,y,xmin,xmax,ymin,ymax;
894  if(R.bottom() >= height) ymax = height;
895  else ymax = int(R.bottom()+1);
896  if(R.top() < 0) ymin = 0;
897  else ymin = int(R.top());
898  if(R.right() >= width) xmax = width;
899  else xmax = int(R.right()+1);
900  if(R.left() < 0) xmin = 0;
901  else xmin = int(R.left());
902  for(y = ymin ; y < ymax; y++)
903  for(x = xmin ; x < xmax; x++)
904  t[x][y] = 1;
905 }
906 short MAP::check_TemplateSpace(QRectF R, char l){
907  if(R.height() == 0 || R.width() == 0)
908  return 1;
909  short result = 1;
910  int x,y,xmin,xmax,ymin,ymax;
911  if(R.bottom() >= height) ymax = height;
912  else ymax = int(R.bottom()+1);
913  if(R.top() < 0) ymin = 0;
914  else ymin = int(R.top());
915  if(R.right() >= width) xmax = width;
916  else xmax = int(R.right()+1);
917  if(R.left() < 0) xmin = 0;
918  else xmin = int(R.left());
919  for(y = ymin ; y < ymax; y++)
920  for(x = xmin ; x < xmax; x++)
921  if (t[x][y] >= l){
922  y = ymax;
923  x = xmax;
924  result = 0;
925  }
926  return result;
927 }
928 void MAP::set_TemplateSpace(QRectF R, char l){
929  if(R.height() == 0 || R.width() == 0)
930  return;
931  int x,y,xmin,xmax,ymin,ymax;
932  if(R.bottom() >= height) ymax = height;
933  else ymax = int(R.bottom()+1);
934  if(R.top() < 0) ymin = 0;
935  else ymin = int(R.top());
936  if(R.right() >= width) xmax = width;
937  else xmax = int(R.right()+1);
938  if(R.left() < 0) xmin = 0;
939  else xmin = int(R.left());
940  for(y = ymin ; y < ymax; y++)
941  for(x = xmin ; x < xmax; x++)
942  t[x][y] = l;
943 }
944 int MAP::IntSec(QRectF R, char l){
945  if(R.height() == 0 || R.width() == 0)
946  return 0;
947  short result = 0;
948  int x,y,xmin,xmax,ymin,ymax;
949  if(R.bottom() >= height) ymax = height;
950  else ymax = int(R.bottom()+1);
951  if(R.top() < 0) ymin = 0;
952  else ymin = int(R.top());
953  if(R.right() >= width) xmax = width;
954  else xmax = int(R.right()+1);
955  if(R.left() < 0) xmin = 0;
956  else xmin = int(R.left());
957  for(y = ymin ; y < ymax; y++)
958  for(x = xmin ; x < xmax; x++)
959  if (t[x][y] >= l)
960  result++;
961  return result;
962 }
963 int MAP::Draw_aligned_text(QPainter* g,QPointF* path,int pointcount, QString*w,
964  QPointF P,QBrush* lightbrush, QBrush* textbrush){
965  int i,j;
966 
967  QMatrix matrix, KOOfwd,KOObwd;
968  QFontMetricsF fm(g->font());
969 
970  QRectF brect,crect;
971  QPointF O(0,0);
972 
973  /*Bestimme die Laenge des zu druckenden Wortes*/
974  int strhigh = w->length();
975  double* x;
976 
977  /*Drehe Koordinatensystem, zuerst Drehwinkel bestimmen*/
978  double PHI;
979  brect = fm.boundingRect(*w);
980  if(sqrt((path[0].y()-path[pointcount-1].y())*(path[0].y()-path[pointcount-1].y())
981  +(path[0].x()-path[pointcount-1].x())*(path[0].x()-path[pointcount-1].x()))
982  < brect.width()){
983  /*falls die Linienenden nah beieinander liegen wird eine Gerade durch
984  die Punktwolke gefittet und aus ihr der Drehwinkel bestimmt*/
985  x = FitPolynom(path,pointcount,1);
986  if(x != NULL) PHI = -atan(x[0])/M_PI*180;
987  else PHI = 90;
988  }
989  else
990  /*sonst wird einfach die durchschnittliche Steiung der Linie fĂ¼r den
991  Drehwinkel herangezogen*/
992  PHI = -atan((path[0].y()-path[pointcount-1].y())/(path[0].x()-path[pointcount-1].x()))/M_PI*180;
993 
994  KOOfwd.reset();
995  KOOfwd.rotate(qreal(PHI));
996  KOOfwd.translate(-path[pointcount/2].x(),-path[pointcount/2].y());
997  for(int i = 0; i < pointcount; i++)
998  path[i] = KOOfwd.map(path[i]);
999  P = KOOfwd.map(P);
1000  KOObwd = KOOfwd.inverted();
1001 
1002  /*Bestimme das Polynom, an dem Text ausgerichet werden soll*/
1003  int grad = min(5,pointcount); //Startwert
1004  x = NULL;
1005  while(x == NULL && grad >= 0){
1006  grad--;
1007  x = FitPolynom(path,pointcount,grad);
1008  }
1009 
1010  /*falls Polynom gefunden wurde, kann die Routine durchgefĂ¼hrt werden*/
1011  if(x != NULL){
1012  /*malt das Polynom
1013  g->setPen(QPen(Qt::white,1));
1014  QPointF polynom[300];
1015  for(j = 0; j < 300; j++){
1016  polynom[j].setX(j-150);
1017  polynom[j].setY(fpln(polynom[j].x(),x,grad));
1018  polynom[j] = KOObwd.map(polynom[j]);
1019  }
1020  g->drawPoints(polynom,300);*/
1021 
1022  /*Lege die Buchstaben an*/
1023  QPainterPath* c = new QPainterPath[strhigh];
1024  float* clen = new float[strhigh];
1025  //länge eines Buchstaben
1026  float* cangle = new float[strhigh];
1027  //Winkel eines Buchstaben, in Grad
1028  float strlenpx = 0, lent = 0;
1029  double em = fm.width('M');
1030  double yoffset = fm.strikeOutPos();
1031  for(i = 0; i < strhigh; i++){
1032  brect = fm.boundingRect(w->mid(i,1));
1033  c[i].addText(0,0,g->font(),w->mid(i,1));
1034  crect = c[i].boundingRect();
1035  clen[i] = qMax(crect.width()*1.4,0.3*em);
1036  strlenpx = strlenpx + clen[i];
1037  c[i].translate(-crect.left(),yoffset);
1038  }
1039 
1040  /*Startpunkte (sp) und Winkel (cangle) der Buchstaben anlegen*/
1041  i = 0;
1042  while(lent < strlenpx/2 && i < strhigh-1){
1043  lent = lent + clen[i];
1044  i++;
1045  }
1046  lent = lent-strlenpx/2;
1047 
1048 
1049  QPointF* sp = new QPointF[strhigh];
1050  float dx = 0, dy = 0;
1051 
1052  /*Zuerst Wort mittig in P platzieren*/
1053  P.setY(fpln(P.x(),x,grad));
1054  while(sqrt(dx*dx+dy*dy) <= lent){
1055  dx = dx + float(0.01);
1056  dy = float(P.y()-fpln(double(P.x() + dx),x,grad));
1057  }
1058  sp[i].setX(P.x() + dx);
1059  sp[i].setY(fpln(sp[i].x(),x,grad));
1060 
1061  /*dann den rechten und linken Worteil ergänzen*/
1062  for(j = i-1; j >= 0; j--){ //linker Wortteil
1063  dx = 0;
1064  dy = 0;
1065  while(sqrt(dx*dx+dy*dy) <= clen[j]){
1066  dx = dx + float(0.01);
1067  dy = sp[j+1].y()-float(fpln(sp[j+1].x()-dx,x,grad));
1068  }
1069  sp[j].setX(sp[j+1].x() - dx);
1070  sp[j].setY(sp[j+1].y() - dy);
1071  cangle[j] = float(atan(dy/dx)/M_PI*180);
1072  }
1073 
1074  for(j = i+1; j < strhigh; j++){ //rechter Wortteil
1075  dx = 0;
1076  dy = 0;
1077  while(sqrt(dx*dx+dy*dy) <= clen[j-1]){
1078  dx = dx + float(0.01);
1079  dy = sp[j-1].y()-float(fpln(sp[j-1].x()+dx,x,grad));
1080  }
1081  sp[j].setX(sp[j-1].x() + dx);
1082  sp[j].setY(sp[j-1].y() - dy);
1083  cangle[j-1] = float(atan(-dy/dx)/M_PI*180);
1084  }
1085 
1086  dx = 0; //Winkel des letzten Buchstaben
1087  dy = 0;
1088  while(sqrt(dx*dx+dy*dy) <= clen[strhigh-1]){
1089  dx = dx + float(0.01);
1090  dy = sp[strhigh-1].y()-float(fpln(sp[strhigh-1].x()+dx,x,grad));
1091  }
1092  cangle[strhigh-1] = float(atan(-dy/dx)/M_PI*180);
1093 
1094  /*Buchstaben an die Richtige Stelle verschieben und
1095  KOO-Ruecktransformation durchfĂ¼hren, Buchstaben wieder zu Wort
1096  zusammenfĂ¼gen und zeichnen*/
1097  QPainterPath cg;
1098  cg.setFillRule(Qt::WindingFill);
1099  int freespace = 1;
1100  QList<QRectF> spacelist;
1101  for(i = 0; i < strhigh; i++){
1102  matrix.reset();
1103  matrix.translate(sp[i].x(),sp[i].y());
1104  matrix.rotate(cangle[i]);
1105  c[i] = matrix.map(c[i]);
1106  c[i] = KOObwd.map(c[i]);
1107  brect = c[i].boundingRect();
1108  if(!check_TemplateSpace(brect)){
1109  freespace = 0;
1110  i = strhigh;
1111  }
1112  else{
1113  cg.addPath(c[i]);
1114  spacelist.append(brect);
1115  }
1116  }
1117  if(freespace){
1118  Draw_lighted_Path(g,&cg,lightbrush,textbrush);
1119  for(i = 0; i < strhigh; i++)
1120  set_TemplateSpace(spacelist.at(i));
1121  }
1122 
1123 
1124  /*Hilfsdaten löschen*/
1125  delete clen;
1126  delete cangle;
1127  delete sp;
1128  delete[] c;
1129 
1130  if(freespace)
1131  return 1;
1132  else
1133  return 0;
1134  }
1135  else
1136  return 0;
1137 }
1138 void MAP::Draw_lighted_Path(QPainter* g, QPainterPath* p,
1139  QBrush* lightbrush,QBrush* textbrush){
1140  g->setPen(QPen(*lightbrush,4.5));
1141  g->setBrush(Qt::NoBrush);
1142  g->drawPath(*p);
1143  g->setPen(Qt::NoPen);
1144  g->setBrush(*textbrush);
1145  g->drawPath(*p);
1146 }
1147 double MAP::scale(){
1148  /*km pro Pixel*/
1149  return zoom/1000.;
1150 }
1151 void MAP::draw_line(QPainter* p, KOOlist* k, int kc){
1152  if(kc > 0){
1153  QPointF* pts = new QPointF[kc];
1154  int ci = 1;
1155  pts[0].setX(lontox(k[0].k->lon));
1156  pts[0].setY(lattoy(k[0].k->lat));
1157  for(int i = 1; i < kc; i++){
1158  pts[ci].setX(lontox(k[i].k->lon));
1159  pts[ci].setY(lattoy(k[i].k->lat));
1160  if((pts[ci]-pts[ci-1]).manhattanLength()>5
1161  || i == kc-1)
1162  ci++;
1163  }
1164  p->drawPolyline(pts,ci);
1165  delete pts;
1166  }
1167 }
1168 void MAP::draw_line(QPainter* p, KOO** k, int count){
1169  QPointF* pts = new QPointF[count];
1170  for(int cp = 0; cp < count; cp++){
1171  pts[cp].setX(lontox(k[cp]->lon));
1172  pts[cp].setY(lattoy(k[cp]->lat));
1173  }
1174  p->drawPolyline(pts,count);
1175  delete pts;
1176 }
1177 void MAP::draw_line(QPainter* p, double** k, int count){
1178  QPointF* pts = new QPointF[count];
1179  for(int cp = 0; cp < count; cp++){
1180  pts[cp].setX(lontox(k[1][cp]));
1181  pts[cp].setY(lattoy(k[0][cp]));
1182  }
1183  p->drawPolyline(pts,count);
1184  delete pts;
1185 }
1186 void MAP::draw_line(QPainter* p, Track* ct){
1187  int kc;
1188  KOOlist* kl;
1189  ct->get_data_ref(NULL,NULL,&kl,&kc);
1190  draw_line(p,kl,kc);
1191  for(int i = 0; i < kc; i++)
1192  if(kl[i].marked)
1193  p->drawEllipse(lon_to_x(kl[i].k->lon)-5,
1194  lat_to_y(kl[i].k->lat)-5,
1195  11,11);
1196 }
1197 void MAP::save_to_png(QString filename){
1198  cmap->save(filename,"PNG");
1199 }
1201  QPainter p(cmap);
1202  p.setRenderHint(QPainter::Antialiasing);
1203  QColor blight(140,140,140,60);
1204  /*Strecken malen*/
1205  for(long i = 0; i < cl->climbcount; i++){
1206  float linewidth = zoomsize(3);
1207  QColor c = colorgradient((sqrt(cl->climb[i].P)-2.23)/7.61);
1208  p.setPen(QPen(Qt::black,linewidth*zoomsize(0.6)+2));
1209  draw_line(&p,cl->climb[i].KOOarray,cl->climb[i].KOOcount);
1210  p.setPen(QPen(c,linewidth*zoomsize(0.6)));
1211  draw_line(&p,cl->climb[i].KOOarray,cl->climb[i].KOOcount);
1212  }
1213  /*Beschriftungen malen*/
1214  QString w;
1215  reset_Template();
1216  for(long i = cl->climbcount - 1; i >= 0 ; i--){
1217  int mindex = cl->climb[i].KOOcount/2;
1218  KOO k;
1219  k.lon = cl->climb[i].KOOarray[1][mindex];
1220  k.lat = cl->climb[i].KOOarray[0][mindex];
1221  if(o->isin(&k,minlat,maxlat,minlon,maxlon)){
1222  QColor c = colorgradient((sqrt(cl->climb[i].P)-2.23)/7.61);
1223  c = c.dark(300);
1224  /*w = QString("%.1f P %.0f Hm\n%.1f %% %.1f S")
1225  .arg(cl->climb[i].P),
1226  .arg(cl->climb[i].hmup,
1227  .arg(cl->climb[i].slope,
1228  .arg(cl->climb[i].bend);*/
1229  w = QString("%1 m").arg(cl->climb[i].P,0,'f',1);
1230  p.setFont(QFont("Arial",8 + 10 * cl->climb[i].LocRank,QFont::Bold));
1231  if(!Draw_lighted_text(&p,&k,&w,&blight,&c)){
1232  int s = 0; short repeat;
1233  do{
1234  if(s > 0) s = -s;
1235  else s = -s + 1;
1236  if((mindex+s)>= 0 && (mindex+s)< cl->climb[i].KOOcount){
1237  k.lon = cl->climb[i].KOOarray[1][mindex];
1238  k.lat = cl->climb[i].KOOarray[0][mindex];
1239  if(Draw_lighted_text(&p,&k,&w,&blight,&c))
1240  repeat = 0;
1241  }
1242  else
1243  repeat = 0;
1244 
1245  }while(repeat);
1246  }
1247  }
1248  }
1249 }
1250 void MAP::STRONGlayer_to_Map(QPainter* p,STRONGlayer* SL){
1251  if(SL->data != NULL){
1252  QPainter* g;
1253  if(p != NULL)
1254  g = p;
1255  else{
1256  g = new QPainter(cmap);
1257  g->setRenderHint(QPainter::Antialiasing);
1258  }
1259  KOO** k;
1260  float linewidth;
1261  float x;
1262  for(int drawblack = 1; drawblack >= 0; drawblack --){
1263  for(long int i = 0; i < SL->ncount; i++){
1264  if(SL->data[i].n != NULL){
1265  k = &(SL->data[i].n->node[0]);
1266  x = sqrt(qMax(float(0.),SL->data[i].index));
1267  linewidth = 1+(4+zoomsize(6.8))*x;
1268  QPointF* p = new QPointF[SL->data[i].n->nodec];
1269  for(int j = 0; j < SL->data[i].n->nodec; j++){
1270  p[j].setX(lontox(k[j]->lon));
1271  p[j].setY(lattoy(k[j]->lat));
1272  }
1273  if(drawblack){
1274  g->setPen(QPen(Qt::black,linewidth,Qt::SolidLine,Qt::RoundCap));
1275  g->drawPolyline(p,SL->data[i].n->nodec);
1276  }
1277  else{
1278  if(linewidth >= 2){
1279  linewidth = linewidth - 2;
1280  g->setPen(QPen(Qt::green,linewidth,Qt::SolidLine,Qt::RoundCap));
1281  g->drawPolyline(p,SL->data[i].n->nodec);
1282  }
1283  }
1284  delete p;
1285  }
1286  }
1287  }
1288  if(p == NULL)
1289  delete g;
1290  }
1291 }
1292 void MAP::add_BestClimb_Bar(QPainter* p,climblayer* cl){
1293  if(cl != NULL){
1294  float bendv;
1295  int vsteps = height / 15;
1296  int hsteps = width / 20;
1297  float *hP = new float[hsteps];
1298  float *hbend = new float[hsteps];
1299  float *hslope = new float[hsteps];
1300  float *vP = new float[vsteps];
1301  float *vbend = new float[vsteps];
1302  float *vslope = new float[vsteps];
1303  for(int i = 0; i < hsteps; i++)
1304  hP[i] = hbend[i] = hslope[i] = 0;
1305  for(int i = 0; i < vsteps; i++)
1306  vP[i] = vbend[i] = vslope[i] = 0;
1307  int ix,iy;
1308  /*Array fuellen*/
1309  for(int i = 0; i < cl->climbcount; i++){
1310  ix = hsteps * lontox(cl->climb[i].midlon)/width;
1311  iy = vsteps * lattoy(cl->climb[i].midlat)/height;
1312  if(ix >= 0 && ix < hsteps && iy >= 0 && iy < vsteps){
1313  bendv = cl->climb[i].bend*cl->climb[i].bend*cl->climb[i].d/48.;
1314  if(cl->climb[i].P > hP[ix])
1315  hP[ix] = cl->climb[i].P;
1316  if(cl->climb[i].slope > hslope[ix])
1317  hslope[ix] = cl->climb[i].slope;
1318  if(bendv > hbend[ix])
1319  hbend[ix] = bendv;
1320  if(cl->climb[i].P > vP[iy])
1321  vP[iy] = cl->climb[i].P;
1322  if(cl->climb[i].slope > vslope[iy])
1323  vslope[iy] = cl->climb[i].slope;
1324  if(bendv > vbend[iy])
1325  vbend[iy] = bendv;
1326  }
1327 
1328  }
1329  /*Arrays zeichnen*/
1330  QPainter* g;
1331  if(p != NULL)
1332  g = p;
1333  else
1334  g = new QPainter(cmap);
1335  g->setRenderHint(QPainter::Antialiasing);
1336  g->setFont(QFont("Arial",10,QFont::Bold));
1337  QString w;
1338  float t,l,rt;
1339  for(int i = 0; i < hsteps; i++){
1340  if(hP[i] > 0){
1341  w = QString("%1").arg(hP[i],0,'f',0);
1342  QColor c = colorgradient((sqrt(hP[i])-2.23)/7.61);
1343  l = 1.*width * i/hsteps;
1344  rt = qMin(width-1.,1.*width * (i+1)/hsteps);
1345  QRectF r; r.setRect(l,height-13.5,rt-l,13);
1346  g->setBrush(QBrush(c));
1347  g->setPen(Qt::NoPen);
1348  g->drawRect(r);
1349  g->setPen(QPen(Qt::black,2));
1350  g->drawText(r,Qt::AlignCenter,w);
1351  g->setPen(QPen(Qt::white,2));
1352  g->drawLine(r.left(),r.top()+1,
1353  r.left()+ r.width()*qMin(1.,double(sqrt(hbend[i]))),r.top()+1);
1354  g->drawLine(r.left(),r.bottom()-1,
1355  r.left()+ r.width()*qMin(1.,double(sqrt(hbend[i]))),r.bottom()-1);
1356  r.moveTop(0.5);
1357  g->setPen(Qt::NoPen);
1358  g->drawRect(r);
1359  g->setPen(QPen(Qt::black,2));
1360  g->drawText(r,Qt::AlignCenter,w);
1361  g->setPen(QPen(Qt::white,2));
1362  g->drawLine(r.left(),r.top()+1,
1363  r.left()+ r.width()*qMin(1.,double(sqrt(hbend[i]))),r.top()+1);
1364  g->drawLine(r.left(),r.bottom()-1,
1365  r.left()+ r.width()*qMin(1.,double(sqrt(hbend[i]))),r.bottom()-1);
1366  }
1367  }
1368  for(int i = 0; i < vsteps; i++){
1369  if(vP[i] > 0){
1370  w = QString("%1").arg(vP[i],0,'f',0);
1371  QColor c = colorgradient((sqrt(vP[i])-2.23)/7.61);
1372  t = floor(1.*height * i/vsteps)+0.5;
1373  QRectF r; r.setRect(0,t,20,14);
1374  g->setBrush(QBrush(c));
1375  g->setPen(Qt::NoPen);
1376  g->drawRect(r);
1377  g->setPen(QPen(Qt::black,2));
1378  g->drawText(r,Qt::AlignCenter,w);
1379  g->setPen(QPen(Qt::white,2));
1380  g->drawLine(r.left(),r.top()+1,
1381  r.left()+ r.width()*qMin(1.,double(sqrt(hbend[i]))),r.top()+1);
1382  g->drawLine(r.left(),r.bottom()-1,
1383  r.left()+ r.width()*qMin(1.,double(sqrt(hbend[i]))),r.bottom()-1);
1384  r.moveRight(width-0.5);
1385  g->setPen(Qt::NoPen);
1386  g->drawRect(r);
1387  g->setPen(QPen(Qt::black,2));
1388  g->drawText(r,Qt::AlignCenter,w);
1389  g->setPen(QPen(Qt::white,2));
1390  g->drawLine(r.left(),r.top()+1,
1391  r.left()+ r.width()*qMin(1.,double(sqrt(hbend[i]))),r.top()+1);
1392  g->drawLine(r.left(),r.bottom()-1,
1393  r.left()+ r.width()*qMin(1.,double(sqrt(hbend[i]))),r.bottom()-1);
1394  }
1395  }
1396  if(p == NULL)
1397  delete g;
1398  if(hsteps>0){
1399  delete hP;
1400  delete hbend;
1401  delete hslope;
1402  }
1403  if(vsteps){
1404  delete vP;
1405  delete vbend;
1406  delete vslope;
1407  }
1408  }
1409 }
1410 void MAP::draw_map(STRONGlayer* SL, climblayer* cl, Track *ct, int fastmode){
1411  if(fastmode || cl == NULL) SRTM3toMAP(0);
1412  else SRTM3ClimbtoMAP(cl);
1413  reset_Template();
1414  if(MS->drawwood) facetoTemplate(o->wood,1);
1415  if(MS->drawater) facetoTemplate(o->water,10);
1416  if(MS->drawater || MS->drawwood)
1417  TemplatetoColorData();
1418  QImage img(cd,width,height,QImage::Format_RGB888);
1419  //QPainter p(cmap);
1420  //p.drawImage(0,0,img);
1421  QPainter p(&img);
1422  p.setRenderHint(QPainter::Antialiasing);
1423  if(MS->drawater){
1424  linetomap(o,&p,o->creek,QColor::fromRgba(MS->watercolor), zoomsize(1 ),1);
1425  linetomap(o,&p,o->river,QColor::fromRgba(MS->watercolor), zoomsize(4 ),1);
1426  }
1427  if(SL != NULL)
1428  STRONGlayer_to_Map(&p,SL);
1429  else{
1430  if(MS->drawstreetcontour){
1431  linetomap(o,&p,o->track, Qt::black,zoomsize(MS->roadwidth[4])+2,3);
1432  linetomap(o,&p,o->secondary,Qt::black,zoomsize(MS->roadwidth[3])+2,3);
1433  linetomap(o,&p,o->primary, Qt::black,zoomsize(MS->roadwidth[2])+2,3);
1434  linetomap(o,&p,o->highway, Qt::black,zoomsize(MS->roadwidth[1])+2,3);
1435  linetomap(o,&p,o->motorWay, Qt::black,zoomsize(MS->roadwidth[0])+2,3);
1436  }
1437  linetomap(o,&p,o->track2, QColor::fromRgba(MS->roadcolor[5]),zoomsize(MS->roadwidth[5]),1);
1438  linetomap(o,&p,o->track, QColor::fromRgba(MS->roadcolor[4]),zoomsize(MS->roadwidth[4]),1);
1439  linetomap(o,&p,o->secondary,QColor::fromRgba(MS->roadcolor[3]),zoomsize(MS->roadwidth[3]),1);
1440  linetomap(o,&p,o->primary, QColor::fromRgba(MS->roadcolor[2]),zoomsize(MS->roadwidth[2]),1);
1441  linetomap(o,&p,o->highway, QColor::fromRgba(MS->roadcolor[1]),zoomsize(MS->roadwidth[1]),1);
1442  linetomap(o,&p,o->motorWay, QColor::fromRgba(MS->roadcolor[0]),zoomsize(MS->roadwidth[0]),1);
1443  }
1444  if(cl != NULL)
1445  ClimbTracks(&p,cl);
1446  if(ct != NULL){
1447  p.setPen(QPen(Qt::green,5));
1448  draw_line(&p,ct);
1449  }
1450  reset_Template();
1451  if(MS->drawpoints){
1452  pointtomap(o,&p,o->metropolis, QColor::fromRgba(MS->pointcolor[0]),zoomsize(MS->pointsize[0]));
1453  pointtomap(o,&p,o->city, QColor::fromRgba(MS->pointcolor[1]),zoomsize(MS->pointsize[1]));
1454  }
1455  if(MS->drawsummit)
1456  peaktomap(o,&p,o->peak,1500,1e10,QColor::fromRgba(MS->summitcolor),zoomsize(MS->summitsize));
1457  if(cl != NULL)
1458  ClimbLabels(&p,cl,fastmode);
1459  if(MS->drawater)
1460  rivernametomap(o,&p,o->river, QColor::fromRgba(MS->watercolor), zoomsize(8 ));
1461  if(MS->drawpoints)
1462  pointtomap(o,&p,o->town, QColor::fromRgba(MS->pointcolor[2]),zoomsize(MS->pointsize[2]));
1463  if(MS->drawsummit)
1464  peaktomap(o,&p,o->peak,0,1500, QColor::fromRgba(MS->summitcolor),zoomsize(MS->summitsize));
1465  if(MS->drawater)
1466  waternametomap(o,&p,o->water, QColor::fromRgba(MS->watercolor), zoomsize(8 ));
1467  if(MS->drawpoints){
1468  pointtomap(o,&p,o->village, QColor::fromRgba(MS->pointcolor[3]),zoomsize(MS->pointsize[3]));
1469  pointtomap(o,&p,o->locality, QColor::fromRgba(MS->pointcolor[4]),zoomsize(MS->pointsize[4]));
1470  pointtomap(o,&p,o->col, QColor::fromRgba(MS->pointcolor[5]),zoomsize(MS->pointsize[5]));
1471  }
1472  if(MS->drawstreetlabel){
1473  rivernametomap(o,&p,o->track2, QColor(1,1,1),zoomsize(8));
1474  rivernametomap(o,&p,o->track, QColor(1,1,1),zoomsize(8));
1475  rivernametomap(o,&p,o->secondary, QColor(1,1,1),zoomsize(4));
1476  rivernametomap(o,&p,o->primary, QColor(1,1,1),zoomsize(4));
1477  rivernametomap(o,&p,o->highway, QColor(1,1,1),zoomsize(4));
1478  rivernametomap(o,&p,o->motorWay, QColor(1,1,1),zoomsize(8));
1479  }
1480  if(MS->drawscale)
1481  add_scale(&p);
1482 
1483  add_BestClimb_Bar(&p,cl);
1484  //p.end();
1485  delete cmap;
1486  //cmap = new QPixmap(width,height);
1487  //cmap->fill(Qt::red);
1488  cmap = new QPixmap(width,height);
1489  //cmap->fill(Qt::red);
1490  cmap->convertFromImage(img);
1491  //QPainter p2(cmap);
1492  //p2.drawImage(0,0,img);
1493 }
1495  // first extend heighdata area by 1 screen px in every direction
1496  double minlatex = mercatortolat(mminlat - (mmaxlat-mminlat)/height);
1497  double maxlatex = mercatortolat(mmaxlat + (mmaxlat-mminlat)/height);
1498  double minlonex = minlon - (maxlon - minlon)/width;
1499  double maxlonex = maxlon + (maxlon - minlon)/width;
1500 
1501  hd->set_rect(minlatex,maxlatex,minlonex,maxlonex);
1502  if(pxperlat < 1)
1503  /*map show big area*/
1504  hd->interpolate_linear_mercator(width+2,height+2,0,hc,dhdx,dhdy);
1505  else
1506  /*map shows small area, detailed presentation necessary*/
1507  hd->interpolate_bicubic_conv3_mercator(width+2,height+2,0,hc,dhdx,dhdy);
1508  add_DEM();
1509  if(MS->drawcontour)
1510  add_contour();
1511  climblayer_schading(cl);
1512 }
1514  if(cl != NULL){
1515  /*Rasterdaten anlegen*/
1516  double d, lat, lon, dx ,dy,gmax = 0;
1517  double spergx = 20;
1518  double spergy = 20;
1519  int gx = width / spergx;
1520  int gy = height / spergy;
1521  spergx = 1.*width / (gx-1);
1522  spergy = 1.*height / (gy-1);
1523 
1524  double **grid = (double**)malloc(gx*sizeof(double*));
1525  for(int x = 0; x < gx; x++)
1526  grid[x] = (double*)malloc(gy*sizeof(double));
1527  for(int x = 0; x < gx; x++)
1528  for(int y = 0; y < gy; y++){
1529  grid[x][y] = 0;
1530  lat = maxlat - (maxlat-minlat)*y/(gy-1);
1531  lon = minlon + (maxlon-minlon)*x/(gx-1);
1532  for(int i = 0; i < cl->climbcount; i++){
1533  d = distance(lat,lon,cl->climb[i].midlat,cl->climb[i].midlon);
1534  grid[x][y] += cl->climb[i].P/(1.+(d*d*d*d*d*d/512./512.));
1535  }
1536  grid[x][y] = sqrt(grid[x][y]);
1537  if(grid[x][y] > gmax)
1538  gmax = grid[x][y];
1539 
1540  }
1541  for(int x = 0; x < gx-1; x++)
1542  for(int y = 0; y < gy-1; y++)
1543  for(int xx = ceil(x * spergx); xx < qMin(double(width-1.),(x+1)*spergx); xx++)
1544  for(int yy = ceil(y * spergy); yy < qMin(double(height-1.),(y+1)*spergy); yy++){
1545  dx = 1.*xx/spergx - x;
1546  dy = 1.*yy/spergy - y;
1547  d = grid[x+0][y+0]*(1-dx) * (1-dy) +
1548  grid[x+1][y+0]*( dx) * (1-dy) +
1549  grid[x+0][y+1]*(1-dx) * ( dy) +
1550  grid[x+1][y+1]*( dx) * ( dy);
1551  d = d / gmax;
1552  QRgb c = colorgradientSchading(d).rgb();
1553  uchar* cdt = &(cd[yy*(3*width+lineos)+xx*3]);
1554  cdt[0] = uchar((1.-MS->climblayershading) * cdt[0] +
1555  MS->climblayershading * cdt[0]* qRed(c)/255.);
1556  cdt[1] = uchar((1.-MS->climblayershading) * cdt[1] +
1557  MS->climblayershading * cdt[1]* qGreen(c)/255.);
1558  cdt[2] = uchar((1.-MS->climblayershading) * cdt[2] +
1559  MS->climblayershading * cdt[2]* qBlue(c)/255.);
1560  }
1561  for(int x = 0; x < gx; x++)
1562  free(grid[x]);
1563  free(grid);
1564  }
1565 }
1566 void MAP::ClimbTracks(QPainter*p,climblayer* cl){
1567  /*Strecken malen*/
1568  for(long i = 0; i < cl->climbcount; i++){
1569  float linewidth = zoomsize(1.8);
1570  QColor c = colorgradient((sqrt(cl->climb[i].P)-2.23)/7.61);
1571  QColor b(0,0,0);
1572  p->setPen(QPen(Qt::black,linewidth+2));
1573  draw_line(p,cl->climb[i].KOOarray,cl->climb[i].KOOcount);
1574  p->setPen(QPen(c,linewidth));
1575  draw_line(p,cl->climb[i].KOOarray,cl->climb[i].KOOcount);
1576  }
1577 }
1578 void MAP::ClimbLabels(QPainter*p,climblayer* cl, int fastmode){
1579  QColor blight(140,140,140,60);
1580  QString w;
1581  for(long i = cl->climbcount - 1; i >= 0 ; i--){
1582  KOO k;
1583  k.lat = cl->climb[i].midlat;
1584  k.lon = cl->climb[i].midlon;
1585  QPointF P(float(lontox(cl->climb[i].midlon)),
1586  float(lattoy(cl->climb[i].midlat)));
1587  if(o->isin(&k,minlat,maxlat,minlon,maxlon)){
1588  QColor c = colorgradient((sqrt(cl->climb[i].P)-2.23)/7.61);
1589  c = c.darker(500);
1590  w = QString("%1").arg(cl->climb[i].P,0,'f',1);
1591  w = QString().fromUtf8(cl->climb[i].name);
1592  p->setPen(c);
1593  p->setFont(QFont("Arial",8 + 10 * cl->climb[i].LocRank,QFont::Bold));
1594  /*nach bestem Labelplatz suchen*/
1595  QFontMetricsF fm(p->font());
1596  QRectF R,Rt;
1597  int drawn = 1, minIntSec = R.height() * R.width()+100;
1598  QPointF Pmin = P;
1599  Track t(cl->climb[i].KOOarray,cl->climb[i].KOOcount);
1600  double d = cl->climb[i].d / 2.;
1601  KOO kt;
1602  int IntSect;
1603  if(fastmode){
1604  for(double dt = 0.0; dt < d; dt += d/3.){
1605  for(int dtm = -1; dtm <= 1; dtm = dtm + 2){
1606  t.extract_KOO(&kt,d+dtm*dt);
1607  P = QPointF(float(lontox(kt.lon)),
1608  float(lattoy(kt.lat)));
1609  R = fm.boundingRect(w);
1610  R.moveTo(P);
1611  R.translate(-R.width()/2,-R.height()/2);
1612  IntSect = IntSec(R,1);
1613  if(IntSect < minIntSec){
1614  /*bisher bester Platz*/
1615  minIntSec = IntSect;
1616  Pmin = P;
1617  }
1618  if(IntSect == 0){
1619  /*perfekter Platz gefunden*/
1620  dtm = 2;
1621  dt = d;
1622 
1623  }
1624  }
1625  }
1626  }
1627  else{
1628  int pr; // plus-radius
1629  int mr; // minus-radius
1630  int j;
1631  int* ref[4][2];
1632  ref[0][0] = &j; ref[0][1] = &pr;
1633  ref[1][0] = &j; ref[1][1] = &mr;
1634  ref[2][0] = &pr; ref[2][1] = &j;
1635  ref[3][0] = &mr; ref[3][1] = &j;
1636  R = fm.boundingRect(w);
1637  int radius = floor(min(R.width(),R.height()));
1638  for(pr = 0; pr <= radius; pr++){
1639  mr = -pr;
1640  for(double dt = 0.0; dt < d; dt += 0.1){
1641  for(int dtm = -1; dtm <= 1; dtm = dtm + 2){
1642  t.extract_KOO(&kt,d+dtm*dt);
1643  P = QPointF(float(lontox(kt.lon)),float(lattoy(kt.lat)));
1644  R = fm.boundingRect(w);
1645  R.moveTo(P);
1646  R.translate(-R.width()/2,-R.height()/2);
1647  for(int k = 0; k < 4; k++){
1648  for(j = -pr; j <= pr; j++){
1649  Rt = R;
1650  Rt.translate(*ref[k][0],*ref[k][1]);
1651  IntSect = IntSec(Rt,1);
1652  if(IntSect < minIntSec){
1653  /*bisher bester Platz*/
1654  minIntSec = IntSect;
1655  Pmin = P + QPointF(float(*(ref[k][0])),
1656  float(*(ref[k][1])));
1657  }
1658  if(IntSect == 0){
1659  /*perfekter Platz gefunden*/
1660  pr = radius;
1661  j = pr + 1;
1662  k = 4;
1663  dtm = 2;
1664  dt = d;
1665 
1666  }
1667  }
1668  }
1669  }
1670  }
1671  }
1672  }
1673  R = fm.boundingRect(w);
1674  R.moveTo(Pmin);
1675  R.translate(-R.width()/2,-R.height()/2);
1676  P = QPointF(R.left(),R.top()+fm.ascent());
1677  if(minIntSec == 0){
1678  Draw_lighted_text(p,&w,P,&blight,&c);
1679  set_TemplateSpace(R,2);
1680  drawn = 1;
1681  }
1682  else{
1683  drawn = 0;
1684  if(fastmode == 0){
1685  float alpha = 255*cl->climb[i].LocRank*(1-1.*minIntSec/(R.width()*R.height()));
1686  c = colorgradient((sqrt(cl->climb[i].P)-2.23)/7.61);
1687  c.setAlpha(alpha);
1688  p->setPen(c);
1689  p->drawText(P,w);
1690  if(alpha > 0.5)
1691  set_TemplateSpace(R,2);
1692  }
1693  }
1694  if(drawn){
1695  float d = - R.left() + R.right();
1696  p->setPen(QPen(c,2));
1697  p->drawLine(R.left(),R.top()+1.,R.right(),R.top()+1.);
1698  p->drawLine(R.left(),R.bottom()-1.,R.right(),R.bottom()-1.);
1699  p->setPen(QPen(Qt::white,2));
1700  p->drawLine(R.left(),R.top()+1.,
1701  R.left() + d *qMin(1.,sqrt(
1702  cl->climb[i].bend*cl->climb[i].bend*cl->climb[i].d/48.)),R.top()+1.);
1703  p->drawLine(R.left(),R.bottom()-1.,
1704  R.left() + d*qMin(1.,(cl->climb[i].slope-5)/10.),R.bottom()-1.);
1705  }
1706  }
1707  }
1708 }
1709 QColor MAP::colorgradient(float x){
1710  if(x<0 ) return QColor( 0, 0, 0);
1711  if(x<0.25) return QColor( 255*x/0.25,255, 0);
1712  if(x<0.50) return QColor( 255,255*(0.50-x)/0.25, 0);
1713  if(x<0.75) return QColor(255,0, (x-0.5)/0.25*255);
1714  if(x<=1) return QColor((1-x)/0.25*255,0,255);
1715  if(x>1) return QColor(0,0,255);
1716  return Qt::black;
1717 }
1718 QColor MAP::colorgradientSchading(float x){
1719  int min = 100;
1720  int d = 255 - min;
1721  if(x<0 ) return QColor( 255, 255, 255);
1722  if(x<0.2) return QColor( min+d*(0.2-x)/0.2,255,min+d*(0.2-x)/0.2);
1723  if(x<0.4) return QColor( min+d*(x-0.2)/0.2,255, min);
1724  if(x<0.6) return QColor( 255,min+d*(0.60-x)/0.2, min);
1725  if(x<0.8) return QColor(255,min, min+d*(x-0.6)/0.2);
1726  if(x<=1) return QColor(min+d*(1-x)/0.2,min,255);
1727  if(x>1) return QColor(min,min,255);
1728  return Qt::black;
1729 }
1730 inline void MAP::mult_color(unsigned char* cd, QColor* c){
1731  cd[0] = cd[0] * c->red() / 255.;
1732  cd[1] = cd[1] * c->green() / 255.;
1733  cd[2] = cd[2] * c->blue() / 255.;
1734 }
points ** locality
&lt; 20 : tag hamlet, locality, isolated_dwelling
Definition: osm.h:72
void SRTM3ClimbtoMAP(climblayer *cl)
climb layer method: SRTM3 DEM plus shading of climbs
Definition: MAP.cpp:1494
void settings(MapSettings *MS)
assigns new settings
Definition: MAP.cpp:122
float mperlat
meter per SRTM3 cell vertical
Definition: MAP.h:146
void add_contour()
adds contours to relief
Definition: MAP.cpp:265
short ** h
Definition: MAP.h:137
void OSMtoMAP(short getcmap, short drawroads, short drawnature, short drawpoints)
draws Open Street Map data
Definition: MAP.cpp:408
int lowcontour
small contour step
Definition: MAP.h:144
double minlon
Definition: MAP.h:105
void reset_Template()
clears tamplate
Definition: MAP.cpp:862
double heights[5]
heights of 5 step color scale
Definition: DataTyps.h:234
void draw_line(QPainter *p, KOOlist *k, int kc)
drawing commends from outside
Definition: MAP.cpp:1151
void set(int x, int y, char val)
edge flag algorithm marking the px(x,y), used by linestoTemplate
Definition: MAP.cpp:841
QPointF HP[28]
help data to render picture
Definition: MAP.h:133
float pxperlon
px per SRTM3 cell horizontal
Definition: MAP.h:149
MAP(HeightData *h, OSM *o)
create with SRTM3 class and OSM-data manager
Definition: MAP.cpp:3
float index
connection to be drawn
Definition: DataTyps.h:346
double maxlat
Definition: MAP.h:105
float stheta
precalculated sin
Definition: DataTyps.h:190
double ** dhdy
Definition: MAP.h:136
short lineos
Definition: MAP.h:140
float sphi
precalculated sin
Definition: DataTyps.h:188
double scale()
Definition: MAP.cpp:1147
void STRONGlayer_to_Map(QPainter *p, STRONGlayer *SL)
draws STRONG calculation network
Definition: MAP.cpp:1250
short isin(lines *l, double minlat, double maxlat, double minlon, double maxlon)
Definition: osm.cpp:670
double maxlat0
Definition: MAP.h:100
void add_DEM()
transform heighdata with sun settings into colors
Definition: MAP.cpp:256
double getminlat()
return real borders
Definition: MAP.cpp:357
float maxlon
bounding rect, for rendering
Definition: DataTyps.h:126
double ** hc
Definition: MAP.h:134
float index
for summit ranking
Definition: DataTyps.h:139
list elements to handle multiple STRONGlayers
Definition: DataTyps.h:349
container struct to hold data of a coordinate
Definition: DataTyps.h:82
QRgb roadcolor[6]
color for all different road types
Definition: DataTyps.h:217
KOO ** node
reference to KOO (of way)
Definition: DataTyps.h:61
double lat
Definition: DataTyps.h:86
lines ** water
Definition: osm.h:70
QRgb heightcolor[5]
5 step color scale
Definition: DataTyps.h:233
void SRTM3toMAP(short getcmap)
draws the relief
Definition: MAP.cpp:230
lines ** creek
Definition: osm.h:70
short wxxold
Definition: MAP.h:142
float zoom
meter per px
Definition: MAP.h:150
short extract_KOO(KOO *k, double d)
creates KOO refering distance point d
Definition: track.cpp:358
float zoomsize(float size)
Definition: MAP.cpp:764
lines ** track2
Definition: osm.h:70
lines ** primary
Definition: osm.h:70
int highcontour
big contour step
Definition: MAP.h:145
void facetoTemplate(lines **ff, char val)
fills areas marked by edge flag algorithm
Definition: MAP.cpp:488
void climblayer_schading(climblayer *cl)
climb layer method: shading called from SRTM3ClimbtoMAP()
Definition: MAP.cpp:1513
int nodec
count of used KOO in way
Definition: DataTyps.h:59
QColor colorgradient(float x)
color functions
Definition: MAP.cpp:1709
KOO * k
reference to KOO
Definition: DataTyps.h:138
lines ** secondary
Definition: osm.h:70
double minlon0
Definition: MAP.h:100
unsigned char * cd
Definition: MAP.h:138
double maxlon
Definition: DataTyps.h:216
short check_TemplateSpace(QRectF R)
check R on the picture if free
Definition: MAP.cpp:868
float pxperlat
px per SRTM3 cell vertical
Definition: MAP.h:148
void linetomap(OSM *o, QPainter *p, lines **ll, QColor QColor, float linewidth, float minlinewidth)
OSM drawing.
Definition: MAP.cpp:465
char * name
OSM name of point
Definition: DataTyps.h:140
holds digital elevation model extracted from SRTM3 data
Definition: HeightData.h:26
void ClimbTracks(QPainter *p, climblayer *cl)
climb layer method: draw tracks
Definition: MAP.cpp:1566
official representation of Track in BTP3
Definition: track.h:14
void set_rect(double minlat, double maxlat, double minlon, double maxlon)
specifies area of the precalculated data grid
Definition: HeightData.cpp:11
points ** col
mountain pass
Definition: osm.h:72
double mmaxlat
marcator projection scaled lattitude
Definition: MAP.h:110
void save_to_png(QString filename)
save map as picture to hard disk
Definition: MAP.cpp:1197
void resize(int width, int height)
adapts size, recalculate borders from desired borders
Definition: MAP.cpp:126
double y_to_lat(int y)
map coordinate information
Definition: MAP.cpp:375
void interpolate_bicubic_conv3_mercator(int width, int height, double alpha, double **h, double **dhdx, double **dhdy)
returns heigth data grid h with size (width,height)
Definition: HeightData.cpp:194
double maxlon
Definition: MAP.h:105
SunSetting sun
lighting of relief
Definition: DataTyps.h:236
int width
specified picture format
Definition: MAP.h:98
QRgb pointcolor[6]
fontcolor of town, village, ...
Definition: DataTyps.h:222
float mperlon
meter per SRTM3 cell horizontal
Definition: MAP.h:147
float I
intensity
Definition: DataTyps.h:187
void set_borders(double latmin0, double latmax0, double lonmin0, double lonmax0)
sets desired borders, recalculate bordes due to window size
Definition: MAP.cpp:132
points ** peak
summit
Definition: osm.h:72
points ** city
10000
Definition: osm.h:72
KOO ** node
array KOO pointers
Definition: DataTyps.h:125
short wyyold
Definition: MAP.h:143
char ** t
Definition: MAP.h:192
double maxlon0
Definition: MAP.h:100
double minlat0
desired area with ordinary coordinates
Definition: MAP.h:100
QPixmap * get_Map()
return pixmap of the last generated map
Definition: MAP.cpp:139
void calc_borders()
desired borders to real borders
Definition: MAP.cpp:142
void set_TemplateSpace(QRectF R)
marks R on the picture as occupied
Definition: MAP.cpp:890
char * name
OSM name of line
Definition: DataTyps.h:146
void draw_map(STRONGlayer *SL, climblayer *cl, Track *ct, int fastmode)
universal high quality drawing
Definition: MAP.cpp:1410
BTP3 database, created from OpenStreetMap data.
Definition: osm.h:34
void ClimbLabels(QPainter *p, climblayer *cl, int fastmode)
climb layer method: draw labels
Definition: MAP.cpp:1578
lines ** wood
Definition: osm.h:70
int IntSec(QRectF R, char l)
quantifies l-content in r-region
Definition: MAP.cpp:944
lines ** highway
Definition: osm.h:70
points ** metropolis
100000 : tag city
Definition: osm.h:72
double minlat
smaller area inside desired conform width picture scales
Definition: MAP.h:105
float pointsize[6]
fontsize of town, village, ...
Definition: DataTyps.h:221
void linestoTemplate(lines *f, char val)
edge flag algorithm to draw polyedges
Definition: MAP.cpp:767
void interpolate_linear_mercator(int width, int height, double alpha, double **h, double **dhdx, double **dhdy)
returns heigth data grid h with size (width,height)
Definition: HeightData.cpp:498
void change_intensity(int x, int y, double dI)
Definition: MAP.cpp:342
lines ** track
Definition: osm.h:70
void add_BestClimb_Bar(QPainter *p, climblayer *cl)
projects best climbs to the borders of the picture
Definition: MAP.cpp:1292
void htocolorfast(unsigned char *cd, float h, float dxf, float dyf)
function to height to color operation
Definition: MAP.cpp:313
main container for Track, WayHeight and ClimbAnalyse
Definition: DataTyps.h:172
osm data container list for line like data (roads, rivers)
Definition: DataTyps.h:143
float roadwidth[6]
width for all different road types
Definition: DataTyps.h:218
float ctheta
precalculated cos
Definition: DataTyps.h:191
osm data container list for point like data (summits, towns, ...)
Definition: DataTyps.h:137
void climblayer_to_map(climblayer *cl)
draws climbs
Definition: MAP.cpp:1200
int nodec
count of KOO
Definition: DataTyps.h:124
float cphi
precalculated cos
Definition: DataTyps.h:189
int get_status()
returns current class state
Definition: osm.cpp:790
points ** village
20 : tag village, suburban
Definition: osm.h:72
double ** dhdx
Definition: MAP.h:135
points ** town
3000 : tag town
Definition: osm.h:72
Way * way
reference element of this list
Definition: DataTyps.h:144
lines ** motorWay
Definition: osm.h:70
lines ** river
Definition: osm.h:70