Re-factoring
authorSami Rämö <sami.ramo@ixonos.com>
Fri, 30 Jul 2010 09:08:52 +0000 (12:08 +0300)
committerSami Rämö <sami.ramo@ixonos.com>
Fri, 30 Jul 2010 09:08:52 +0000 (12:08 +0300)
 - Re-factored / moved MapEngine::greatCircleDistance()
   to GeoCoordinate::distanceTo()

 - Implemented operator- for GeoCoordinate

 - Changed GPSPositionPrivate implementation to return always the
   accuracy got from the GeoPositionInfo, and not the
   GPS_ACCURACY_UNDEFINED value in case of network positioning.

 - Changed the GPSLocationItem inherit from QGraphicsItem instead of
   QGraphicsPixmapItem. Implemented GPSLocationItem::boundingRect()

src/coordinates/geocoordinate.cpp
src/coordinates/geocoordinate.h
src/gps/gpspositionprivateliblocation.cpp
src/gps/liblocationwrapper.cpp
src/map/gpslocationitem.cpp
src/map/gpslocationitem.h
src/map/mapcommon.h
src/map/mapengine.cpp
src/map/mapengine.h

index ddf2d99..67e612e 100644 (file)
@@ -75,6 +75,25 @@ void GeoCoordinate::convertFrom(const SceneCoordinate &coordinate)
     setLongitude(longitude);
 }
 
+qreal GeoCoordinate::distanceTo(const GeoCoordinate &other) const
+{
+    qDebug() << __PRETTY_FUNCTION__;
+
+    const qreal EARTH_RADIUS = 6371.01;     // Earth radius in km
+    const qreal TO_RAD = (M_PI / 180);      // Conversion factor to radians
+    const int KM_TO_M = 1000;               // Conversion from kilometers to meters
+
+    GeoCoordinate delta = other - *this;
+
+    qreal a = pow(sin(delta.latitude() * TO_RAD / 2), 2)
+              + cos(m_latitude * TO_RAD)
+              * cos(other.latitude() * TO_RAD)
+              * pow(sin(delta.longitude() * TO_RAD / 2), 2);
+    qreal c = 2 * atan2(sqrt(a), sqrt(1 - a));
+
+    return (EARTH_RADIUS * c  * KM_TO_M);
+}
+
 bool GeoCoordinate::isNull() const
 {
     qDebug() << __PRETTY_FUNCTION__;
@@ -144,6 +163,12 @@ void GeoCoordinate::setLongitude(double longitude)
     m_validityFlags |= LongitudeSet;
 }
 
