Skip to content

Commit 0c51c3f

Browse files
committed
Housekeeping in WMS provider - move some calculations to utility functions
1 parent e2bcba5 commit 0c51c3f

File tree

3 files changed

+123
-70
lines changed

3 files changed

+123
-70
lines changed

src/providers/wms/qgswmscapabilities.cpp

+74-3
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,7 @@ void QgsWmsCapabilities::parseTileSetProfile( QDomElement const &e )
12581258
m.matrixWidth = ceil( l.boundingBoxes.at( 0 ).box.width() / m.tileWidth / r );
12591259
m.matrixHeight = ceil( l.boundingBoxes.at( 0 ).box.height() / m.tileHeight / r );
12601260
m.topLeft = QgsPoint( l.boundingBoxes.at( 0 ).box.xMinimum(), l.boundingBoxes.at( 0 ).box.yMinimum() + m.matrixHeight * m.tileHeight * r );
1261+
m.tres = r;
12611262
ms.tileMatrices.insert( r, m );
12621263
i++;
12631264
}
@@ -1340,17 +1341,19 @@ void QgsWmsCapabilities::parseWMTSContents( QDomElement const &e )
13401341
m.matrixWidth = e1.firstChildElement( "MatrixWidth" ).text().toInt();
13411342
m.matrixHeight = e1.firstChildElement( "MatrixHeight" ).text().toInt();
13421343

1343-
double res = m.scaleDenom * 0.00028 / metersPerUnit;
1344+
// the magic number below is "standardized rendering pixel size" defined
1345+
// in WMTS (and WMS 1.3) standard, being 0.28 pixel
1346+
m.tres = m.scaleDenom * 0.00028 / metersPerUnit;
13441347

13451348
QgsDebugMsg( QString( " %1: scale=%2 res=%3 tile=%4x%5 matrix=%6x%7 topLeft=%8" )
13461349
.arg( m.identifier )
1347-
.arg( m.scaleDenom ).arg( res )
1350+
.arg( m.scaleDenom ).arg( m.tres )
13481351
.arg( m.tileWidth ).arg( m.tileHeight )
13491352
.arg( m.matrixWidth ).arg( m.matrixHeight )
13501353
.arg( m.topLeft.toString() )
13511354
);
13521355

1353-
s.tileMatrices.insert( res, m );
1356+
s.tileMatrices.insert( m.tres, m );
13541357
}
13551358

13561359
mTileMatrixSets.insert( s.identifier, s );
@@ -1797,6 +1800,8 @@ bool QgsWmsCapabilities::detectTileLayerBoundingBox( QgsWmtsTileLayer& l )
17971800

17981801
const QgsWmtsTileMatrix& tm = *tmIt;
17991802
double metersPerUnit = QgsUnitTypes::fromUnitToUnitFactor( crs.mapUnits(), QgsUnitTypes::DistanceMeters );
1803+
// the magic number below is "standardized rendering pixel size" defined
1804+
// in WMTS (and WMS 1.3) standard, being 0.28 pixel
18001805
double res = tm.scaleDenom * 0.00028 / metersPerUnit;
18011806
QgsPoint bottomRight( tm.topLeft.x() + res * tm.tileWidth * tm.matrixWidth,
18021807
tm.topLeft.y() - res * tm.tileHeight * tm.matrixHeight );
@@ -2049,3 +2054,69 @@ void QgsWmsCapabilitiesDownload::capabilitiesReplyFinished()
20492054

