Undoed the parameter for user drag actions
[situare] / src / map / mapengine.cpp
index b6dc498..8c2a706 100644 (file)
@@ -34,6 +34,7 @@
 #include <QRect>
 
 #include "common.h"
+#include "coordinates/geocoordinate.h"
 #include "frienditemshandler.h"
 #include "gpslocationitem.h"
 #include "mapcommon.h"
@@ -130,21 +131,31 @@ QRect MapEngine::calculateTileGrid(SceneCoordinate coordinate)
     return QRect(topLeft, m_tilesGridSize);
 }
 
-void MapEngine::centerAndZoomTo(QRect rect)
+void MapEngine::centerAndZoomTo(QRect rect, bool useMargins)
 {
-    const int MARGIN_HORIZONTAL = 50;
-    const int MARGIN_VERTICAL = 5;
+    qDebug() << __PRETTY_FUNCTION__;
+
+    int marginHorizontal = 0;
+    int marginVertical = 0;
+
+    if (useMargins) {
+        marginHorizontal = 50;
+        marginVertical = 5;
+    }
 
     // calculate the usable size of the view
-    int viewUsableHeight = m_viewSize.height() - 2 * MARGIN_VERTICAL;
-    int viewUsableWidth = m_viewSize.width() - 2 * MARGIN_HORIZONTAL;
+    int viewUsableHeight = m_viewSize.height() - 2 * marginHorizontal;
+    int viewUsableWidth = m_viewSize.width() - 2 * marginVertical;
 
     // calculate how many levels must be zoomed out from the closest zoom level to get the rect
     // fit inside the usable view area
     int shift = 0;
     while ((rect.height() > (viewUsableHeight * (1 << shift)))
-           || (rect.width() > (viewUsableWidth * (1 << shift))))
+           || (rect.width() > (viewUsableWidth * (1 << shift)))) {
+
         shift++;
+    }
+
 
     scrollToPosition(SceneCoordinate(double(rect.center().x()), double(rect.center().y())));
 
@@ -177,24 +188,13 @@ QPoint MapEngine::convertSceneCoordinateToTileNumber(int zoomLevel, SceneCoordin
     return QPoint(x, y);
 }
 
