#include <QtAlgorithms>
#include <QDebug>
+#include <QGraphicsView>
#include <QString>
#include <QStringList>
#include <QUrl>
#include <QRect>
#include "common.h"
+#include "coordinates/geocoordinate.h"
#include "frienditemshandler.h"
#include "gpslocationitem.h"
#include "mapcommon.h"
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())));
return QPoint(x, y);
}
+QRectF MapEngine::currentViewSceneRect() const
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ const QPoint ONE_PIXEL = QPoint(1, 1);
+
+ 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);
+
+ return QRectF(sceneTopLeft, sceneBottomRight);
+}
+
void MapEngine::disableAutoCenteringIfRequired(SceneCoordinate coordinate)
{
if (isAutoCenteringEnabled()) {
{
qDebug() << __PRETTY_FUNCTION__;
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+ m_mapScene->spanItems(currentViewSceneRect());
}
void MapEngine::getTiles(SceneCoordinate coordinate)
{
qDebug() << __PRETTY_FUNCTION__;
- m_gpsLocationItem->updatePosition(SceneCoordinate(position), accuracy);
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+ 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;
scrollToPosition(m_lastAutomaticPosition);
}
+
+ updateDirectionIndicator();
}
void MapEngine::init()
return (centerTile != temp);
}
-qreal MapEngine::sceneResolution()
-{
- qDebug() << __PRETTY_FUNCTION__;
-
- const int SHIFT = 200;
-
- 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 = centerCoordinate.distanceTo(shiftedCoordinate);
- return (dist / SHIFT);
-}
-
void MapEngine::mapImageReceived(int zoomLevel, int x, int y, const QPixmap &image)
{
qDebug() << __PRETTY_FUNCTION__;
m_ownLocation->hide();
}
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
+ m_mapScene->spanItems(currentViewSceneRect());
}
QGraphicsScene* MapEngine::scene()
qDebug() << __PRETTY_FUNCTION__;
m_autoCenteringEnabled = enabled;
+
+ if (!m_autoCenteringEnabled && m_gpsLocationItem->isVisible())
+ updateDirectionIndicator();
}
void MapEngine::setCenterPosition(SceneCoordinate coordinate)
m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
}
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
- emit newMapResolution(sceneResolution());
+ m_mapScene->spanItems(currentViewSceneRect());
+ emit newMapResolution(viewResolution());
+
+ updateDirectionIndicator();
}
void MapEngine::setGPSEnabled(bool enabled)
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
m_tilesGridSize.setWidth(gridWidth);
}
+void MapEngine::showMapArea(const GeoCoordinate &swBound, const GeoCoordinate &neBound)
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ QRect area;
+ area.setTopRight(SceneCoordinate(neBound).toPointF().toPoint());
+ area.setBottomLeft(SceneCoordinate(swBound).toPointF().toPoint());
+
+ centerAndZoomTo(area, false);
+}
+
+void MapEngine::updateDirectionIndicator()
+{
+ qDebug() << __PRETTY_FUNCTION__;
+
+ qreal distance = m_gpsPosition.distanceTo(m_sceneCoordinate);
+
+ qreal direction = m_sceneCoordinate.azimuthTo(SceneCoordinate(m_gpsPosition));
+
+ // direction indicator triangle should be drawn only if the gps location item is not currently
+ // visible on the view
+ bool drawDirectionIndicatorTriangle = true;
+ if (currentViewSceneRect().contains(m_gpsLocationItem->pos()))
+ drawDirectionIndicatorTriangle = false;
+
+ emit directionIndicatorValuesUpdate(direction, distance, drawDirectionIndicatorTriangle);
+}
+
void MapEngine::updateViewTilesSceneRect()
{
qDebug() << __PRETTY_FUNCTION__;
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__;
+ updateDirectionIndicator();
+
if (m_zoomedIn) {
m_zoomedIn = false;
m_mapScene->removeOutOfViewTiles(m_viewTilesGrid, m_zoomLevel);
m_mapScene->setZoomLevel(m_zoomLevel);
getTiles(m_sceneCoordinate);
m_mapScene->setSceneVerticalOverlap(m_viewSize.height(), m_zoomLevel);
- m_mapScene->spanItems(m_zoomLevel, m_sceneCoordinate, m_viewSize);
- emit newMapResolution(sceneResolution());
+ m_mapScene->spanItems(currentViewSceneRect());
+ emit newMapResolution(viewResolution());
}
void MapEngine::zoomIn()