Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Move determination of tiles in ranges to QgsTileMatrixSet
This gives more flexibility in future to handle known missing tiles or
other special circumstances (eg falling back to lower
zoom level tiles from the matrix set in certain circumstances)
  • Loading branch information
nyalldawson committed May 10, 2023
1 parent aee823a commit 5d9ea98
Show file tree
Hide file tree
Showing 7 changed files with 59 additions and 17 deletions.
7 changes: 7 additions & 0 deletions python/core/auto_generated/qgstiles.sip.in
Expand Up @@ -365,6 +365,13 @@ Returns the scale to tile zoom method.
Sets the scale to tile zoom method.

.. seealso:: :py:func:`scaleToTileZoomMethod`
%End

QVector<QgsTileXYZ> tilesInRange( QgsTileRange range, int zoomLevel ) const;
%Docstring
Returns a list of tiles in the given tile range.

.. versionadded:: 3.32
%End

};
Expand Down
18 changes: 18 additions & 0 deletions src/core/qgstiles.cpp
Expand Up @@ -398,3 +398,21 @@ QDomElement QgsTileMatrixSet::writeXml( QDomDocument &document, const QgsReadWri

return setElement;
}

QVector<QgsTileXYZ> QgsTileMatrixSet::tilesInRange( QgsTileRange range, int zoomLevel ) const
{
QVector<QgsTileXYZ> tiles;
tiles.reserve( static_cast< std::size_t>( range.endColumn() - range.startColumn() + 1 ) * ( range.endRow() - range.startRow() + 1 ) );

const QgsTileMatrix &matrix = mTileMatrices.value( zoomLevel );

for ( int tileRow = range.startRow(); tileRow <= range.endRow(); ++tileRow )
{
for ( int tileColumn = range.startColumn(); tileColumn <= range.endColumn(); ++tileColumn )
{
tiles.append( QgsTileXYZ( tileColumn, tileRow, zoomLevel ) );
}
}
return tiles;
}

7 changes: 7 additions & 0 deletions src/core/qgstiles.h
Expand Up @@ -376,6 +376,13 @@ class CORE_EXPORT QgsTileMatrixSet
*/
void setScaleToTileZoomMethod( Qgis::ScaleToTileZoomLevelMethod method ) { mScaleToTileZoomMethod = method; }

/**
* Returns a list of tiles in the given tile range.
*
* \since QGIS 3.32
*/
QVector<QgsTileXYZ> tilesInRange( QgsTileRange range, int zoomLevel ) const;

private:

// Usually corresponds to zoom level 0, even if that zoom level is NOT present in the actual tile matrices for this set
Expand Down
4 changes: 2 additions & 2 deletions src/core/vectortile/qgsvectortileloader.cpp
Expand Up @@ -39,7 +39,7 @@ QgsVectorTileLoader::QgsVectorTileLoader( const QgsVectorTileDataProvider *provi
}

QgsDebugMsgLevel( QStringLiteral( "Starting network loader" ), 2 );
QVector<QgsTileXYZ> tiles = QgsVectorTileUtils::tilesInRange( range, zoomLevel );
QVector<QgsTileXYZ> tiles = tileMatrixSet.tilesInRange( range, zoomLevel );
QgsVectorTileUtils::sortTilesByDistanceFromCenter( tiles, viewCenter );
for ( QgsTileXYZ id : std::as_const( tiles ) )
{
Expand Down Expand Up @@ -152,7 +152,7 @@ QList<QgsVectorTileRawData> QgsVectorTileLoader::blockingFetchTileRawData( const
if ( feedback && feedback->isCanceled() )
return {};

QVector<QgsTileXYZ> tiles = QgsVectorTileUtils::tilesInRange( range, zoomLevel );
QVector<QgsTileXYZ> tiles = tileMatrixSet.tilesInRange( range, zoomLevel );

// if a tile matrix results in a HUGE number of tile requests, we skip the sort -- it can be expensive
if ( tiles.size() < 10000 )
Expand Down
13 changes: 0 additions & 13 deletions src/core/vectortile/qgsvectortileutils.cpp
Expand Up @@ -163,19 +163,6 @@ struct LessThanTileRequest
}
};

