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

Bernhard Beschow bbeschow at cs.tu-berlin.de
Thu Jul 15 16:21:43 CEST 2010


SVN commit 1150267 by beschow:

support Equirectangular *and* Mercator projection for WMS

Since WMS query items are overridable in Marble, this allows to cheat with projections at
high zoom levels: Although most maps seem to be provided in Equirectangular projection,
one can tell Marble to interpret a map as Mercator-projected by specifying "Mercator" in
the DGML file and adding a WMS query item "srs=EPSG:4326" (Equirectangular projection) in
the download URL.
This allows for blending WMS maps onto OpenStreetMap and using WMS maps on devices that
only support Mercator projection.

 M  +71 -17    ServerLayout.cpp  
 M  +13 -7     ServerLayout.h  
 M  +1 -1      geodata/handlers/dgml/DgmlStorageLayoutTagHandler.cpp  


--- trunk/KDE/kdeedu/marble/src/lib/ServerLayout.cpp #1150266:1150267
@@ -20,13 +20,27 @@
 namespace Marble
 {
 
+ServerLayout::ServerLayout( GeoSceneTexture *textureLayer )
+    : m_textureLayer( textureLayer )
+{
+}
+
 ServerLayout::~ServerLayout()
 {
 }
 
+qint64 ServerLayout::numTilesX( const Marble::TileId& tileId ) const
+{
+    return ( 1 << tileId.zoomLevel() ) * m_textureLayer->levelZeroColumns();
+}
 
+qint64 ServerLayout::numTilesY( const Marble::TileId& tileId ) const
+{
+    return ( 1 << tileId.zoomLevel() ) * m_textureLayer->levelZeroRows();
+}
+
 MarbleServerLayout::MarbleServerLayout( GeoSceneTexture *textureLayer )
-    : m_textureLayer( textureLayer )
+    : ServerLayout( textureLayer )
 {
 }
 
@@ -40,7 +54,7 @@
 
 
 OsmServerLayout::OsmServerLayout( GeoSceneTexture *textureLayer )
-    : m_textureLayer( textureLayer )
+    : ServerLayout( textureLayer )
 {
 }
 
@@ -59,6 +73,11 @@
 }
 
 
+CustomServerLayout::CustomServerLayout( GeoSceneTexture *texture )
+    : ServerLayout( texture )
+{
+}
+
 QUrl CustomServerLayout::downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const
 {
     QString urlStr = prototypeUrl.toString();
@@ -71,18 +90,15 @@
 }
 
 WmsServerLayout::WmsServerLayout( GeoSceneTexture *texture )
-    : m_textureLayer( texture )
+    : ServerLayout( texture )
 {
 }
 
 QUrl WmsServerLayout::downloadUrl( const QUrl &prototypeUrl, const Marble::TileId &tileId ) const
 {
-    const qint64 radius = ( 1 << ( tileId.zoomLevel() - 1 ) );
+    const qint64 radius = numTilesX( tileId ) / 2;
     const qint64 x = tileId.x();
-    const qint64 y = tileId.y();
 
-    const qreal latBottom = ( radius - y - 1 ) / (double)radius *  90.0;
-    const qreal latTop    = ( radius - y     ) / (double)radius *  90.0;
     const qreal lonLeft   = ( x - radius     ) / (double)radius * 180.0;
     const qreal lonRight  = ( x - radius + 1 ) / (double)radius * 180.0;
 
@@ -99,25 +115,63 @@
             url.addQueryItem( "format", "image/" + m_textureLayer->fileFormat().toLower() );
     }
     if ( !url.hasQueryItem( "srs" ) ) {
-        switch ( m_textureLayer->projection() ) {
-            case GeoSceneTexture::Equirectangular:
-                url.addQueryItem( "srs", "EPSG:4326" );
-                break;
-            case GeoSceneTexture::Mercator:
-                url.addQueryItem( "srs", "EPSG:3785" );
-                break;
+        url.addQueryItem( "srs", epsgCode() );
         }
-    }
     if ( !url.hasQueryItem( "layers" ) )
         url.addQueryItem( "layers", m_textureLayer->name() );
     url.addQueryItem( "width", QString::number( m_textureLayer->tileSize().width() ) );
     url.addQueryItem( "height", QString::number( m_textureLayer->tileSize().height() ) );
     url.addQueryItem( "bbox", QString( "%1,%2,%3,%4" ).arg( QString::number( lonLeft, 'f', 12 ) )
-                                                      .arg( QString::number( latBottom, 'f', 12 ) )
+                                                      .arg( QString::number( latBottom( tileId ), 'f', 12 ) )
                                                       .arg( QString::number( lonRight, 'f', 12 ) )
-                                                      .arg( QString::number( latTop, 'f', 12 ) ) );
+                                                      .arg( QString::number( latTop( tileId ), 'f', 12 ) ) );
 
     return url;
 }
 
