Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qgeotiledmapscene.cpp
Go to the documentation of this file.
1// Copyright (C) 2015 The Qt Company Ltd.
2// Copyright (C) 2014 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4// Qt-Security score:significant reason:default
5
10#include "qgeotilespec_p.h"
11
12#include <QtQuick/QQuickWindow>
13#include <QtGui/QVector3D>
14
15#include <QtCore/private/qobject_p.h>
16#include <QtPositioning/private/qdoublevector3d_p.h>
17#include <QtPositioning/private/qlocationutils_p.h>
18#include <QtPositioning/private/qdoublematrix4x4_p.h>
19#include <QtPositioning/private/qwebmercator_p.h>
20
21#include <cmath>
22
23static QVector3D toVector3D(const QDoubleVector3D& in)
24{
25 return QVector3D(in.x(), in.y(), in.z());
26}
27
28QT_BEGIN_NAMESPACE
29
30QGeoTiledMapScene::QGeoTiledMapScene(QObject *parent)
31 : QObject(*new QGeoTiledMapScenePrivate(),parent)
32{
33}
34
35QGeoTiledMapScene::~QGeoTiledMapScene()
36{
37}
38
39void QGeoTiledMapScene::setScreenSize(const QSize &size)
40{
41 Q_D(QGeoTiledMapScene);
42 d->m_screenSize = size;
43}
44
45void QGeoTiledMapScene::updateSceneParameters()
46{
47 Q_D(QGeoTiledMapScene);
48 d->m_intZoomLevel = static_cast<int>(std::floor(d->m_cameraData.zoomLevel()));
49 const float delta = d->m_cameraData.zoomLevel() - d->m_intZoomLevel;
50 d->m_linearScaling = qAbs(delta) > 0.05 || d->isTiltedOrRotated();
51 d->m_sideLength = 1 << d->m_intZoomLevel;
52}
53
54void QGeoTiledMapScene::setTileSize(int tileSize)
55{
56 Q_D(QGeoTiledMapScene);
57 if (d->m_tileSize == tileSize)
58 return;
59
60 d->m_tileSize = tileSize;
61 updateSceneParameters();
62}
63
64void QGeoTiledMapScene::setCameraData(const QGeoCameraData &cameraData)
65{
66 Q_D(QGeoTiledMapScene);
67 d->m_cameraData = cameraData;
68 updateSceneParameters();
69}
70
71void QGeoTiledMapScene::setVisibleArea(const QRectF &visibleArea)
72{
73 Q_D(QGeoTiledMapScene);
74 if (d->m_visibleArea == visibleArea)
75 return;
76 d->m_visibleArea = visibleArea;
77 updateSceneParameters();
78}
79
80void QGeoTiledMapScene::setVisibleTiles(const QSet<QGeoTileSpec> &tiles)
81{
82 Q_D(QGeoTiledMapScene);
83 d->setVisibleTiles(tiles);
84}
85
86const QSet<QGeoTileSpec> &QGeoTiledMapScene::visibleTiles() const
87{
88 Q_D(const QGeoTiledMapScene);
89 return d->m_visibleTiles;
90}
91
92void QGeoTiledMapScene::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture)
93{
94 Q_D(QGeoTiledMapScene);
95 d->addTile(spec, texture);
96}
97
98QSet<QGeoTileSpec> QGeoTiledMapScene::texturedTiles()
99{
100 Q_D(QGeoTiledMapScene);
101 QSet<QGeoTileSpec> textured;
102 for (auto it = d->m_textures.cbegin(); it != d->m_textures.cend(); ++it)
103 textured += it.value()->spec;
104
105 return textured;
106}
107
108void QGeoTiledMapScene::clearTexturedTiles()
109{
110 Q_D(QGeoTiledMapScene);
111 d->m_textures.clear();
112 d->m_dropTextures = true;
113}
114
115QGeoTiledMapScenePrivate::QGeoTiledMapScenePrivate()
116 : QObjectPrivate()
117{
118}
119
120QGeoTiledMapScenePrivate::~QGeoTiledMapScenePrivate()
121{
122}
123
124bool QGeoTiledMapScenePrivate::buildGeometry(const QGeoTileSpec &spec, QSGImageNode *imageNode, bool &overzooming)
125{
126 overzooming = false;
127 int x = spec.x();
128
129 if (x < m_tileXWrapsBelow)
130 x += m_sideLength;
131
132 if ((x < m_minTileX)
133 || (m_maxTileX < x)
134 || (spec.y() < m_minTileY)
135 || (m_maxTileY < spec.y())
136 || (spec.zoom() != m_intZoomLevel)) {
137 return false;
138 }
139
140 double edge = m_scaleFactor * m_tileSize;
141
142 double x1 = (x - m_minTileX);
143 double x2 = x1 + 1.0;
144
145 double y1 = (m_minTileY - spec.y());
146 double y2 = y1 - 1.0;
147
148 x1 *= edge;
149 x2 *= edge;
150 y1 *= edge;
151 y2 *= edge;
152
153 imageNode->setRect(QRectF(QPointF(x1, y2), QPointF(x2, y1)));
154 imageNode->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically);
155
156 // Calculate the texture mapping, in case we are magnifying some lower ZL tile
157 const auto it = m_textures.find(spec); // This should be always found, but apparently sometimes it isn't, possibly due to memory shortage
158 if (it != m_textures.end()) {
159 if (it.value()->spec.zoom() < spec.zoom()) {
160 // Currently only using lower ZL tiles for the overzoom.
161 const int tilesPerTexture = 1 << (spec.zoom() - it.value()->spec.zoom());
162 const int mappedSize = imageNode->texture()->textureSize().width() / tilesPerTexture;
163 const int x = (spec.x() % tilesPerTexture) * mappedSize;
164 const int y = (spec.y() % tilesPerTexture) * mappedSize;
165 imageNode->setSourceRect(QRectF(x, y, mappedSize, mappedSize));
166 overzooming = true;
167 } else {
168 imageNode->setSourceRect(QRectF(QPointF(0,0), imageNode->texture()->textureSize()));
169 }
170 } else {
171 qWarning() << "!! buildGeometry: tileSpec not present in m_textures !!";
172 imageNode->setSourceRect(QRectF(QPointF(0,0), imageNode->texture()->textureSize()));
173 }
174
175 return true;
176}
177
178void QGeoTiledMapScenePrivate::addTile(const QGeoTileSpec &spec, QSharedPointer<QGeoTileTexture> texture)
179{
180 if (!m_visibleTiles.contains(spec)) // Don't add the geometry if it isn't visible
181 return;
182
183 if (m_textures.contains(spec))
184 m_updatedTextures.append(spec);
185 m_textures.insert(spec, texture);
186}
187
188void QGeoTiledMapScenePrivate::setVisibleTiles(const QSet<QGeoTileSpec> &visibleTiles)
189{
190 // work out the tile bounds for the new scene
191 updateTileBounds(visibleTiles);
192
193 // set up the gl camera for the new scene
194 setupCamera();
195
196 QSet<QGeoTileSpec> toRemove = m_visibleTiles - visibleTiles;
197 if (!toRemove.isEmpty())
198 removeTiles(toRemove);
199
200 m_visibleTiles = visibleTiles;
201}
202
203void QGeoTiledMapScenePrivate::removeTiles(const QSet<QGeoTileSpec> &oldTiles)
204{
205 typedef QSet<QGeoTileSpec>::const_iterator iter;
206 iter i = oldTiles.constBegin();
207 iter end = oldTiles.constEnd();
208
209 for (; i != end; ++i) {
210 QGeoTileSpec tile = *i;
211 m_textures.remove(tile);
212 }
213}
214
215void QGeoTiledMapScenePrivate::updateTileBounds(const QSet<QGeoTileSpec> &tiles)
216{
217 if (tiles.isEmpty()) {
218 m_minTileX = -1;
219 m_minTileY = -1;
220 m_maxTileX = -1;
221 m_maxTileY = -1;
222 return;
223 }
224
225 typedef QSet<QGeoTileSpec>::const_iterator iter;
226 iter i = tiles.constBegin();
227 iter end = tiles.constEnd();
228
229 // determine whether the set of map tiles crosses the dateline.
230 // A gap in the tiles indicates dateline crossing
231 bool hasFarLeft = false;
232 bool hasFarRight = false;
233 bool hasMidLeft = false;
234 bool hasMidRight = false;
235
236 for (; i != end; ++i) {
237 if ((*i).zoom() != m_intZoomLevel)
238 continue;
239 int x = (*i).x();
240 if (x == 0)
241 hasFarLeft = true;
242 else if (x == (m_sideLength - 1))
243 hasFarRight = true;
244 else if (x == ((m_sideLength / 2) - 1)) {
245 hasMidLeft = true;
246 } else if (x == (m_sideLength / 2)) {
247 hasMidRight = true;
248 }
249 }
250
251 // if dateline crossing is detected we wrap all x pos of tiles
252 // that are in the left half of the map.
253 m_tileXWrapsBelow = 0;
254
255 if (hasFarLeft && hasFarRight) {
256 if (!hasMidRight) {
257 m_tileXWrapsBelow = m_sideLength / 2;
258 } else if (!hasMidLeft) {
259 m_tileXWrapsBelow = (m_sideLength / 2) - 1;
260 }
261 }
262
263 // finally, determine the min and max bounds
264 i = tiles.constBegin();
265
266 QGeoTileSpec tile = *i;
267
268 int x = tile.x();
269 if (tile.x() < m_tileXWrapsBelow)
270 x += m_sideLength;
271
272 m_minTileX = x;
273 m_maxTileX = x;
274 m_minTileY = tile.y();
275 m_maxTileY = tile.y();
276
277 ++i;
278
279 for (; i != end; ++i) {
280 tile = *i;
281 if (tile.zoom() != m_intZoomLevel)
282 continue;
283
284 int x = tile.x();
285 if (tile.x() < m_tileXWrapsBelow)
286 x += m_sideLength;
287
288 m_minTileX = qMin(m_minTileX, x);
289 m_maxTileX = qMax(m_maxTileX, x);
290 m_minTileY = qMin(m_minTileY, tile.y());
291 m_maxTileY = qMax(m_maxTileY, tile.y());
292 }
293}
294
295void QGeoTiledMapScenePrivate::setupCamera()
296{
297 // NOTE: The following instruction is correct only because WebMercator is a square projection!
298 double f = m_screenSize.height();
299
300 // Using fraction of zoom level, z varies between [ m_tileSize , 2 * m_tileSize [
301 double z = std::pow(2.0, m_cameraData.zoomLevel() - m_intZoomLevel) * m_tileSize;
302
303 // calculate altitude that allows the visible map tiles
304 // to fit in the screen correctly (note that a larger f will cause
305 // the camera be higher, resulting in gray areas displayed around
306 // the tiles)
307 double altitude = f / (2.0 * z);
308
309 // calculate center
310 double edge = m_scaleFactor * m_tileSize;
311
312 // first calculate the camera center in map space in the range of 0 <-> sideLength (2^z)
313 QDoubleVector2D camCenterMercator = QWebMercator::coordToMercator(m_cameraData.center());
314 QDoubleVector3D center = (m_sideLength * camCenterMercator);
315
316 // wrap the center if necessary (due to dateline crossing)
317 if (center.x() < m_tileXWrapsBelow)
318 center.setX(center.x() + 1.0 * m_sideLength);
319
320 // work out where the camera center is w.r.t minimum tile bounds
321 center.setX(center.x() - 1.0 * m_minTileX);
322 center.setY(1.0 * m_minTileY - center.y());
323
324 // apply necessary scaling to the camera center
325 center *= edge;
326
327 // calculate eye
328 double apertureSize = 1.0;
329 if (m_cameraData.fieldOfView() != 90.0) //aperture(90 / 2) = 1
330 apertureSize = tan(QLocationUtils::radians(m_cameraData.fieldOfView()) * 0.5);
331 QDoubleVector3D eye = center;
332 eye.setZ(altitude * edge / apertureSize);
333
334 // calculate up
335
336 QDoubleVector3D view = eye - center;
337 QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0));
338 QDoubleVector3D up = QDoubleVector3D::normal(side, view);
339
340 // old bearing, tilt and roll code.
341 // Now using double matrices until distilling the transformation to QMatrix4x4
342 QDoubleMatrix4x4 mBearing;
343 // -1.0 * bearing removed, now map north goes in the bearing direction
344 mBearing.rotate(-1.0 * m_cameraData.bearing(), view);
345 up = mBearing * up;
346
347 QDoubleVector3D side2 = QDoubleVector3D::normal(up, view);
348 if (m_cameraData.tilt() > 0.01) {
349 QDoubleMatrix4x4 mTilt;
350 mTilt.rotate(m_cameraData.tilt(), side2);
351 eye = mTilt * view + center;
352 }
353
354 view = eye - center;
355 view.normalize();
356 side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0));
357 up = QDoubleVector3D::normal(view, side2);
358
359 // QMatrix4x4 mRoll;
360 // mRoll.rotate(camera.roll(), view);
361 // up = mRoll * up;
362
363 // near plane and far plane
364
365 double nearPlane = 1.0;
366 // Clip plane. Used to be (altitude + 1.0) * edge. This does not affect the perspective. minimum value would be > 0.0
367 // Since, for some reasons possibly related to how QSG works, this clipping plane is unable to clip part of tiles,
368 // Instead of farPlane = (altitude + m_cameraData.clipDistance()) * edge , we use a fixed large clipDistance, and
369 // leave the clipping only in QGeoCameraTiles::createFrustum
370 double farPlane = (altitude + 10000.0) * edge;
371
372 m_cameraUp = up;
373 m_cameraCenter = center;
374 m_cameraEye = eye;
375
376 double aspectRatio = 1.0 * m_screenSize.width() / m_screenSize.height();
377 float halfWidth = 1 * apertureSize;
378 float halfHeight = 1 * apertureSize;
379 halfWidth *= aspectRatio;
380
381// m_projectionMatrix.setToIdentity();
382// m_projectionMatrix.frustum(-halfWidth, halfWidth, -halfHeight, halfHeight, nearPlane, farPlane);
383
384 QRectF va = m_visibleArea;
385 if (va.isNull())
386 va = QRectF(0, 0, m_screenSize.width(), m_screenSize.height());
387
388 QRectF screen = QRectF(QPointF(0,0),m_screenSize);
389 QPointF vaCenter = va.center();
390
391 QPointF screenCenter = screen.center();
392 QPointF diff = screenCenter - vaCenter;
393 float xdiffpct = diff.x() / m_screenSize.width();
394 float ydiffpct = -(diff.y() / m_screenSize.height());
395
396 m_projectionMatrix.setToIdentity();
397 float l = -halfWidth + (2 * halfWidth) * xdiffpct;
398 float r = halfWidth + (2 * halfWidth) * xdiffpct;
399 float t = halfHeight + (2 * halfHeight) * ydiffpct;
400 float b = -halfHeight + (2 * halfHeight) * ydiffpct;
401
402 m_projectionMatrix.frustum(l,
403 r,
404 b,
405 t,
406 nearPlane, farPlane);
407}
408
409static bool qgeotiledmapscene_isTileInViewport_Straight(const QRectF &tileRect, const QMatrix4x4 &matrix)
410{
411 const QRectF boundingRect = QRectF(matrix.map(tileRect.topLeft()), matrix.map(tileRect.bottomRight()));
412 return QRectF(-1, -1, 2, 2).intersects(boundingRect);
413}
414
415static bool qgeotiledmapscene_isTileInViewport_rotationTilt(const QRectF &tileRect, const QMatrix4x4 &matrix)
416{
417 // Transformed corners
418 const QPointF tlt = matrix.map(tileRect.topLeft());
419 const QPointF trt = matrix.map(tileRect.topRight());
420 const QPointF blt = matrix.map(tileRect.bottomLeft());
421 const QPointF brt = matrix.map(tileRect.bottomRight());
422
423 const QRectF boundingRect = QRectF(QPointF(qMin(qMin(qMin(tlt.x(), trt.x()), blt.x()), brt.x())
424 ,qMax(qMax(qMax(tlt.y(), trt.y()), blt.y()), brt.y()))
425 ,QPointF(qMax(qMax(qMax(tlt.x(), trt.x()), blt.x()), brt.x())
426 ,qMin(qMin(qMin(tlt.y(), trt.y()), blt.y()), brt.y()))
427 );
428 return QRectF(-1, -1, 2, 2).intersects(boundingRect);
429}
430
431static bool qgeotiledmapscene_isTileInViewport(const QRectF &tileRect, const QMatrix4x4 &matrix, const bool straight)
432{
433 if (straight)
434 return qgeotiledmapscene_isTileInViewport_Straight(tileRect, matrix);
435 return qgeotiledmapscene_isTileInViewport_rotationTilt(tileRect, matrix);
436}
437
438void QGeoTiledMapRootNode::updateTiles(QGeoTiledMapTileContainerNode *root,
439 QGeoTiledMapScenePrivate *d,
440 double camAdjust,
441 QQuickWindow *window)
442{
443 // Set up the matrix...
444 QDoubleVector3D eye = d->m_cameraEye;
445 eye.setX(eye.x() + camAdjust);
446 QDoubleVector3D center = d->m_cameraCenter;
447 center.setX(center.x() + camAdjust);
448 QMatrix4x4 cameraMatrix;
449 cameraMatrix.lookAt(toVector3D(eye), toVector3D(center), toVector3D(d->m_cameraUp));
450 root->setMatrix(d->m_projectionMatrix * cameraMatrix);
451
452 QSet<QGeoTileSpec> tilesInSG;
453 for (auto it = root->tiles.cbegin(), end = root->tiles.cend(); it != end; ++it)
454 tilesInSG.insert(it.key());
455 const QSet<QGeoTileSpec> toRemove = tilesInSG - d->m_visibleTiles;
456 const QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - tilesInSG;
457
458 for (const QGeoTileSpec &s : toRemove)
459 delete root->tiles.take(s);
460 bool straight = !d->isTiltedOrRotated();
461 bool overzooming;
462 qreal pixelRatio = window->effectiveDevicePixelRatio();
463#ifdef QT_LOCATION_DEBUG
464 QList<QGeoTileSpec> droppedTiles;
465#endif
466 for (QHash<QGeoTileSpec, QSGImageNode *>::iterator it = root->tiles.begin();
467 it != root->tiles.end(); ) {
468 QSGImageNode *node = it.value();
469 bool ok = d->buildGeometry(it.key(), node, overzooming)
470 && qgeotiledmapscene_isTileInViewport(node->rect(), root->matrix(), straight);
471
472 QSGNode::DirtyState dirtyBits = {};
473
474 if (!ok) {
475#ifdef QT_LOCATION_DEBUG
476 droppedTiles.append(it.key());
477#endif
478 it = root->tiles.erase(it);
479 delete node;
480 } else {
481 if (isTextureLinear != d->m_linearScaling) {
482 if (node->texture()->textureSize().width() > d->m_tileSize * pixelRatio) {
483 node->setFiltering(QSGTexture::Linear); // With mipmapping QSGTexture::Nearest generates artifacts
484 node->setMipmapFiltering(QSGTexture::Linear);
485 } else {
486 node->setFiltering((d->m_linearScaling || overzooming) ? QSGTexture::Linear : QSGTexture::Nearest);
487 }
488 dirtyBits |= QSGNode::DirtyMaterial;
489 }
490 if (dirtyBits != 0)
491 node->markDirty(dirtyBits);
492 it++;
493 }
494 }
495
496 for (const QGeoTileSpec &s : toAdd) {
497 QGeoTileTexture *tileTexture = d->m_textures.value(s).data();
498 if (!tileTexture || tileTexture->image.isNull()) {
499#ifdef QT_LOCATION_DEBUG
500 droppedTiles.append(s);
501#endif
502 continue;
503 }
504 QSGImageNode *tileNode = window->createImageNode();
505 // note: setTexture will update coordinates so do it here, before we buildGeometry
506 tileNode->setTexture(textures.value(s));
507 if (d->buildGeometry(s, tileNode, overzooming)
508 && qgeotiledmapscene_isTileInViewport(tileNode->rect(), root->matrix(), straight)) {
509 if (tileNode->texture()->textureSize().width() > d->m_tileSize * pixelRatio) {
510 tileNode->setFiltering(QSGTexture::Linear); // with mipmapping QSGTexture::Nearest generates artifacts
511 tileNode->setMipmapFiltering(QSGTexture::Linear);
512 } else {
513 tileNode->setFiltering((d->m_linearScaling || overzooming) ? QSGTexture::Linear : QSGTexture::Nearest);
514 }
515 root->addChild(s, tileNode);
516 } else {
517#ifdef QT_LOCATION_DEBUG
518 droppedTiles.append(s);
519#endif
520 delete tileNode;
521 }
522 }
523
524#ifdef QT_LOCATION_DEBUG
525 m_droppedTiles[camAdjust] = droppedTiles;
526#endif
527}
528
529QSGNode *QGeoTiledMapScene::updateSceneGraph(QSGNode *oldNode, QQuickWindow *window)
530{
531 Q_D(QGeoTiledMapScene);
532 float w = d->m_screenSize.width();
533 float h = d->m_screenSize.height();
534 if (w <= 0 || h <= 0) {
535 delete oldNode;
536 return nullptr;
537 }
538
539 QGeoTiledMapRootNode *mapRoot = static_cast<QGeoTiledMapRootNode *>(oldNode);
540 if (!mapRoot)
541 mapRoot = new QGeoTiledMapRootNode();
542
543#ifdef QT_LOCATION_DEBUG
544 mapRoot->m_droppedTiles.clear();
545 d->m_mapRoot = mapRoot;
546#endif
547
548 // Setting clip rect to fullscreen, as now the map can never be smaller than the viewport.
549 mapRoot->setClipRect(QRect(0, 0, w, h));
550
551 QMatrix4x4 itemSpaceMatrix;
552 itemSpaceMatrix.scale(w / 2, h / 2);
553 itemSpaceMatrix.translate(1, 1);
554 itemSpaceMatrix.scale(1, -1);
555 mapRoot->root->setMatrix(itemSpaceMatrix);
556
557 if (d->m_dropTextures) {
558 for (const QGeoTileSpec &s : mapRoot->tiles->tiles.keys())
559 delete mapRoot->tiles->tiles.take(s);
560 for (const QGeoTileSpec &s : mapRoot->wrapLeft->tiles.keys())
561 delete mapRoot->wrapLeft->tiles.take(s);
562 for (const QGeoTileSpec &s : mapRoot->wrapRight->tiles.keys())
563 delete mapRoot->wrapRight->tiles.take(s);
564 for (const QGeoTileSpec &spec : mapRoot->textures.keys())
565 mapRoot->textures.take(spec)->deleteLater();
566 d->m_dropTextures = false;
567 }
568
569 // Evicting loZL tiles temporarily used in place of hiZL ones
570 if (d->m_updatedTextures.size()) {
571 const QList<QGeoTileSpec> &toRemove = d->m_updatedTextures;
572 for (const QGeoTileSpec &s : toRemove) {
573 if (mapRoot->tiles->tiles.contains(s))
574 delete mapRoot->tiles->tiles.take(s);
575
576 if (mapRoot->wrapLeft->tiles.contains(s))
577 delete mapRoot->wrapLeft->tiles.take(s);
578
579 if (mapRoot->wrapRight->tiles.contains(s))
580 delete mapRoot->wrapRight->tiles.take(s);
581
582 if (mapRoot->textures.contains(s))
583 mapRoot->textures.take(s)->deleteLater();
584 }
585 d->m_updatedTextures.clear();
586 }
587
588 QSet<QGeoTileSpec> textures;
589 for (auto it = mapRoot->textures.cbegin(), end = mapRoot->textures.cend(); it != end; ++it)
590 textures.insert(it.key());
591 const QSet<QGeoTileSpec> toRemove = textures - d->m_visibleTiles;
592 const QSet<QGeoTileSpec> toAdd = d->m_visibleTiles - textures;
593
594 for (const QGeoTileSpec &spec : toRemove)
595 mapRoot->textures.take(spec)->deleteLater();
596 for (const QGeoTileSpec &spec : toAdd) {
597 QGeoTileTexture *tileTexture = d->m_textures.value(spec).data();
598 if (!tileTexture || tileTexture->image.isNull())
599 continue;
600 mapRoot->textures.insert(spec, window->createTextureFromImage(tileTexture->image));
601 }
602
603 double sideLength = d->m_scaleFactor * d->m_tileSize * d->m_sideLength;
604#ifdef QT_LOCATION_DEBUG
605 d->m_sideLengthPixel = sideLength;
606#endif
607 mapRoot->updateTiles(mapRoot->tiles, d, 0, window);
608 mapRoot->updateTiles(mapRoot->wrapLeft, d, +sideLength, window);
609 mapRoot->updateTiles(mapRoot->wrapRight, d, -sideLength, window);
610
611 mapRoot->isTextureLinear = d->m_linearScaling;
612
613 return mapRoot;
614}
615
616QT_END_NAMESPACE
static bool qgeotiledmapscene_isTileInViewport_rotationTilt(const QRectF &tileRect, const QMatrix4x4 &matrix)
static bool qgeotiledmapscene_isTileInViewport(const QRectF &tileRect, const QMatrix4x4 &matrix, const bool straight)
static bool qgeotiledmapscene_isTileInViewport_Straight(const QRectF &tileRect, const QMatrix4x4 &matrix)
static QVector3D toVector3D(const QDoubleVector3D &in)