MapWidget.cc 26.8 KB
Newer Older
1
/*==================================================================
pixhawk's avatar
pixhawk committed
2 3 4 5
======================================================================*/

/**
 * @file
lm's avatar
lm committed
6
 *   @brief Implementation of MapWidget
pixhawk's avatar
pixhawk committed
7 8
 *
 *   @author Lorenz Meier <mavteam@student.ethz.ch>
lm's avatar
lm committed
9
 *   @author Mariano Lizarraga
pixhawk's avatar
pixhawk committed
10 11 12
 *
 */

lm's avatar
lm committed
13 14
#include <QComboBox>
#include <QGridLayout>
15
#include <QDir>
16
#include <QDoubleSpinBox>
17

18
#include "QGC.h"
pixhawk's avatar
pixhawk committed
19 20
#include "MapWidget.h"
#include "ui_MapWidget.h"
lm's avatar
lm committed
21 22
#include "UASInterface.h"
#include "UASManager.h"
23 24
#include "MAV2DIcon.h"
#include "Waypoint2DIcon.h"
pixhawk's avatar
pixhawk committed
25

pixhawk's avatar
pixhawk committed
26 27
#include "MG.h"

28

pixhawk's avatar
pixhawk committed
29 30 31
MapWidget::MapWidget(QWidget *parent) :
        QWidget(parent),
        zoomLevel(0),
32 33
        uasIcons(),
        uasTrails(),
34
        mav(NULL),
35
        lastUpdate(0),
