[Marble-commits] KDE/kdeedu/marble/src/lib/Projections

Bernhard Beschow bbeschow at cs.tu-berlin.de
Sun Aug 29 21:40:22 CEST 2010


SVN commit 1169604 by beschow:

add another *Projection::geoCoordinates(), where given x and y are normalized absolute coordinates rather than offsets to a viewport

 M  +25 -4     AbstractProjection.h  
 M  +32 -4     EquirectProjection.cpp  
 M  +12 -4     EquirectProjection.h  
 M  +45 -4     MercatorProjection.cpp  
 M  +12 -4     MercatorProjection.h  
 M  +46 -3     SphericalProjection.cpp  
 M  +12 -4     SphericalProjection.h  


--- trunk/KDE/kdeedu/marble/src/lib/Projections/AbstractProjection.h #1169603:1169604
@@ -177,10 +177,16 @@
                                     const ViewportParams *viewport,
                                     QVector<QPolygonF*> &polygons );
 
+    virtual QPointF projectionCoordinates( qreal lon, qreal lat ) const = 0;
+
     /**
-     * @brief Get the earth coordinates corresponding to a pixel in the map.
-     * @param x      the x coordinate of the pixel
-     * @param y      the y coordinate of the pixel
+     * @brief Get the earth coordinates corresponding to a position in the projection.
+     *
+     * The projected area has its origin (0.0, 0.0) at (-180, +90) and reaches to
+     * (1.0, 1.0) at (+180, -90).
+     *
+     * @param normalizedX the x coordinate of the pixel relative to the origin of the viewport
+     * @param normalizedY the y coordinate of the pixel relative to the origin of the viewport
      * @param viewport the viewport parameters
      * @param lon    the longitude angle is returned through this parameter
      * @param lat    the latitude angle is returned through this parameter
@@ -188,7 +194,22 @@
      * @return @c true  if the pixel (x, y) is within the globe
      *         @c false if the pixel (x, y) is outside the globe, i.e. in space.
      */
-    virtual bool geoCoordinates( const int x, const int y,
+    virtual bool geoCoordinates( qreal normalizedX, qreal normalizedY,
+                                 qreal& lon, qreal& lat,
+                                 GeoDataCoordinates::Unit unit = GeoDataCoordinates::Degree ) const = 0;
+
+    /**
+     * @brief Get the earth coordinates corresponding to a pixel on the screen.
+     * @param viewportX the x coordinate of the pixel relative to the origin of the viewport
+     * @param viewportY the y coordinate of the pixel relative to the origin of the viewport
+     * @param viewport  the viewport parameters
+     * @param lon       the longitude angle is returned through this parameter
+     * @param lat       the latitude angle is returned through this parameter
+     * @param unit      the unit of the angles for lon and lat.
+     * @return @c true  if the pixel (x, y) is within the globe
+     *         @c false if the pixel (x, y) is outside the globe, i.e. in space.
+     */
+    virtual bool geoCoordinates( const int viewportX, const int viewportY,
                                  const ViewportParams *viewport,
                                  qreal& lon, qreal& lat,
                                  GeoDataCoordinates::Unit unit = GeoDataCoordinates::Degree ) = 0;
--- trunk/KDE/kdeedu/marble/src/lib/Projections/EquirectProjection.cpp #1169603:1169604
@@ -198,7 +198,35 @@
 }
 
 
-bool EquirectProjection::geoCoordinates( const int x, const int y,
+QPointF EquirectProjection::projectionCoordinates( qreal lon, qreal lat ) const
+{
+    const qreal x = ( 0.5 + 0.5 * lon / M_PI );
+    const qreal y = ( 0.5 -       lat / M_PI );
+
+    return QPointF( x, y );
+}
+
+
+bool EquirectProjection::geoCoordinates( qreal normalizedX, qreal normalizedY,
+                                         qreal& lon, qreal& lat,
+                                         GeoDataCoordinates::Unit unit) const
+{
+    lat = ( 0.5 - normalizedY ) * M_PI;
+    lon = ( normalizedX - 0.5 ) * 2 * M_PI;
+
+    while ( lon > M_PI )  lon -= 2.0 * M_PI;
+    while ( lon < -M_PI ) lon += 2.0 * M_PI;
+
+    if ( unit == GeoDataCoordinates::Degree ) {
+        lon *= RAD2DEG;
+        lat *= RAD2DEG;
+    }
+
+    return true;
+}
+
+
+bool EquirectProjection::geoCoordinates( const int viewportX, const int viewportY,
                                          const ViewportParams *viewport,
                                          qreal& lon, qreal& lat,
                                          GeoDataCoordinates::Unit unit )
@@ -218,11 +246,11 @@
     int yBottom       = yTop + 2 * radius;
 
     // Return here if the y coordinate is outside the map
-    if ( y < yTop || y >= yBottom )
+    if ( viewportY < yTop || viewportY >= yBottom )
         return false;
 
-    int const xPixels = x - halfImageWidth;
-    int const yPixels = y - halfImageHeight;
+    int const xPixels = viewportX - halfImageWidth;
+    int const yPixels = viewportY - halfImageHeight;
 
     qreal const pixel2Rad = M_PI / (2.0 * radius);
     lat = - yPixels * pixel2Rad + centerLat;
--- trunk/KDE/kdeedu/marble/src/lib/Projections/EquirectProjection.h #1169603:1169604
@@ -84,16 +84,24 @@
                             const ViewportParams *viewport,
                             QVector<QPolygonF*> &polygons );
 
