Added routedialog to read route data from file.
[speedfreak] / Client / routedialog.cpp
1 /*
2  * RouteDialog class
3  *
4  * @author     Olavi Pulkkinen <olavi.pulkkinen@fudeco.com>
5  * @copyright  (c) 2010 Speed Freak team
6  * @license    http://opensource.org/licenses/gpl-license.php GNU Public License
7  */
8
9 #include "routedialog.h"
10 #include "ui_routedialog.h"
11 #include <cmath>
12 #include <QPainter>
13 #include <QList>
14 #include <QMessageBox>
15 #include <QFile>
16
17 /*
18   * Vector class
19   */
20 class Vector
21 {
22     qreal x, y, z;
23 public:
24     Vector() { x=0.; y=0. ; z=0.; };
25     Vector( qreal initX, qreal initY, qreal initZ) { x = initX, y = initY; z = initZ; };
26     void setX( qreal newX) { x = newX; };
27     void setY( qreal newY) { y = newY; };
28     void setZ( qreal newZ) { z = newZ; };
29     qreal getX() { return x; };
30     qreal getY() { return y; };
31     qreal getZ() { return z; };
32     qreal length() { return sqrt(x*x+y*y+z*z); };
33     Vector operator+(Vector v)
34     {
35         x = x + v.x; y = y + v.y; z = z + v.z;
36         return *this;
37     };
38     Vector operator-(Vector v)
39     {
40         x = x - v.x; y = y - v.y; z = z - v.z;
41         return *this;
42     };
43     Vector operator/(qreal c)
44     {
45         x = x/c; y = y/c; z = z/c;
46         return *this;
47     };
48     Vector crossProduct( Vector a, Vector b)
49     {
50         x = a.y*b.z - a.z*b.y;
51         y = a.z*b.x - a.x*b.z;
52         z = a.x*b.y - a.y*b.x;
53         return *this;
54     };
55 };
56
57
58 class Viewing
59 {
60     Vector atPoint, fromPoint, up, a1, a2, a3;
61     qreal offsx, offsy, offsz;
62     qreal dval;
63     qreal angle;
64 public:
65     qreal getOffsx() { return offsx; };
66     qreal getOffsy() { return offsx; };
67     qreal getOffsz() { return offsz; };
68     qreal getDval() { return dval; };
69     void setAngle( qreal newA) { angle = newA; };
70     void setUp( qreal newUpX, qreal newUpY, qreal newUpZ)
71     {
72         up.setX(newUpX); up.setY(newUpY); up.setZ(newUpZ);
73     };
74     void setAtPoint( qreal newX, qreal newY, qreal newZ)
75     {
76         atPoint.setX(newX); atPoint.setY(newY); atPoint.setZ(newZ);
77     };
78     void setFromPoint(qreal newX, qreal newY, qreal newZ)
79     {
80         fromPoint.setX(newX); fromPoint.setY(newY); fromPoint.setZ(newZ);
81     }
82     void setEye()
83     {
84         double amarkmag, tempmag;
85         Vector temp, dist;
86
87         dval = cos(angle/2.0)/sin(angle/2.0);
88         dist = atPoint-fromPoint;
89         amarkmag = dist.length();
90         a3 = dist/amarkmag;
91
92         temp.crossProduct( dist, up);
93         tempmag = temp.length();
94         a1 = temp/tempmag;
95
96         temp.crossProduct( a1, a3);
97         tempmag = temp.length();
98         a2 = temp/tempmag;
99
100         offsx = -a1.getX()*fromPoint.getX() - a1.getY()*fromPoint.getY() - a1.getZ()*fromPoint.getZ();
101         offsy = -a2.getX()*fromPoint.getX() - a2.getY()*fromPoint.getY() - a2.getZ()*fromPoint.getZ();
102         offsz = -a3.getX()*fromPoint.getX() - a3.getY()*fromPoint.getY() - a3.getZ()*fromPoint.getZ();
103         QString jono2 = QString("offsx %1 offsy %2 offsz %3").arg(offsx).arg(offsy).arg(offsz);
104         QMessageBox::about(0,"offs x y z", jono2);
105     } ;
106     Vector getAtPoint() { return atPoint; };
107     Vector getFromPoint() { return fromPoint; };
108     Vector getA1() { return a1; };
109     Vector getA2() { return a2; };
110     Vector getA3() { return a3; };
111     Viewing () {};
112 };
113
114 qreal xmax, xmin, ymin, ymax;       // Limits in world coordinates
115
116 QList<Vector> vertexList;           // Vertecies of route
117
118 //Vector atPoint, fromPoint, up, a1, a2, a3;
119 //qreal offsx, offsy, offsz;
120
121 qreal objxmin, objxmax, objymin, objymax, objzmin, objzmax;
122 //qreal angle;
123 qreal a, b,c,d; //, dval;
124
125 #define maxof(val1,val2)  ((val1>val2)?val1:val2)
126 #define toradians( degrees) (degrees*0.017453293)
127
128 #define WIDTH 1.8
129
130 int length = 34; // 24;
131 int connection[50];
132
133 void setAtPoint( Viewing *v);
134 void setFromPoint( Viewing *v);
135 //void setEye();
136
137 Viewing view3d;
138
139 void dataMinMax( void);
140
141
142
143 RouteDialog::RouteDialog(QWidget *parent) :
144     QDialog(parent),
145     ui(new Ui::RouteDialog)
146 {
147     ui->setupUi(this);
148     left = 5; top = 5; right = 395; bottom = 195; // Limits in screen coordinates
149 }
150
151 RouteDialog::~RouteDialog()
152 {
153     delete ui;
154 }
155
156 void RouteDialog::changeEvent(QEvent *e)
157 {
158     QDialog::changeEvent(e);
159     switch (e->type()) {
160     case QEvent::LanguageChange:
161         ui->retranslateUi(this);
162         break;
163     default:
164         break;
165     }
166 }
167
168
169 /**
170   * Draws route to the route dialog
171   * @param QPaintEvent
172  */
173 /* */
174 void RouteDialog::paintEvent(QPaintEvent *)
175 {
176     // 2d draw
177     int startx, starty; // Starting point of the route
178     int i, maxi;
179     qreal x1, y1, x2, y2;
180     int scx1, scy1, scx2, scy2;
181     Vector v1, v2;
182     QPainter painter(this);
183
184     painter.setRenderHint(QPainter::Antialiasing, true);
185     painter.setPen(QPen((Qt::black),2));
186     painter.setBrush(QBrush((Qt::yellow), Qt::SolidPattern));
187
188     // Draw route window frame
189     /*painter.drawLine(left,top,right,top);
190     painter.drawLine(right,top,right,bottom);
191     painter.drawLine(left,top,left,bottom);
192     painter.drawLine(left,bottom,right,bottom);
193     */
194
195     maxi = vertexList.size()-1; // -1 to remove wrong last point !!!
196     for (i=0; i<maxi-1; i++)
197     {
198         v1 = vertexList.at(i);
199         v2 = vertexList.at(i+1);
200         x1 = v1.getX(); y1 = v1.getY();
201         x2 = v2.getX(); y2 = v2.getY();
202         //QString jono = QString("x: %1 y: %2").arg(x1).arg(y1);
203         //QMessageBox::about(0,"Tark",jono);
204
205         scx1 = left + (x1-xmin)/(xmax-xmin)*(right-left);
206         scy1 = top + (ymax-y1)/(ymax-ymin)*(bottom-top);
207         scx2 = left + (x2-xmin)/(xmax-xmin)*(right-left);
208         scy2 = top + (ymax-y2)/(ymax-ymin)*(bottom-top);
209
210         // Show with circle if starting point
211         if (i==0)
212         {
213             // Starting point
214             startx = scx1; starty = scy1;
215             painter.drawEllipse( scx1-5, scy1-5, 10, 10);
216         }
217         painter.drawLine( scx1, scy1, scx2, scy2);
218     }
219     // Show the endig point if different than the starting point
220     if (scx2 != startx || scy2 != starty)
221     {
222         painter.drawEllipse( scx2-5, scy2-5, 10, 10);
223     }
224 }
225 /* */
226
227 void RouteDialog::on_closePushButton_clicked()
228 {
229     close();
230 }
231
232 bool RouteDialog::readRouteFromFile( QString &filename)
233 {
234 /* 2d */
235     Vector temp;
236     int i;
237     QString rivi;
238     QFile file;
239     //file.setFileName("route.txt");
240     file.setFileName( filename);
241     if (!file.open(QIODevice::ReadOnly))
242     {
243         QMessageBox::about(0, "Error", "File not found");
244         return false;
245     }
246
247     vertexList.clear();
248     i = 0;
249     //while( file.canReadLine())
250     while(!file.atEnd())
251     {
252         QString str1, str2, str3;
253         rivi = file.readLine();
254
255         str1 = rivi.section(" ", 0, 0);
256         if (str1.compare("Start:") == 0 || str1.compare("Stop:") == 0)
257         {
258
259         }
260         else
261         {
262             //QMessageBox::about(0, "LUKEE", file.readLine());
263             str1 = rivi.section(" ",  2, 2); // latitude y-value
264             str2 = rivi.section(" ",  4, 4); // longitude x-value
265             str3 = rivi.section(" ",  6, 6); // altitude z-value
266             QString str = QString("la: %1 lo: %2 al: %3").arg(str1).arg(str2).arg(str3);
267             //QMessageBox::about(0, "LUKEE", str);
268
269             double x, y, z;
270             x = str2.toDouble();
271             y = str1.toDouble();
272             z = str3.toDouble();
273             temp.setX( x); // Longitude
274             temp.setY( y);// Latitude
275             temp.setZ( z);// altitude
276
277            vertexList.append(temp);
278         }
279         i++;
280     }
281
282    // la: lo: al:
283     file.close();
284
285    /* */
286      /* for 3D test */
287      /*vertexList.append(Vector(0.0, 0.0, 0.0));
288      vertexList.append(Vector(1.0, 1.0, 1.0));
289      vertexList.append(Vector(1.0, 1.0, 0.0));
290
291      vertexList.append(Vector(1.0, 0.0, 0.0));
292      vertexList.append(Vector(1.0, 0.0, 1.0));
293      vertexList.append(Vector(0.0, 1.0, 1.0));
294
295      vertexList.append(Vector(0.0, 1.0, 0.0));
296      vertexList.append(Vector(0.0, 0.0, 0.0));
297      vertexList.append(Vector(0.0, 0.0, 1.0));
298 */
299      /* For 3d */
300      //int i;
301      for(i= 0; i<35; i++)
302      {
303          connection[i] = i;
304      }
305  /* connection[0] = 0;
306  connection[1] = 1; connection[2] = 5; connection[3] = 8; connection[4] = -4;
307  connection[5] =  5; connection[6] = 6; connection[7] = 7; connection[8] = -8;
308  connection[9] =  6; connection[10] = 2; connection[11] = 3; connection[12] = -7;
309  connection[13] = 1; connection[14] = 4; connection[15] = 3; connection[16] = -2;
310  connection[17] = 8; connection[18] = 7; connection[19] = 3; connection[20] = -4;
311  connection[21] = 6;  connection[22] = 5; connection[23] = 1;  connection[24] = -2;*/
312
313      /********  in 3d use only */
314      a = 400/2.;
315      b = 1 - a*(-1);
316      c = -300/2.;
317      d = 300 - c*(-1);
318      //angle = toradians(60);
319
320      view3d.setUp( 0.0, 0.0, 1.0);
321      view3d.setAngle(toradians(60));
322      setAtPoint( &view3d);
323      xmin = objxmin; xmax = objxmax; ymin = objymin; ymax = objymax;
324      setFromPoint( &view3d);
325      view3d.setEye();
326      /****** end of 3d *****/
327      return true;
328 }
329
330 /*
331   * Find out data range for x-, y- and z-coordinates
332   */
333 void dataMinMax( void)
334 {
335     int i, maxi;
336     qreal x,y,z;
337     Vector temp;
338
339     temp = vertexList.at(0);
340     objxmax = objxmin = temp.getX();
341     objymax = objymin = temp.getY();
342     objzmax = objzmin = temp.getZ();
343
344     maxi = vertexList.size()-1; // Wrong last data
345     //maxi = 9;
346     for (i=1; i<maxi; i++)
347     {
348         temp = vertexList.at(i);
349         x = temp.getX();
350         y = temp.getY();
351         z = temp.getZ();
352
353         if (x < objxmin)
354         {
355                 objxmin = x;
356         }
357         else if (x > objxmax)
358         {
359                objxmax = x;
360         }
361
362         if (y < objymin)
363         {
364                 objymin = y;
365         }
366         else if (y > objymax)
367         {
368                objymax = y;
369         }
370
371         if (z < objzmin)
372         {
373                 objzmin = z;
374         }
375         else if (z > objzmax)
376         {
377                objzmax = z;
378         }
379     }
380     //QString jono = QString("ojxmin %1 objxmax %2").arg(objxmin).arg(objxmax);
381     //QString jono = QString("ojymin %1 objymax %2").arg(objymin).arg(objymax);
382     //QString jono = QString("ojzmin %1 objzmax %2").arg(objzmin).arg(objzmax);
383     //QMessageBox::about(0,"Tark", jono);
384 }
385
386
387 void setAtPoint( Viewing *v)
388 {
389     qreal x, y, z;
390     dataMinMax();
391     Vector test;
392     //atPoint.setX((
393             x = (objxmax+objxmin)/2.0;
394     //atPoint.setY(
395             y= (objymax+objymin)/2.0;
396     //atPoint.setZ(
397             z= (objzmax+objzmin)/2.0;
398             v->setAtPoint( x, y, z);
399     //QString jono = QString("AtX %1 Aty %2 AtZ %3").arg(atPoint.x()).arg(atPoint.y()).arg(atPoint.z());
400     //QString jono = QString("AtX %1 Aty %2 AtZ %3").arg(atPoint.x).arg(atPoint.y).arg(atPoint.z);
401
402     /* *
403     test = v->getAtPoint();
404     QString jono = QString("AtX %1 Aty %2 AtZ %3").arg(test.getX()).arg(test.getY()).arg(test.getZ());
405     QMessageBox::about(0,"At point", jono);
406     * */
407 }
408
409 void setFromPoint( Viewing *v)
410 {
411     qreal x, y, z;
412     Vector point;
413     point = v->getAtPoint();
414     Vector test;
415     //fromPoint.setX( atPoint.getX() + (objxmax-objxmin)/2.0 + WIDTH*maxof((objzmax-objzmin)/2.0,(objymax-objymin)/2.0));
416     //fromPoint.setX(
417             //x = 3.0;
418             x = point.getX() + 300; //25;
419     //fromPoint.setY(
420             y = point.getY();
421     //fromPoint.setZ(
422             z = point.getZ(); // + 150;
423             v->setFromPoint(x,y,z);
424     //QString jono = QString("FromX %1 FromY %2 FromZ %3").arg(fromPoint.x()).arg(fromPoint.y()).arg(fromPoint.z());
425     //QString jono = QString("FromX %1 FromY %2 FromZ %3").arg(fromPoint.x).arg(fromPoint.y).arg(fromPoint.z);
426     /* *
427     test = v->getFromPoint();
428     QString jono = QString("FromX %1 FromY %2 FromZ %3").arg(test.getX()).arg(test.getY()).arg(test.getZ());
429     QMessageBox::about(0,"From point", jono); // (1.9, 0.5, 0.5)
430     * */
431 }
432
433 /*void setEye()
434 {
435     double amarkmag, tempmag;
436     Vector temp, dist;
437
438     dval = cos(angle/2.0)/sin(angle/2.0);
439     dist = atPoint-fromPoint;
440     amarkmag = dist.length();
441     a3 = dist/amarkmag;
442
443     temp.crossProduct( dist, up);
444     tempmag = temp.length();
445     a1 = temp/tempmag;
446
447     temp.crossProduct( a1, a3);
448     tempmag = temp.length();
449     a2 = temp/tempmag;
450
451     offsx = -a1.getX()*fromPoint.getX() - a1.getY()*fromPoint.getY() - a1.getZ()*fromPoint.getZ();
452     offsy = -a2.getX()*fromPoint.getX() - a2.getY()*fromPoint.getY() - a2.getZ()*fromPoint.getZ();
453     offsz = -a3.getX()*fromPoint.getX() - a3.getY()*fromPoint.getY() - a3.getZ()*fromPoint.getZ();
454     //QString jono2 = QString("offsx %1 offsy %2 offsz %3").arg(offsx).arg(offsy).arg(offsz);
455     //QMessageBox::about(0,"offs x y z", jono2);
456 }*/
457
458 #define NOEDGE     0x00
459 #define LEFTEDGE   0x01
460 #define RIGHTEDGE  0x02
461 #define BOTTOMEDGE 0x04
462 #define TOPEDGE    0x08
463 /*
464   * Returns a code specifying which edge in the viewing pyramid was crossed.
465   * There may be more than one.
466   */
467 int code( qreal x, qreal y, qreal z)
468 {
469     int c;
470
471     c = NOEDGE;
472     if (x<-z) c |= LEFTEDGE;
473     if (x>z) c |= RIGHTEDGE;
474     if (y<-z) c |= BOTTOMEDGE;
475     if (y>z) c |= TOPEDGE;
476
477     return c;
478 }
479 /*
480   * Converts clipped world coordinates to screen coordinates.
481   */
482 void WORLDtoSCREEN( qreal xWorld, qreal yWorld, int *xScreen, int *yScreen)
483 {
484    *xScreen = (int) (a*xWorld+b);
485    *yScreen = (int) (c*yWorld+d);
486 }
487
488 /*
489   * Clips the line segment in three-dimensional coordinates to the
490   * viewing pyramid.
491   */
492 void clip3d( qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2, int *xscreen1, int *yscreen1, int *xscreen2, int *yscreen2)
493 {
494     int c,c1,c2;
495     qreal x,y,z,t;
496
497     c1 = code(x1,y1,z1);
498     c2 = code(x2,y2,z2);
499
500     while (c1!= NOEDGE || c2 != NOEDGE)
501     {
502         if ((c1 & c2 ) != NOEDGE) return;
503         c = c1;
504         if (c == NOEDGE) c = c2;
505         if ((c&LEFTEDGE) == LEFTEDGE)
506         {
507                 // Crosses left edge
508                 t = (z1+x1)/((x1-x2)-(z2-z1));
509                 z = t*(z2-z1)+z1;
510                 x = -z;
511                 y = t*(y2-y1)+y1;
512         }
513         else if ((c&RIGHTEDGE) == RIGHTEDGE)
514         {
515                 // Crosses right edge
516                 t = (z1-x1)/((x2-x1)-(z2-z1));
517                 z = t*(z2-z1)+z1;
518                 x = z;
519                 y = t*(y2-y1)+y1;
520         }
521         else if ((c&BOTTOMEDGE) == BOTTOMEDGE)
522         {
523                 // Crosses bottom edge
524                 t = (z1+y1)/((y1-y2)-(z2-z1));
525                 z = t*(z2-z1)+z1;
526                 x = t*(x2-x1)+x1;
527                 y = -z;
528         }
529         else if ((c&TOPEDGE) == TOPEDGE)
530         {
531                 // Crosses top edge
532                 t = (z1-y1)/((y2-y1)-(z2-z1));
533                 z = t*(z2-z1)+z1;
534                 x = t*(x2-x1)+x1;
535                 y = z;
536         }
537
538         if (c == c1)
539         {
540             x1=x; y1=y; z1=z;
541             c1 = code(x,y,z);
542         }
543         else
544         {
545             x2=x; y2=y; z2=z;
546             c2 = code(x,y,z);
547         }
548     }
549
550     if (z1 != 0)
551     {
552         WORLDtoSCREEN(x1/z1,y1/z1,xscreen1, yscreen1);
553         WORLDtoSCREEN(x2/z2,y2/z2,xscreen2, yscreen2);
554     }
555     else
556     {
557         WORLDtoSCREEN(x1,y1,xscreen1, yscreen1);
558         WORLDtoSCREEN(x2,y2,xscreen2, yscreen2);
559     }
560     //line( xscreen1, yscreen1, xscreen2, yscreen2);
561 }
562
563 /*
564   * Transform the segment connecting the two vectors into the viewing plane.
565   * clip3d() clips the line if needed.
566   */
567 void transformseg( Viewing *v, Vector *v1, Vector *v2, int *xscreen1, int *yscreen1, int *xscreen2, int *yscreen2 )
568
569 {
570     qreal x1, y1, z1, x2, y2, z2;
571     qreal offsx, offsy, offsz;
572     qreal dval;
573     Vector a1, a2, a3;
574     a1 = v->getA1();
575     a2 = v->getA2();
576     a3 = v->getA3();
577     offsx = v->getOffsx();
578     offsy = v->getOffsy();
579     offsz = v->getOffsz();
580     dval = v->getDval();
581
582     x1 = (a1.getX()*v1->getX() + a1.getY()*v1->getY() + a1.getZ()*v1->getZ() + offsx)*dval;
583     y1 = (a2.getX()*v1->getX() + a2.getY()*v1->getY() + a2.getZ()*v1->getZ() + offsy)*dval;
584     z1 = a3.getX()*v1->getX() + a3.getY()*v1->getY() + a3.getZ()*v1->getZ() + offsz;
585
586     x2 = (a1.getX()*v2->getX() + a1.getY()*v2->getY() + a1.getZ()*v2->getZ() + offsx)*dval;
587     y2 = (a2.getX()*v2->getX() + a2.getY()*v2->getY() + a2.getZ()*v2->getZ() + offsy)*dval;
588     z2 = a3.getX()*v2->getX() + a3.getY()*v2->getY() + a3.getZ()*v2->getZ() + offsz;
589
590     clip3d(x1,y1,z1,x2,y2,z2, xscreen1, yscreen1, xscreen2, yscreen2 );
591 }
592
593 /*
594   *
595   * 3D route viewing
596 *
597 void RouteDialog::paintEvent(QPaintEvent *)
598 {
599     int i, startofside;
600     int xscreen1, yscreen1, xscreen2, yscreen2;
601     Vector temp1, temp2;
602
603     QPainter painter(this);
604
605     painter.setRenderHint(QPainter::Antialiasing, true);
606     painter.setPen(QPen((Qt::black),2));
607     painter.setBrush(QBrush((Qt::yellow), Qt::SolidPattern));
608
609     // Draw route window frsme
610     //painter.drawLine(left,top,right,top);
611     //painter.drawLine(right,top,right,bottom);
612     //painter.drawLine(left,top,left,bottom);
613     //painter.drawLine(left,bottom,right,bottom);
614
615     i = 1;
616     while (i<length)
617     {
618         temp1 = vertexList.at(connection[i-1]);
619         temp2 = vertexList.at(connection[i]);
620         transformseg( &view3d, &temp1,&temp2, &xscreen1, &yscreen1, &xscreen2, &yscreen2);
621
622         painter.drawLine(xscreen1, yscreen1, xscreen2, yscreen2);
623         if (i==1)
624         {
625             painter.drawEllipse( xscreen1-5, yscreen1-5, 10, 10);
626         }
627         i++;
628     }
629     /*
630     i=1;
631     while(i<length)
632     {
633         startofside = i;
634         i++;
635         while (connection[i] > 0)
636         {
637             //transformseg( &pa[connection[i-1]],&pa[connection[i]], &xpc1, &ypc1, &xpc2, &ypc2);
638             temp1 = vertexList.at(connection[i-1]);
639             temp2 = vertexList.at(connection[i]);
640             transformseg( &view3d, &temp1,&temp2, &xscreen1, &yscreen1, &xscreen2, &yscreen2);
641
642             painter.drawLine(xscreen1, yscreen1, xscreen2, yscreen2);
643             if (i==2)
644             {
645                 painter.drawEllipse( xscreen1-5, yscreen1-5, 10, 10);
646             }
647             i++;
648         }
649         // to last segment
650         //transformseg( &pa[connection[i-1]],&pa[-connection[i]],&xpc1, &ypc1, &xpc2, &ypc2);
651         temp1 = vertexList.at(connection[i-1]);
652         temp2 = vertexList.at(-connection[i]);
653         transformseg( &view3d, &temp1,&temp2, &xscreen1, &yscreen1, &xscreen2, &yscreen2);
654         painter.drawLine(xscreen1, yscreen1, xscreen2, yscreen2);
655         // from last segemt to start
656         //transformseg( &pa[-connection[i]],&pa[connection[startofside]],&xpc1, &ypc1, &xpc2, &ypc2);
657         temp1 = vertexList.at(-connection[i]);
658         temp2 = vertexList.at(connection[startofside]);
659         transformseg( &view3d, &temp1,&temp2, &xscreen1, &yscreen1, &xscreen2, &yscreen2);
660         painter.drawLine(xscreen1, yscreen1, xscreen2, yscreen2);
661         i++;
662     }
663     *
664 }
665 ** */