pixhawk's avatar
pixhawk committed
36 37 38
        m_ui(new Ui::MapWidget)
{
    m_ui->setupUi(this);
39 40 41
    mc = new qmapcontrol::MapControl(QSize(320, 240));

    //   VISUAL MAP STYLE
42
    QString buttonStyle("QAbstractButton { background-color: rgba(20, 20, 20, 45%); border-color: rgba(10, 10, 10, 50%)}  QDoubleSpinBox { background-color: rgba(20, 20, 20, 45%); border-color: rgba(10, 10, 10, 50%)}");
43 44 45 46 47 48 49 50 51
    mc->setPen(QGC::colorCyan.darker(400));








pixhawk's avatar
pixhawk committed
52

53
    waypointIsDrag = false;
pixhawk's avatar
pixhawk committed
54

pixhawk's avatar
pixhawk committed
55 56
    // Accept focus by clicking or keyboard
    this->setFocusPolicy(Qt::StrongFocus);
pixhawk's avatar
pixhawk committed
57

pixhawk's avatar
pixhawk committed
58
    // create MapControl
59

pixhawk's avatar
pixhawk committed
60
    mc->showScale(true);
61
    mc->showCoord(true);
62
    mc->enablePersistentCache();
63
    mc->setMouseTracking(true); // required to update the mouse position for diplay and capture
pixhawk's avatar
pixhawk committed
64

pixhawk's avatar
pixhawk committed
65
    // create MapAdapter to get maps from
lm's avatar
lm committed
66
    //TileMapAdapter* osmAdapter = new TileMapAdapter("tile.openstreetmap.org", "/%1/%2/%3.png", 256, 0, 17);
pixhawk's avatar
pixhawk committed
67

68
    qmapcontrol::MapAdapter* mapadapter_overlay = new qmapcontrol::YahooMapAdapter("us.maps3.yimg.com", "/aerial.maps.yimg.com/png?v=2.2&t=h&s=256&x=%2&y=%3&z=%1");
pixhawk's avatar
pixhawk committed
69

lm's avatar
lm committed
70
    // MAP BACKGROUND
71 72
    mapadapter = new qmapcontrol::GoogleSatMapAdapter();
    l = new qmapcontrol::MapLayer("Google Satellite", mapadapter);
lm's avatar
lm committed
73
    mc->addLayer(l);
pixhawk's avatar
pixhawk committed
74

lm's avatar
lm committed
75
    // STREET OVERLAY
76
    overlay = new qmapcontrol::MapLayer("Overlay", mapadapter_overlay);
lm's avatar
lm committed
77 78
    overlay->setVisible(false);
    mc->addLayer(overlay);
pixhawk's avatar
pixhawk committed
79

80 81 82 83
    // MAV FLIGHT TRACKS
    tracks = new qmapcontrol::MapLayer("Tracking", mapadapter);
    mc->addLayer(tracks);

lm's avatar
lm committed
84 85
    // WAYPOINT LAYER
    // create a layer with the mapadapter and type GeometryLayer (for waypoints)
86
    geomLayer = new qmapcontrol::GeometryLayer("Waypoints", mapadapter);
87
    mc->addLayer(geomLayer);
pixhawk's avatar
pixhawk committed
88 89 90



91 92 93
    //
    //    Layer* gsatLayer = new Layer("Google Satellite", gsat, Layer::MapLayer);
    //    mc->addLayer(gsatLayer);
pixhawk's avatar
pixhawk committed
94

lm's avatar
lm committed
95 96 97 98
    // SET INITIAL POSITION AND ZOOM
    // Set default zoom level
    mc->setZoom(16);
    // Zurich, ETH
99
    mc->setView(QPointF(8.548056,47.376389));
pixhawk's avatar
pixhawk committed
100

101 102
    // Veracruz Mexico
    //mc->setView(QPointF(-96.105208,19.138955));
pixhawk's avatar
pixhawk committed
103

lm's avatar
lm committed
104 105 106
    // Add controls to select map provider
    /////////////////////////////////////////////////
    QActionGroup* mapproviderGroup = new QActionGroup(this);
107 108 109 110 111
    osmAction = new QAction(QIcon(":/images/mapproviders/openstreetmap.png"), tr("OpenStreetMap"), mapproviderGroup);
    yahooActionMap = new QAction(QIcon(":/images/mapproviders/yahoo.png"), tr("Yahoo: Map"), mapproviderGroup);
    yahooActionSatellite = new QAction(QIcon(":/images/mapproviders/yahoo.png"), tr("Yahoo: Satellite"), mapproviderGroup);
    googleActionMap = new QAction(QIcon(":/images/mapproviders/google.png"), tr("Google: Map"), mapproviderGroup);
    googleSatAction = new QAction(QIcon(":/images/mapproviders/google.png"), tr("Google: Sat"), mapproviderGroup);
lm's avatar
lm committed
112 113 114 115 116 117 118 119
    osmAction->setCheckable(true);
    yahooActionMap->setCheckable(true);
    yahooActionSatellite->setCheckable(true);
    googleActionMap->setCheckable(true);
    googleSatAction->setCheckable(true);
    googleSatAction->setChecked(true);
    connect(mapproviderGroup, SIGNAL(triggered(QAction*)),
            this, SLOT(mapproviderSelected(QAction*)));
pixhawk's avatar
pixhawk committed
120

lm's avatar
lm committed
121
    // Overlay seems currently broken
122 123 124 125 126
    //    yahooActionOverlay = new QAction(tr("Yahoo: street overlay"), this);
    //    yahooActionOverlay->setCheckable(true);
    //    yahooActionOverlay->setChecked(overlay->isVisible());
    //    connect(yahooActionOverlay, SIGNAL(toggled(bool)),
    //            overlay, SLOT(setVisible(bool)));
pixhawk's avatar
pixhawk committed
127

128 129 130 131 132 133
    //    mapproviderGroup->addAction(googleSatAction);
    //    mapproviderGroup->addAction(osmAction);
    //    mapproviderGroup->addAction(yahooActionOverlay);
    //    mapproviderGroup->addAction(googleActionMap);
    //    mapproviderGroup->addAction(yahooActionMap);
    //    mapproviderGroup->addAction(yahooActionSatellite);
pixhawk's avatar
pixhawk committed
134

lm's avatar
lm committed
135 136 137 138
    // Create map provider selection menu
    mapMenu = new QMenu(this);
    mapMenu->addActions(mapproviderGroup->actions());
    mapMenu->addSeparator();
139
    //    mapMenu->addAction(yahooActionOverlay);
pixhawk's avatar
pixhawk committed
140

lm's avatar
lm committed
141 142 143
    mapButton = new QPushButton(this);
    mapButton->setText("Map Source");
    mapButton->setMenu(mapMenu);
144
    mapButton->setStyleSheet(buttonStyle);
pixhawk's avatar
pixhawk committed
145

pixhawk's avatar
pixhawk committed
146
    // display the MapControl in the application
lm's avatar
lm committed
147
    QGridLayout* layout = new QGridLayout(this);
pixhawk's avatar
pixhawk committed
148
    layout->setMargin(0);
149 150
    layout->setSpacing(0);
    layout->addWidget(mc, 0, 0);
pixhawk's avatar
pixhawk committed
151
    setLayout(layout);
pixhawk's avatar
pixhawk committed
152

153
    // create buttons to control the map (zoom, GPS tracking and WP capture)
pixhawk's avatar
pixhawk committed
154
    QPushButton* zoomin = new QPushButton(QIcon(":/images/actions/list-add.svg"), "", this);
155
    zoomin->setStyleSheet(buttonStyle);
pixhawk's avatar
pixhawk committed
156
    QPushButton* zoomout = new QPushButton(QIcon(":/images/actions/list-remove.svg"), "", this);
157
    zoomout->setStyleSheet(buttonStyle);
158
    createPath = new QPushButton(QIcon(":/images/actions/go-bottom.svg"), "", this);
159
    createPath->setStyleSheet(buttonStyle);
160
    clearTracking = new QPushButton(QIcon(""), "", this);
161
    clearTracking->setStyleSheet(buttonStyle);
pixhawk's avatar
pixhawk committed
162
    followgps = new QPushButton(QIcon(":/images/actions/system-lock-screen.svg"), "", this);
163 164 165
    followgps->setStyleSheet(buttonStyle);
    QPushButton* goToButton = new QPushButton(QIcon(""), "T", this);
    goToButton->setStyleSheet(buttonStyle);
pixhawk's avatar
pixhawk committed
166

167 168 169 170 171 172 173 174 175 176 177 178 179
    // SAVE FILES
    QPushButton* saveButton = new QPushButton(QIcon(""), "S", this);
    saveButton->setStyleSheet(buttonStyle);

    // SET OFFSCREEN BUFFER SIZE
    QDoubleSpinBox* offscreenSpinBox = new QDoubleSpinBox(this);
    offscreenSpinBox->setStyleSheet(buttonStyle);
    offscreenSpinBox->setMinimum(2);
    offscreenSpinBox->setMaximum(30);
    offscreenSpinBox->setValue(mc->offscreenImageFactor());
    connect(offscreenSpinBox, SIGNAL(valueChanged(double)), mc, SLOT(setOffscreenImageFactor(double)));


180 181 182 183 184
    zoomin->setMaximumWidth(30);
    zoomout->setMaximumWidth(30);
    createPath->setMaximumWidth(30);
    clearTracking->setMaximumWidth(30);
    followgps->setMaximumWidth(30);
185
    goToButton->setMaximumWidth(30);
pixhawk's avatar
pixhawk committed
186

187 188 189 190 191
    // Set checkable buttons
    // TODO: Currently checked buttons are are very difficult to distinguish when checked.
    //       create a style and the slots to change the background so it is easier to distinguish
    followgps->setCheckable(true);
    createPath->setCheckable(true);
pixhawk's avatar
pixhawk committed
192

193
    // add buttons to control the map (zoom, GPS tracking and WP capture)
lm's avatar
lm committed
194
    QGridLayout* innerlayout = new QGridLayout(mc);
195 196
    innerlayout->setMargin(3);
    innerlayout->setSpacing(3);
lm's avatar
lm committed
197 198 199 200
    innerlayout->addWidget(zoomin, 0, 0);
    innerlayout->addWidget(zoomout, 1, 0);
    innerlayout->addWidget(followgps, 2, 0);
    innerlayout->addWidget(createPath, 3, 0);
201
    innerlayout->addWidget(clearTracking, 4, 0);
lm's avatar
lm committed
202
    // Add spacers to compress buttons on the top left
203
    innerlayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding), 5, 0);
