Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Added two new forgotten files with QgsTileXYZ, QgsTileMatrx, QgsTileR…
…ange
  • Loading branch information
wonder-sk committed Mar 26, 2020
1 parent 8105ad1 commit da57d93
Show file tree
Hide file tree
Showing 2 changed files with 212 additions and 0 deletions.
81 changes: 81 additions & 0 deletions src/core/qgstiles.cpp
@@ -0,0 +1,81 @@

#include "qgstiles.h"

#include <QtDebug>

QgsTileMatrix QgsTileMatrix::fromWebMercator( int zoomLevel )
{
int numTiles = static_cast<int>( pow( 2, zoomLevel ) ); // assuming we won't ever go over 30 zoom levels
double z0xMin = -20037508.3427892, z0yMin = -20037508.3427892;
double z0xMax = 20037508.3427892, z0yMax = 20037508.3427892;
double s0 = 559082264.0287178; // scale denominator at zoom level 0 of GoogleCRS84Quad

QgsTileMatrix tm;
tm.mZoomLevel = zoomLevel;
tm.mMatrixWidth = numTiles;
tm.mMatrixHeight = numTiles;
tm.mTileXSpan = ( z0xMax - z0xMin ) / tm.mMatrixWidth;
tm.mTileYSpan = ( z0yMax - z0yMin ) / tm.mMatrixHeight;
tm.mExtent = QgsRectangle( z0xMin, z0yMin, z0xMax, z0yMax );
tm.mScaleDenom = s0 / pow( 2, zoomLevel );
return tm;
}

QgsRectangle QgsTileMatrix::tileExtent( QgsTileXYZ id ) const
{
double xMin = mExtent.xMinimum() + mTileXSpan * id.column();
double xMax = xMin + mTileXSpan;
double yMax = mExtent.yMaximum() - mTileYSpan * id.row();
double yMin = yMax - mTileYSpan;
return QgsRectangle( xMin, yMin, xMax, yMax );
}

QgsPointXY QgsTileMatrix::tileCenter( QgsTileXYZ id ) const
{
double x = mExtent.xMinimum() + mTileXSpan / 2 * id.column();
double y = mExtent.yMaximum() - mTileYSpan / 2 * id.row();
return QgsPointXY( x, y );
}

inline double clampDouble( double lo, double v, double hi )
{
return ( v < lo ) ? lo : ( hi < v ) ? hi : v;
}

static int clampTile( int tile, int nTiles )
{
if ( tile < 0 ) return 0;
if ( tile >= nTiles ) return nTiles - 1;
return tile;
}

QgsTileRange QgsTileMatrix::tileRangeFromExtent( const QgsRectangle &r )
{
double x0 = clampDouble( mExtent.xMinimum(), r.xMinimum(), mExtent.xMaximum() );
double y0 = clampDouble( mExtent.yMinimum(), r.yMinimum(), mExtent.yMaximum() );
double x1 = clampDouble( mExtent.xMinimum(), r.xMaximum(), mExtent.xMaximum() );
double y1 = clampDouble( mExtent.yMinimum(), r.yMaximum(), mExtent.yMaximum() );
if ( x0 >= x1 || y0 >= y1 )
return QgsTileRange(); // nothing to display

double tileX1 = ( x0 - mExtent.xMinimum() ) / mTileXSpan;
double tileX2 = ( x1 - mExtent.xMinimum() ) / mTileXSpan;
double tileY1 = ( mExtent.yMaximum() - y1 ) / mTileYSpan;
double tileY2 = ( mExtent.yMaximum() - y0 ) / mTileYSpan;

qDebug() << "tile range of edges" << tileX1 << tileY1 << tileX2 << tileY2;

// figure out tile range from zoom
int startColumn = clampTile( static_cast<int>( floor( tileX1 ) ), mMatrixWidth );
int endColumn = clampTile( static_cast<int>( floor( tileX2 ) ), mMatrixWidth );
int startRow = clampTile( static_cast<int>( floor( tileY1 ) ), mMatrixHeight );
int endRow = clampTile( static_cast<int>( floor( tileY2 ) ), mMatrixHeight );
return QgsTileRange( startColumn, endColumn, startRow, endRow );
}

