#include "QtGuiFwd.hpp"
#include <QApplication>
#include <QStatusBar>
#include <QMouseEvent>
#include <QBrush>
#include <QPen>
#include <QLine>
#include <QSize>
#include <QMenuBar>
#include <QMessageBox>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
ISeeMLFrame frame("ISeeML V1.0 Qt Interface");
frame.show();
return app.exec();
}
void ISeeMLDrawingArea::mousePressEvent(QMouseEvent *event) {
movingConfig = !movingConfig;
mouseMoveEvent(event);
QString msg;
if (movingConfig) {
setMouseTracking(true);
msg = msg + "Clic to fix, use wheel, arrows or" +
" page up/down to change orientation";
} else {
setMouseTracking(false);
msg += "Clic to modify goal configuration";
}
parentFrame->statusBar()->showMessage(msg);
}
void ISeeMLDrawingArea::mouseMoveEvent(QMouseEvent *event) {
if (movingConfig) {
const OrPtConfig newGoal( (event->x() - centerPoint.x()) / scale,
(-event->y()+ centerPoint.y()) / scale,
goal.orientation() ); ;
changeGoal(newGoal);
}
}
void ISeeMLDrawingArea::wheelEvent(QWheelEvent *event) {
if (movingConfig) {
static const double PI_196 = M_PI / 196, PI_28 = M_PI / 28,
PI_4 = M_PI / 4;
const int change = goal.sign( event->delta() );
double newTh = goal.orientation();
if (event->modifiers() & Qt::ShiftModifier)
newTh += change * PI_4;
else if (event->modifiers() & Qt::ControlModifier)
newTh += change * PI_196;
else newTh += change * PI_28;
changeGoal(newGoal);
}
}
void ISeeMLDrawingArea::resizeEvent(QResizeEvent *event) {
const QSize& sz = event->size();
centerPoint = QPoint(sz.width() / 2, sz.height() / 2);
}
void ISeeMLDrawingArea::paintEvent(QPaintEvent *) {
static const QBrush cvGP;
static const QPen
bgGP(Qt::white), configGP(Qt::red),
#ifndef SHOW_TYPE
dubinsGP(Qt::blue), fscpGP(Qt::green),
#endif
dubinsTCGP(QColor("darkorange"), 1, Qt::DashLine),
fscpTCGP(QColor("gold"), 1, Qt::DashLine);
QPainter pntr(this);
if (drawing) pntr.setPen(configGP);
else pntr.setPen(bgGP);
pntr.setBrush(cvGP);
draw(pntr, start);
draw(pntr, goal);
if (drawing && drawDubins) {
#ifndef SHOW_TYPE
pntr.setPen(dubinsGP);
#endif
draw(pntr, dubins);
if (showTC) {
pntr.setPen(dubinsTCGP);
drawTC(pntr, dubins);
}
}
if (drawing && drawFSC) {
#ifndef SHOW_TYPE
pntr.setPen(fscpGP);
#endif
draw(pntr, fscp);
if (showTC) {
pntr.setPen(fscpTCGP);
drawTC(pntr, fscp);
}
}
}
void ISeeMLDrawingArea::keyPressEvent(QKeyEvent *event) {
static const double PI_196 = M_PI / 196, PI_28 = M_PI / 28,
PI_4 = M_PI / 4;
double newTh = goal.orientation();
bool handled = movingConfig;
if (movingConfig)
switch ( event->key() ) {
case Qt::Key_Home : newTh = 0; break;
case Qt::Key_End : newTh = M_PI; break;
case Qt::Key_PageUp : newTh += PI_4; break;
case Qt::Key_PageDown: newTh -= PI_4; break;
case Qt::Key_Up : newTh += PI_28; break;
case Qt::Key_Down : newTh -= PI_28; break;
case Qt::Key_Right : newTh += PI_196; break;
case Qt::Key_Left : newTh -= PI_196; break;
default: handled = false;
}
if (handled) {
changeGoal(newGoal);
}
else
QWidget::keyPressEvent(event);
}
void ISeeMLDrawingArea::draw(QPainter& pntr,
const OrPtConfig& q) {
const static int configSize = 20;
QPoint startP = dblPt2intPt( q.
position() );
hfMn = (di + dj) / 4, delta = (di - dj) / 4,
iF = startP.x() + di, jF = startP.y() + dj;
pntr.drawLine(startP.x(), startP.y(), iF, jF);
pntr.drawLine(iF, jF, iF - hfMn, jF + delta);
pntr.drawLine(iF, jF, iF - delta, jF - hfMn);
}
void ISeeMLDrawingArea::draw(QPainter& pntr,
#define rad2int(th) (int)( (th) * 16 * 180 / M_PI )
#ifdef SHOW_TYPE
static const QPen lineGP(QColor("limegreen"), 2),
circleGP(QColor("blue"), 2), transGP(QColor("cyan"), 2);
#endif
QPoint endP = dblPt2intPt( linPiece.
end().
position() );
if (linPiece.
length() > 1.5 / scale)
#ifdef SHOW_TYPE
pntr.setPen(lineGP);
#endif
pntr.drawLine( startP.x(), startP.y(), endP.x(), endP.y() );
} else {
const double rad = fabs( 1 / start.
curvature() );
Pi_2 = 90 * 16;
+ v.rotate(M_PI_2) * sgnTrn * rad;
const QPoint hautGch = dblPt2intPt(cntr - diag * rad),
basDt = dblPt2intPt(cntr + diag * rad);
const int minX = hautGch.x(), minY = hautGch.y(),
dX = basDt.x() - minX, dY = basDt.y() - minY,
startAngle = startOr - sgnTrn * Pi_2;
int diffAngle = endOr - startOr;
if (diffAngle * sgnTrn < 0)
diffAngle += sgnTrn * 360 * 16;
#ifdef SHOW_TYPE
pntr.setPen(circleGP);
#endif
pntr.drawArc(minX, minY, dX, dY, startAngle, diffAngle);
startOr = endOr;
}
else {
const double step = 5. / scale;
double arcLngth = step;
#ifdef SHOW_TYPE
pntr.setPen(transGP);
#endif
while (arcLngth < linPiece.
length()) {
QPoint midP =
dblPt2intPt( linPiece[arcLngth].position() );
pntr.drawLine( startP.x(), startP.y(), midP.x(), midP.y() );
startP = midP;
arcLngth += step; }
pntr.drawLine( startP.x(), startP.y(), endP.x(), endP.y() );
startOr = endOr; }
else
pntr.drawLine( startP.x(), startP.y(), endP.x(), endP.y() );
startP = endP;
}
#undef rad2int
}
void ISeeMLDrawingArea::drawTC(QPainter& pntr,
pntr.drawEllipse(dblPt2intPt(centers[i]), radius, radius);
}
void ISeeMLDrawingArea::changeGoal(
const OrPtConfig& q){
draw(false);
goal = q;
dubins.connect(start, goal);
fscp.connect(start, goal);
draw();
}
ISeeMLFrame::ISeeMLFrame(const QString& title)
: drawingArea(*this, 50) {
int idx;
setWindowTitle(title);
QMenuBar *menuBar = new QMenuBar;
QMenu *menu = new QMenu(tr("File"), menuBar);
menu->addAction(tr("Exit"), this, SLOT( close() ), 'X')
->setStatusTip( tr("Close GUI and quit") );
menuBar->addMenu(menu);
menu = new QMenu(tr("Edit"), menuBar);
menuBar->addMenu(menu);
menu = new QMenu(tr("View"), menuBar);
QMenu *pathVisible = menu->addMenu( tr("Drawn Paths") );
QActionGroup *pathGroup = new QActionGroup(pathVisible);
static const char *pathLabels[nbPathShow][3] =
{ {"Dubins", "D", "Only draw Dubins' path"},
{"Linear Curvature (FSCP)", "L", "Only draw FSC path"},
{"Both", "B", "Draw both Dubins' and FSC paths"} };
for(idx = 0; idx < nbPathShow; idx++) {
pathShow[idx] = pathVisible->addAction( tr(pathLabels[idx][0]) );
pathGroup->addAction(pathShow[idx]);
pathShow[idx]->setShortcut( QString(pathLabels[idx][1]) );
pathShow[idx]->setToolTip( tr(pathLabels[idx][2]) );
pathShow[idx]->setCheckable(true);
if (idx == bothShow)
pathShow[idx]->setChecked(true);
connect( pathShow[idx], SIGNAL( triggered() ),
this, SLOT( setPathShow() ) );
}
circleShow = menu->addAction( tr("Show Turning Circles") );
circleShow->setShortcut( QString("T") );
circleShow->setToolTip( tr("Show turning circles for drawn paths") );
circleShow->setCheckable(true);
connect( circleShow, SIGNAL( triggered() ),
this, SLOT( setTurningCircles() ) );
menuBar->addMenu(menu);
menu = new QMenu(tr("About"), menuBar);
menu->addAction(tr("About"), this, SLOT( about() ), 'A')
->setStatusTip( tr("Display information about this application") );
menuBar->addMenu(menu);
setMenuBar(menuBar);
setCentralWidget(&drawingArea);
setMinimumSize(750, 800);
setStatusBar( new QStatusBar() );
QString msg("Clic in the drawing array to change");
statusBar()->showMessage(msg + " goal configuration");
}
void ISeeMLFrame::about() {
QString message( tr("This is ISeeML V1.1 GUI\n\n") );
message += tr("It uses Qt (www.qt.io),\n")
+ tr("and will probably become\n")
+ tr("ISeeML V2.0 base GUI toolkit.\n\n")
+ tr("Written by A. Scheuer\n")
+ tr("(Alexis.Scheuer@loria.fr)");
QMessageBox::information(this, tr("About ISeeML V1.1 Interface"),
message);
}