204
    innerlayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding), 0, 1, 0, 7);
205 206 207 208
    innerlayout->addWidget(mapButton, 0, 2);
    innerlayout->addWidget(goToButton, 0, 3);
    innerlayout->addWidget(saveButton, 0, 4);
    innerlayout->addWidget(offscreenSpinBox, 0, 5);
lm's avatar
lm committed
209 210
    innerlayout->setRowStretch(0, 1);
    innerlayout->setRowStretch(1, 100);
pixhawk's avatar
pixhawk committed
211
    mc->setLayout(innerlayout);
pixhawk's avatar
pixhawk committed
212 213


214
    // Connect the required signals-slots
215 216
    connect(zoomin, SIGNAL(clicked(bool)),
            mc, SLOT(zoomIn()));
pixhawk's avatar
pixhawk committed
217

218 219
    connect(zoomout, SIGNAL(clicked(bool)),
            mc, SLOT(zoomOut()));
pixhawk's avatar
pixhawk committed
220

221 222
    connect(goToButton, SIGNAL(clicked()), this, SLOT(goTo()));

223 224
    connect(saveButton, SIGNAL(clicked()), mc, SLOT(openImageSaveDialog()));

pixhawk's avatar
pixhawk committed
225 226 227 228 229 230
    QList<UASInterface*> systems = UASManager::instance()->getUASList();
    foreach(UASInterface* system, systems)
    {
        addUAS(system);
    }

231 232
    connect(UASManager::instance(), SIGNAL(UASCreated(UASInterface*)),
            this, SLOT(addUAS(UASInterface*)));
pixhawk's avatar
pixhawk committed
233 234

    activeUASSet(UASManager::instance()->getActiveUAS());
235
    connect(UASManager::instance(), SIGNAL(activeUASSet(UASInterface*)), this, SLOT(activeUASSet(UASInterface*)));
pixhawk's avatar
pixhawk committed
236

237 238
    connect(mc, SIGNAL(mouseEventCoordinate(const QMouseEvent*, const QPointF)),
            this, SLOT(captureMapClick(const QMouseEvent*, const QPointF)));
pixhawk's avatar
pixhawk committed
239

240
    connect(createPath, SIGNAL(clicked(bool)),
241
            this, SLOT(createPathButtonClicked(bool)));
pixhawk's avatar
pixhawk committed
242 243


244 245
    connect(geomLayer, SIGNAL(geometryClicked(Geometry*,QPoint)),
            this, SLOT(captureGeometryClick(Geometry*, QPoint)));
pixhawk's avatar
pixhawk committed
246

247 248
    connect(geomLayer, SIGNAL(geometryDragged(Geometry*, QPointF)),
            this, SLOT(captureGeometryDrag(Geometry*, QPointF)));
pixhawk's avatar
pixhawk committed
249

250 251
    connect(geomLayer, SIGNAL(geometryEndDrag(Geometry*, QPointF)),
            this, SLOT(captureGeometryEndDrag(Geometry*, QPointF)));
pixhawk's avatar
pixhawk committed
252

253 254 255
    // Configure the WP Path's pen
    pointPen = new QPen(QColor(0, 255,0));
    pointPen->setWidth(3);
256 257
    waypointPath = new qmapcontrol::LineString (wps, "Waypoint path", pointPen);
    mc->layer("Waypoints")->addGeometry(waypointPath);
pixhawk's avatar
pixhawk committed
258

259 260 261 262 263
    //Camera Control
    // CAMERA INDICATOR LAYER
    // create a layer with the mapadapter and type GeometryLayer (for camera indicator)
    camLayer = new qmapcontrol::GeometryLayer("Camera", mapadapter);
    mc->addLayer(camLayer);
