void QgsProjectionSelectionTreeWidget::updateBoundsPreview() { QTreeWidgetItem *lvi = lstCoordinateSystems->currentItem(); if ( !lvi || lvi->text( QgisCrsIdColumn ).isEmpty() ) return; QgsCoordinateReferenceSystem currentCrs = crs(); if ( !currentCrs.isValid() ) return; QgsRectangle rect = currentCrs.bounds(); if ( !qgsDoubleNear( rect.area(), 0.0 ) ) { QgsGeometry geom; if ( rect.xMinimum() > rect.xMaximum() ) { QgsRectangle rect1 = QgsRectangle( -180, rect.yMinimum(), rect.xMaximum(), rect.yMaximum() ); QgsRectangle rect2 = QgsRectangle( rect.xMinimum(), rect.yMinimum(), 180, rect.yMaximum() ); geom = QgsGeometry::fromRect( rect1 ); geom.addPart( QgsGeometry::fromRect( rect2 ) ); } else { geom = QgsGeometry::fromRect( rect ); } mPreviewBand->setToGeometry( geom, nullptr ); mPreviewBand->setColor( QColor( 255, 0, 0, 65 ) ); QgsRectangle extent = geom.boundingBox(); extent.scale( 1.1 ); mAreaCanvas->setExtent( extent ); mAreaCanvas->refresh(); mPreviewBand->show(); QString extentString = tr( "Extent: %1, %2, %3, %4" ) .arg( rect.xMinimum(), 0, 'f', 2 ) .arg( rect.yMinimum(), 0, 'f', 2 ) .arg( rect.xMaximum(), 0, 'f', 2 ) .arg( rect.yMaximum(), 0, 'f', 2 ); QString proj4String = tr( "Proj4: %1" ).arg( selectedProj4String() ); teProjection->setText( extentString + "\n" + proj4String ); } else { mPreviewBand->hide(); mAreaCanvas->zoomToFullExtent(); QString extentString = tr( "Extent: Extent not known" ); QString proj4String = tr( "Proj4: %1" ).arg( selectedProj4String() ); teProjection->setText( extentString + "\n" + proj4String ); } }
tileMatrixInfo calculateTileMatrixInfo( const QString &crsStr, const QgsProject *project ) { // Does the CRS have fixed tile matrices if ( fixedTileMatrixInfoMap.contains( crsStr ) ) return fixedTileMatrixInfoMap[crsStr]; // Does the CRS have already calculated tile matrices if ( calculatedTileMatrixInfoMap.contains( crsStr ) ) return calculatedTileMatrixInfoMap[crsStr]; tileMatrixInfo tmi; tmi.ref = crsStr; QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crsStr ); QgsCoordinateTransform crsTransform( wgs84, crs, project ); try { tmi.extent = crsTransform.transformBoundingBox( crs.bounds() ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ) } tmi.unit = crs.mapUnits(); tmi.hasAxisInverted = crs.hasAxisInverted(); // calculate tile matrix scale denominator double scaleDenominator = 0.0; int colRes = ( tmi.extent.xMaximum() - tmi.extent.xMinimum() ) / tileSize; int rowRes = ( tmi.extent.yMaximum() - tmi.extent.yMinimum() ) / tileSize; double UNIT_TO_M = QgsUnitTypes::fromUnitToUnitFactor( tmi.unit, QgsUnitTypes::DistanceMeters ); if ( colRes > rowRes ) scaleDenominator = std::ceil( colRes * UNIT_TO_M / POINTS_TO_M ); else scaleDenominator = std::ceil( rowRes * UNIT_TO_M / POINTS_TO_M ); // Update extent to get a square one QgsRectangle extent = tmi.extent; double res = POINTS_TO_M * scaleDenominator / UNIT_TO_M; int col = std::ceil( ( extent.xMaximum() - extent.xMinimum() ) / ( tileSize * res ) ); int row = std::ceil( ( extent.yMaximum() - extent.yMinimum() ) / ( tileSize * res ) ); if ( col > 1 || row > 1 ) { // Update scale if ( col > row ) { res = col * res; scaleDenominator = col * scaleDenominator; } else { res = row * res; scaleDenominator = row * scaleDenominator; } // set col and row to 1 for the square col = 1; row = 1; } // Calculate extent double left = ( extent.xMinimum() + ( extent.xMaximum() - extent.xMinimum() ) / 2.0 ) - ( col / 2.0 ) * ( tileSize * res ); double bottom = ( extent.yMinimum() + ( extent.yMaximum() - extent.yMinimum() ) / 2.0 ) - ( row / 2.0 ) * ( tileSize * res ); double right = ( extent.xMinimum() + ( extent.xMaximum() - extent.xMinimum() ) / 2.0 ) + ( col / 2.0 ) * ( tileSize * res ); double top = ( extent.yMinimum() + ( extent.yMaximum() - extent.yMinimum() ) / 2.0 ) + ( row / 2.0 ) * ( tileSize * res ); tmi.extent = QgsRectangle( left, bottom, right, top ); tmi.resolution = res; tmi.scaleDenominator = scaleDenominator; calculatedTileMatrixInfoMap[crsStr] = tmi; return tmi; }
QList< tileMatrixSetDef > getTileMatrixSetList( const QgsProject *project, const QString &tms_ref ) { QList< tileMatrixSetDef > tmsList; bool gridsDefined = false; QStringList wmtsGridList = project->readListEntry( QStringLiteral( "WMTSGrids" ), QStringLiteral( "CRS" ), QStringList(), &gridsDefined ); if ( gridsDefined ) { if ( !tms_ref.isEmpty() && !wmtsGridList.contains( tms_ref ) ) { throw QgsRequestNotWellFormedException( QStringLiteral( "TileMatrixSet is unknown" ) ); } QStringList wmtsGridConfigList = project->readListEntry( QStringLiteral( "WMTSGrids" ), QStringLiteral( "Config" ) ); for ( const QString &c : wmtsGridConfigList ) { QStringList config = c.split( ',' ); QString crsStr = config[0]; if ( !tms_ref.isEmpty() && tms_ref != crsStr ) { continue; } tileMatrixInfo tmi; double fixedTop = 0.0; double fixedLeft = 0.0; double resolution = -1.0; int col = -1; int row = -1; // Does the CRS have fixed tile matrices if ( fixedTileMatrixInfoMap.contains( crsStr ) ) { tmi = fixedTileMatrixInfoMap[crsStr]; // Calculate resolution based on scale denominator resolution = tmi.resolution; // Get fixed corner QgsRectangle extent = tmi.extent; fixedTop = extent.yMaximum(); fixedLeft = extent.xMinimum(); // Get numbers of column and row for the resolution to cover the extent col = std::ceil( ( extent.xMaximum() - extent.xMinimum() ) / ( tileSize * resolution ) ); row = std::ceil( ( extent.yMaximum() - extent.yMinimum() ) / ( tileSize * resolution ) ); } else { tmi.ref = crsStr; fixedTop = QVariant( config[1] ).toDouble(); fixedLeft = QVariant( config[2] ).toDouble(); double minScale = QVariant( config[3] ).toDouble(); tmi.scaleDenominator = minScale; QgsCoordinateReferenceSystem crs = QgsCoordinateReferenceSystem::fromOgcWmsCrs( crsStr ); tmi.unit = crs.mapUnits(); tmi.hasAxisInverted = crs.hasAxisInverted(); QgsCoordinateTransform crsTransform( QgsCoordinateReferenceSystem::fromOgcWmsCrs( GEO_EPSG_CRS_AUTHID ), crs, project ); try { // firstly transform CRS bounds expressed in WGS84 to CRS QgsRectangle extent = crsTransform.transformBoundingBox( crs.bounds() ); // Calculate resolution based on scale denominator resolution = POINTS_TO_M * minScale / QgsUnitTypes::fromUnitToUnitFactor( tmi.unit, QgsUnitTypes::DistanceMeters ); // Get numbers of column and row for the resolution to cover the extent col = std::ceil( ( extent.xMaximum() - extent.xMinimum() ) / ( tileSize * resolution ) ); row = std::ceil( ( extent.yMaximum() - extent.yMinimum() ) / ( tileSize * resolution ) ); // Calculate extent double bottom = fixedTop - row * tileSize * resolution; double right = fixedLeft + col * tileSize * resolution; tmi.extent = QgsRectangle( fixedLeft, bottom, right, fixedTop ); } catch ( QgsCsException &cse ) { Q_UNUSED( cse ) continue; } } // get lastLevel tmi.lastLevel = QVariant( config[4] ).toInt(); QList< tileMatrixDef > tileMatrixList; for ( int i = 0; i <= tmi.lastLevel; ++i ) { double scale = tmi.scaleDenominator / std::pow( 2, i ); double res = resolution / std::pow( 2, i ); tileMatrixDef tm; tm.resolution = res; tm.scaleDenominator = scale; tm.col = col * std::pow( 2, i ); tm.row = row * std::pow( 2, i ); tm.left = fixedLeft; tm.top = fixedTop; tileMatrixList.append( tm ); } tileMatrixSetDef tms; tms.ref = tmi.ref; tms.extent = tmi.extent; tms.unit = tmi.unit; tms.hasAxisInverted = tmi.hasAxisInverted; tms.tileMatrixList = tileMatrixList; tmsList.append( tms ); } return tmsList; } double minScale = project->readNumEntry( QStringLiteral( "WMTSMinScale" ), QStringLiteral( "/" ), -1.0 ); if ( minScale == -1.0 ) { minScale = getProjectMinScale( project ); } QStringList crsList = QgsServerProjectUtils::wmsOutputCrsList( *project ); if ( !tms_ref.isEmpty() && !crsList.contains( tms_ref ) ) { throw QgsRequestNotWellFormedException( QStringLiteral( "TileMatrixSet is unknown" ) ); } for ( const QString &crsStr : crsList ) { if ( !tms_ref.isEmpty() && tms_ref != crsStr ) { continue; } tileMatrixInfo tmi = calculateTileMatrixInfo( crsStr, project ); if ( tmi.scaleDenominator > 0.0 ) { tmsList.append( calculateTileMatrixSet( tmi, minScale ) ); } } return tmsList; }