+    virtual QPointF projectionCoordinates( qreal lon, qreal lat ) const;
+
+    virtual bool geoCoordinates( qreal normalizedX, qreal normalizedY,
+                                 qreal& lon, qreal& lat,
+                                 GeoDataCoordinates::Unit unit = GeoDataCoordinates::Degree ) const;
+
     /**
-     * @brief Get the earth coordinates corresponding to a pixel in the map.
-     * @param x      the x coordinate of the pixel
-     * @param y      the y coordinate of the pixel
+     * @brief Get the earth coordinates corresponding to a pixel on the screen.
+     * @param viewportX the x coordinate of the pixel relative to the origin of the viewport
+     * @param viewportY the y coordinate of the pixel relative to the origin of the viewport
+     * @param viewport  the viewport parameters
      * @param lon    the longitude angle is returned through this parameter
      * @param lat    the latitude angle is returned through this parameter
+     * @param unit      the unit of the angles for lon and lat.
      * @return @c true  if the pixel (x, y) is within the globe
      *         @c false if the pixel (x, y) is outside the globe, i.e. in space.
      */
-    bool geoCoordinates( const int x, const int y,
+    bool geoCoordinates( const int viewportX, const int viewportY,
                          const ViewportParams *params,
                          qreal& lon, qreal& lat,
                          GeoDataCoordinates::Unit unit = GeoDataCoordinates::Degree );
--- trunk/KDE/kdeedu/marble/src/lib/Projections/MercatorProjection.cpp #1169603:1169604
@@ -244,7 +244,48 @@
 }
 
 