pixhawk's avatar
pixhawk committed
264

265
    //camLine = new qmapcontrol::LineString(camPoints,"Camera Eje", camBorderPen);
pixhawk's avatar
pixhawk committed
266

267 268
    drawCamBorder = false;
    radioCamera = 10;
269 270

    //mc->setOffscreenImageFactor(15);
lm's avatar
lm committed
271 272
}

273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297
void MapWidget::goTo()
{
    bool ok;
         QString text = QInputDialog::getText(this, tr("Please enter coordinates"),
                                              tr("Coordinates (Lat,Lon):"), QLineEdit::Normal,
                                              QString("%1,%2").arg(mc->currentCoordinate().x()).arg(mc->currentCoordinate().y()), &ok);
         if (ok && !text.isEmpty())
         {
             QStringList split = text.split(",");
             if (split.length() == 2)
             {
                 bool convert;
                 double latitude = split.first().toDouble(&convert);
                 ok &= convert;
                 double longitude = split.last().toDouble(&convert);
                 ok &= convert;

                 if (ok)
                 {
                     mc->setView(QPointF(latitude, longitude));
                 }
             }
         }
}

298

lm's avatar
lm committed
299 300 301 302 303 304 305 306
void MapWidget::mapproviderSelected(QAction* action)
{
    //delete mapadapter;
    mapButton->setText(action->text());
    if (action == osmAction)
    {
        int zoom = mapadapter->adaptedZoom();
        mc->setZoom(0);
pixhawk's avatar
pixhawk committed
307

308
        mapadapter = new qmapcontrol::OSMMapAdapter();
lm's avatar
lm committed
309 310
        l->setMapAdapter(mapadapter);
        geomLayer->setMapAdapter(mapadapter);
pixhawk's avatar
pixhawk committed
311

lm's avatar
lm committed
312 313
        mc->updateRequestNew();
        mc->setZoom(zoom);
314
        //        yahooActionOverlay->setEnabled(false);
lm's avatar
lm committed
315
        overlay->setVisible(false);
316
        //        yahooActionOverlay->setChecked(false);
pixhawk's avatar
pixhawk committed
317

lm's avatar
lm committed
318 319 320 321 322
    }
    else if (action == yahooActionMap)
    {
        int zoom = mapadapter->adaptedZoom();
        mc->setZoom(0);
pixhawk's avatar
pixhawk committed
323

324
        mapadapter = new qmapcontrol::YahooMapAdapter();
lm's avatar
lm committed
325 326
        l->setMapAdapter(mapadapter);
        geomLayer->setMapAdapter(mapadapter);
pixhawk's avatar
pixhawk committed
327

lm's avatar
lm committed
328 329
        mc->updateRequestNew();
        mc->setZoom(zoom);
330
        //        yahooActionOverlay->setEnabled(false);
lm's avatar
lm committed
331
        overlay->setVisible(false);
332
        //        yahooActionOverlay->setChecked(false);
lm's avatar
lm committed
333 334 335 336 337 338
    }
    else if (action == yahooActionSatellite)
    {
        int zoom = mapadapter->adaptedZoom();
        QPointF a = mc->currentCoordinate();
        mc->setZoom(0);
pixhawk's avatar
pixhawk committed
339

340
        mapadapter = new qmapcontrol::YahooMapAdapter("us.maps3.yimg.com", "/aerial.maps.yimg.com/png?v=1.7&t=a&s=256&x=%2&y=%3&z=%1");
lm's avatar
lm committed
341
        l->setMapAdapter(mapadapter);
pixhawk's avatar
pixhawk committed
342

lm's avatar
lm committed
343 344
        mc->updateRequestNew();
        mc->setZoom(zoom);
345
        //        yahooActionOverlay->setEnabled(true);
lm's avatar
lm committed
346 347 348 349 350
    }
    else if (action == googleActionMap)
    {
        int zoom = mapadapter->adaptedZoom();
        mc->setZoom(0);
351
        mapadapter = new qmapcontrol::GoogleMapAdapter();
lm's avatar
lm committed
352 353
        l->setMapAdapter(mapadapter);
        geomLayer->setMapAdapter(mapadapter);
pixhawk's avatar
pixhawk committed
354

lm's avatar
lm committed
355 356
        mc->updateRequestNew();
        mc->setZoom(zoom);
357
        //        yahooActionOverlay->setEnabled(false);
lm's avatar
lm committed
358
        overlay->setVisible(false);
359
        //        yahooActionOverlay->setChecked(false);
lm's avatar
lm committed
360 361 362 363 364
    }
    else if (action == googleSatAction)
    {
        int zoom = mapadapter->adaptedZoom();
        mc->setZoom(0);
365
        mapadapter = new qmapcontrol::GoogleSatMapAdapter();
lm's avatar
lm committed
366 367
        l->setMapAdapter(mapadapter);
        geomLayer->setMapAdapter(mapadapter); 
pixhawk's avatar
pixhawk committed
368

lm's avatar
lm committed
369 370
        mc->updateRequestNew();
        mc->setZoom(zoom);
371
        //        yahooActionOverlay->setEnabled(false);
lm's avatar
lm committed
372
        overlay->setVisible(false);
373
        //        yahooActionOverlay->setChecked(false);
lm's avatar
lm committed
374 375 376 377 378
    }
    else
    {
        mapButton->setText("Select..");
    }
379
}
lm's avatar
lm committed
380