20502055
emit downloadFinished();
20512056
}
2057+
2058+
QRectF QgsWmtsTileMatrix::tileRect( int col, int row ) const
2059+
{
2060+
double twMap = tileWidth * tres;
2061+
double thMap = tileHeight * tres;
2062+
return QRectF( topLeft.x() + col * twMap, topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
2063+
}
2064+
2065+
QgsRectangle QgsWmtsTileMatrix::tileBBox( int col, int row ) const
2066+
{
2067+
double twMap = tileWidth * tres;
2068+
double thMap = tileHeight * tres;
2069+
return QgsRectangle(
2070+
topLeft.x() + col * twMap,
2071+
topLeft.y() - ( row + 1 ) * thMap,
2072+
topLeft.x() + ( col + 1 ) * twMap,
2073+
topLeft.y() - row * thMap );
2074+
}
2075+
2076+
void QgsWmtsTileMatrix::viewExtentIntersection( const QgsRectangle &viewExtent, const QgsWmtsTileMatrixLimits* tml, int &col0, int &row0, int &col1, int &row1 ) const
2077+
{
2078+
double twMap = tileWidth * tres;
2079+
double thMap = tileHeight * tres;
2080+
2081+
int minTileCol = 0;
2082+
int maxTileCol = matrixWidth - 1;
2083+
int minTileRow = 0;
2084+
int maxTileRow = matrixHeight - 1;
2085+
2086+
if ( tml )
2087+
{
2088+
minTileCol = tml->minTileCol;
2089+
maxTileCol = tml->maxTileCol;
2090+
minTileRow = tml->minTileRow;
2091+
maxTileRow = tml->maxTileRow;
2092+
//QgsDebugMsg( QString( "%1 %2: TileMatrixLimits col %3-%4 row %5-%6" )
2093+
// .arg( tileMatrixSet->identifier, identifier )
2094+
// .arg( minTileCol ).arg( maxTileCol )
2095+
// .arg( minTileRow ).arg( maxTileRow ) );
2096+
}
2097+
2098+
col0 = qBound( minTileCol, ( int ) floor(( viewExtent.xMinimum() - topLeft.x() ) / twMap ), maxTileCol );
2099+
row0 = qBound( minTileRow, ( int ) floor(( topLeft.y() - viewExtent.yMaximum() ) / thMap ), maxTileRow );
2100+
col1 = qBound( minTileCol, ( int ) floor(( viewExtent.xMaximum() - topLeft.x() ) / twMap ), maxTileCol );
2101+
row1 = qBound( minTileRow, ( int ) floor(( topLeft.y() - viewExtent.yMinimum() ) / thMap ), maxTileRow );
2102+
}
2103+
2104+
const QgsWmtsTileMatrix* QgsWmtsTileMatrixSet::findNearestResolution( double vres ) const
2105+
{
2106+
QMap<double, QgsWmtsTileMatrix>::const_iterator prev, it = tileMatrices.constBegin();
2107+
while ( it != tileMatrices.constEnd() && it.key() < vres )
2108+
{
2109+
//QgsDebugMsg( QString( "res:%1 >= %2" ).arg( it.key() ).arg( vres ) );
2110+
prev = it;
2111+
++it;
2112+
}
2113+
2114+
if ( it == tileMatrices.constEnd() ||
2115+
( it != tileMatrices.constBegin() && vres - prev.key() < it.key() - vres ) )
2116+
{
2117+
//QgsDebugMsg( "back to previous res" );
2118+
it = prev;
2119+
}
2120+
2121+
return &it.value();
2122+
}

src/providers/wms/qgswmscapabilities.h

+24-5
Original file line numberDiff line numberDiff line change
@@ -308,17 +308,33 @@ struct QgsWmtsTheme
308308
~QgsWmtsTheme() { delete subTheme; }
309309
};
310310

311+
struct QgsWmtsTileMatrixLimits;
312+
311313
struct QgsWmtsTileMatrix
312314
{
313315
QString identifier;
314316
QString title, abstract;
315317
QStringList keywords;
316318
double scaleDenom;
317-
QgsPoint topLeft;
318-
int tileWidth;
319-
int tileHeight;
320-
int matrixWidth;
321-
int matrixHeight;
319+
QgsPoint topLeft; //!< top-left corner of the tile matrix in map units
320+
int tileWidth; //!< width of a tile in pixels
321+
int tileHeight; //!< height of a tile in pixels
322+
int matrixWidth; //!< number of tiles horizontally
323+
int matrixHeight; //!< number of tiles vertically
324+
double tres; //!< pixel span in map units
325+
326+
//! Returns extent of a tile in map coordinates.
327+
//! (same function as tileBBox() but returns QRectF instead of QgsRectangle)
328+
QRectF tileRect( int col, int row ) const;
329+
330+
//! Returns extent of a tile in map coordinates
331+
//! (same function as tileRect() but returns QgsRectangle instead of QRectF)
332+
QgsRectangle tileBBox( int col, int row ) const;
333+
334+
//! Returns range of tiles that intersects with the view extent
335+
//! (tml may be null)
336+
void viewExtentIntersection( const QgsRectangle& viewExtent, const QgsWmtsTileMatrixLimits* tml, int& col0, int& row0, int& col1, int& row1 ) const;
337+
322338
};
323339