+qreal WmsServerLayout::latBottom( const Marble::TileId &tileId ) const
+{
+    const qint64 radius = numTilesY( tileId ) / 2;
+
+    switch( m_textureLayer->projection() )
+    {
+    case GeoSceneTexture::Equirectangular:
+        return ( radius - tileId.y() - 1 ) / (double)radius *  90.0;
+    case GeoSceneTexture::Mercator:
+        return atan( sinh( ( radius - tileId.y() - 1 ) / (double)radius * M_PI ) ) * 180.0 / M_PI;
 }
+
+    Q_ASSERT( false ); // not reached
+    return 0.0;
+}
+
+qreal WmsServerLayout::latTop( const Marble::TileId &tileId ) const
+{
+    const qint64 radius = numTilesY( tileId ) / 2;
+
+    switch( m_textureLayer->projection() )
+    {
+    case GeoSceneTexture::Equirectangular:
+        return ( radius - tileId.y() ) / (double)radius *  90.0;
+    case GeoSceneTexture::Mercator:
+        return atan( sinh( ( radius - tileId.y() ) / (double)radius * M_PI ) ) * 180.0 / M_PI;
+    }
+
+    Q_ASSERT( false ); // not reached
+    return 0.0;
+}
+
+QString WmsServerLayout::epsgCode() const
+{
+    switch ( m_textureLayer->projection() ) {
+        case GeoSceneTexture::Equirectangular:
+            return "EPSG:4326";
+        case GeoSceneTexture::Mercator:
+            return "EPSG:3785";
+    }
+
+    Q_ASSERT( false ); // not reached
+    return QString();
+}
+
+}
--- trunk/KDE/kdeedu/marble/src/lib/ServerLayout.h #1150266:1150267
@@ -21,6 +21,7 @@
 class ServerLayout
 {
 public:
+    ServerLayout( GeoSceneTexture *textureLayer );
     virtual ~ServerLayout();
 
     /**
@@ -32,6 +33,13 @@
      * @return completed URL for requested tile id
      */
     virtual QUrl downloadUrl( const QUrl &prototypeUrl, const TileId &id ) const = 0;
+
+protected:
+    qint64 numTilesX( const Marble::TileId &tileId ) const;
+    qint64 numTilesY( const Marble::TileId &tileId ) const;
+
+protected:
+    GeoSceneTexture *const m_textureLayer;
 };
 
 class MarbleServerLayout : public ServerLayout
@@ -43,9 +51,6 @@
      * Completes the path of the @p prototypeUrl and returns it.
      */
     virtual QUrl downloadUrl( const QUrl &prototypeUrl, const TileId & ) const;
-
-private:
-    GeoSceneTexture *const m_textureLayer;
 };
 
 class OsmServerLayout : public ServerLayout
@@ -58,14 +63,13 @@
      * the result.
      */
     virtual QUrl downloadUrl( const QUrl &prototypeUrl, const TileId & ) const;
-
-private:
-    GeoSceneTexture *const m_textureLayer;
 };
 
 class CustomServerLayout : public ServerLayout
 {
 public:
+    CustomServerLayout( GeoSceneTexture *texture );
+
     /**
      * Replaces escape sequences in the @p prototypeUrl by the values in @p id
      * and returns the result.
@@ -91,7 +95,9 @@
     virtual QUrl downloadUrl( const QUrl &prototypeUrl, const Marble::TileId &tileId ) const;
 
 private:
-    GeoSceneTexture *const m_textureLayer;
+    qreal latBottom( const Marble::TileId &tileId ) const;
+    qreal latTop( const Marble::TileId &tileId ) const;
+    QString epsgCode() const;
 };
 
 }
--- trunk/KDE/kdeedu/marble/src/lib/geodata/handlers/dgml/DgmlStorageLayoutTagHandler.cpp #1150266:1150267
@@ -73,7 +73,7 @@
         if ( modeStr == "OpenStreetMap" )
             serverLayout = new OsmServerLayout( texture );
         else if ( modeStr == "Custom" )
-            serverLayout = new CustomServerLayout();
+            serverLayout = new CustomServerLayout( texture );
         else if ( modeStr == "WebMapService" )
             serverLayout = new WmsServerLayout( texture );
         else {


More information about the Marble-commits mailing list