lm's avatar
lm committed
381

382
void MapWidget::createPathButtonClicked(bool checked)
lm's avatar
lm committed
383
{
384
    Q_UNUSED(checked);
pixhawk's avatar
pixhawk committed
385

lm's avatar
lm committed
386 387 388 389
    if (createPath->isChecked())
    {
        // change the cursor shape
        this->setCursor(Qt::PointingHandCursor);
390
        mc->setMouseMode(qmapcontrol::MapControl::None);
pixhawk's avatar
pixhawk committed
391 392


393
        // emit signal start to create a Waypoint global
394
        emit createGlobalWP(true, mc->currentCoordinate());
pixhawk's avatar
pixhawk committed
395

396 397 398 399 400 401 402
        //        // Clear the previous WP track
        //        // TODO: Move this to an actual clear track button and add a warning dialog
        //        mc->layer("Waypoints")->clearGeometries();
        //        wps.clear();
        //        path->setPoints(wps);
        //        mc->layer("Waypoints")->addGeometry(path);
        //        wpIndex.clear();
403 404 405
    }
    else
    {
pixhawk's avatar
pixhawk committed
406

lm's avatar
lm committed
407
        this->setCursor(Qt::ArrowCursor);
408
        mc->setMouseMode(qmapcontrol::MapControl::Panning);
lm's avatar
lm committed
409
    }
pixhawk's avatar
pixhawk committed
410

411
}
412

413 414 415 416 417 418 419
/**
 * Captures a click on the map and if in create WP path mode, it adds the WP on MouseButtonRelease
 *
 * @param event The mouse event
 * @param coordinate The coordinate in which it occured the mouse event
 * @note  This slot is connected to the mouseEventCoordinate of the QMapControl object
 */
420

421 422
void MapWidget::captureMapClick(const QMouseEvent* event, const QPointF coordinate)
{
423
    //qDebug() << mc->mouseMode();
424
    if (QEvent::MouseButtonRelease == event->type() && createPath->isChecked())
425
    {
426 427
        // Create waypoint name
        QString str;
pixhawk's avatar
pixhawk committed
428

429
        str = QString("%1").arg(waypointPath->numberOfPoints());
pixhawk's avatar
pixhawk committed
430

431 432
        // create the WP and set everything in the LineString to display the path
        Waypoint2DIcon* tempCirclePoint;
pixhawk's avatar
pixhawk committed
433

434 435 436 437 438 439 440 441 442
        if (mav)
        {
            tempCirclePoint = new Waypoint2DIcon(coordinate.x(), coordinate.y(), 20, str, qmapcontrol::Point::Middle, new QPen(mav->getColor()));
        }
        else
        {
            tempCirclePoint = new Waypoint2DIcon(coordinate.x(), coordinate.y(), 20, str, qmapcontrol::Point::Middle);
        }
        mc->layer("Waypoints")->addGeometry(tempCirclePoint);
pixhawk's avatar
pixhawk committed
443

444 445
        qmapcontrol::Point* tempPoint = new qmapcontrol::Point(coordinate.x(), coordinate.y(),str);
        wps.append(tempPoint);
446
        waypointPath->addPoint(tempPoint);
pixhawk's avatar
pixhawk committed
447

448
        wpIndex.insert(str,tempPoint);
pixhawk's avatar
pixhawk committed
449

450
        // Refresh the screen
451
        mc->updateRequest(tempPoint->boundingBox().toRect());
pixhawk's avatar
pixhawk committed
452

453 454
        // emit signal mouse was clicked
        emit captureMapCoordinateClick(coordinate);
455
    }
pixhawk's avatar
pixhawk committed
456 457
}

458 459
void MapWidget::createWaypointGraphAtMap(const QPointF coordinate)
{
460 461
    if (!wpExists(coordinate))
    {
462 463
        // Create waypoint name
        QString str;
pixhawk's avatar
pixhawk committed
464 465


466
        str = QString("%1").arg(waypointPath->numberOfPoints());
pixhawk's avatar
pixhawk committed
467

468 469 470
        // create the WP and set everything in the LineString to display the path
        //CirclePoint* tempCirclePoint = new CirclePoint(coordinate.x(), coordinate.y(), 10, str);
        Waypoint2DIcon* tempCirclePoint;
pixhawk's avatar
pixhawk committed
471

472 473 474 475 476 477 478 479
        if (mav)
        {
            tempCirclePoint = new Waypoint2DIcon(coordinate.x(), coordinate.y(), 20, str, qmapcontrol::Point::Middle, new QPen(mav->getColor()));
        }
        else
        {
            tempCirclePoint = new Waypoint2DIcon(coordinate.x(), coordinate.y(), 20, str, qmapcontrol::Point::Middle);
        }
pixhawk's avatar
pixhawk committed
480 481


482
        mc->layer("Waypoints")->addGeometry(tempCirclePoint);
pixhawk's avatar
pixhawk committed
483

484 485
        Point* tempPoint = new Point(coordinate.x(), coordinate.y(),str);
        wps.append(tempPoint);
486
        waypointPath->addPoint(tempPoint);
pixhawk's avatar
pixhawk committed
487

488
        wpIndex.insert(str,tempPoint);
tecnosapiens's avatar
tecnosapiens committed
489
        qDebug()<<"Funcion createWaypointGraphAtMap WP= "<<str<<" -> x= "<<tempPoint->latitude()<<" y= "<<tempPoint->longitude();
pixhawk's avatar
pixhawk committed
490

tecnosapiens's avatar
tecnosapiens committed
491
        // Refresh the screen
492
        mc->updateRequest(tempPoint->boundingBox().toRect());
493
    }
pixhawk's avatar
pixhawk committed
494

495 496
    ////    // emit signal mouse was clicked
    //    emit captureMapCoordinateClick(coordinate);
497 498
}