324340
struct QgsWmtsTileMatrixSet
@@ -329,6 +345,9 @@ struct QgsWmtsTileMatrixSet
329345
QString crs;
330346
QString wkScaleSet;
331347
QMap<double, QgsWmtsTileMatrix> tileMatrices;
348+
349+
//! Returns closest tile resolution to the requested one. (resolution = width [map units] / with [pixels])
350+
const QgsWmtsTileMatrix* findNearestResolution( double vres ) const;
332351
};
333352

334353
enum QgsTileMode { WMTS, WMSC };

src/providers/wms/qgswmsprovider.cpp

+25-62
Original file line numberDiff line numberDiff line change
@@ -566,9 +566,9 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
566566
mTileReqNo++;
567567

568568
double vres = viewExtent.width() / pixelWidth;
569-
double tres = vres;
570569

571570
const QgsWmtsTileMatrix *tm = nullptr;
571+
QScopedPointer<QgsWmtsTileMatrix> tempTm;
572572
enum QgsTileMode tileMode;
573573

574574
if ( mSettings.mTiled )
@@ -577,38 +577,22 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
577577
Q_ASSERT( mTileMatrixSet );
578578
Q_ASSERT( !mTileMatrixSet->tileMatrices.isEmpty() );
579579

580-
QMap<double, QgsWmtsTileMatrix> &m = mTileMatrixSet->tileMatrices;
581-
582580
// find nearest resolution
583-
QMap<double, QgsWmtsTileMatrix>::const_iterator prev, it = m.constBegin();
584-
while ( it != m.constEnd() && it.key() < vres )
585-
{
586-
QgsDebugMsg( QString( "res:%1 >= %2" ).arg( it.key() ).arg( vres ) );
587-
prev = it;
588-
++it;
589-
}
590-
591-
if ( it == m.constEnd() ||
592-
( it != m.constBegin() && vres - prev.key() < it.key() - vres ) )
593-
{
594-
QgsDebugMsg( "back to previous res" );
595-
it = prev;
596-
}
597-
598-
tres = it.key();
599-
tm = &it.value();
581+
tm = mTileMatrixSet->findNearestResolution( vres );
582+
Q_ASSERT( tm );
600583

601584
tileMode = mTileLayer->tileMode;
602585
}
603586
else if ( mSettings.mMaxWidth != 0 && mSettings.mMaxHeight != 0 )
604587
{
605-
static QgsWmtsTileMatrix tempTm;
606-
tempTm.topLeft = QgsPoint( mLayerExtent.xMinimum(), mLayerExtent.yMaximum() );
607-
tempTm.tileWidth = mSettings.mMaxWidth;
608-
tempTm.tileHeight = mSettings.mMaxHeight;
609-
tempTm.matrixWidth = ceil( mLayerExtent.width() / mSettings.mMaxWidth / vres );
610-
tempTm.matrixHeight = ceil( mLayerExtent.height() / mSettings.mMaxHeight / vres );
611-
tm = &tempTm;
588+
tempTm.reset( new QgsWmtsTileMatrix );
589+
tempTm->topLeft = QgsPoint( mLayerExtent.xMinimum(), mLayerExtent.yMaximum() );
590+
tempTm->tileWidth = mSettings.mMaxWidth;
591+
tempTm->tileHeight = mSettings.mMaxHeight;
592+
tempTm->matrixWidth = ceil( mLayerExtent.width() / mSettings.mMaxWidth / vres );
593+
tempTm->matrixHeight = ceil( mLayerExtent.height() / mSettings.mMaxHeight / vres );
594+
tempTm->tres = vres;
595+
tm = tempTm.data();
612596

613597
tileMode = WMSC;
614598
}
@@ -634,43 +618,24 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
634618
);
635619

636620
QgsDebugMsg( QString( "tile matrix %1,%2 res:%3 tilesize:%4x%5 matrixsize:%6x%7 id:%8" )
637-
.arg( tm->topLeft.x() ).arg( tm->topLeft.y() ).arg( tres )
621+
.arg( tm->topLeft.x() ).arg( tm->topLeft.y() ).arg( tm->tres )
638622
.arg( tm->tileWidth ).arg( tm->tileHeight )
639623
.arg( tm->matrixWidth ).arg( tm->matrixHeight )
640624
.arg( tm->identifier )
641625
);
642626

643-
// calculate tile coordinates
644-
double twMap = tm->tileWidth * tres;
645-
double thMap = tm->tileHeight * tres;
646-
QgsDebugMsg( QString( "tile map size: %1,%2" ).arg( qgsDoubleToString( twMap ), qgsDoubleToString( thMap ) ) );
647-
648-
int minTileCol = 0;
649-
int maxTileCol = tm->matrixWidth - 1;
650-
int minTileRow = 0;
651-
int maxTileRow = tm->matrixHeight - 1;
652-
627+
const QgsWmtsTileMatrixLimits *tml = nullptr;
653628

