File indexing completed on 2024-04-21 03:49:59

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 
0003 #include "TileCoordsPyramid.h"
0004 
0005 #include <QRect>
0006 #include <QVector>
0007 #include <MarbleDebug.h>
0008 
0009 #include <algorithm>
0010 
0011 namespace Marble
0012 {
0013 
0014 class Q_DECL_HIDDEN TileCoordsPyramid::Private
0015 {
0016 public:
0017     Private( int const topLevel, int const bottomLevel );
0018 
0019     int m_topLevel;
0020     int m_bottomLevel;
0021     QRect m_bottomLevelCoords;
0022     QVector<int> m_validLevels;
0023 };
0024 
0025 TileCoordsPyramid::Private::Private( int const topLevel, int const bottomLevel )
0026     : m_topLevel( topLevel ),
0027       m_bottomLevel( bottomLevel )
0028 {
0029     Q_ASSERT( m_topLevel <= m_bottomLevel );
0030 }
0031 
0032 
0033 TileCoordsPyramid::TileCoordsPyramid( int const topLevel, int const bottomLevel )
0034     : d( new Private( topLevel, bottomLevel ))
0035 {
0036 }
0037 
0038 TileCoordsPyramid::TileCoordsPyramid( TileCoordsPyramid const & other )
0039     : d( new Private( *other.d ))
0040 {
0041 }
0042 
0043 TileCoordsPyramid::TileCoordsPyramid()
0044     :d( new Private( 0, 0 ) )
0045 {
0046 
0047 }
0048 
0049 TileCoordsPyramid & TileCoordsPyramid::operator=( TileCoordsPyramid const & rhs )
0050 {
0051     TileCoordsPyramid temp( rhs );
0052     swap( temp );
0053     return *this;
0054 }
0055 
0056 TileCoordsPyramid::~TileCoordsPyramid()
0057 {
0058     delete d;
0059 }
0060 
0061 int TileCoordsPyramid::topLevel() const
0062 {
0063     return d->m_topLevel;
0064 }
0065 
0066 int TileCoordsPyramid::bottomLevel() const
0067 {
0068     return d->m_bottomLevel;
0069 }
0070 
0071 void TileCoordsPyramid::setBottomLevelCoords( QRect const & coords )
0072 {
0073     d->m_bottomLevelCoords = coords;
0074 }
0075 
0076 QRect TileCoordsPyramid::coords( int const level ) const
0077 {
0078     Q_ASSERT( d->m_topLevel <= level && level <= d->m_bottomLevel );
0079     int bottomX1, bottomY1, bottomX2, bottomY2;
0080     d->m_bottomLevelCoords.getCoords( &bottomX1, &bottomY1, &bottomX2, &bottomY2 );
0081     int const deltaLevel = d->m_bottomLevel - level;
0082     int const x1 = bottomX1 >> deltaLevel;
0083     int const y1 = bottomY1 >> deltaLevel;
0084     int const x2 = bottomX2 >> deltaLevel;
0085     int const y2 = bottomY2 >> deltaLevel;
0086     QRect result;
0087     result.setCoords( x1, y1, x2, y2 );
0088     return result;
0089 }
0090 
0091 void TileCoordsPyramid::setValidTileLevels(const QVector<int> validLevels)
0092 {
0093     d->m_validLevels = validLevels;
0094 }
0095 
0096 QVector<int> TileCoordsPyramid::validTileLevels()
0097 {
0098     return d->m_validLevels;
0099 }
0100 
0101 qint64 TileCoordsPyramid::tilesCount() const
0102 {
0103     qint64 result = 0;
0104     for ( int level = d->m_topLevel; level <= d->m_bottomLevel; ++level ) {
0105         if (!d->m_validLevels.isEmpty() && !d->m_validLevels.contains(level)) continue;
0106 
0107         QRect const levelCoords = coords( level );
0108         // w*h can exceed 32 bit range, so force 64 bit calculation; see bug 342397
0109         result += qint64( levelCoords.width() ) * levelCoords.height();
0110     }
0111     return result;
0112 }
0113 
0114 void TileCoordsPyramid::swap( TileCoordsPyramid & other )
0115 {
0116     std::swap( d, other.d );
0117 }
0118 
0119 }