499
int MapWidget::wpExists(const QPointF coordinate){
500 501 502 503 504
    for (int i = 0; i < wps.size(); i++){
        if (wps.at(i)->latitude() == coordinate.y() &&
            wps.at(i)->longitude()== coordinate.x()){
            return 1;
        }
505
    }
506
    return 0;
507 508
}

509

510 511
void MapWidget::captureGeometryClick(Geometry* geom, QPoint point)
{
512 513
    Q_UNUSED(geom);
    Q_UNUSED(point);
pixhawk's avatar
pixhawk committed
514

515
    mc->setMouseMode(qmapcontrol::MapControl::None);
pixhawk's avatar
pixhawk committed
516

517 518
}

519 520
void MapWidget::captureGeometryDrag(Geometry* geom, QPointF coordinate)
{
pixhawk's avatar
pixhawk committed
521 522


523
    waypointIsDrag = true;
pixhawk's avatar
pixhawk committed
524

525
    // Refresh the screen
526
    mc->updateRequest(geom->boundingBox().toRect());
pixhawk's avatar
pixhawk committed
527

528 529 530
    int temp = 0;
    qmapcontrol::Point* point2Find;
    point2Find = wpIndex[geom->name()];
pixhawk's avatar
pixhawk committed
531

532 533 534
    if (point2Find)
    {
        point2Find->setCoordinate(coordinate);
pixhawk's avatar
pixhawk committed
535

536 537 538 539
        point2Find = dynamic_cast <qmapcontrol::Point*> (geom);
        if (point2Find)
        {
            point2Find->setCoordinate(coordinate);
pixhawk's avatar
pixhawk committed
540

541 542 543 544 545 546
            // qDebug() << geom->name();
            temp = geom->get_myIndex();
            //qDebug() << temp;
            emit sendGeometryEndDrag(coordinate,temp);
        }
    }
pixhawk's avatar
pixhawk committed
547

548 549
}

550
void MapWidget::captureGeometryEndDrag(Geometry* geom, QPointF coordinate)
551
{
552 553 554
    Q_UNUSED(geom);
    Q_UNUSED(coordinate);
    // TODO: Investigate why when creating the waypoint path this slot is being called
pixhawk's avatar
pixhawk committed
555

556 557 558 559 560 561
    // Only change the mouse mode back to panning when not creating a WP path
    if (!createPath->isChecked())
    {
        waypointIsDrag = false;
        mc->setMouseMode(qmapcontrol::MapControl::Panning);
    }
pixhawk's avatar
pixhawk committed
562

563 564
}

pixhawk's avatar
pixhawk committed
565 566 567 568
MapWidget::~MapWidget()
{
    delete m_ui;
}
lm's avatar
lm committed
569 570 571 572 573 574
/**
 *
 * @param uas the UAS/MAV to monitor/display with the HUD
 */
void MapWidget::addUAS(UASInterface* uas)
{
575
    connect(uas, SIGNAL(globalPositionChanged(UASInterface*,double,double,double,quint64)), this, SLOT(updateGlobalPosition(UASInterface*,double,double,double,quint64)));
lm's avatar
lm committed
576 577
}

578 579 580 581 582
void MapWidget::activeUASSet(UASInterface* uas)
{
    if (uas)
    {
        mav = uas;
583 584 585 586 587
        QColor color = mav->getColor();
        color.setAlphaF(0.6);
        QPen* pen = new QPen(color);
        pen->setWidth(3.0);
        // FIXME Load waypoints of this system
588 589 590
    }
}

lm's avatar
lm committed
591 592 593 594 595 596 597 598 599
/**
 * Updates the global position of one MAV and append the last movement to the trail
 *
 * @param uas The unmanned air system
 * @param lat Latitude in WGS84 ellipsoid
 * @param lon Longitutde in WGS84 ellipsoid
 * @param alt Altitude over mean sea level
 * @param usec Timestamp of the position message in milliseconds FIXME will move to microseconds
 */