654629
if ( mTileLayer &&
655630
mTileLayer->setLinks.contains( mTileMatrixSet->identifier ) &&
656631
mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits.contains( tm->identifier ) )
657632
{
658-
const QgsWmtsTileMatrixLimits &tml = mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits[ tm->identifier ];
659-
minTileCol = tml.minTileCol;
660-
maxTileCol = tml.maxTileCol;
661-
minTileRow = tml.minTileRow;
662-
maxTileRow = tml.maxTileRow;
663-
QgsDebugMsg( QString( "%1 %2: TileMatrixLimits col %3-%4 row %5-%6" )
664-
.arg( mTileMatrixSet->identifier,
665-
tm->identifier )
666-
.arg( minTileCol ).arg( maxTileCol )
667-
.arg( minTileRow ).arg( maxTileRow ) );
633+
tml = &mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits[ tm->identifier ];
668634
}
669635

670-
int col0 = qBound( minTileCol, ( int ) floor(( viewExtent.xMinimum() - tm->topLeft.x() ) / twMap ), maxTileCol );
671-
int row0 = qBound( minTileRow, ( int ) floor(( tm->topLeft.y() - viewExtent.yMaximum() ) / thMap ), maxTileRow );
672-
int col1 = qBound( minTileCol, ( int ) floor(( viewExtent.xMaximum() - tm->topLeft.x() ) / twMap ), maxTileCol );
673-
int row1 = qBound( minTileRow, ( int ) floor(( tm->topLeft.y() - viewExtent.yMinimum() ) / thMap ), maxTileRow );
636+
// calculate tile coordinates
637+
int col0, col1, row0, row1;
638+
tm->viewExtentIntersection( viewExtent, tml, col0, row0, col1, row1 );
674639

675640
#if QGISDEBUG
676641
int n = ( col1 - col0 + 1 ) * ( row1 - row0 + 1 );
@@ -728,17 +693,17 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
728693
{
729694
for ( int col = col0; col <= col1; col++ )
730695
{
696+
QgsRectangle bbox( tm->tileBBox( col, row ) );
731697
QString turl;
732698
turl += url.toString();
733699
turl += QString( changeXY ? "&BBOX=%2,%1,%4,%3" : "&BBOX=%1,%2,%3,%4" )
734-
.arg( qgsDoubleToString( tm->topLeft.x() + col * twMap /* + twMap * 0.001 */ ),
735-
qgsDoubleToString( tm->topLeft.y() - ( row + 1 ) * thMap /* - thMap * 0.001 */ ),
736-
qgsDoubleToString( tm->topLeft.x() + ( col + 1 ) * twMap /* - twMap * 0.001 */ ),
737-
qgsDoubleToString( tm->topLeft.y() - row * thMap /* + thMap * 0.001 */ ) );
700+
.arg( qgsDoubleToString( bbox.xMinimum() ),
701+
qgsDoubleToString( bbox.yMinimum() ),
702+
qgsDoubleToString( bbox.xMaximum() ),
703+
qgsDoubleToString( bbox.yMaximum() ) );
738704

739705
QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
740-
QRectF rect( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
741-
requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, rect, i );
706+
requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, tm->tileRect( col, row ), i );
742707
}
743708
}
744709
}
@@ -779,8 +744,7 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
779744
turl += QString( "&TILEROW=%1&TILECOL=%2" ).arg( row ).arg( col );
780745

781746
QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
782-
QRectF rect( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
783-
requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, rect, i );
747+
requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, tm->tileRect( col, row ), i );
784748
}
785749
}
786750
}
@@ -810,8 +774,7 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
810774

811775
if ( feedback && !feedback->preview_only )
812776
QgsDebugMsg( QString( "tileRequest %1 %2/%3 (%4,%5): %6" ).arg( mTileReqNo ).arg( i++ ).arg( n ).arg( row ).arg( col ).arg( turl ) );
813-
QRectF rect( tm->topLeft.x() + col * twMap, tm->topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
814-
requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, rect, i );
777+
requests << QgsWmsTiledImageDownloadHandler::TileRequest( turl, tm->tileRect( col, row ), i );
815778
}
816779
}
817780
}

0 commit comments

Comments
 (0)