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
9 #include "routedialog.h"
10 #include "ui_routedialog.h"
14 #include <QMessageBox>
16 #include <QFileDialog>
25 Vector() { x=0.; y=0. ; z=0.; };
26 Vector( qreal initX, qreal initY, qreal initZ) { x = initX, y = initY; z = initZ; };
27 void setX( qreal newX) { x = newX; };
28 void setY( qreal newY) { y = newY; };
29 void setZ( qreal newZ) { z = newZ; };
30 qreal getX() { return x; };
31 qreal getY() { return y; };
32 qreal getZ() { return z; };
33 qreal length() { return sqrt(x*x+y*y+z*z); };
34 Vector operator+(Vector v)
36 x = x + v.x; y = y + v.y; z = z + v.z;
39 Vector operator-(Vector v)
41 x = x - v.x; y = y - v.y; z = z - v.z;
44 Vector operator/(qreal c)
46 x = x/c; y = y/c; z = z/c;
49 Vector crossProduct( Vector a, Vector b)
51 x = a.y*b.z - a.z*b.y;
52 y = a.z*b.x - a.x*b.z;
53 z = a.x*b.y - a.y*b.x;
61 Vector atPoint, fromPoint, up, a1, a2, a3;
62 qreal offsx, offsy, offsz;
66 qreal getOffsx() { return offsx; };
67 qreal getOffsy() { return offsx; };
68 qreal getOffsz() { return offsz; };
69 qreal getDval() { return dval; };
70 void setAngle( qreal newA) { angle = newA; };
71 void setUp( qreal newUpX, qreal newUpY, qreal newUpZ)
73 up.setX(newUpX); up.setY(newUpY); up.setZ(newUpZ);
75 void setAtPoint( qreal newX, qreal newY, qreal newZ)
77 atPoint.setX(newX); atPoint.setY(newY); atPoint.setZ(newZ);
79 void setFromPoint(qreal newX, qreal newY, qreal newZ)
81 fromPoint.setX(newX); fromPoint.setY(newY); fromPoint.setZ(newZ);
85 double amarkmag, tempmag;
88 dval = cos(angle/2.0)/sin(angle/2.0);
89 dist = atPoint-fromPoint;
90 amarkmag = dist.length();
93 temp.crossProduct( dist, up);
94 tempmag = temp.length();
97 temp.crossProduct( a1, a3);
98 tempmag = temp.length();
101 offsx = -a1.getX()*fromPoint.getX() - a1.getY()*fromPoint.getY() - a1.getZ()*fromPoint.getZ();
102 offsy = -a2.getX()*fromPoint.getX() - a2.getY()*fromPoint.getY() - a2.getZ()*fromPoint.getZ();
103 offsz = -a3.getX()*fromPoint.getX() - a3.getY()*fromPoint.getY() - a3.getZ()*fromPoint.getZ();
104 QString jono2 = QString("offsx %1 offsy %2 offsz %3").arg(offsx).arg(offsy).arg(offsz);
105 QMessageBox::about(0,"offs x y z", jono2);
107 Vector getAtPoint() { return atPoint; };
108 Vector getFromPoint() { return fromPoint; };
109 Vector getA1() { return a1; };
110 Vector getA2() { return a2; };
111 Vector getA3() { return a3; };
115 qreal xmax, xmin, ymin, ymax; // Limits in world coordinates
117 QList<Vector> vertexList; // Vertecies of route
119 //Vector atPoint, fromPoint, up, a1, a2, a3;
120 //qreal offsx, offsy, offsz;
122 qreal objxmin, objxmax, objymin, objymax, objzmin, objzmax;
124 qreal a, b,c,d; //, dval;
126 #define maxof(val1,val2) ((val1>val2)?val1:val2)
127 #define toradians( degrees) (degrees*0.017453293)
131 int length = 34; // 24;
134 void setAtPoint( Viewing *v);
135 void setFromPoint( Viewing *v);
140 void dataMinMax( void);
144 RouteDialog::RouteDialog(QWidget *parent) :
146 ui(new Ui::RouteDialog)
149 left = 5; top = 5; right = 395; bottom = 195; // Limits in screen coordinates
152 RouteDialog::~RouteDialog()
157 void RouteDialog::changeEvent(QEvent *e)
159 QDialog::changeEvent(e);
161 case QEvent::LanguageChange:
162 ui->retranslateUi(this);
171 * Draws route to the route dialog
175 void RouteDialog::paintEvent(QPaintEvent *)
178 int startx, starty; // Starting point of the route
180 qreal x1, y1, x2, y2;
181 int scx1, scy1, scx2, scy2;
183 QPainter painter(this);
185 painter.setRenderHint(QPainter::Antialiasing, true);
186 painter.setPen(QPen((Qt::white),2));
187 painter.setBrush(QBrush((Qt::yellow), Qt::SolidPattern));
189 // Draw route window frame
190 /*painter.drawLine(left,top,right,top);
191 painter.drawLine(right,top,right,bottom);
192 painter.drawLine(left,top,left,bottom);
193 painter.drawLine(left,bottom,right,bottom);
196 maxi = vertexList.size()-1; // -1 to remove wrong last point !!!
197 for (i=0; i<maxi-1; i++)
199 v1 = vertexList.at(i);
200 v2 = vertexList.at(i+1);
201 x1 = v1.getX(); y1 = v1.getY();
202 x2 = v2.getX(); y2 = v2.getY();
203 //QString jono = QString("x: %1 y: %2").arg(x1).arg(y1);
204 //QMessageBox::about(0,"Tark",jono);
206 scx1 = left + (x1-xmin)/(xmax-xmin)*(right-left);
207 scy1 = top + (ymax-y1)/(ymax-ymin)*(bottom-top);
208 scx2 = left + (x2-xmin)/(xmax-xmin)*(right-left);
209 scy2 = top + (ymax-y2)/(ymax-ymin)*(bottom-top);
211 // Show with circle if starting point
215 startx = scx1; starty = scy1;
216 painter.drawEllipse( scx1-5, scy1-5, 10, 10);
218 painter.drawLine( scx1, scy1, scx2, scy2);
220 // Show the endig point if different than the starting point
221 if (scx2 != startx || scy2 != starty)
223 painter.drawEllipse( scx2-5, scy2-5, 10, 10);
228 void RouteDialog::on_closePushButton_clicked()
233 bool RouteDialog::readRouteFromFile( QString &filename)
240 //file.setFileName("route.txt");
241 QString fileName = QFileDialog::getOpenFileName(this,
242 tr("Read Route"), "./", tr("Route Files (*.txt)"));
244 file.setFileName( fileName);
245 if (!file.open(QIODevice::ReadOnly))
247 QMessageBox::about(0, "Error", "File not found");
253 //while( file.canReadLine())
256 QString str1, str2, str3;
257 rivi = file.readLine();
259 str1 = rivi.section(" ", 0, 0);
260 if (str1.compare("Start:") == 0 || str1.compare("Stop:") == 0)
266 //QMessageBox::about(0, "LUKEE", file.readLine());
267 str1 = rivi.section(" ", 2, 2); // latitude y-value
268 str2 = rivi.section(" ", 4, 4); // longitude x-value
269 str3 = rivi.section(" ", 6, 6); // altitude z-value
270 QString str = QString("la: %1 lo: %2 al: %3").arg(str1).arg(str2).arg(str3);
271 //QMessageBox::about(0, "LUKEE", str);
277 temp.setX( x); // Longitude
278 temp.setY( y);// Latitude
279 temp.setZ( z);// altitude
281 vertexList.append(temp);
291 /*vertexList.append(Vector(0.0, 0.0, 0.0));
292 vertexList.append(Vector(1.0, 1.0, 1.0));
293 vertexList.append(Vector(1.0, 1.0, 0.0));
295 vertexList.append(Vector(1.0, 0.0, 0.0));
296 vertexList.append(Vector(1.0, 0.0, 1.0));
297 vertexList.append(Vector(0.0, 1.0, 1.0));
299 vertexList.append(Vector(0.0, 1.0, 0.0));
300 vertexList.append(Vector(0.0, 0.0, 0.0));
301 vertexList.append(Vector(0.0, 0.0, 1.0));
309 /* connection[0] = 0;
310 connection[1] = 1; connection[2] = 5; connection[3] = 8; connection[4] = -4;
311 connection[5] = 5; connection[6] = 6; connection[7] = 7; connection[8] = -8;
312 connection[9] = 6; connection[10] = 2; connection[11] = 3; connection[12] = -7;
313 connection[13] = 1; connection[14] = 4; connection[15] = 3; connection[16] = -2;
314 connection[17] = 8; connection[18] = 7; connection[19] = 3; connection[20] = -4;
315 connection[21] = 6; connection[22] = 5; connection[23] = 1; connection[24] = -2;*/
317 /******** in 3d use only */
322 //angle = toradians(60);
324 view3d.setUp( 0.0, 0.0, 1.0);
325 view3d.setAngle(toradians(60));
326 setAtPoint( &view3d);
327 xmin = objxmin; xmax = objxmax; ymin = objymin; ymax = objymax;
328 setFromPoint( &view3d);
330 /****** end of 3d *****/
335 * Find out data range for x-, y- and z-coordinates
337 void dataMinMax( void)
343 temp = vertexList.at(0);
344 objxmax = objxmin = temp.getX();
345 objymax = objymin = temp.getY();
346 objzmax = objzmin = temp.getZ();
348 maxi = vertexList.size()-1; // Wrong last data
350 for (i=1; i<maxi; i++)
352 temp = vertexList.at(i);
361 else if (x > objxmax)
370 else if (y > objymax)
379 else if (z > objzmax)
384 //QString jono = QString("ojxmin %1 objxmax %2").arg(objxmin).arg(objxmax);
385 //QString jono = QString("ojymin %1 objymax %2").arg(objymin).arg(objymax);
386 //QString jono = QString("ojzmin %1 objzmax %2").arg(objzmin).arg(objzmax);
387 //QMessageBox::about(0,"Tark", jono);
391 void setAtPoint( Viewing *v)
397 x = (objxmax+objxmin)/2.0;
399 y= (objymax+objymin)/2.0;
401 z= (objzmax+objzmin)/2.0;
402 v->setAtPoint( x, y, z);
403 //QString jono = QString("AtX %1 Aty %2 AtZ %3").arg(atPoint.x()).arg(atPoint.y()).arg(atPoint.z());
404 //QString jono = QString("AtX %1 Aty %2 AtZ %3").arg(atPoint.x).arg(atPoint.y).arg(atPoint.z);
407 test = v->getAtPoint();
408 QString jono = QString("AtX %1 Aty %2 AtZ %3").arg(test.getX()).arg(test.getY()).arg(test.getZ());
409 QMessageBox::about(0,"At point", jono);
413 void setFromPoint( Viewing *v)
417 point = v->getAtPoint();
419 //fromPoint.setX( atPoint.getX() + (objxmax-objxmin)/2.0 + WIDTH*maxof((objzmax-objzmin)/2.0,(objymax-objymin)/2.0));
422 x = point.getX() + 300; //25;
426 z = point.getZ(); // + 150;
427 v->setFromPoint(x,y,z);
428 //QString jono = QString("FromX %1 FromY %2 FromZ %3").arg(fromPoint.x()).arg(fromPoint.y()).arg(fromPoint.z());
429 //QString jono = QString("FromX %1 FromY %2 FromZ %3").arg(fromPoint.x).arg(fromPoint.y).arg(fromPoint.z);
431 test = v->getFromPoint();
432 QString jono = QString("FromX %1 FromY %2 FromZ %3").arg(test.getX()).arg(test.getY()).arg(test.getZ());
433 QMessageBox::about(0,"From point", jono); // (1.9, 0.5, 0.5)
439 double amarkmag, tempmag;
442 dval = cos(angle/2.0)/sin(angle/2.0);
443 dist = atPoint-fromPoint;
444 amarkmag = dist.length();
447 temp.crossProduct( dist, up);
448 tempmag = temp.length();
451 temp.crossProduct( a1, a3);
452 tempmag = temp.length();
455 offsx = -a1.getX()*fromPoint.getX() - a1.getY()*fromPoint.getY() - a1.getZ()*fromPoint.getZ();
456 offsy = -a2.getX()*fromPoint.getX() - a2.getY()*fromPoint.getY() - a2.getZ()*fromPoint.getZ();
457 offsz = -a3.getX()*fromPoint.getX() - a3.getY()*fromPoint.getY() - a3.getZ()*fromPoint.getZ();
458 //QString jono2 = QString("offsx %1 offsy %2 offsz %3").arg(offsx).arg(offsy).arg(offsz);
459 //QMessageBox::about(0,"offs x y z", jono2);
463 #define LEFTEDGE 0x01
464 #define RIGHTEDGE 0x02
465 #define BOTTOMEDGE 0x04
468 * Returns a code specifying which edge in the viewing pyramid was crossed.
469 * There may be more than one.
471 int code( qreal x, qreal y, qreal z)
476 if (x<-z) c |= LEFTEDGE;
477 if (x>z) c |= RIGHTEDGE;
478 if (y<-z) c |= BOTTOMEDGE;
479 if (y>z) c |= TOPEDGE;
484 * Converts clipped world coordinates to screen coordinates.
486 void WORLDtoSCREEN( qreal xWorld, qreal yWorld, int *xScreen, int *yScreen)
488 *xScreen = (int) (a*xWorld+b);
489 *yScreen = (int) (c*yWorld+d);
493 * Clips the line segment in three-dimensional coordinates to the
496 void clip3d( qreal x1, qreal y1, qreal z1, qreal x2, qreal y2, qreal z2, int *xscreen1, int *yscreen1, int *xscreen2, int *yscreen2)
504 while (c1!= NOEDGE || c2 != NOEDGE)
506 if ((c1 & c2 ) != NOEDGE) return;
508 if (c == NOEDGE) c = c2;
509 if ((c&LEFTEDGE) == LEFTEDGE)
512 t = (z1+x1)/((x1-x2)-(z2-z1));
517 else if ((c&RIGHTEDGE) == RIGHTEDGE)
519 // Crosses right edge
520 t = (z1-x1)/((x2-x1)-(z2-z1));
525 else if ((c&BOTTOMEDGE) == BOTTOMEDGE)
527 // Crosses bottom edge
528 t = (z1+y1)/((y1-y2)-(z2-z1));
533 else if ((c&TOPEDGE) == TOPEDGE)
536 t = (z1-y1)/((y2-y1)-(z2-z1));
556 WORLDtoSCREEN(x1/z1,y1/z1,xscreen1, yscreen1);
557 WORLDtoSCREEN(x2/z2,y2/z2,xscreen2, yscreen2);
561 WORLDtoSCREEN(x1,y1,xscreen1, yscreen1);
562 WORLDtoSCREEN(x2,y2,xscreen2, yscreen2);
564 //line( xscreen1, yscreen1, xscreen2, yscreen2);
568 * Transform the segment connecting the two vectors into the viewing plane.
569 * clip3d() clips the line if needed.
571 void transformseg( Viewing *v, Vector *v1, Vector *v2, int *xscreen1, int *yscreen1, int *xscreen2, int *yscreen2 )
574 qreal x1, y1, z1, x2, y2, z2;
575 qreal offsx, offsy, offsz;
581 offsx = v->getOffsx();
582 offsy = v->getOffsy();
583 offsz = v->getOffsz();
586 x1 = (a1.getX()*v1->getX() + a1.getY()*v1->getY() + a1.getZ()*v1->getZ() + offsx)*dval;
587 y1 = (a2.getX()*v1->getX() + a2.getY()*v1->getY() + a2.getZ()*v1->getZ() + offsy)*dval;
588 z1 = a3.getX()*v1->getX() + a3.getY()*v1->getY() + a3.getZ()*v1->getZ() + offsz;
590 x2 = (a1.getX()*v2->getX() + a1.getY()*v2->getY() + a1.getZ()*v2->getZ() + offsx)*dval;
591 y2 = (a2.getX()*v2->getX() + a2.getY()*v2->getY() + a2.getZ()*v2->getZ() + offsy)*dval;
592 z2 = a3.getX()*v2->getX() + a3.getY()*v2->getY() + a3.getZ()*v2->getZ() + offsz;
594 clip3d(x1,y1,z1,x2,y2,z2, xscreen1, yscreen1, xscreen2, yscreen2 );
601 void RouteDialog::paintEvent(QPaintEvent *)
604 int xscreen1, yscreen1, xscreen2, yscreen2;
607 QPainter painter(this);
609 painter.setRenderHint(QPainter::Antialiasing, true);
610 painter.setPen(QPen((Qt::black),2));
611 painter.setBrush(QBrush((Qt::yellow), Qt::SolidPattern));
613 // Draw route window frsme
614 //painter.drawLine(left,top,right,top);
615 //painter.drawLine(right,top,right,bottom);
616 //painter.drawLine(left,top,left,bottom);
617 //painter.drawLine(left,bottom,right,bottom);
622 temp1 = vertexList.at(connection[i-1]);
623 temp2 = vertexList.at(connection[i]);
624 transformseg( &view3d, &temp1,&temp2, &xscreen1, &yscreen1, &xscreen2, &yscreen2);
626 painter.drawLine(xscreen1, yscreen1, xscreen2, yscreen2);
629 painter.drawEllipse( xscreen1-5, yscreen1-5, 10, 10);
639 while (connection[i] > 0)
641 //transformseg( &pa[connection[i-1]],&pa[connection[i]], &xpc1, &ypc1, &xpc2, &ypc2);
642 temp1 = vertexList.at(connection[i-1]);
643 temp2 = vertexList.at(connection[i]);
644 transformseg( &view3d, &temp1,&temp2, &xscreen1, &yscreen1, &xscreen2, &yscreen2);
646 painter.drawLine(xscreen1, yscreen1, xscreen2, yscreen2);
649 painter.drawEllipse( xscreen1-5, yscreen1-5, 10, 10);
654 //transformseg( &pa[connection[i-1]],&pa[-connection[i]],&xpc1, &ypc1, &xpc2, &ypc2);
655 temp1 = vertexList.at(connection[i-1]);
656 temp2 = vertexList.at(-connection[i]);
657 transformseg( &view3d, &temp1,&temp2, &xscreen1, &yscreen1, &xscreen2, &yscreen2);
658 painter.drawLine(xscreen1, yscreen1, xscreen2, yscreen2);
659 // from last segemt to start
660 //transformseg( &pa[-connection[i]],&pa[connection[startofside]],&xpc1, &ypc1, &xpc2, &ypc2);
661 temp1 = vertexList.at(-connection[i]);
662 temp2 = vertexList.at(connection[startofside]);
663 transformseg( &view3d, &temp1,&temp2, &xscreen1, &yscreen1, &xscreen2, &yscreen2);
664 painter.drawLine(xscreen1, yscreen1, xscreen2, yscreen2);