+const GeoCoordinate operator-(const GeoCoordinate &coordinate1, const GeoCoordinate &coordinate2)
+{
+    return GeoCoordinate(coordinate1.m_latitude - coordinate2.m_latitude,
+                         coordinate1.m_longitude - coordinate2.m_longitude);
+}
+
 QDataStream &operator<<(QDataStream &out, const GeoCoordinate &coordinate)
 {
     out << coordinate.m_latitude << coordinate.m_longitude;
index 1406de1..008ecb5 100644 (file)
@@ -63,6 +63,18 @@ public:
  ******************************************************************************/
 public:
     /**
+    * @brief Distance to other coordinate
+    *
+    * This calculation returns the great-circle distance between the two coordinates, with an
+    * assumption that the Earth is spherical. Calculation is done using haversine formula. Altitude
+    * is not used in the calculation.
+    *
+    * @param other Coordinate where the distance is calculated from this coordinate
+    * @returns Distance to other coordinate (in meters)
+    */
+    qreal distanceTo(const GeoCoordinate &other) const;
+
+    /**
     * @brief Check if coordinate is (0.0, 0.0)
     *
     * @returns True if both latitude and longitude are 0.0, otherwise false
@@ -146,6 +158,9 @@ private:
  * OPERATORS
  ******************************************************************************/
 public:
+    friend const GeoCoordinate operator-(const GeoCoordinate &coordinate1,
+                                         const GeoCoordinate &coordinate2);
+
     /**
     * @brief Output operator
     *
index 5dced5a..caca7d6 100644 (file)
@@ -209,8 +209,5 @@ qreal GPSPositionPrivate::accuracy(const GeoPositionInfo &positionInfo)
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    if (positionInfo.isAccurate())
-        return positionInfo.accuracy();
-    else
-        return GPS_ACCURACY_UNDEFINED;
+    return positionInfo.accuracy();
 }
index 1b2da69..0dcafd0 100644 (file)
@@ -86,7 +86,7 @@ void LiblocationWrapper::changed(LocationGPSDevice *device, gpointer data)
                 coordinate.setLatitude(device->fix->latitude);
                 coordinate.setLongitude(device->fix->longitude);
                 positionInfo.setCoordinate(coordinate);
-            }    
+            }
         }
         wrapper->setLastKnownPosition(positionInfo);
         emit wrapper->locationChanged(positionInfo);
index b10ed45..e822bad 100644 (file)
 
 #include "gpslocationitem.h"
 
+const qreal RING_OUTLINE_PEN_WIDTH = 1.0;
+
 GPSLocationItem::GPSLocationItem()
-    : m_showOnNextUpdate(true)
+    : m_showOnNextUpdate(true),
+      m_radius(3000)
 {
     qDebug() << __PRETTY_FUNCTION__;
 
-    setPixmap(QPixmap(":/res/images/gps_position.png"));
+    m_pixmap = QPixmap(":/res/images/gps_position.png");
 
     setPos(QPoint(UNDEFINED, UNDEFINED));
     setZValue(OWN_LOCATION_ICON_Z_LEVEL);
-    setOffset(-pixmap().width() / 2, -pixmap().height() / 2);
-    setFlag(QGraphicsItem::ItemIgnoresTransformations);
+    //setOffset(-m_pixmap.width() / 2, -m_pixmap.height() / 2);
+//    setFlag(QGraphicsItem::ItemIgnoresTransformations);
+}
+
+QRectF GPSLocationItem::boundingRect() const
+{
+    return QRectF(-m_radius - RING_OUTLINE_PEN_WIDTH / 2, -m_radius - RING_OUTLINE_PEN_WIDTH / 2,
+                  2 * m_radius + RING_OUTLINE_PEN_WIDTH, 2 * m_radius + RING_OUTLINE_PEN_WIDTH);
+}
+
+void GPSLocationItem::calculateAccuracyRingRadius()
+{
+    /// @todo calculate radius based on the current zoom level
+    m_radius;
 }
 
 void GPSLocationItem::paint(QPainter *painter,
                             const QStyleOptionGraphicsItem *option,
                             QWidget *widget)
 {
-    QGraphicsPixmapItem::paint(painter, option, widget);
+//    QGraphicsPixmapItem::paint(painter, option, widget);
 
     QColor color = QColor(Qt::red);
 
-    const int OUTLINE_ALPHA = 96;
-    const int FILL_ALPHA = 48;
+    const int RING_OUTLINE_ALPHA = 96;
+    const int RING_FILL_ALPHA = 48;
 
-    color.setAlpha(OUTLINE_ALPHA);
-    painter->setPen(color);
+    color.setAlpha(RING_OUTLINE_ALPHA);
+    QPen pen = QPen(color);
+    pen.setWidthF(RING_OUTLINE_PEN_WIDTH);
+    pen.setCosmetic(true);
+    painter->setPen(pen);
 
-    color.setAlpha(FILL_ALPHA);
+    color.setAlpha(RING_FILL_ALPHA);
     painter->setBrush(color);
 
     painter->setRenderHint(QPainter::Antialiasing);
 
     QPointF center = QPointF();
-    qreal radius = 30;
-    painter->drawEllipse(center, radius, radius);
+    painter->drawEllipse(center, m_radius, m_radius);
 }
 
 void GPSLocationItem::setEnabled(bool enable)
@@ -82,7 +99,7 @@ void GPSLocationItem::setEnabled(bool enable)
 
 void GPSLocationItem::updatePosition(SceneCoordinate coordinate, qreal accuracy)
 {
-    qDebug() << __PRETTY_FUNCTION__;
+    qWarning() << __PRETTY_FUNCTION__ << "accuracy:" << accuracy;
 
     setPos(coordinate.toPointF());
     m_accuracy = accuracy;
index 53813b4..c9ef6a4 100644 (file)
 #ifndef GPSLOCATIONITEM_H
 #define GPSLOCATIONITEM_H
 
-#include <QGraphicsPixmapItem>
+#include <QGraphicsItem>
 
 class SceneCoordinate;
 
 /**
   * @brief Class for indicating current position accuired from GPS on the map.
   *
-  * Also GPS fix accuracy is indicated by using two different color indicator images
-  * based on current accuracy
+  * Also the GPS fix accuracy is indicated by the radius of the circle around the position item.
   */
-class GPSLocationItem : public QGraphicsPixmapItem
+class GPSLocationItem : public QGraphicsItem
 {
 public:
     /**
@@ -45,7 +44,14 @@ public:
  ******************************************************************************/
 public:
     /**
-    * @brief Reimplementing the painter from QGraphicsPixmapItem
+    * @brief Implements the bounding rect
+    *
+    * @returns Bounding rect of the item
+    */
+    QRectF boundingRect() const;
+
+    /**
+    * @brief Implements the painter
     */
     void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
 
@@ -56,6 +62,9 @@ public:
     /**
       * @brief Enable / disable item
       *
+      * Actual enabling is done when next position update is received, so the old value before
+      * hiding the item is not used.
+      *
       * @param enable True if item should be enabled, otherwise false
       */
     void setEnabled(bool enable);
@@ -68,6 +77,9 @@ public:
       */
     void updatePosition(SceneCoordinate coordinate, qreal accuracy);
 
+private:
+    void calculateAccuracyRingRadius();
+
 /*******************************************************************************
  * DATA MEMBERS
  ******************************************************************************/
@@ -75,6 +87,9 @@ private:
     bool m_showOnNextUpdate;    ///< should the item be shown when next update arrives
 
     qreal m_accuracy;           ///< current accuracy
+    qreal m_radius;             ///< accuracy ring radius in scene pixels
+
+    QPixmap m_pixmap;           ///< red led pixmap
 };
 
 #endif // GPSLOCATIONITEM_H
index da2c98c..f779c02 100644 (file)
@@ -85,8 +85,6 @@ const int OWN_LOCATION_ICON_Z_LEVEL = FRIEND_LOCATION_ICON_Z_LEVEL + 1;
 const double MIN_LONGITUDE = -180.0;  ///< Minimum longitude value
 const double MAX_LONGITUDE = 180.0;  ///< Maximum longitude value
 
-const qreal EARTH_RADIUS = 6371.01;         ///< Earth radius in km
-
 const int MAP_GRID_PADDING = 0;  ///< Grid padding used in tile grid calculation
 
 const QString OSM_LICENSE = QString::fromUtf8("© OpenStreetMap contributors, CC-BY-SA");
index 0edebee..019e05b 100644 (file)
@@ -254,23 +254,6 @@ void MapEngine::gpsPositionUpdate(GeoCoordinate position, qreal accuracy)
     }
 }
 
-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__;
@@ -317,13 +300,13 @@ 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;
+    qreal dist = centerCoordinate.distanceTo(shiftedCoordinate);
     return (dist / SHIFT);
 }
 
index 0fe23aa..75b84c5 100644 (file)
@@ -103,18 +103,6 @@ public:
     static SceneCoordinate convertTileNumberToSceneCoordinate(int zoomLevel, QPoint tileNumber);
 
     /**
-     * @brief Calculate great-circle distance between two geographic coordinates
-     *
-     * Calculate great-circle distance between two given geographic locations using
-     * haversine formula
-     *
-     * @param firstLocation Coordinates of the first location
-     * @param secondLocation Coordinates of the second location
-     * @return qreal Distance in kilometers
-     */
-    qreal greatCircleDistance(GeoCoordinate firstLocation, GeoCoordinate secondLocation);
-
-    /**
      * @brief Set initial values for the map
      *
      * Set initial location and zoom level from the settings, if available, or use the default