Skip to content

Commit

Permalink
Housekeeping in WMS provider - move some calculations to utility func…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
wonder-sk committed Aug 31, 2016
1 parent e2bcba5 commit 0c51c3f
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 70 deletions.
77 changes: 74 additions & 3 deletions src/providers/wms/qgswmscapabilities.cpp
Expand Up @@ -1258,6 +1258,7 @@ void QgsWmsCapabilities::parseTileSetProfile( QDomElement const &e )
m.matrixWidth = ceil( l.boundingBoxes.at( 0 ).box.width() / m.tileWidth / r );
m.matrixHeight = ceil( l.boundingBoxes.at( 0 ).box.height() / m.tileHeight / r );
m.topLeft = QgsPoint( l.boundingBoxes.at( 0 ).box.xMinimum(), l.boundingBoxes.at( 0 ).box.yMinimum() + m.matrixHeight * m.tileHeight * r );
m.tres = r;
ms.tileMatrices.insert( r, m );
i++;
}
Expand Down Expand Up @@ -1340,17 +1341,19 @@ void QgsWmsCapabilities::parseWMTSContents( QDomElement const &e )
m.matrixWidth = e1.firstChildElement( "MatrixWidth" ).text().toInt();
m.matrixHeight = e1.firstChildElement( "MatrixHeight" ).text().toInt();

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

QgsDebugMsg( QString( " %1: scale=%2 res=%3 tile=%4x%5 matrix=%6x%7 topLeft=%8" )
.arg( m.identifier )
.arg( m.scaleDenom ).arg( res )
.arg( m.scaleDenom ).arg( m.tres )
.arg( m.tileWidth ).arg( m.tileHeight )
.arg( m.matrixWidth ).arg( m.matrixHeight )
.arg( m.topLeft.toString() )
);

s.tileMatrices.insert( res, m );
s.tileMatrices.insert( m.tres, m );
}

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

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

emit downloadFinished();
}

QRectF QgsWmtsTileMatrix::tileRect( int col, int row ) const
{
double twMap = tileWidth * tres;
double thMap = tileHeight * tres;
return QRectF( topLeft.x() + col * twMap, topLeft.y() - ( row + 1 ) * thMap, twMap, thMap );
}

QgsRectangle QgsWmtsTileMatrix::tileBBox( int col, int row ) const
{
double twMap = tileWidth * tres;
double thMap = tileHeight * tres;
return QgsRectangle(
topLeft.x() + col * twMap,
topLeft.y() - ( row + 1 ) * thMap,
topLeft.x() + ( col + 1 ) * twMap,
topLeft.y() - row * thMap );
}

void QgsWmtsTileMatrix::viewExtentIntersection( const QgsRectangle &viewExtent, const QgsWmtsTileMatrixLimits* tml, int &col0, int &row0, int &col1, int &row1 ) const
{
double twMap = tileWidth * tres;
double thMap = tileHeight * tres;

int minTileCol = 0;
int maxTileCol = matrixWidth - 1;
int minTileRow = 0;
int maxTileRow = matrixHeight - 1;

if ( tml )
{
minTileCol = tml->minTileCol;
maxTileCol = tml->maxTileCol;
minTileRow = tml->minTileRow;
maxTileRow = tml->maxTileRow;
//QgsDebugMsg( QString( "%1 %2: TileMatrixLimits col %3-%4 row %5-%6" )
// .arg( tileMatrixSet->identifier, identifier )
// .arg( minTileCol ).arg( maxTileCol )
// .arg( minTileRow ).arg( maxTileRow ) );
}

col0 = qBound( minTileCol, ( int ) floor(( viewExtent.xMinimum() - topLeft.x() ) / twMap ), maxTileCol );
row0 = qBound( minTileRow, ( int ) floor(( topLeft.y() - viewExtent.yMaximum() ) / thMap ), maxTileRow );
col1 = qBound( minTileCol, ( int ) floor(( viewExtent.xMaximum() - topLeft.x() ) / twMap ), maxTileCol );
row1 = qBound( minTileRow, ( int ) floor(( topLeft.y() - viewExtent.yMinimum() ) / thMap ), maxTileRow );
}

