LCOV - code coverage report
Current view: top level - core/vectortile - qgsvectortileutils.cpp (source / functions) Hit Total Coverage
Test: coverage.info.cleaned Lines: 0 98 0.0 %
Date: 2021-03-26 12:19:53 Functions: 0 0 -
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : /***************************************************************************
       2                 :            :   qgsvectortileutils.cpp
       3                 :            :   --------------------------------------
       4                 :            :   Date                 : March 2020
       5                 :            :   Copyright            : (C) 2020 by Martin Dobias
       6                 :            :   Email                : wonder dot sk at gmail dot com
       7                 :            :  ***************************************************************************
       8                 :            :  *                                                                         *
       9                 :            :  *   This program is free software; you can redistribute it and/or modify  *
      10                 :            :  *   it under the terms of the GNU General Public License as published by  *
      11                 :            :  *   the Free Software Foundation; either version 2 of the License, or     *
      12                 :            :  *   (at your option) any later version.                                   *
      13                 :            :  *                                                                         *
      14                 :            :  ***************************************************************************/
      15                 :            : 
      16                 :            : #include "qgsvectortileutils.h"
      17                 :            : 
      18                 :            : #include <math.h>
      19                 :            : 
      20                 :            : #include <QPolygon>
      21                 :            : 
      22                 :            : #include "qgscoordinatetransform.h"
      23                 :            : #include "qgsgeometrycollection.h"
      24                 :            : #include "qgsfields.h"
      25                 :            : #include "qgslogger.h"
      26                 :            : #include "qgsmaptopixel.h"
      27                 :            : #include "qgsrectangle.h"
      28                 :            : #include "qgsvectorlayer.h"
      29                 :            : 
      30                 :            : #include "qgsvectortilemvtdecoder.h"
      31                 :            : #include "qgsvectortilelayer.h"
      32                 :            : #include "qgsvectortilerenderer.h"
      33                 :            : 
      34                 :            : 
      35                 :            : 
      36                 :          0 : QPolygon QgsVectorTileUtils::tilePolygon( QgsTileXYZ id, const QgsCoordinateTransform &ct, const QgsTileMatrix &tm, const QgsMapToPixel &mtp )
      37                 :            : {
      38                 :          0 :   QgsRectangle r = tm.tileExtent( id );
      39                 :          0 :   QgsPointXY p00a = mtp.transform( ct.transform( r.xMinimum(), r.yMinimum() ) );
      40                 :          0 :   QgsPointXY p11a = mtp.transform( ct.transform( r.xMaximum(), r.yMaximum() ) );
      41                 :          0 :   QgsPointXY p01a = mtp.transform( ct.transform( r.xMinimum(), r.yMaximum() ) );
      42                 :          0 :   QgsPointXY p10a = mtp.transform( ct.transform( r.xMaximum(), r.yMinimum() ) );
      43                 :          0 :   QPolygon path;
      44                 :          0 :   path << p00a.toQPointF().toPoint();
      45                 :          0 :   path << p01a.toQPointF().toPoint();
      46                 :          0 :   path << p11a.toQPointF().toPoint();
      47                 :          0 :   path << p10a.toQPointF().toPoint();
      48                 :          0 :   return path;
      49                 :          0 : }
      50                 :            : 
      51                 :          0 : QgsFields QgsVectorTileUtils::makeQgisFields( QSet<QString> flds )
      52                 :            : {
      53                 :          0 :   QgsFields fields;
      54                 :          0 :   QStringList fieldsSorted = qgis::setToList( flds );
      55                 :          0 :   std::sort( fieldsSorted.begin(), fieldsSorted.end() );
      56                 :          0 :   for ( const QString &fieldName : std::as_const( fieldsSorted ) )
      57                 :            :   {
      58                 :          0 :     fields.append( QgsField( fieldName, QVariant::String ) );
      59                 :            :   }
      60                 :          0 :   return fields;
      61                 :          0 : }
      62                 :            : 
      63                 :          0 : double QgsVectorTileUtils::scaleToZoom( double mapScale )
      64                 :            : {
      65                 :          0 :   double s0 = 559082264.0287178;   // scale denominator at zoom level 0 of GoogleCRS84Quad
      66                 :          0 :   double tileZoom2 = log( s0 / mapScale ) / log( 2 );
      67                 :          0 :   tileZoom2 -= 1;   // TODO: it seems that map scale is double (is that because of high-dpi screen?)
      68                 :          0 :   return tileZoom2;
      69                 :            : }
      70                 :            : 
      71                 :          0 : int QgsVectorTileUtils::scaleToZoomLevel( double mapScale, int sourceMinZoom, int sourceMaxZoom )
      72                 :            : {
      73                 :          0 :   int tileZoom = static_cast<int>( floor( scaleToZoom( mapScale ) ) );
      74                 :            : 
      75                 :          0 :   if ( tileZoom < sourceMinZoom )
      76                 :          0 :     tileZoom = sourceMinZoom;
      77                 :          0 :   if ( tileZoom > sourceMaxZoom )
      78                 :          0 :     tileZoom = sourceMaxZoom;
      79                 :            : 
      80                 :          0 :   return tileZoom;
      81                 :            : }
      82                 :            : 
      83                 :          0 : QgsVectorLayer *QgsVectorTileUtils::makeVectorLayerForTile( QgsVectorTileLayer *mvt, QgsTileXYZ tileID, const QString &layerName )
      84                 :            : {
      85                 :          0 :   QgsVectorTileMVTDecoder decoder;
      86                 :          0 :   decoder.decode( tileID, mvt->getRawTile( tileID ) );
      87                 :          0 :   QSet<QString> fieldNames = qgis::listToSet( decoder.layerFieldNames( layerName ) );
      88                 :          0 :   fieldNames << QStringLiteral( "_geom_type" );
      89                 :          0 :   QMap<QString, QgsFields> perLayerFields;
      90                 :          0 :   QgsFields fields = QgsVectorTileUtils::makeQgisFields( fieldNames );
      91                 :          0 :   perLayerFields[layerName] = fields;
      92                 :          0 :   QgsVectorTileFeatures data = decoder.layerFeatures( perLayerFields, QgsCoordinateTransform() );
      93                 :          0 :   QgsFeatureList featuresList = data[layerName].toList();
      94                 :            : 
      95                 :            :   // turn all geometries to geom. collections (otherwise they won't be accepted by memory provider)
      96                 :          0 :   for ( int i = 0; i < featuresList.count(); ++i )
      97                 :            :   {
      98                 :          0 :     QgsGeometry g = featuresList[i].geometry();
      99                 :          0 :     QgsGeometryCollection *gc = new QgsGeometryCollection;
     100                 :          0 :     const QgsAbstractGeometry *gg = g.constGet();
     101                 :          0 :     if ( const QgsGeometryCollection *ggc = qgsgeometry_cast<const QgsGeometryCollection *>( gg ) )
     102                 :            :     {
     103                 :          0 :       for ( int k = 0; k < ggc->numGeometries(); ++k )
     104                 :          0 :         gc->addGeometry( ggc->geometryN( k )->clone() );
     105                 :          0 :     }
     106                 :            :     else
     107                 :          0 :       gc->addGeometry( gg->clone() );
     108                 :          0 :     featuresList[i].setGeometry( QgsGeometry( gc ) );
     109                 :          0 :   }
     110                 :            : 
     111                 :          0 :   QgsVectorLayer *vl = new QgsVectorLayer( QStringLiteral( "GeometryCollection" ), layerName, QStringLiteral( "memory" ) );
     112                 :          0 :   vl->dataProvider()->addAttributes( fields.toList() );
     113                 :          0 :   vl->updateFields();
     114                 :          0 :   bool res = vl->dataProvider()->addFeatures( featuresList );
     115                 :            :   Q_UNUSED( res );
     116                 :            :   Q_ASSERT( res );
     117                 :            :   Q_ASSERT( featuresList.count() == vl->featureCount() );
     118                 :          0 :   vl->updateExtents();
     119                 :          0 :   QgsDebugMsgLevel( QStringLiteral( "Layer %1 features %2" ).arg( layerName ).arg( vl->featureCount() ), 2 );
     120                 :          0 :   return vl;
     121                 :          0 : }
     122                 :            : 
     123                 :            : 
     124                 :          0 : QString QgsVectorTileUtils::formatXYZUrlTemplate( const QString &url, QgsTileXYZ tile, const QgsTileMatrix &tileMatrix )
     125                 :            : {
     126                 :          0 :   QString turl( url );
     127                 :            : 
     128                 :          0 :   turl.replace( QLatin1String( "{x}" ), QString::number( tile.column() ), Qt::CaseInsensitive );
     129                 :          0 :   if ( turl.contains( QLatin1String( "{-y}" ) ) )
     130                 :            :   {
     131                 :          0 :     turl.replace( QLatin1String( "{-y}" ), QString::number( tileMatrix.matrixHeight() - tile.row() - 1 ), Qt::CaseInsensitive );
     132                 :          0 :   }
     133                 :            :   else
     134                 :            :   {
     135                 :          0 :     turl.replace( QLatin1String( "{y}" ), QString::number( tile.row() ), Qt::CaseInsensitive );
     136                 :            :   }
     137                 :          0 :   turl.replace( QLatin1String( "{z}" ), QString::number( tile.zoomLevel() ), Qt::CaseInsensitive );
     138                 :          0 :   return turl;
     139                 :          0 : }
     140                 :            : 
     141                 :          0 : bool QgsVectorTileUtils::checkXYZUrlTemplate( const QString &url )
     142                 :            : {
     143                 :          0 :   return url.contains( QStringLiteral( "{x}" ) ) &&
     144                 :          0 :          ( url.contains( QStringLiteral( "{y}" ) ) || url.contains( QStringLiteral( "{-y}" ) ) ) &&
     145                 :          0 :          url.contains( QStringLiteral( "{z}" ) );
     146                 :          0 : }
     147                 :            : 
     148                 :            : //! a helper class for ordering tile requests according to the distance from view center
     149                 :          0 : struct LessThanTileRequest
     150                 :            : {
     151                 :            :   QPointF center;  //!< Center in tile matrix (!) coordinates
     152                 :          0 :   bool operator()( const QgsTileXYZ &req1, const QgsTileXYZ &req2 )
     153                 :            :   {
     154                 :          0 :     QPointF p1( req1.column() + 0.5, req1.row() + 0.5 );
     155                 :          0 :     QPointF p2( req2.column() + 0.5, req2.row() + 0.5 );
     156                 :            :     // using chessboard distance (loading order more natural than euclidean/manhattan distance)
     157                 :          0 :     double d1 = std::max( std::fabs( center.x() - p1.x() ), std::fabs( center.y() - p1.y() ) );
     158                 :          0 :     double d2 = std::max( std::fabs( center.x() - p2.x() ), std::fabs( center.y() - p2.y() ) );
     159                 :          0 :     return d1 < d2;
     160                 :            :   }
     161                 :            : };
     162                 :            : 
     163                 :          0 : QVector<QgsTileXYZ> QgsVectorTileUtils::tilesInRange( const QgsTileRange &range, int zoomLevel )
     164                 :            : {
     165                 :          0 :   QVector<QgsTileXYZ> tiles;
     166                 :          0 :   for ( int tileRow = range.startRow(); tileRow <= range.endRow(); ++tileRow )
     167                 :            :   {
     168                 :          0 :     for ( int tileColumn = range.startColumn(); tileColumn <= range.endColumn(); ++tileColumn )
     169                 :            :     {
     170                 :          0 :       tiles.append( QgsTileXYZ( tileColumn, tileRow, zoomLevel ) );
     171                 :          0 :     }
     172                 :          0 :   }
     173                 :          0 :   return tiles;
     174                 :          0 : }
     175                 :            : 
     176                 :          0 : void QgsVectorTileUtils::sortTilesByDistanceFromCenter( QVector<QgsTileXYZ> &tiles, const QPointF &center )
     177                 :            : {
     178                 :          0 :   LessThanTileRequest cmp;
     179                 :          0 :   cmp.center = center;
     180                 :          0 :   std::sort( tiles.begin(), tiles.end(), cmp );
     181                 :          0 : }

Generated by: LCOV version 1.14