-SceneCoordinate MapEngine::convertTileNumberToSceneCoordinate(int zoomLevel, QPoint tileNumber)
-{
-    qDebug() << __PRETTY_FUNCTION__;
-
-    int pow = 1 << (OSM_MAX_ZOOM_LEVEL - zoomLevel);
-    int x = tileNumber.x() * OSM_TILE_SIZE_X * pow;
-    int y = tileNumber.y() * OSM_TILE_SIZE_Y * pow;
-
-    return SceneCoordinate(x, y);
-}
-
 QRectF MapEngine::currentViewSceneRect() const
 {
     qDebug() << __PRETTY_FUNCTION__;
 
     const QPoint ONE_PIXEL = QPoint(1, 1);
 
-    QGraphicsView *view = m_mapScene->views().at(0);
+    QGraphicsView *view = m_mapScene->views().first();
     QPointF sceneTopLeft = view->mapToScene(0, 0);
     QPoint viewBottomRight = QPoint(view->size().width(), view->size().height()) - ONE_PIXEL;
     QPointF sceneBottomRight = view->mapToScene(viewBottomRight);
@@ -241,14 +241,14 @@ void MapEngine::getTiles(SceneCoordinate coordinate)
     int bottomRightX = m_viewTilesGrid.bottomRight().x();
     int bottomRightY = m_viewTilesGrid.bottomRight().y();
 
-    int tileMaxVal = tileMaxIndex(m_zoomLevel);
+    int tileMaxVal = MapTile::lastTileIndex(m_zoomLevel);
 
     for (int x = topLeftX; x <= bottomRightX; ++x) {
         for (int y = topLeftY; y <= bottomRightY; ++y) {
 
             // map doesn't span in vertical direction, so y index must be inside the limits
             if (y >= MAP_TILE_MIN_INDEX && y <= tileMaxVal) {
-                if (!m_mapScene->tileInScene(tilePath(m_zoomLevel, x, y)))
+                if (!m_mapScene->tileInScene(MapTile::tilePath(m_zoomLevel, x, y)))
                     emit fetchImage(m_zoomLevel, normalize(x, MAP_TILE_MIN_INDEX, tileMaxVal), y);
             }
         }
@@ -259,10 +259,17 @@ void MapEngine::gpsPositionUpdate(GeoCoordinate position, qreal accuracy)
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    m_gpsLocationItem->updatePosition(SceneCoordinate(position), accuracy);
     m_gpsPosition = position;
+
+    // update GPS location item (but only if accuracy is a valid number)
+    if (!isnan(accuracy)) {
+        qreal resolution = MapScene::horizontalResolutionAtLatitude(position.latitude());
+        m_gpsLocationItem->updateItem(SceneCoordinate(position).toPointF(), accuracy, resolution);
+    }
+
     m_mapScene->spanItems(currentViewSceneRect());
 
+    // do automatic centering (if enabled)
     if (m_autoCenteringEnabled) {
         m_lastAutomaticPosition = SceneCoordinate(position);
         m_scrollStartedByGps = true;
@@ -272,23 +279,6 @@ void MapEngine::gpsPositionUpdate(GeoCoordinate position, qreal accuracy)
     updateDirectionIndicator();
 }
 
-qreal MapEngine::greatCircleDistance(GeoCoordinate firstLocation, GeoCoordinate secondLocation)
-{
-    qDebug() << __PRETTY_FUNCTION__;
-
-    const qreal TO_RAD = (M_PI / 180);
-
-    qreal dLat = (secondLocation.latitude() - firstLocation.latitude()) * TO_RAD;
-    qreal dLon = (secondLocation.longitude() - firstLocation.longitude()) * TO_RAD;
-    qreal a = pow(sin(dLat / 2), 2)
-              + cos(firstLocation.latitude() * TO_RAD)
-                * cos(secondLocation.latitude() * TO_RAD)
-                * pow(sin(dLon / 2), 2);
-    qreal c = 2 * atan2(sqrt(a), sqrt(1 - a));
-
-    return (EARTH_RADIUS * c);
-}
-
 void MapEngine::init()
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -330,21 +320,6 @@ bool MapEngine::isCenterTileChanged(SceneCoordinate coordinate)
     return (centerTile != temp);
 }
 
-qreal MapEngine::sceneResolution()
-{
-    qDebug() << __PRETTY_FUNCTION__;
-
-    const int SHIFT = 200;
-    const int KM_TO_M = 1000;
-    qreal scale = (1 << (OSM_MAX_ZOOM_LEVEL - m_zoomLevel));
-    GeoCoordinate centerCoordinate = centerGeoCoordinate();
-    SceneCoordinate shiftedSceneCoordinate(m_sceneCoordinate.x() + SHIFT * scale,
-                                           m_sceneCoordinate.y());
-    GeoCoordinate shiftedCoordinate(shiftedSceneCoordinate);
-    qreal dist = greatCircleDistance(centerCoordinate, shiftedCoordinate) * KM_TO_M;
-    return (dist / SHIFT);
-}
-
 void MapEngine::mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image)
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -358,13 +333,17 @@ void MapEngine::mapImageReceived(int zoomLevel, int x, int y, const QPixmap &ima
 
     // duplicate to east side? (don't need to duplicate over padding)
     if (tileNumber.x() < (tilesGridWidthHalf - MAP_GRID_PADDING)) {
-        QPoint adjustedTileNumber(tileNumber.x() + tileMaxIndex(zoomLevel) + 1, tileNumber.y());
+        QPoint adjustedTileNumber(tileNumber.x() + MapTile::lastTileIndex(zoomLevel) + 1,
+                                  tileNumber.y());
         m_mapScene->addTile(zoomLevel, adjustedTileNumber, image, m_zoomLevel);
     }
 
     // duplicate to west side? (don't need to duplicate over padding)
-    if (tileNumber.x() > (tileMaxIndex(zoomLevel) - tilesGridWidthHalf + MAP_GRID_PADDING)) {
-        QPoint adjustedTileNumber(tileNumber.x() - tileMaxIndex(zoomLevel) - 1, tileNumber.y());
+    if (tileNumber.x() > (MapTile::lastTileIndex(zoomLevel)
+                          - tilesGridWidthHalf
+                          + MAP_GRID_PADDING)) {
+        QPoint adjustedTileNumber(tileNumber.x() - MapTile::lastTileIndex(zoomLevel) - 1,
+                                  tileNumber.y());
         m_mapScene->addTile(zoomLevel, adjustedTileNumber, image, m_zoomLevel);
     }
 }
@@ -439,6 +418,9 @@ void MapEngine::setAutoCentering(bool enabled)
     qDebug() << __PRETTY_FUNCTION__;
 
     m_autoCenteringEnabled = enabled;
+
+    if (!m_autoCenteringEnabled && m_gpsLocationItem->isVisible())
+        updateDirectionIndicator();
 }
 
 void MapEngine::setCenterPosition(SceneCoordinate coordinate)
@@ -465,7 +447,7 @@ void MapEngine::setCenterPosition(SceneCoordinate coordinate)
     }
 
     m_mapScene->spanItems(currentViewSceneRect());
-    emit newMapResolution(sceneResolution());
+    emit newMapResolution(viewResolution());
 
     updateDirectionIndicator();
 }
