File indexing completed on 2025-01-05 03:59:10
0001 /* 0002 SPDX-FileCopyrightText: 2016 Friedrich W. H. Kossebau <kossebau@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "GeoSceneEquirectTileProjection.h" 0008 0009 #include <GeoDataLatLonBox.h> 0010 0011 namespace Marble 0012 { 0013 0014 GeoSceneEquirectTileProjection::GeoSceneEquirectTileProjection() 0015 { 0016 } 0017 0018 0019 GeoSceneEquirectTileProjection::~GeoSceneEquirectTileProjection() 0020 { 0021 } 0022 0023 GeoSceneAbstractTileProjection::Type GeoSceneEquirectTileProjection::type() const 0024 { 0025 return Equirectangular; 0026 } 0027 0028 0029 static inline 0030 unsigned int lowerBoundTileIndex(qreal baseTileIndex) 0031 { 0032 const qreal floorBaseTileIndex = floor(baseTileIndex); 0033 unsigned int tileIndex = static_cast<unsigned int>(floorBaseTileIndex); 0034 return (baseTileIndex == floorBaseTileIndex) ? tileIndex-1 : tileIndex; 0035 } 0036 0037 static inline 0038 unsigned int upperBoundTileIndex(qreal baseTileIndex) 0039 { 0040 return (unsigned int)floor(baseTileIndex); 0041 } 0042 0043 static inline 0044 qreal baseTileXFromLon(qreal lon, unsigned int tileCount) 0045 { 0046 return 0.5 * (lon / M_PI + 1.0) * tileCount; 0047 } 0048 0049 static inline 0050 qreal baseTileYFromLat(qreal lat, unsigned int tileCount) 0051 { 0052 return (0.5 - lat / M_PI) * tileCount; 0053 } 0054 0055 0056 // on tile borders selects the tile to the east 0057 static inline 0058 unsigned int eastBoundTileXFromLon(qreal lon, unsigned int tileCount) 0059 { 0060 // special casing tile-map end 0061 if (lon == M_PI) { 0062 return 0; 0063 } 0064 return upperBoundTileIndex(baseTileXFromLon(lon, tileCount)); 0065 } 0066 0067 // on tile borders selects the tile to the west 0068 static inline 0069 unsigned int westBoundTileXFromLon(qreal lon, unsigned int tileCount) 0070 { 0071 // special casing tile-map end 0072 if (lon == -M_PI) { 0073 return tileCount-1; 0074 } 0075 return lowerBoundTileIndex(baseTileXFromLon(lon, tileCount)); 0076 } 0077 0078 // on tile borders selects the tile to the south 0079 static inline 0080 unsigned int southBoundTileYFromLat(qreal lat, unsigned int tileCount) 0081 { 0082 // special casing tile-map end 0083 if (lat == -M_PI*0.5) { 0084 return 0; 0085 } 0086 return upperBoundTileIndex(baseTileYFromLat(lat, tileCount)); 0087 } 0088 0089 // on tile borders selects the tile to the north 0090 static inline 0091 unsigned int northBoundTileYFromLat(qreal lat, unsigned int tileCount) 0092 { 0093 // special casing tile-map end 0094 if (lat == M_PI*0.5) { 0095 return tileCount-1; 0096 } 0097 return lowerBoundTileIndex(baseTileYFromLat(lat, tileCount)); 0098 } 0099 0100 0101 QRect GeoSceneEquirectTileProjection::tileIndexes(const GeoDataLatLonBox &latLonBox, int zoomLevel) const 0102 { 0103 const unsigned int xTileCount = (1 << zoomLevel) * levelZeroColumns(); 0104 0105 const int westX = eastBoundTileXFromLon(latLonBox.west(), xTileCount); 0106 const int eastX = westBoundTileXFromLon(latLonBox.east(), xTileCount); 0107 0108 const unsigned int yTileCount = (1 << zoomLevel) * levelZeroRows(); 0109 0110 const int northY = southBoundTileYFromLat(latLonBox.north(), yTileCount); 0111 const int southY = northBoundTileYFromLat(latLonBox.south(), yTileCount); 0112 0113 return QRect(QPoint(westX, northY), QPoint(eastX, southY)); 0114 } 0115 0116 GeoDataLatLonBox GeoSceneEquirectTileProjection::geoCoordinates(int zoomLevel, int x, int y) const 0117 { 0118 const qreal radiusX = (1 << zoomLevel) * levelZeroColumns() / 2.0; 0119 const qreal radiusY = (1 << zoomLevel) * levelZeroRows() / 2.0; 0120 0121 const qreal west = (x - radiusX) / radiusX * M_PI; 0122 const qreal north = (radiusY - y) / radiusY * M_PI / 2.0; 0123 0124 const qreal east = ((x + 1) - radiusX) / radiusX * M_PI; 0125 const qreal south = (radiusY - (y + 1)) / radiusY * M_PI / 2.0; 0126 0127 return GeoDataLatLonBox(north, south, east, west); 0128 } 0129 0130 }