QVector<QgsTileXYZ> QgsVectorTileUtils::tilesInRange( QgsTileRange range, int zoomLevel )
{
QVector<QgsTileXYZ> tiles;
for ( int tileRow = range.startRow(); tileRow <= range.endRow(); ++tileRow )
{
for ( int tileColumn = range.startColumn(); tileColumn <= range.endColumn(); ++tileColumn )
{
tiles.append( QgsTileXYZ( tileColumn, tileRow, zoomLevel ) );
}
}
return tiles;
}

void QgsVectorTileUtils::sortTilesByDistanceFromCenter( QVector<QgsTileXYZ> &tiles, QPointF center )
{
LessThanTileRequest cmp;
Expand Down
2 changes: 0 additions & 2 deletions src/core/vectortile/qgsvectortileutils.h
Expand Up @@ -48,8 +48,6 @@ class CORE_EXPORT QgsVectorTileUtils
{
public:

//! Returns a list of tiles in the given tile range
static QVector<QgsTileXYZ> tilesInRange( QgsTileRange range, int zoomLevel );
//! Orders tile requests according to the distance from view center (given in tile matrix coords)
static void sortTilesByDistanceFromCenter( QVector<QgsTileXYZ> &tiles, QPointF center );

Expand Down
25 changes: 25 additions & 0 deletions tests/src/python/test_qgstiles.py
Expand Up @@ -94,6 +94,14 @@ def testQgsTileMatrixSet(self):
self.assertEqual(matrix_set.maximumZoom(), 1)
self.assertEqual(matrix_set.crs().authid(), 'EPSG:4326')

range = QgsTileRange(1, 3, 4, 7)
tiles = matrix_set.tilesInRange(range, 1)
self.assertEqual(len(tiles), 12)
self.assertEqual(min(t.column() for t in tiles), 1)
self.assertEqual(max(t.column() for t in tiles), 3)
self.assertEqual(min(t.row() for t in tiles), 4)
self.assertEqual(max(t.row() for t in tiles), 7)

# should not apply any special logic here, and return scales unchanged
self.assertEqual(matrix_set.calculateTileScaleForMap(1000, QgsCoordinateReferenceSystem('EPSG:4326'),
QgsRectangle(0, 2, 20, 12), QSize(20, 10), 96), 1000)
Expand Down Expand Up @@ -123,6 +131,23 @@ def testQgsTileMatrixSet(self):
self.assertEqual(matrix_set.tileMatrix(2).zoomLevel(), 2)
self.assertEqual(matrix_set.tileMatrix(99).zoomLevel(), -1)

tiles = matrix_set.tilesInRange(QgsTileRange(1, 3, 4, 7), 1)
self.assertEqual(len(tiles), 12)
self.assertEqual(min(t.column() for t in tiles), 1)
self.assertEqual(max(t.column() for t in tiles), 3)
self.assertEqual(min(t.row() for t in tiles), 4)
self.assertEqual(max(t.row() for t in tiles), 7)
self.assertEqual(min(t.zoomLevel() for t in tiles), 1)
self.assertEqual(max(t.zoomLevel() for t in tiles), 1)
tiles = matrix_set.tilesInRange(QgsTileRange(2, 4, 1, 3), 2)
self.assertEqual(len(tiles), 9)
self.assertEqual(min(t.column() for t in tiles), 2)
self.assertEqual(max(t.column() for t in tiles), 4)
self.assertEqual(min(t.row() for t in tiles), 1)
self.assertEqual(max(t.row() for t in tiles), 3)
self.assertEqual(min(t.zoomLevel() for t in tiles), 2)
self.assertEqual(max(t.zoomLevel() for t in tiles), 2)

self.assertAlmostEqual(matrix_set.scaleToZoom(776503144), 1, 5)
self.assertEqual(matrix_set.scaleToZoom(1776503144), 1)
self.assertAlmostEqual(matrix_set.scaleToZoom(76503144), 2, 5)
Expand Down

0 comments on commit 5d9ea98

Please sign in to comment.