QPointF QgsTileMatrix::mapToTileCoordinates( const QgsPointXY &mapPoint ) const
{
double dx = mapPoint.x() - mExtent.xMinimum();
double dy = mExtent.yMaximum() - mapPoint.y();
return QPointF( dx / mTileXSpan, dy / mTileYSpan );
}
131 changes: 131 additions & 0 deletions src/core/qgstiles.h
@@ -0,0 +1,131 @@
/***************************************************************************
qgstiles.h
--------------------------------------
Date : March 2020
Copyright : (C) 2020 by Martin Dobias
Email : wonder dot sk at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/

#ifndef QGSTILES_H
#define QGSTILES_H

#include "qgis_core.h"
#include "qgis_sip.h"

#include "qgsrectangle.h"

/**
* \ingroup core
* Stores coordinates of a tile in a tile matrix set. Tile matrix is identified
* by the zoomLevel(), and the position within tile matrix is given by column()
* and row().
*
* \since QGIS 3.14
*/
class CORE_EXPORT QgsTileXYZ
{
public:
//! Constructs a tile identifier from given column, row and zoom level indices
QgsTileXYZ( int tc = -1, int tr = -1, int tz = -1 )
: mColumn( tc ), mRow( tr ), mZoomLevel( tz )
{
}

//! Returns tile's column index (X)
int column() const { return mColumn; }
//! Returns tile's row index (Y)
int row() const { return mRow; }
//! Returns tile's zoom level (Z)
int zoomLevel() const { return mZoomLevel; }

private:
int mColumn;
int mRow;
int mZoomLevel;
};


/**
* \ingroup core
* Range of tiles in a tile matrix to be rendered. The selection is rectangular,
* given by start/end row and column numbers.
*
* \since QGIS 3.14
*/
class CORE_EXPORT QgsTileRange
{
public:
//! Constructs a range of tiles from given span of columns and rows
QgsTileRange( int c1 = -1, int c2 = -1, int r1 = -1, int r2 = -1 )
: mStartColumn( c1 ), mEndColumn( c2 ), mStartRow( r1 ), mEndRow( r2 ) {}

//! Returns whether the range is valid (when all row/column numbers are not negative)
bool isValid() const { return mStartColumn >= 0 && mEndColumn >= 0 && mStartRow >= 0 && mEndRow >= 0; }

int startColumn() const { return mStartColumn; }
int endColumn() const { return mEndColumn; }
int startRow() const { return mStartRow; }
int endRow() const { return mEndRow; }

private:
int mStartColumn;
int mEndColumn;
int mStartRow;
int mEndRow;
};


/**
* \ingroup core
* Defines a matrix of tiles for a single zoom level: it is defined by its size (width * height)
* and map extent that it covers.
*
* Please note that we follow the XYZ convention of X/Y axes, i.e. top-left tile has [0,0] coordinate
* (which is different from TMS convention where bottom-left tile has [0,0] coordinate).
*
* \since QGIS 3.14
*/
struct CORE_EXPORT QgsTileMatrix
{
public:

//! Returns a tile matrix for the usual web mercator
static QgsTileMatrix fromWebMercator( int mZoomLevel );

//! Returns extent of the given tile in this matrix
QgsRectangle tileExtent( QgsTileXYZ id ) const;

//! Returns center of the given tile in this matrix
QgsPointXY tileCenter( QgsTileXYZ id ) const;

//! Returns tile range that fully covers the given extent
QgsTileRange tileRangeFromExtent( const QgsRectangle &mExtent );

//! Returns row/column coordinates (floating point number) from the given point in map coordinates
QPointF mapToTileCoordinates( const QgsPointXY &mapPoint ) const;

private:
//! Zoom level index associated with the tile matrix
int mZoomLevel;
//! Number of columns of the tile matrix
int mMatrixWidth;
//! Number of rows of the tile matrix
int mMatrixHeight;
//! Matrix extent in map units in the CRS of tile matrix set
QgsRectangle mExtent;
//! Scale denominator of the map scale associated with the tile matrix
double mScaleDenom;
//! Width of a single tile in map units (derived from extent and matrix size)
double mTileXSpan;
//! Height of a single tile in map units (derived from extent and matrix size)
double mTileYSpan;
};

#endif // QGSTILES_H

0 comments on commit da57d93

Please sign in to comment.