Skip to content

Commit ba24653

Browse files
committedAug 24, 2018
[Server][Feature][needs-docs] Enhancing TileMatrixSetLimits
1 parent 355a387 commit ba24653

File tree

4 files changed

+499
-887
lines changed

4 files changed

+499
-887
lines changed
 

‎src/server/services/wmts/qgswmtsgetcapabilities.cpp

Lines changed: 10 additions & 198 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ namespace QgsWmts
3232
{
3333
namespace
3434
{
35-
QList< layerDef > getWmtsLayerList( QgsServerInterface *serverIface, const QgsProject *project );
36-
3735
void appendLayerElements( QDomDocument &doc, QDomElement &contentsElement,
3836
QList< layerDef > wmtsLayers, QList< tileMatrixSetDef > tmsList,
3937
const QgsProject *project );
@@ -322,182 +320,6 @@ namespace QgsWmts
322320
}
323321
namespace
324322
{
325-
QList< layerDef > getWmtsLayerList( QgsServerInterface *serverIface, const QgsProject *project )
326-
{
327-
QList< layerDef > wmtsLayers;
328-
#ifdef HAVE_SERVER_PYTHON_PLUGINS
329-
QgsAccessControl *accessControl = serverIface->accessControls();
330-
#endif
331-
QgsCoordinateReferenceSystem wgs84 = QgsCoordinateReferenceSystem::fromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
332-
333-
QStringList nonIdentifiableLayers = project->nonIdentifiableLayers();
334-
335-
// WMTS Project configuration
336-
bool wmtsProject = project->readBoolEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Project" ) );
337-
338-
// Root Layer name
339-
QString rootLayerName = QgsServerProjectUtils::wmsRootName( *project );
340-
if ( rootLayerName.isEmpty() && !project->title().isEmpty() )
341-
{
342-
rootLayerName = project->title();
343-
}
344-
345-
if ( wmtsProject && !rootLayerName.isEmpty() )
346-
{
347-
layerDef pLayer;
348-
pLayer.id = rootLayerName;
349-
350-
if ( !project->title().isEmpty() )
351-
{
352-
pLayer.title = project->title();
353-
pLayer.abstract = project->title();
354-
}
355-
356-
//transform the project native CRS into WGS84
357-
QgsRectangle projRect = QgsServerProjectUtils::wmsExtent( *project );
358-
QgsCoordinateReferenceSystem projCrs = project->crs();
359-
QgsCoordinateTransform exGeoTransform( projCrs, wgs84, project );
360-
try
361-
{
362-
pLayer.wgs84BoundingRect = exGeoTransform.transformBoundingBox( projRect );
363-
}
364-
catch ( const QgsCsException & )
365-
{
366-
pLayer.wgs84BoundingRect = QgsRectangle( -180, -90, 180, 90 );
367-
}
368-
369-
// Formats
370-
bool wmtsPngProject = project->readBoolEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Project" ) );
371-
if ( wmtsPngProject )
372-
pLayer.formats << QStringLiteral( "image/png" );
373-
bool wmtsJpegProject = project->readBoolEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Project" ) );
374-
if ( wmtsJpegProject )
375-
pLayer.formats << QStringLiteral( "image/jpeg" );
376-
377-
// Project is not queryable in WMS
378-
//pLayer.queryable = ( nonIdentifiableLayers.count() != project->count() );
379-
pLayer.queryable = false;
380-
381-
wmtsLayers.append( pLayer );
382-
}
383-
384-
QStringList wmtsGroupNameList = project->readListEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Group" ) );
385-
if ( !wmtsGroupNameList.isEmpty() )
386-
{
387-
QgsLayerTreeGroup *treeRoot = project->layerTreeRoot();
388-
389-
QStringList wmtsPngGroupNameList = project->readListEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Group" ) );
390-
QStringList wmtsJpegGroupNameList = project->readListEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Group" ) );
391-
392-
for ( const QString gName : wmtsGroupNameList )
393-
{
394-
QgsLayerTreeGroup *treeGroup = treeRoot->findGroup( gName );
395-
if ( !treeGroup )
396-
{
397-
continue;
398-
}
399-
400-
layerDef pLayer;
401-
pLayer.id = treeGroup->customProperty( QStringLiteral( "wmsShortName" ) ).toString();
402-
if ( pLayer.id.isEmpty() )
403-
pLayer.id = gName;
404-
405-
pLayer.title = treeGroup->customProperty( QStringLiteral( "wmsTitle" ) ).toString();
406-
if ( pLayer.title.isEmpty() )
407-
pLayer.title = gName;
408-
409-
pLayer.abstract = treeGroup->customProperty( QStringLiteral( "wmsAbstract" ) ).toString();
410-
411-
QgsRectangle wgs84BoundingRect;
412-
bool queryable = false;
413-
for ( QgsLayerTreeLayer *layer : treeGroup->findLayers() )
414-
{
415-
QgsMapLayer *l = layer->layer();
416-
if ( !l )
417-
{
418-
continue;
419-
}
420-
//transform the layer native CRS into WGS84
421-
QgsCoordinateReferenceSystem layerCrs = l->crs();
422-
QgsCoordinateTransform exGeoTransform( layerCrs, wgs84, project );
423-
try
424-
{
425-
wgs84BoundingRect.combineExtentWith( exGeoTransform.transformBoundingBox( l->extent() ) );
426-
}
427-
catch ( const QgsCsException & )
428-
{
429-
wgs84BoundingRect.combineExtentWith( QgsRectangle( -180, -90, 180, 90 ) );
430-
}
431-
if ( !queryable && !nonIdentifiableLayers.contains( l->id() ) )
432-
{
433-
queryable = true;
434-
}
435-
}
436-
pLayer.wgs84BoundingRect = wgs84BoundingRect;
437-
pLayer.queryable = queryable;
438-
439-
// Formats
440-
if ( wmtsPngGroupNameList.contains( gName ) )
441-
pLayer.formats << QStringLiteral( "image/png" );
442-
if ( wmtsJpegGroupNameList.contains( gName ) )
443-
pLayer.formats << QStringLiteral( "image/jpeg" );
444-
445-
wmtsLayers.append( pLayer );
446-
}
447-
}
448-
449-
QStringList wmtsLayerIdList = project->readListEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Layer" ) );
450-
QStringList wmtsPngLayerIdList = project->readListEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Layer" ) );
451-
QStringList wmtsJpegLayerIdList = project->readListEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Layer" ) );
452-
453-
for ( const QString lId : wmtsLayerIdList )
454-
{
455-
QgsMapLayer *l = project->mapLayer( lId );
456-
if ( !l )
457-
{
458-
continue;
459-
}
460-
#ifdef HAVE_SERVER_PYTHON_PLUGINS
461-
if ( !accessControl->layerReadPermission( l ) )
462-
{
463-
continue;
464-
}
465-
#endif
466-
467-
layerDef pLayer;
468-
pLayer.id = l->name();
469-
if ( !l->shortName().isEmpty() )
470-
pLayer.id = l->shortName();
471-
pLayer.id = pLayer.id.replace( ' ', '_' );
472-
473-
pLayer.title = l->title();
474-
pLayer.abstract = l->abstract();
475-
476-
//transform the layer native CRS into WGS84
477-
QgsCoordinateReferenceSystem layerCrs = l->crs();
478-
QgsCoordinateTransform exGeoTransform( layerCrs, wgs84, project );
479-
try
480-
{
481-
pLayer.wgs84BoundingRect = exGeoTransform.transformBoundingBox( l->extent() );
482-
}
483-
catch ( const QgsCsException & )
484-
{
485-
pLayer.wgs84BoundingRect = QgsRectangle( -180, -90, 180, 90 );
486-
}
487-
488-
// Formats
489-
if ( wmtsPngLayerIdList.contains( lId ) )
490-
pLayer.formats << QStringLiteral( "image/png" );
491-
if ( wmtsJpegLayerIdList.contains( lId ) )
492-
pLayer.formats << QStringLiteral( "image/jpeg" );
493-
494-
pLayer.queryable = ( !nonIdentifiableLayers.contains( l->id() ) );
495-
496-
wmtsLayers.append( pLayer );
497-
}
498-
return wmtsLayers;
499-
}
500-
501323
void appendLayerElements( QDomDocument &doc, QDomElement &contentsElement,
502324
QList< layerDef > wmtsLayers, QList< tileMatrixSetDef > tmsList,
503325
const QgsProject *project )
@@ -616,19 +438,10 @@ namespace QgsWmts
616438

617439
for ( const tileMatrixSetDef tms : tmsList )
618440
{
619-
if ( tms.ref != QLatin1String( "EPSG:4326" ) )
441+
tileMatrixSetLinkDef tmsl = getLayerTileMatrixSetLink( wmtsLayer, tms, project );
442+
if ( tmsl.ref.isEmpty() || tmsl.ref != tms.ref )
620443
{
621-
QgsRectangle rect;
622-
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( tms.ref );
623-
QgsCoordinateTransform exGeoTransform( wgs84, crs, project );
624-
try
625-
{
626-
rect = exGeoTransform.transformBoundingBox( wmtsLayer.wgs84BoundingRect );
627-
}
628-
catch ( const QgsCsException & )
629-
{
630-
continue;
631-
}
444+
continue;
632445
}
633446

634447
//wmts:TileMatrixSetLink
@@ -641,8 +454,7 @@ namespace QgsWmts
641454

642455
//wmts:TileMatrixSetLimits
643456
QDomElement tmsLimitsElement = doc.createElement( QStringLiteral( "TileMatrixSetLimits" )/*wmts:TileMatrixSetLimits*/ );
644-
int tmIdx = 0;
645-
for ( const tileMatrixDef tm : tms.tileMatrixList )
457+
for ( int tmIdx : tmsl.tileMatrixLimits.keys() )
646458
{
647459
QDomElement tmLimitsElement = doc.createElement( QStringLiteral( "TileMatrixLimits" )/*wmts:TileMatrixLimits*/ );
648460

@@ -651,29 +463,29 @@ namespace QgsWmts
651463
tmIdentifierElem.appendChild( tmIdentifierText );
652464
tmLimitsElement.appendChild( tmIdentifierElem );
653465

466+
tileMatrixLimitDef tml = tmsl.tileMatrixLimits[tmIdx];
467+
654468
QDomElement minTileColElem = doc.createElement( QStringLiteral( "MinTileCol" ) );
655-
QDomText minTileColText = doc.createTextNode( QString::number( 0 ) );
469+
QDomText minTileColText = doc.createTextNode( QString::number( tml.minCol ) );
656470
minTileColElem.appendChild( minTileColText );
657471
tmLimitsElement.appendChild( minTileColElem );
658472

659473
QDomElement maxTileColElem = doc.createElement( QStringLiteral( "MaxTileCol" ) );
660-
QDomText maxTileColText = doc.createTextNode( QString::number( tm.col ) );
474+
QDomText maxTileColText = doc.createTextNode( QString::number( tml.maxCol ) );
661475
maxTileColElem.appendChild( maxTileColText );
662476
tmLimitsElement.appendChild( maxTileColElem );
663477

664478
QDomElement minTileRowElem = doc.createElement( QStringLiteral( "MinTileRow" ) );
665-
QDomText minTileRowText = doc.createTextNode( QString::number( 0 ) );
479+
QDomText minTileRowText = doc.createTextNode( QString::number( tml.minRow ) );
666480
minTileRowElem.appendChild( minTileRowText );
667481
tmLimitsElement.appendChild( minTileRowElem );
668482

669483
QDomElement maxTileRowElem = doc.createElement( QStringLiteral( "MaxTileRow" ) );
670-
QDomText maxTileRowText = doc.createTextNode( QString::number( tm.row ) );
484+
QDomText maxTileRowText = doc.createTextNode( QString::number( tml.maxRow ) );
671485
maxTileRowElem.appendChild( maxTileRowText );
672486
tmLimitsElement.appendChild( maxTileRowElem );
673487

674488
tmsLimitsElement.appendChild( tmLimitsElement );
675-
676-
++tmIdx;
677489
}
678490
tmslElement.appendChild( tmsLimitsElement );
679491

‎src/server/services/wmts/qgswmtsutils.cpp

Lines changed: 284 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -105,13 +105,44 @@ namespace QgsWmts
105105
double scaleDenominator = 0.0;
106106
int colRes = ( tmi.extent.xMaximum() - tmi.extent.xMinimum() ) / tileWidth;
107107
int rowRes = ( tmi.extent.yMaximum() - tmi.extent.yMinimum() ) / tileHeight;
108-
if ( colRes < rowRes )
109-
scaleDenominator = colRes * INCHES_PER_UNIT[ tmi.unit ] * METERS_PER_INCH / 0.00028;
108+
if ( colRes > rowRes )
109+
scaleDenominator = std::ceil( colRes * INCHES_PER_UNIT[ tmi.unit ] * METERS_PER_INCH / 0.00028 );
110110
else
111-
scaleDenominator = rowRes * INCHES_PER_UNIT[ tmi.unit ] * METERS_PER_INCH / 0.00028;
111+
scaleDenominator = std::ceil( rowRes * INCHES_PER_UNIT[ tmi.unit ] * METERS_PER_INCH / 0.00028 );
112+
113+
// Update extent to get a square one
114+
QgsRectangle extent = tmi.extent;
115+
double res = 0.00028 * scaleDenominator / METERS_PER_INCH / INCHES_PER_UNIT[ tmi.unit ];
116+
int col = std::ceil( ( extent.xMaximum() - extent.xMinimum() ) / ( tileWidth * res ) );
117+
int row = std::ceil( ( extent.yMaximum() - extent.yMinimum() ) / ( tileHeight * res ) );
118+
if ( col > 1 || row > 1 )
119+
{
120+
// Update scale
121+
if ( col > row )
122+
{
123+
res = col * res;
124+
scaleDenominator = col * scaleDenominator;
125+
}
126+
else
127+
{
128+
res = row * res;
129+
scaleDenominator = row * scaleDenominator;
130+
}
131+
// set col and row to 1 for the square
132+
col = 1;
133+
row = 1;
134+
}
135+
// Calculate extent
136+
double left = ( extent.xMinimum() + ( extent.xMaximum() - extent.xMinimum() ) / 2.0 ) - ( col / 2.0 ) * ( tileWidth * res );
137+
double bottom = ( extent.yMinimum() + ( extent.yMaximum() - extent.yMinimum() ) / 2.0 ) - ( row / 2.0 ) * ( tileHeight * res );
138+
double right = ( extent.xMinimum() + ( extent.xMaximum() - extent.xMinimum() ) / 2.0 ) + ( col / 2.0 ) * ( tileWidth * res );
139+
double top = ( extent.yMinimum() + ( extent.yMaximum() - extent.yMinimum() ) / 2.0 ) + ( row / 2.0 ) * ( tileHeight * res );
140+
tmi.extent = QgsRectangle( left, bottom, right, top );
141+
112142
tmi.scaleDenominator = scaleDenominator;
113143

114144
tileMatrixInfoMap[crsStr] = tmi;
145+
115146
return tmi;
116147
}
117148

@@ -126,8 +157,8 @@ namespace QgsWmts
126157
{
127158
double scale = scaleDenominator;
128159
double res = 0.00028 * scale / METERS_PER_INCH / INCHES_PER_UNIT[ unit ];
129-
int col = std::round( ( extent.xMaximum() - extent.xMinimum() ) / ( tileWidth * res ) );
130-
int row = std::round( ( extent.yMaximum() - extent.yMinimum() ) / ( tileHeight * res ) );
160+
int col = std::ceil( ( extent.xMaximum() - extent.xMinimum() ) / ( tileWidth * res ) );
161+
int row = std::ceil( ( extent.yMaximum() - extent.yMinimum() ) / ( tileHeight * res ) );
131162
double left = ( extent.xMinimum() + ( extent.xMaximum() - extent.xMinimum() ) / 2.0 ) - ( col / 2.0 ) * ( tileWidth * res );
132163
double top = ( extent.yMinimum() + ( extent.yMaximum() - extent.yMinimum() ) / 2.0 ) + ( row / 2.0 ) * ( tileHeight * res );
133164

@@ -211,6 +242,254 @@ namespace QgsWmts
211242
return tmsList;
212243
}
213244

245+
QList< layerDef > getWmtsLayerList( QgsServerInterface *serverIface, const QgsProject *project )
246+
{
247+
QList< layerDef > wmtsLayers;
248+
#ifdef HAVE_SERVER_PYTHON_PLUGINS
249+
QgsAccessControl *accessControl = serverIface->accessControls();
250+
#endif
251+
QgsCoordinateReferenceSystem wgs84 = QgsCoordinateReferenceSystem::fromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
252+
253+
QStringList nonIdentifiableLayers = project->nonIdentifiableLayers();
254+
255+
// WMTS Project configuration
256+
bool wmtsProject = project->readBoolEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Project" ) );
257+
258+
// Root Layer name
259+
QString rootLayerName = QgsServerProjectUtils::wmsRootName( *project );
260+
if ( rootLayerName.isEmpty() && !project->title().isEmpty() )
261+
{
262+
rootLayerName = project->title();
263+
}
264+
265+
if ( wmtsProject && !rootLayerName.isEmpty() )
266+
{
267+
layerDef pLayer;
268+
pLayer.id = rootLayerName;
269+
270+
if ( !project->title().isEmpty() )
271+
{
272+
pLayer.title = project->title();
273+
pLayer.abstract = project->title();
274+
}
275+
276+
//transform the project native CRS into WGS84
277+
QgsRectangle projRect = QgsServerProjectUtils::wmsExtent( *project );
278+
QgsCoordinateReferenceSystem projCrs = project->crs();
279+
QgsCoordinateTransform exGeoTransform( projCrs, wgs84, project );
280+
try
281+
{
282+
pLayer.wgs84BoundingRect = exGeoTransform.transformBoundingBox( projRect );
283+
}
284+
catch ( const QgsCsException & )
285+
{
286+
pLayer.wgs84BoundingRect = QgsRectangle( -180, -90, 180, 90 );
287+
}
288+
289+
// Formats
290+
bool wmtsPngProject = project->readBoolEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Project" ) );
291+
if ( wmtsPngProject )
292+
pLayer.formats << QStringLiteral( "image/png" );
293+
bool wmtsJpegProject = project->readBoolEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Project" ) );
294+
if ( wmtsJpegProject )
295+
pLayer.formats << QStringLiteral( "image/jpeg" );
296+
297+
// Project is not queryable in WMS
298+
//pLayer.queryable = ( nonIdentifiableLayers.count() != project->count() );
299+
pLayer.queryable = false;
300+
301+
wmtsLayers.append( pLayer );
302+
}
303+
304+
QStringList wmtsGroupNameList = project->readListEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Group" ) );
305+
if ( !wmtsGroupNameList.isEmpty() )
306+
{
307+
QgsLayerTreeGroup *treeRoot = project->layerTreeRoot();
308+
309+
QStringList wmtsPngGroupNameList = project->readListEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Group" ) );
310+
QStringList wmtsJpegGroupNameList = project->readListEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Group" ) );
311+
312+
for ( const QString gName : wmtsGroupNameList )
313+
{
314+
QgsLayerTreeGroup *treeGroup = treeRoot->findGroup( gName );
315+
if ( !treeGroup )
316+
{
317+
continue;
318+
}
319+
320+
layerDef pLayer;
321+
pLayer.id = treeGroup->customProperty( QStringLiteral( "wmsShortName" ) ).toString();
322+
if ( pLayer.id.isEmpty() )
323+
pLayer.id = gName;
324+
325+
pLayer.title = treeGroup->customProperty( QStringLiteral( "wmsTitle" ) ).toString();
326+
if ( pLayer.title.isEmpty() )
327+
pLayer.title = gName;
328+
329+
pLayer.abstract = treeGroup->customProperty( QStringLiteral( "wmsAbstract" ) ).toString();
330+
331+
QgsRectangle wgs84BoundingRect;
332+
bool queryable = false;
333+
double maxScale = 0.0;
334+
double minScale = 0.0;
335+
for ( QgsLayerTreeLayer *layer : treeGroup->findLayers() )
336+
{
337+
QgsMapLayer *l = layer->layer();
338+
if ( !l )
339+
{
340+
continue;
341+
}
342+
//transform the layer native CRS into WGS84
343+
QgsCoordinateReferenceSystem layerCrs = l->crs();
344+
QgsCoordinateTransform exGeoTransform( layerCrs, wgs84, project );
345+
try
346+
{
347+
wgs84BoundingRect.combineExtentWith( exGeoTransform.transformBoundingBox( l->extent() ) );
348+
}
349+
catch ( const QgsCsException & )
350+
{
351+
wgs84BoundingRect.combineExtentWith( QgsRectangle( -180, -90, 180, 90 ) );
352+
}
353+
if ( !queryable && !nonIdentifiableLayers.contains( l->id() ) )
354+
{
355+
queryable = true;
356+
}
357+
358+
double lMaxScale = l->maximumScale();
359+
if ( lMaxScale > 0.0 && lMaxScale > maxScale )
360+
{
361+
maxScale = lMaxScale;
362+
}
363+
double lMinScale = l->minimumScale();
364+
if ( lMinScale > 0.0 && ( minScale == 0.0 || lMinScale < minScale ) )
365+
{
366+
minScale = lMinScale;
367+
}
368+
}
369+
pLayer.wgs84BoundingRect = wgs84BoundingRect;
370+
pLayer.queryable = queryable;
371+
pLayer.maxScale = maxScale;
372+
pLayer.minScale = minScale;
373+
374+
// Formats
375+
if ( wmtsPngGroupNameList.contains( gName ) )
376+
pLayer.formats << QStringLiteral( "image/png" );
377+
if ( wmtsJpegGroupNameList.contains( gName ) )
378+
pLayer.formats << QStringLiteral( "image/jpeg" );
379+
380+
wmtsLayers.append( pLayer );
381+
}
382+
}
383+
384+
QStringList wmtsLayerIdList = project->readListEntry( QStringLiteral( "WMTSLayers" ), QStringLiteral( "Layer" ) );
385+
QStringList wmtsPngLayerIdList = project->readListEntry( QStringLiteral( "WMTSPngLayers" ), QStringLiteral( "Layer" ) );
386+
QStringList wmtsJpegLayerIdList = project->readListEntry( QStringLiteral( "WMTSJpegLayers" ), QStringLiteral( "Layer" ) );
387+
388+
for ( const QString lId : wmtsLayerIdList )
389+
{
390+
QgsMapLayer *l = project->mapLayer( lId );
391+
if ( !l )
392+
{
393+
continue;
394+
}
395+
#ifdef HAVE_SERVER_PYTHON_PLUGINS
396+
if ( !accessControl->layerReadPermission( l ) )
397+
{
398+
continue;
399+
}
400+
#endif
401+
402+
layerDef pLayer;
403+
pLayer.id = l->name();
404+
if ( !l->shortName().isEmpty() )
405+
pLayer.id = l->shortName();
406+
pLayer.id = pLayer.id.replace( ' ', '_' );
407+
408+
pLayer.title = l->title();
409+
pLayer.abstract = l->abstract();
410+
411+
//transform the layer native CRS into WGS84
412+
QgsCoordinateReferenceSystem layerCrs = l->crs();
413+
QgsCoordinateTransform exGeoTransform( layerCrs, wgs84, project );
414+
try
415+
{
416+
pLayer.wgs84BoundingRect = exGeoTransform.transformBoundingBox( l->extent() );
417+
}
418+
catch ( const QgsCsException & )
419+
{
420+
pLayer.wgs84BoundingRect = QgsRectangle( -180, -90, 180, 90 );
421+
}
422+
423+
// Formats
424+
if ( wmtsPngLayerIdList.contains( lId ) )
425+
pLayer.formats << QStringLiteral( "image/png" );
426+
if ( wmtsJpegLayerIdList.contains( lId ) )
427+
pLayer.formats << QStringLiteral( "image/jpeg" );
428+
429+
pLayer.queryable = ( !nonIdentifiableLayers.contains( l->id() ) );
430+
431+
pLayer.maxScale = l->maximumScale();
432+
pLayer.minScale = l->minimumScale();
433+
434+
wmtsLayers.append( pLayer );
435+
}
436+
return wmtsLayers;
437+
}
438+
439+
tileMatrixSetLinkDef getLayerTileMatrixSetLink( const layerDef layer, const tileMatrixSetDef tms, const QgsProject *project )
440+
{
441+
tileMatrixSetLinkDef tmsl;
442+
443+
QMap< int, tileMatrixLimitDef > tileMatrixLimits;
444+
445+
QgsRectangle rect( layer.wgs84BoundingRect );
446+
if ( tms.ref != QLatin1String( "EPSG:4326" ) )
447+
{
448+
QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( tms.ref );
449+
QgsCoordinateReferenceSystem wgs84 = QgsCoordinateReferenceSystem::fromOgcWmsCrs( GEO_EPSG_CRS_AUTHID );
450+
QgsCoordinateTransform exGeoTransform( wgs84, crs, project );
451+
try
452+
{
453+
rect = exGeoTransform.transformBoundingBox( layer.wgs84BoundingRect );
454+
}
455+
catch ( const QgsCsException & )
456+
{
457+
return tmsl;
458+
}
459+
}
460+
tmsl.ref = tms.ref;
461+
462+
rect = rect.intersect( tms.extent );
463+
464+
int tmIdx = -1;
465+
for ( const tileMatrixDef tm : tms.tileMatrixList )
466+
{
467+
++tmIdx;
468+
469+
if ( layer.maxScale > 0.0 && tm.scaleDenominator > layer.maxScale )
470+
{
471+
continue;
472+
}
473+
if ( layer.minScale > 0.0 && tm.scaleDenominator < layer.minScale )
474+
{
475+
continue;
476+
}
477+
478+
double res = tm.resolution;
479+
480+
tileMatrixLimitDef tml;
481+
tml.minCol = std::floor( ( rect.xMinimum() - tm.left ) / ( tileWidth * res ) );
482+
tml.maxCol = std::ceil( ( rect.xMaximum() - tm.left ) / ( tileWidth * res ) ) - 1;
483+
tml.minRow = std::floor( ( tm.top - rect.yMaximum() ) / ( tileHeight * res ) );
484+
tml.maxRow = std::ceil( ( tm.top - rect.yMinimum() ) / ( tileHeight * res ) ) - 1;
485+
486+
tileMatrixLimits[tmIdx] = tml;
487+
}
488+
489+
tmsl.tileMatrixLimits = tileMatrixLimits;
490+
return tmsl;
491+
}
492+
214493
QUrlQuery translateWmtsParamToWmsQueryItem( const QString &request, const QgsWmtsParameters &params,
215494
const QgsProject *project, QgsServerInterface *serverIface )
216495
{

‎src/server/services/wmts/qgswmtsutils.h

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,24 @@ namespace QgsWmts
7272
QList< tileMatrixDef > tileMatrixList;
7373
};
7474

75+
struct tileMatrixLimitDef
76+
{
77+
int minCol;
78+
79+
int maxCol;
80+
81+
int minRow;
82+
83+
int maxRow;
84+
};
85+
86+
struct tileMatrixSetLinkDef
87+
{
88+
QString ref;
89+
90+
QMap< int, tileMatrixLimitDef > tileMatrixLimits;
91+
};
92+
7593
struct layerDef
7694
{
7795
QString id;
@@ -85,6 +103,10 @@ namespace QgsWmts
85103
QStringList formats;
86104

87105
bool queryable = false;
106+
107+
double maxScale = 0.0;
108+
109+
double minScale = 0.0;
88110
};
89111

90112
/**
@@ -107,6 +129,9 @@ namespace QgsWmts
107129
double getProjectMinScale( const QgsProject *project );
108130
QList< tileMatrixSetDef > getTileMatrixSetList( const QgsProject *project );
109131

132+
QList< layerDef > getWmtsLayerList( QgsServerInterface *serverIface, const QgsProject *project );
133+
tileMatrixSetLinkDef getLayerTileMatrixSetLink( const layerDef layer, const tileMatrixSetDef tms, const QgsProject *project );
134+
110135
/**
111136
* Translate WMTS parameters to WMS query item
112137
*/

‎tests/testdata/qgis_server/wmts_getcapabilities.txt

Lines changed: 180 additions & 684 deletions
Large diffs are not rendered by default.

0 commit comments

Comments
 (0)
Please sign in to comment.