lm's avatar
lm committed
600 601 602
void MapWidget::updateGlobalPosition(UASInterface* uas, double lat, double lon, double alt, quint64 usec)
{
    Q_UNUSED(usec);
603
    Q_UNUSED(alt); // FIXME Use altitude
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656

    // create a LineString
    //QList<Point*> points;
    // Points with a circle
    // A QPen can be used to customize the
    //pointpen->setWidth(3);
    //points.append(new CirclePoint(lat, lon, 10, uas->getUASName(), Point::Middle, pointpen));

    MAV2DIcon* p;

    if (!uasIcons.contains(uas->getUASID()))
    {
        // Get the UAS color
        QColor uasColor = uas->getColor();

        // Icon
        QPen* pointpen = new QPen(uasColor);
        qDebug() << uas->getUASName();
        p = new MAV2DIcon(lat, lon, 20, uas->getUASName(), qmapcontrol::Point::Middle, pointpen);
        uasIcons.insert(uas->getUASID(), p);
        tracks->addGeometry(p);

        // Line
        // A QPen also can use transparency

        QList<qmapcontrol::Point*> points;
        points.append(new qmapcontrol::Point(lat, lon, ""));
        QPen* linepen = new QPen(uasColor.darker());
        linepen->setWidth(2);

        // Create tracking line string
        qmapcontrol::LineString* ls = new qmapcontrol::LineString(points, uas->getUASName(), linepen);
        uasTrails.insert(uas->getUASID(), ls);

        // Add the LineString to the layer
        mc->layer("Tracking")->addGeometry(ls);
    }
    else
    {
        p = dynamic_cast<MAV2DIcon*>(uasIcons.value(uas->getUASID()));
        if (p)
        {
            p->setCoordinate(QPointF(lat, lon));
            p->setYaw(uas->getYaw());
        }
        // Extend trail
        uasTrails.value(uas->getUASID())->addPoint(new qmapcontrol::Point(lat, lon, ""));
    }

    //mc->updateRequestNew();//(uasTrails.value(uas->getUASID())->boundingBox().toRect());


    // Limit the position update rate
pixhawk's avatar
pixhawk committed
657
    quint64 currTime = MG::TIME::getGroundTimeNow();
658
    if (currTime - lastUpdate > 120)
pixhawk's avatar
pixhawk committed
659 660
    {
        lastUpdate = currTime;
661 662
        // Sets the view to the interesting area
        if (followgps->isChecked())
663
        {
664
            updatePosition(0, lat, lon);
665 666 667
        }
        else
        {
668 669
            // Refresh the screen
            //mc->updateRequestNew();
670
        }
pixhawk's avatar
pixhawk committed
671 672
    }
}
pixhawk's avatar
pixhawk committed
673

lm's avatar
lm committed
674 675 676
/**
 * Center the view on this position
 */
lm's avatar
lm committed
677
void MapWidget::updatePosition(float time, double lat, double lon)
pixhawk's avatar
pixhawk committed
678
{
lm's avatar
lm committed
679
    Q_UNUSED(time);
680
    //gpsposition->setText(QString::number(time) + " / " + QString::number(lat) + " / " + QString::number(lon));
681
    if (followgps->isChecked() && isVisible())
pixhawk's avatar
pixhawk committed
682
    {
lm's avatar
lm committed
683
        mc->setView(QPointF(lat, lon));
pixhawk's avatar
pixhawk committed
684 685 686 687 688 689 690 691 692 693 694 695 696 697
    }
}

void MapWidget::wheelEvent(QWheelEvent *event)
{
    int numDegrees = event->delta() / 8;
    int numSteps = numDegrees / 15;
    // Calculate new zoom level
    int newZoom = mc->currentZoom()+numSteps;
    // Set new zoom level, level is bounded by map control
    mc->setZoom(newZoom);
    // Detail zoom level is the number of steps zoomed in further
    // after the bounding has taken effect
    detailZoom = qAbs(qMin(0, mc->currentZoom()-newZoom));
pixhawk's avatar
pixhawk committed
698

699
    // visual field of camera
700
    updateCameraPosition(20*newZoom,0,"no");
pixhawk's avatar
pixhawk committed
701

pixhawk's avatar
pixhawk committed
702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729
}

void MapWidget::keyPressEvent(QKeyEvent *event)
{
    switch (event->key()) {
    case Qt::Key_Plus:
        mc->zoomIn();
        break;
    case Qt::Key_Minus:
        mc->zoomOut();
        break;
    case Qt::Key_Left:
        mc->scrollLeft(this->width()/scrollStep);
        break;
    case Qt::Key_Right:
        mc->scrollRight(this->width()/scrollStep);
        break;
    case Qt::Key_Down:
        mc->scrollDown(this->width()/scrollStep);
        break;
    case Qt::Key_Up:
        mc->scrollUp(this->width()/scrollStep);
        break;
    default:
        QWidget::keyPressEvent(event);
    }
}

730
void MapWidget::resizeEvent(QResizeEvent* event )
pixhawk's avatar
pixhawk committed
731
{
732 733
    Q_UNUSED(event);
    mc->resize(this->size());
pixhawk's avatar
pixhawk committed
734 735
}

736 737 738 739 740 741 742 743 744 745
void MapWidget::showEvent(QShowEvent* event)
{
    Q_UNUSED(event);
}

void MapWidget::hideEvent(QHideEvent* event)
{
    Q_UNUSED(event);
}

pixhawk's avatar
pixhawk committed
746 747 748 749 750 751 752 753 754 755 756 757

void MapWidget::changeEvent(QEvent *e)
{
    QWidget::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        m_ui->retranslateUi(this);
        break;
    default:
        break;
    }
}
758 759