const QgsWmtsTileMatrix* QgsWmtsTileMatrixSet::findNearestResolution( double vres ) const
{
QMap<double, QgsWmtsTileMatrix>::const_iterator prev, it = tileMatrices.constBegin();
while ( it != tileMatrices.constEnd() && it.key() < vres )
{
//QgsDebugMsg( QString( "res:%1 >= %2" ).arg( it.key() ).arg( vres ) );
prev = it;
++it;
}

if ( it == tileMatrices.constEnd() ||
( it != tileMatrices.constBegin() && vres - prev.key() < it.key() - vres ) )
{
//QgsDebugMsg( "back to previous res" );
it = prev;
}

return &it.value();
}
29 changes: 24 additions & 5 deletions src/providers/wms/qgswmscapabilities.h
Expand Up @@ -308,17 +308,33 @@ struct QgsWmtsTheme
~QgsWmtsTheme() { delete subTheme; }
};

struct QgsWmtsTileMatrixLimits;

struct QgsWmtsTileMatrix
{
QString identifier;
QString title, abstract;
QStringList keywords;
double scaleDenom;
QgsPoint topLeft;
int tileWidth;
int tileHeight;
int matrixWidth;
int matrixHeight;
QgsPoint topLeft; //!< top-left corner of the tile matrix in map units
int tileWidth; //!< width of a tile in pixels
int tileHeight; //!< height of a tile in pixels
int matrixWidth; //!< number of tiles horizontally
int matrixHeight; //!< number of tiles vertically
double tres; //!< pixel span in map units

//! Returns extent of a tile in map coordinates.
//! (same function as tileBBox() but returns QRectF instead of QgsRectangle)
QRectF tileRect( int col, int row ) const;

//! Returns extent of a tile in map coordinates
//! (same function as tileRect() but returns QgsRectangle instead of QRectF)
QgsRectangle tileBBox( int col, int row ) const;

//! Returns range of tiles that intersects with the view extent
//! (tml may be null)
void viewExtentIntersection( const QgsRectangle& viewExtent, const QgsWmtsTileMatrixLimits* tml, int& col0, int& row0, int& col1, int& row1 ) const;

};

struct QgsWmtsTileMatrixSet
Expand All @@ -329,6 +345,9 @@ struct QgsWmtsTileMatrixSet
QString crs;
QString wkScaleSet;
QMap<double, QgsWmtsTileMatrix> tileMatrices;

//! Returns closest tile resolution to the requested one. (resolution = width [map units] / with [pixels])
const QgsWmtsTileMatrix* findNearestResolution( double vres ) const;
};

enum QgsTileMode { WMTS, WMSC };
Expand Down
87 changes: 25 additions & 62 deletions src/providers/wms/qgswmsprovider.cpp
Expand Up @@ -566,9 +566,9 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
mTileReqNo++;

double vres = viewExtent.width() / pixelWidth;
double tres = vres;

const QgsWmtsTileMatrix *tm = nullptr;
QScopedPointer<QgsWmtsTileMatrix> tempTm;
enum QgsTileMode tileMode;

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

QMap<double, QgsWmtsTileMatrix> &m = mTileMatrixSet->tileMatrices;

// find nearest resolution
QMap<double, QgsWmtsTileMatrix>::const_iterator prev, it = m.constBegin();
while ( it != m.constEnd() && it.key() < vres )
{
QgsDebugMsg( QString( "res:%1 >= %2" ).arg( it.key() ).arg( vres ) );
prev = it;
++it;
}

if ( it == m.constEnd() ||
( it != m.constBegin() && vres - prev.key() < it.key() - vres ) )
{
QgsDebugMsg( "back to previous res" );
it = prev;
}

tres = it.key();
tm = &it.value();
tm = mTileMatrixSet->findNearestResolution( vres );
Q_ASSERT( tm );