@@ -483,22 +465,11 @@ void MapEngine::setRoute(Route &route)
 
     m_route = route;
 
-    qDebug() << __PRETTY_FUNCTION__ << "from:" << m_route.startPointName();
-    qDebug() << __PRETTY_FUNCTION__ << "to:" << m_route.endPointName();
-    qDebug() << __PRETTY_FUNCTION__ << "distance:" << m_route.totalDistance();
-    qDebug() << __PRETTY_FUNCTION__ << "estimated time:" << m_route.totalTime();
-
-    foreach (GeoCoordinate point, m_route.geometryPoints())
-        qDebug() << __PRETTY_FUNCTION__ << "geometry point:" << point;
-
-    foreach (RouteSegment segment, m_route.segments()) {
-        qDebug() << __PRETTY_FUNCTION__ << "segment:" << segment.instruction();
-    }
-
     // delete old route track (if exists)
     if (m_mapRouteItem) {
         m_mapScene->removeItem(m_mapRouteItem);
         delete m_mapRouteItem;
+        m_mapRouteItem = 0;
     }
 
     // create new route track
@@ -538,36 +509,22 @@ void MapEngine::setTilesGridSize(const QSize &viewSize)
     m_tilesGridSize.setWidth(gridWidth);
 }
 
-int MapEngine::tileMaxIndex(int zoomLevel)
+void MapEngine::showMapArea(const GeoCoordinate &swBound, const GeoCoordinate &neBound)
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    // subtract one because first tile index is zero
-    return tilesPerSide(zoomLevel) - 1;
-}
+    QRect area;
+    area.setTopRight(SceneCoordinate(neBound).toPointF().toPoint());
+    area.setBottomLeft(SceneCoordinate(swBound).toPointF().toPoint());
 
-QString MapEngine::tilePath(int zoomLevel, int x, int y)
-{
-    qDebug() << __PRETTY_FUNCTION__;
-
-    QString tilePathString(QString::number(zoomLevel) + "/");
-    tilePathString.append(QString::number(x) + "/");
-    tilePathString.append(QString::number(y));
-
-    return tilePathString;
-}
-
-int MapEngine::tilesPerSide(int zoomLevel)
-{
-    return (1 << zoomLevel);
+    centerAndZoomTo(area, false);
 }
 
 void MapEngine::updateDirectionIndicator()
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    /// @todo implement distance calculation
-    qreal distance = greatCircleDistance(m_gpsPosition, m_sceneCoordinate);
+    qreal distance = m_gpsPosition.distanceTo(m_sceneCoordinate);
 
     qreal direction = m_sceneCoordinate.azimuthTo(SceneCoordinate(m_gpsPosition));
 
@@ -587,14 +544,14 @@ void MapEngine::updateViewTilesSceneRect()
     const QPoint ONE_TILE = QPoint(1, 1);
     const double ONE_PIXEL = 1;
 
-    SceneCoordinate topLeft = convertTileNumberToSceneCoordinate(m_zoomLevel,
-                                                        m_viewTilesGrid.topLeft());
+    SceneCoordinate topLeft = MapTile::convertTileNumberToSceneCoordinate(m_zoomLevel,
+                                                                        m_viewTilesGrid.topLeft());
 
     // one tile - one pixel is added because returned coordinates are pointing to upper left corner
     // of the last tile.
-    SceneCoordinate bottomRight = convertTileNumberToSceneCoordinate(m_zoomLevel,
-                                                            m_viewTilesGrid.bottomRight()
-                                                             + ONE_TILE);
+    SceneCoordinate bottomRight
+            = MapTile::convertTileNumberToSceneCoordinate(m_zoomLevel,
+                                                          m_viewTilesGrid.bottomRight() + ONE_TILE);
     bottomRight.setX(bottomRight.x() - ONE_PIXEL);
     bottomRight.setY(bottomRight.y() - ONE_PIXEL);
 
@@ -615,6 +572,15 @@ void MapEngine::viewResized(const QSize &size)
     m_mapScene->setSceneVerticalOverlap(m_viewSize.height(), m_zoomLevel);
 }
 
+qreal MapEngine::viewResolution()
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    qreal scale = (1 << (OSM_MAX_ZOOM_LEVEL - m_zoomLevel));
+
+    return MapScene::horizontalResolutionAtLatitude(centerGeoCoordinate().latitude()) * scale;
+}
+
 void MapEngine::viewZoomFinished()
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -640,7 +606,7 @@ void MapEngine::zoomed()
     getTiles(m_sceneCoordinate);
     m_mapScene->setSceneVerticalOverlap(m_viewSize.height(), m_zoomLevel);
     m_mapScene->spanItems(currentViewSceneRect());
-    emit newMapResolution(sceneResolution());
+    emit newMapResolution(viewResolution());
 }
 
 void MapEngine::zoomIn()