void MapWidget::clearWaypoints()
760 761
{
    // Clear the previous WP track
pixhawk's avatar
pixhawk committed
762

763 764
    mc->layer("Waypoints")->clearGeometries();
    wps.clear();
765 766
    waypointPath->setPoints(wps);
    mc->layer("Waypoints")->addGeometry(waypointPath);
767
    wpIndex.clear();
768
    mc->updateRequest(waypointPath->boundingBox().toRect());
pixhawk's avatar
pixhawk committed
769

770 771 772 773
    if(createPath->isChecked())
    {
        createPath->click();
    }
774
}
pixhawk's avatar
pixhawk committed
775

776 777 778 779 780 781 782 783 784 785 786 787
void MapWidget::clearPath()
{
    mc->layer("Tracking")->clearGeometries();
    foreach (qmapcontrol::LineString* ls, uasTrails)
    {
        QPen* linepen = ls->pen();
        delete ls;
        qmapcontrol::LineString* lsNew = new qmapcontrol::LineString(QList<qmapcontrol::Point*>(), "", linepen);
        mc->layer("Tracking")->addGeometry(lsNew);
    }
    // FIXME update this with update request only for bounding box of trails
    mc->updateRequest(QRect(0, 0, width(), height()));
788
}
789 790 791 792 793 794

void MapWidget::changeGlobalWaypointPositionBySpinBox(int index, float lat, float lon)
{
    if(!waypointIsDrag)
    {
        qDebug() <<"indice WP= "<<index <<"\n";
pixhawk's avatar
pixhawk committed
795

796 797 798
        QPointF coordinate;
        coordinate.setX(lon);
        coordinate.setY(lat);
pixhawk's avatar
pixhawk committed
799

800 801 802
        Point* point2Find;
        point2Find = wpIndex[QString::number(index)];
        point2Find->setCoordinate(coordinate);
pixhawk's avatar
pixhawk committed
803

804 805
        point2Find = dynamic_cast <Point*> (mc->layer("Waypoints")->get_Geometry(index));
        point2Find->setCoordinate(coordinate);
pixhawk's avatar
pixhawk committed
806

807
        // Refresh the screen
808
        mc->updateRequest(point2Find->boundingBox().toRect());
809
    }
pixhawk's avatar
pixhawk committed
810 811


812 813
}

814 815
void MapWidget::updateCameraPosition(double radio, double bearing, QString dir)
{
pixhawk's avatar
pixhawk committed
816
    // FIXME Mariano
817 818
    //camPoints.clear();
    QPointF currentPos = mc->currentCoordinate();
819
    //    QPointF actualPos = getPointxBearing_Range(currentPos.y(),currentPos.x(),bearing,distance);
pixhawk's avatar
pixhawk committed
820

821 822
    //    qmapcontrol::Point* tempPoint1 = new qmapcontrol::Point(currentPos.x(), currentPos.y(),"inicial",qmapcontrol::Point::Middle);
    //    qmapcontrol::Point* tempPoint2 = new qmapcontrol::Point(actualPos.x(), actualPos.y(),"final",qmapcontrol::Point::Middle);
pixhawk's avatar
pixhawk committed
823

824 825
    //    camPoints.append(tempPoint1);
    //    camPoints.append(tempPoint2);
pixhawk's avatar
pixhawk committed
826

827
    //    camLine->setPoints(camPoints);
pixhawk's avatar
pixhawk committed
828

829
    QPen* camBorderPen = new QPen(QColor(255,0,0));
830
    camBorderPen->setWidth(2);
pixhawk's avatar
pixhawk committed
831

832
    //radio = mc->currentZoom()
pixhawk's avatar
pixhawk committed
833

834 835 836 837
    if(drawCamBorder)
    {
        //clear camera borders
        mc->layer("Camera")->clearGeometries();
pixhawk's avatar
pixhawk committed
838

839 840
        //create a camera borders
        qmapcontrol::CirclePoint* camBorder = new qmapcontrol::CirclePoint(currentPos.x(), currentPos.y(), radio, "camBorder", qmapcontrol::Point::Middle, camBorderPen);
pixhawk's avatar
pixhawk committed
841

842
        //camBorder->setCoordinate(currentPos);
pixhawk's avatar
pixhawk committed
843

844
        mc->layer("Camera")->addGeometry(camBorder);
845
        // mc->layer("Camera")->addGeometry(camLine);
846
        mc->updateRequestNew();
pixhawk's avatar
pixhawk committed
847

848
    }
849 850 851 852 853
    else
    {
        //clear camera borders
        mc->layer("Camera")->clearGeometries();
        mc->updateRequestNew();
pixhawk's avatar
pixhawk committed
854

855
    }
pixhawk's avatar
pixhawk committed
856 857


858 859 860 861 862 863
}

void MapWidget::drawBorderCamAtMap(bool status)
{
    drawCamBorder = status;
    updateCameraPosition(20,0,"no");
pixhawk's avatar
pixhawk committed
864

865 866 867 868 869
}

QPointF MapWidget::getPointxBearing_Range(double lat1, double lon1, double bearing, double distance)
{
    QPointF temp;
pixhawk's avatar
pixhawk committed
870

871
    double rad = M_PI/180;
pixhawk's avatar
pixhawk committed
872

873 874 875
    bearing = bearing*rad;
    temp.setX((lon1 + ((distance/60) * (sin(bearing)))));
    temp.setY((lat1 + ((distance/60) * (cos(bearing)))));
pixhawk's avatar
pixhawk committed
876

877 878 879
    return temp;
}