tileMode = mTileLayer->tileMode;
}
else if ( mSettings.mMaxWidth != 0 && mSettings.mMaxHeight != 0 )
{
static QgsWmtsTileMatrix tempTm;
tempTm.topLeft = QgsPoint( mLayerExtent.xMinimum(), mLayerExtent.yMaximum() );
tempTm.tileWidth = mSettings.mMaxWidth;
tempTm.tileHeight = mSettings.mMaxHeight;
tempTm.matrixWidth = ceil( mLayerExtent.width() / mSettings.mMaxWidth / vres );
tempTm.matrixHeight = ceil( mLayerExtent.height() / mSettings.mMaxHeight / vres );
tm = &tempTm;
tempTm.reset( new QgsWmtsTileMatrix );
tempTm->topLeft = QgsPoint( mLayerExtent.xMinimum(), mLayerExtent.yMaximum() );
tempTm->tileWidth = mSettings.mMaxWidth;
tempTm->tileHeight = mSettings.mMaxHeight;
tempTm->matrixWidth = ceil( mLayerExtent.width() / mSettings.mMaxWidth / vres );
tempTm->matrixHeight = ceil( mLayerExtent.height() / mSettings.mMaxHeight / vres );
tempTm->tres = vres;
tm = tempTm.data();

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

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

// calculate tile coordinates
double twMap = tm->tileWidth * tres;
double thMap = tm->tileHeight * tres;
QgsDebugMsg( QString( "tile map size: %1,%2" ).arg( qgsDoubleToString( twMap ), qgsDoubleToString( thMap ) ) );

int minTileCol = 0;
int maxTileCol = tm->matrixWidth - 1;
int minTileRow = 0;
int maxTileRow = tm->matrixHeight - 1;

const QgsWmtsTileMatrixLimits *tml = nullptr;

if ( mTileLayer &&
mTileLayer->setLinks.contains( mTileMatrixSet->identifier ) &&
mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits.contains( tm->identifier ) )
{
const QgsWmtsTileMatrixLimits &tml = mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits[ tm->identifier ];
minTileCol = tml.minTileCol;
maxTileCol = tml.maxTileCol;
minTileRow = tml.minTileRow;
maxTileRow = tml.maxTileRow;
QgsDebugMsg( QString( "%1 %2: TileMatrixLimits col %3-%4 row %5-%6" )
.arg( mTileMatrixSet->identifier,
tm->identifier )
.arg( minTileCol ).arg( maxTileCol )
.arg( minTileRow ).arg( maxTileRow ) );
tml = &mTileLayer->setLinks[ mTileMatrixSet->identifier ].limits[ tm->identifier ];
}

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

#if QGISDEBUG
int n = ( col1 - col0 + 1 ) * ( row1 - row0 + 1 );
Expand Down Expand Up @@ -728,17 +693,17 @@ QImage *QgsWmsProvider::draw( QgsRectangle const & viewExtent, int pixelWidth, i
{
for ( int col = col0; col <= col1; col++ )
{
QgsRectangle bbox( tm->tileBBox( col, row ) );
QString turl;
turl += url.toString();
turl += QString( changeXY ? "&BBOX=%2,%1,%4,%3" : "&BBOX=%1,%2,%3,%4" )
.arg( qgsDoubleToString( tm->topLeft.x() + col * twMap /* + twMap * 0.001 */ ),
qgsDoubleToString( tm->topLeft.y() - ( row + 1 ) * thMap /* - thMap * 0.001 */ ),
qgsDoubleToString( tm->topLeft.x() + ( col + 1 ) * twMap /* - twMap * 0.001 */ ),
qgsDoubleToString( tm->topLeft.y() - row * thMap /* + thMap * 0.001 */ ) );
.arg( qgsDoubleToString( bbox.xMinimum() ),
qgsDoubleToString( bbox.yMinimum() ),
qgsDoubleToString( bbox.xMaximum() ),
qgsDoubleToString( bbox.yMaximum() ) );

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

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

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

0 comments on commit 0c51c3f

Please sign in to comment.