24 constexpr double z0xMin = -20037508.3427892;
25 constexpr double z0yMax = 20037508.3427892;
31 const QgsPointXY &z0TopLeftPoint,
double z0Dimension,
int z0MatrixWidth,
int z0MatrixHeight )
34 double z0xMin = z0TopLeftPoint.
x();
35 double z0yMax = z0TopLeftPoint.
y();
36 double z0xMax = z0xMin + z0MatrixWidth * z0Dimension;
37 double z0yMin = z0yMax - z0MatrixHeight * z0Dimension;
40 constexpr double TILE_SIZE = 256.0;
41 constexpr double PIXELS_TO_M = 2.8 / 10000.0;
44 const double scaleDenom0 = ( z0Dimension / TILE_SIZE ) * ( unitToMeters / PIXELS_TO_M );
46 int numTiles =
static_cast<int>( pow( 2,
zoomLevel ) );
51 tm.mMatrixWidth = z0MatrixWidth * numTiles;
52 tm.mMatrixHeight = z0MatrixHeight * numTiles;
53 tm.mTileXSpan = ( z0xMax - z0xMin ) / tm.mMatrixWidth;
54 tm.mTileYSpan = ( z0yMax - z0yMin ) / tm.mMatrixHeight;
55 tm.mExtent =
QgsRectangle( z0xMin, z0yMin, z0xMax, z0yMax );
56 tm.mScaleDenom = scaleDenom0 / pow( 2,
zoomLevel );
63 int numTiles =
static_cast<int>( pow( 2,
zoomLevel ) );
65 int aNumTiles =
static_cast<int>( pow( 2, aZoomLevel ) );
69 tm.mCrs = tileMatrix.
crs();
71 tm.mMatrixWidth = aMatrixWidth * numTiles / aNumTiles;
72 tm.mMatrixHeight = aMatrixHeight * numTiles / aNumTiles;
73 tm.mTileXSpan = aExtent.
width() / tm.mMatrixWidth;
74 tm.mTileYSpan = aExtent.
height() / tm.mMatrixHeight;
76 tm.mScaleDenom = tileMatrix.
scale() * pow( 2, aZoomLevel ) / pow( 2,
zoomLevel );
82 double xMin = mExtent.
xMinimum() + mTileXSpan *
id.column();
83 double xMax = xMin + mTileXSpan;
84 double yMax = mExtent.
yMaximum() - mTileYSpan *
id.row();
85 double yMin = yMax - mTileYSpan;
91 double x = mExtent.
xMinimum() + mTileXSpan *
id.column() + mTileXSpan / 2;
92 double y = mExtent.
yMaximum() - mTileYSpan *
id.row() - mTileYSpan / 2;
102 if ( x0 >= x1 || y0 >= y1 )
105 double tileX1 = ( x0 - mExtent.
xMinimum() ) / mTileXSpan;
106 double tileX2 = ( x1 - mExtent.
xMinimum() ) / mTileXSpan;
107 double tileY1 = ( mExtent.
yMaximum() - y1 ) / mTileYSpan;
108 double tileY2 = ( mExtent.
yMaximum() - y0 ) / mTileYSpan;
110 QgsDebugMsgLevel( QStringLiteral(
"Tile range of edges [%1,%2] - [%3,%4]" ).arg( tileX1 ).arg( tileY1 ).arg( tileX2 ).arg( tileY2 ), 2 );
113 int startColumn = std::clamp(
static_cast<int>( floor( tileX1 ) ), 0, mMatrixWidth - 1 );
114 int endColumn = std::clamp(
static_cast<int>( floor( tileX2 ) ), 0, mMatrixWidth - 1 );
115 int startRow = std::clamp(
static_cast<int>( floor( tileY1 ) ), 0, mMatrixHeight - 1 );
116 int endRow = std::clamp(
static_cast<int>( floor( tileY2 ) ), 0, mMatrixHeight - 1 );
117 return QgsTileRange( startColumn, endColumn, startRow, endRow );
122 double dx = mapPoint.
x() - mExtent.
xMinimum();
123 double dy = mExtent.
yMaximum() - mapPoint.
y();
124 return QPointF( dx / mTileXSpan, dy / mTileYSpan );
133 return mTileMatrices.isEmpty();
151 return mTileMatrices.value( zoom );
161 mRootMatrix = matrix;
166 mTileMatrices.insert( matrix.
zoomLevel(), matrix );
172 for (
auto it = mTileMatrices.constBegin(); it != mTileMatrices.constEnd(); ++it )
174 if ( res == -1 || it->zoomLevel() < res )
175 res = it->zoomLevel();
183 for (
auto it = mTileMatrices.constBegin(); it != mTileMatrices.constEnd(); ++it )
185 if ( res == -1 || it->zoomLevel() > res )
186 res = it->zoomLevel();
193 for (
auto it = mTileMatrices.begin(); it != mTileMatrices.end(); )
197 it = mTileMatrices.erase( it );
208 if ( mTileMatrices.empty() )
218 double scaleUnder = 0;
219 double scaleOver = 0;
221 switch ( mScaleToTileZoomMethod )
234 for (
auto it = mTileMatrices.constBegin(); it != mTileMatrices.constEnd(); ++it )
236 if ( it->scale() > scale && ( zoomUnder == -1 || zoomUnder < it->zoomLevel() ) )
238 zoomUnder = it->zoomLevel();
239 scaleUnder = it->scale();
241 if ( it->scale() < scale && ( zoomOver == -1 || zoomOver > it->zoomLevel() ) )
243 zoomOver = it->zoomLevel();
244 scaleOver = it->scale();
253 return ( scaleUnder - scale ) / ( scaleUnder - scaleOver ) * ( zoomOver - zoomUnder ) + zoomUnder;
259 switch ( mScaleToTileZoomMethod )
262 tileZoom =
static_cast<int>( round(
scaleToZoom( scale ) ) );
265 tileZoom =
static_cast<int>( floor(
scaleToZoom( scale ) ) );
278 context.
painter()->device()->logicalDpiX() );
283 switch ( mScaleToTileZoomMethod )
286 return actualMapScale;
293 constexpr double METERS_PER_DEGREE = M_PI / 180.0 * 6378137;
294 constexpr double INCHES_PER_METER = 39.370078;
295 const double mapWidthInches = mapExtent.
width() * METERS_PER_DEGREE * INCHES_PER_METER;
297 double scale = mapWidthInches * mapDpi /
static_cast< double >( mapSize.width() );
308 return actualMapScale;
316 mTileMatrices.clear();
320 auto readMatrixFromElement = [](
const QDomElement & matrixElement )->
QgsTileMatrix
323 matrix.mZoomLevel = matrixElement.attribute( QStringLiteral(
"zoomLevel" ) ).toInt();
324 matrix.mMatrixWidth = matrixElement.attribute( QStringLiteral(
"matrixWidth" ) ).toInt();
325 matrix.mMatrixHeight = matrixElement.attribute( QStringLiteral(
"matrixHeight" ) ).toInt();
327 matrixElement.attribute( QStringLiteral(
"xMin" ) ).toDouble(),
328 matrixElement.attribute( QStringLiteral(
"yMin" ) ).toDouble(),
329 matrixElement.attribute( QStringLiteral(
"xMax" ) ).toDouble(),
330 matrixElement.attribute( QStringLiteral(
"yMax" ) ).toDouble()
333 matrix.mScaleDenom = matrixElement.attribute( QStringLiteral(
"scale" ) ).toDouble();
334 matrix.mTileXSpan = matrixElement.attribute( QStringLiteral(
"tileXSpan" ) ).toDouble();
335 matrix.mTileYSpan = matrixElement.attribute( QStringLiteral(
"tileYSpan" ) ).toDouble();
336 matrix.mCrs.
readXml( matrixElement );
340 const QDomNodeList children = element.childNodes();
341 for (
int i = 0; i < children.size(); i++ )
343 const QDomElement matrixElement = children.at( i ).toElement();
344 if ( matrixElement.tagName() == QLatin1String(
"rootMatrix" ) )
347 QgsTileMatrix matrix = readMatrixFromElement( matrixElement );
349 mRootMatrix = matrix;
354 const QDomElement rootElement = element.firstChildElement( QStringLiteral(
"rootMatrix" ) );
355 if ( !rootElement.isNull() )
357 mRootMatrix = readMatrixFromElement( rootElement );
365 QDomElement setElement = document.createElement( QStringLiteral(
"matrixSet" ) );
366 setElement.setAttribute( QStringLiteral(
"scaleToZoomMethod" ),
qgsEnumValueToKey( mScaleToTileZoomMethod ) );
368 auto writeMatrixToElement = [&document](
const QgsTileMatrix & matrix, QDomElement & matrixElement )
370 matrixElement.setAttribute( QStringLiteral(
"zoomLevel" ), matrix.
zoomLevel() );
371 matrixElement.setAttribute( QStringLiteral(
"matrixWidth" ), matrix.
matrixWidth() );
372 matrixElement.setAttribute( QStringLiteral(
"matrixHeight" ), matrix.
matrixHeight() );
380 matrixElement.setAttribute( QStringLiteral(
"tileXSpan" ),
qgsDoubleToString( matrix.mTileXSpan ) );
381 matrixElement.setAttribute( QStringLiteral(
"tileYSpan" ),
qgsDoubleToString( matrix.mTileYSpan ) );
386 for (
auto it = mTileMatrices.constBegin(); it != mTileMatrices.constEnd(); ++it )
388 QDomElement matrixElement = document.createElement( QStringLiteral(
"matrix" ) );
389 writeMatrixToElement( *it, matrixElement );
390 setElement.appendChild( matrixElement );
393 QDomElement rootElement = document.createElement( QStringLiteral(
"rootMatrix" ) );
394 writeMatrixToElement( mRootMatrix, rootElement );
395 setElement.appendChild( rootElement );
@ Esri
No scale doubling, always rounds down when matching to available tile levels.
@ MapBox
Uses a scale doubling approach to account for hi-DPI tiles, and rounds to the nearest tile level for ...
This class represents a coordinate reference system (CRS).
bool readXml(const QDomNode &node)
Restores state from the given DOM node.
bool writeXml(QDomNode &node, QDomDocument &doc) const
Stores state to the given Dom node in the given document.
Q_GADGET QgsUnitTypes::DistanceUnit mapUnits
A class to represent a 2D point.
The class is used as a container of context for various read/write operations on other objects.
A rectangle specified with double values.
double yMaximum() const SIP_HOLDGIL
Returns the y maximum value (top side of rectangle).
double xMaximum() const SIP_HOLDGIL
Returns the x maximum value (right side of rectangle).
double xMinimum() const SIP_HOLDGIL
Returns the x minimum value (left side of rectangle).
double yMinimum() const SIP_HOLDGIL
Returns the y minimum value (bottom side of rectangle).
double height() const SIP_HOLDGIL
Returns the height of the rectangle.
double width() const SIP_HOLDGIL
Returns the width of the rectangle.
Contains information about the context of a rendering operation.
QPainter * painter()
Returns the destination QPainter for the render operation.
double rendererScale() const
Returns the renderer map scale.
QSize outputSize() const
Returns the size of the resulting rendered image, in pixels.
QgsRectangle mapExtent() const
Returns the original extent of the map being rendered.
QgsCoordinateTransform coordinateTransform() const
Returns the current coordinate transform for the context.
virtual QDomElement writeXml(QDomDocument &document, const QgsReadWriteContext &context) const
Writes the set to an XML element.
void addGoogleCrs84QuadTiles(int minimumZoom=0, int maximumZoom=14)
Adds tile matrices corresponding to the standard web mercator/GoogleCRS84Quad setup.
QgsCoordinateReferenceSystem crs() const
Returns the coordinate reference system associated with the tiles.
double scaleForRenderContext(const QgsRenderContext &context) const
Calculates the correct scale to use for the tiles when rendered using the specified render context.
int minimumZoom() const
Returns the minimum zoom level for tiles present in the set.
int scaleToZoomLevel(double scale) const
Finds the best fitting (integer) zoom level given a map scale denominator.
double scaleToZoom(double scale) const
Calculates a fractional zoom level given a map scale denominator.
int maximumZoom() const
Returns the maximum zoom level for tiles present in the set.
QgsTileMatrix tileMatrix(int zoom) const
Returns the tile matrix corresponding to the specified zoom.
QgsTileMatrix rootMatrix() const
Returns the root tile matrix (usually corresponding to zoom level 0).
virtual bool readXml(const QDomElement &element, QgsReadWriteContext &context)
Reads the set from an XML element.
void addMatrix(const QgsTileMatrix &matrix)
Adds a matrix to the set.
double calculateTileScaleForMap(double actualMapScale, const QgsCoordinateReferenceSystem &mapCrs, const QgsRectangle &mapExtent, const QSize mapSize, const double mapDpi) const
Calculates the correct scale to use for the tiles when rendered using the specified map properties.
void dropMatricesOutsideZoomRange(int minimumZoom, int maximumZoom)
Deletes any existing matrices which fall outside the zoom range specified by minimumZoom to maximumZo...
bool isEmpty() const
Returns true if the matrix set is empty.
void setRootMatrix(const QgsTileMatrix &matrix)
Sets the root tile matrix (usually corresponding to zoom level 0).
Defines a matrix of tiles for a single zoom level: it is defined by its size (width *.
QgsRectangle tileExtent(QgsTileXYZ id) const
Returns extent of the given tile in this matrix.
QPointF mapToTileCoordinates(const QgsPointXY &mapPoint) const
Returns row/column coordinates (floating point number) from the given point in map coordinates.
QgsTileRange tileRangeFromExtent(const QgsRectangle &mExtent) const
Returns tile range that fully covers the given extent.
static QgsTileMatrix fromWebMercator(int zoomLevel)
Returns a tile matrix for the usual web mercator.
QgsRectangle extent() const
Returns extent of the tile matrix.
int matrixWidth() const
Returns number of columns of the tile matrix.
QgsCoordinateReferenceSystem crs() const
Returns the crs of the tile matrix.
double scale() const
Returns scale denominator of the tile matrix.
QgsPointXY tileCenter(QgsTileXYZ id) const
Returns center of the given tile in this matrix.
int matrixHeight() const
Returns number of rows of the tile matrix.
static QgsTileMatrix fromTileMatrix(int zoomLevel, const QgsTileMatrix &tileMatrix)
Returns a tile matrix based on another one.
int zoomLevel() const
Returns the zoom level of the tile matrix.
static QgsTileMatrix fromCustomDef(int zoomLevel, const QgsCoordinateReferenceSystem &crs, const QgsPointXY &z0TopLeftPoint, double z0Dimension, int z0MatrixWidth=1, int z0MatrixHeight=1)
Returns a tile matrix for a specific CRS, top left point, zoom level 0 dimension in CRS units.
Range of tiles in a tile matrix to be rendered.
Stores coordinates of a tile in a tile matrix set.
static Q_INVOKABLE double fromUnitToUnitFactor(QgsUnitTypes::DistanceUnit fromUnit, QgsUnitTypes::DistanceUnit toUnit)
Returns the conversion factor between the specified distance units.
T qgsEnumKeyToValue(const QString &key, const T &defaultValue, bool tryValueAsKey=true, bool *returnOk=nullptr)
Returns the value corresponding to the given key of an enum.
QString qgsDoubleToString(double a, int precision=17)
Returns a string representation of a double.
QString qgsEnumValueToKey(const T &value, bool *returnOk=nullptr)
Returns the value for the given key of an enum.
#define BUILTIN_UNREACHABLE
#define QgsDebugMsgLevel(str, level)
const QgsCoordinateReferenceSystem & crs