-bool MercatorProjection::geoCoordinates( const int x, const int y,
+QPointF MercatorProjection::projectionCoordinates( qreal lon, qreal lat ) const
+{
+    if ( lat > maxLat() ) {
+        lat = maxLat();
+    }
+    if ( lat < minLat() ) {
+        lat = minLat();
+    }
+
+    const qreal x = ( 0.5 + 0.5 *             lon     / M_PI );
+    const qreal y = ( 0.5 - 0.5 * atanh( sin( lat ) ) / M_PI );
+
+    return QPointF( x, y );
+}
+
+
+bool MercatorProjection::geoCoordinates( qreal normalizedX, qreal normalizedY,
+                                         qreal& lon, qreal& lat,
+                                         GeoDataCoordinates::Unit unit) const
+{
+    bool          noerr              = false;
+
+    if ( 0 <= normalizedY && normalizedY < 1 ) {
+        lat = atan( sinh( ( 0.5 - normalizedY ) * 2 * M_PI ) );
+        lon =             ( normalizedX - 0.5 ) * 2 * M_PI;
+
+        while ( lon > M_PI )  lon -= 2*M_PI;
+        while ( lon < -M_PI ) lon += 2*M_PI;
+
+        noerr = true;
+    }
+
+    if ( unit == GeoDataCoordinates::Degree ) {
+        lon *= RAD2DEG;
+        lat *= RAD2DEG;
+    }
+
+    return noerr;
+}
+
+
+bool MercatorProjection::geoCoordinates( const int viewportX, const int viewportY,
                                          const ViewportParams *viewport,
                                          qreal& lon, qreal& lat,
                                          GeoDataCoordinates::Unit unit )
@@ -266,11 +307,11 @@
     int yTop          = halfImageHeight - 2 * radius + yCenterOffset;
     int yBottom       = yTop + 4 * radius;
 
-    if ( y >= yTop && y < yBottom ) {
-        int    const  xPixels   = x - halfImageWidth;
+    if ( viewportY >= yTop && viewportY < yBottom ) {
+        int    const  xPixels   = viewportX - halfImageWidth;
         qreal const  pixel2Rad = M_PI / (2 * radius);
 
-        lat = atan( sinh( ( ( halfImageHeight + yCenterOffset ) - y)
+        lat = atan( sinh( ( ( halfImageHeight + yCenterOffset ) - viewportY)
                           * pixel2Rad ) );
         lon = xPixels * pixel2Rad + centerLon;
 
--- trunk/KDE/kdeedu/marble/src/lib/Projections/MercatorProjection.h #1169603:1169604
@@ -83,16 +83,24 @@
                             const ViewportParams *viewport,
                             QVector<QPolygonF*> &polygons );
 
+    virtual QPointF projectionCoordinates( qreal lon, qreal lat ) const;
+
+    virtual bool geoCoordinates( qreal normalizedX, qreal normalizedY,
+                                 qreal& lon, qreal& lat,
+                                 GeoDataCoordinates::Unit unit = GeoDataCoordinates::Degree ) const;
+
    /**
-     * @brief Get the earth coordinates corresponding to a pixel in the map.
-     * @param x      the x coordinate of the pixel
-     * @param y      the y coordinate of the pixel
+     * @brief Get the earth coordinates corresponding to a pixel on the screen.
+     * @param viewportX the x coordinate of the pixel relative to the origin of the viewport
+     * @param viewportY the y coordinate of the pixel relative to the origin of the viewport
+     * @param viewport  the viewport parameters
      * @param lon    the longitude angle is returned through this parameter
      * @param lat    the latitude angle is returned through this parameter
+     * @param unit      the unit of the angles for lon and lat.
      * @return @c true  if the pixel (x, y) is within the globe
      *         @c false if the pixel (x, y) is outside the globe, i.e. in space.
      */
-    bool geoCoordinates( const int x, const int y,
+    bool geoCoordinates( const int viewportX, const int viewportY,
                          const ViewportParams *params,
                          qreal& lon, qreal& lat,
                          GeoDataCoordinates::Unit = GeoDataCoordinates::Degree );
--- trunk/KDE/kdeedu/marble/src/lib/Projections/SphericalProjection.cpp #1169603:1169604
@@ -189,7 +189,50 @@
 }
 
 
-bool SphericalProjection::geoCoordinates( const int x, const int y,
+QPointF SphericalProjection::projectionCoordinates( qreal lon, qreal lat ) const
+{
+    const Quaternion p( lon, lat );
+
+    const qreal x = ( 0.5 + 0.5 * p.v[Q_X] );
+    const qreal y = ( 0.5 - 0.5 * p.v[Q_Y] );
+
+    return QPointF( x, y );
+}
+
+
+bool SphericalProjection::geoCoordinates( qreal normalizedX, qreal normalizedY,
+                                          qreal& lon, qreal& lat,
+                                          GeoDataCoordinates::Unit unit ) const
+{
+    bool noerr = false;
+
+    qreal centerX = normalizedX - 0.5;
+    qreal centerY = normalizedY - 0.5;
+
+    if ( 1 > centerX * centerX + centerY * centerY ) {
+        qreal qx = 2 * +centerX;
+        qreal qy = 2 * -centerY;
+        qreal qr = 1.0 - qy * qy;
+
+        qreal qr2z = qr - qx * qx;
+        qreal qz   = ( qr2z > 0.0 ) ? sqrt( qr2z ) : 0.0;
+
+        Quaternion  qpos( 0.0, qx, qy, qz );
+        qpos.getSpherical( lon, lat );
+
+        noerr = true;
+    }
+
+    if ( unit == GeoDataCoordinates::Degree ) {
+        lon *= RAD2DEG;
+        lat *= RAD2DEG;
+    }
+
+    return noerr;
+}
+
+
+bool SphericalProjection::geoCoordinates( const int viewportX, const int viewportY,
                                           const ViewportParams *viewport,
                                           qreal& lon, qreal& lat,
                                           GeoDataCoordinates::Unit unit )
@@ -198,8 +241,8 @@
     bool          noerr         = false;
 
     qreal radius  = (qreal)( viewport->radius() );
-    qreal centerX = (qreal)( x - viewport->width() / 2 );
-    qreal centerY = (qreal)( y - viewport->height() / 2 );
+    qreal centerX = (qreal)( viewportX - viewport->width() / 2 );
+    qreal centerY = (qreal)( viewportY - viewport->height() / 2 );
 
     if ( radius * radius > centerX * centerX + centerY * centerY ) {
         qreal qx = inverseRadius * +centerX;
--- trunk/KDE/kdeedu/marble/src/lib/Projections/SphericalProjection.h #1169603:1169604
@@ -83,16 +83,24 @@
                             const ViewportParams *viewport,
                             QVector<QPolygonF*> &polygons );
                             
+    virtual QPointF projectionCoordinates( qreal lon, qreal lat ) const;
+
+    virtual bool geoCoordinates( qreal normalizedX, qreal normalizedY,
+                                 qreal& lon, qreal& lat,
+                                 GeoDataCoordinates::Unit unit = GeoDataCoordinates::Degree ) const;
+
     /**
-     * @brief Get the earth coordinates corresponding to a pixel in the map.
-     * @param x      the x coordinate of the pixel
-     * @param y      the y coordinate of the pixel
+     * @brief Get the earth coordinates corresponding to a pixel on the screen.
+     * @param viewportX the x coordinate of the pixel relative to the origin of the viewport
+     * @param viewportY the y coordinate of the pixel relative to the origin of the viewport
+     * @param viewport  the viewport parameters
      * @param lon    the longitude angle is returned through this parameter
      * @param lat    the latitude angle is returned through this parameter
+     * @param unit      the unit of the angles for lon and lat.
      * @return @c true  if the pixel (x, y) is within the globe
      *         @c false if the pixel (x, y) is outside the globe, i.e. in space.
      */
-    bool geoCoordinates( const int x, const int y,
+    bool geoCoordinates( const int viewportX, const int viewportY,
                          const ViewportParams *params,
                          qreal& lon, qreal& lat,
                          GeoDataCoordinates::Unit unit = GeoDataCoordinates::Degree );


More information about the Marble-commits mailing list