Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qgeocameratiles.cpp
Go to the documentation of this file.
1// Copyright (C) 2015 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3#include "qgeocameratiles_p.h"
5#include "qgeocameradata_p.h"
6#include "qgeotilespec_p.h"
7#include "qgeomaptype_p.h"
8
9#include <QtGui/QMatrix4x4>
10#include <QList>
11#include <QMap>
12#include <QPair>
13#include <QSet>
14#include <QSize>
15
16#include <QtPositioning/private/qwebmercator_p.h>
17#include <QtPositioning/private/qdoublevector2d_p.h>
18#include <QtPositioning/private/qdoublevector3d_p.h>
19#include <QtPositioning/private/qlocationutils_p.h>
20
21#include <cmath>
22#include <limits>
23
25{
26 return QVector3D(in.x(), in.y(), in.z());
27}
28
30{
31 return QDoubleVector3D(in.x(), in.y(), in.z());
32}
33
35
38
42
44{
45 if (d_ptr->m_camera == camera)
46 return;
47
48 d_ptr->m_dirtyGeometry = true;
49 d_ptr->m_camera = camera;
50 d_ptr->m_intZoomLevel = static_cast<int>(std::floor(d_ptr->m_camera.zoomLevel()));
51 d_ptr->m_sideLength = 1 << d_ptr->m_intZoomLevel;
52}
53
55{
56 return d_ptr->m_camera;
57}
58
60{
61 if (d_ptr->m_visibleArea == visibleArea)
62 return;
63
64 d_ptr->m_visibleArea = visibleArea;
65 d_ptr->m_dirtyGeometry = true;
66}
67
69{
70 if (d_ptr->m_screenSize == size)
71 return;
72
73 d_ptr->m_dirtyGeometry = true;
74 d_ptr->m_screenSize = size;
75}
76
78{
79 if (d_ptr->m_pluginString == pluginString)
80 return;
81
82 d_ptr->m_dirtyMetadata = true;
83 d_ptr->m_pluginString = pluginString;
84}
85
87{
88 if (d_ptr->m_mapType == mapType)
89 return;
90
91 d_ptr->m_dirtyMetadata = true;
92 d_ptr->m_mapType = mapType;
93}
94
96{
97 return d_ptr->m_mapType;
98}
99
101{
102 if (d_ptr->m_mapVersion == mapVersion)
103 return;
104
105 d_ptr->m_dirtyMetadata = true;
106 d_ptr->m_mapVersion = mapVersion;
107}
108
110{
111 if (d_ptr->m_tileSize == tileSize)
112 return;
113
114 d_ptr->m_dirtyGeometry = true;
115 d_ptr->m_tileSize = tileSize;
116}
117
118void QGeoCameraTiles::setViewExpansion(double viewExpansion)
119{
120 d_ptr->m_viewExpansion = viewExpansion;
121 d_ptr->m_dirtyGeometry = true;
122}
123
125{
126 return d_ptr->m_tileSize;
127}
128
129const QSet<QGeoTileSpec>& QGeoCameraTiles::createTiles()
130{
131 if (d_ptr->m_dirtyGeometry) {
132 d_ptr->m_tiles.clear();
133 d_ptr->updateGeometry();
134 d_ptr->m_dirtyGeometry = false;
135 }
136
137 if (d_ptr->m_dirtyMetadata) {
138 d_ptr->updateMetadata();
139 d_ptr->m_dirtyMetadata = false;
140 }
141
142 return d_ptr->m_tiles;
143}
144
145
147{
149
150 QSet<QGeoTileSpec> newTiles;
151
154
155 for (; i != end; ++i) {
156 QGeoTileSpec tile = *i;
157 newTiles.insert(QGeoTileSpec(m_pluginString, m_mapType.mapId(), tile.zoom(), tile.x(), tile.y(), m_mapVersion));
158 }
159
160 m_tiles = newTiles;
161}
162
164{
165 // Find the frustum from the camera / screen / viewport information
166 // The larger frustum when stationary is a form of prefetching
168#ifdef QT_LOCATION_DEBUG
169 m_frustum = f;
170#endif
171
172 // Find the polygon where the frustum intersects the plane of the map
173 PolygonVector footprint = frustumFootprint(f);
174#ifdef QT_LOCATION_DEBUG
175 m_frustumFootprint = footprint;
176#endif
177
178 // Clip the polygon to the map, split it up if it cross the dateline
179 ClippedFootprint polygons = clipFootprintToMap(footprint);
180#ifdef QT_LOCATION_DEBUG
181 m_clippedFootprint = polygons;
182#endif
183
184
185 if (!polygons.left.isEmpty()) {
186 QSet<QGeoTileSpec> tilesLeft = tilesFromPolygon(polygons.left);
187 m_tiles.unite(tilesLeft);
188 }
189
190 if (!polygons.right.isEmpty()) {
191 QSet<QGeoTileSpec> tilesRight = tilesFromPolygon(polygons.right);
192 m_tiles.unite(tilesRight);
193 }
194
195 if (!polygons.mid.isEmpty()) {
196 QSet<QGeoTileSpec> tilesRight = tilesFromPolygon(polygons.mid);
197 m_tiles.unite(tilesRight);
198 }
199}
200
202{
203 double apertureSize = 1.0;
204 if (m_camera.fieldOfView() != 90.0) //aperture(90 / 2) = 1
205 apertureSize = tan(QLocationUtils::radians(m_camera.fieldOfView()) * 0.5);
207#ifdef QT_LOCATION_DEBUG
208 m_createFrustum_center = center;
209#endif
210
211
212 double f = m_screenSize.height();
213
214 double z = std::pow(2.0, m_camera.zoomLevel() - m_intZoomLevel) * m_tileSize; // between 1 and 2 * m_tileSize
215
216 double altitude = (f / (2.0 * z)) / apertureSize;
217 QDoubleVector3D eye = center;
218 eye.setZ(altitude);
219
220 QDoubleVector3D view = eye - center;
223
224 QMatrix4x4 mBearing;
225 // The rotation direction here is the opposite of QGeoTiledMapScene::setupCamera,
226 // as this is basically rotating the map against a fixed view frustum.
227 mBearing.rotate(1.0 * m_camera.bearing(), toVector3D(view));
228 up = toDoubleVector3D(mBearing.map(toVector3D(up)));
229
230 // same for tilting
232 QMatrix4x4 mTilt;
233 mTilt.rotate(-1.0 * m_camera.tilt(), toVector3D(side2));
234 eye = toDoubleVector3D((mTilt.map(toVector3D(view))) + toVector3D(center));
235
236 view = eye - center;
237 side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0));
238 up = QDoubleVector3D::normal(view, side2);
239
240 double nearPlane = 1.0 / 32.0; // The denominator used to be (4.0 * m_tileSize ), which produces an extremely narrow and tiny near plane.
241 // farPlane plays a role on how much gets clipped when the map gets tilted. It used to be altitude + 1.0
242 // The value of 8.0 has been chosen as an acceptable compromise.
243 // TODO: use m_camera.clipDistance(); when this will be introduced
244 double farPlane = altitude + 8.0;
245
246 double aspectRatio = 1.0 * m_screenSize.width() / m_screenSize.height();
247
248 // Half values. Half width near, far, height near, far.
249 double hhn,hwn,hhf,hwf = 0.0;
250
251 // This used to fix the (half) field of view at 45 degrees
252 // half because this assumed that viewSize = 2*nearPlane x 2*nearPlane
253 viewExpansion *= apertureSize;
254
255 hhn = viewExpansion * nearPlane;
256 hwn = hhn * aspectRatio;
257
258 hhf = viewExpansion * farPlane;
259 hwf = hhf * aspectRatio;
260
261 QDoubleVector3D d = center - eye;
262 d.normalize();
263 up.normalize();
265
266 QDoubleVector3D cf = eye + d * farPlane;
267 QDoubleVector3D cn = eye + d * nearPlane;
268
269 Frustum frustum;
270
271 frustum.apex = eye;
272#ifdef QT_LOCATION_DEBUG
273 m_createFrustum_eye = eye;
274#endif
275
277 if (va.isNull())
280 QPointF vaCenter = va.center();
281 QPointF screenCenter = screen.center();
282 QPointF diff = screenCenter - vaCenter;
283 double xdiffpct = diff.x() / m_screenSize.width();
284 double ydiffpct = -(diff.y() / m_screenSize.height());
285
286 double wn = (2 * hwn) * xdiffpct;
287 double hn = (2 * hhn) * ydiffpct;
288 double wf = (2 * hwf) * xdiffpct;
289 double hf = (2 * hhf) * ydiffpct;
290
291 // TODO: fix eye
292
293 frustum.topLeftFar = cf - (up * (hhf + hf)) - (right * (hwf + wf));
294 frustum.topRightFar = cf - (up * (hhf + hf)) + (right * (hwf + wf));
295 frustum.bottomLeftFar = cf + (up * (hhf + hf)) - (right * (hwf + wf));
296 frustum.bottomRightFar = cf + (up * (hhf + hf)) + (right * (hwf + wf));
297
298 frustum.topLeftNear = cn - (up * (hhn + hn)) - (right * (hwn + wn));
299 frustum.topRightNear = cn - (up * (hhn + hn)) + (right * (hwn + wn));
300 frustum.bottomLeftNear = cn + (up * (hhn + hn)) - (right * (hwn + wn));
301 frustum.bottomRightNear = cn + (up * (hhn + hn)) + (right * (hwn + wn));
302
303 return frustum;
304}
305
306static bool appendZIntersects(const QDoubleVector3D &start, const QDoubleVector3D &end, double z,
307 QList<QDoubleVector3D> &results)
308{
309 if (start.z() == end.z()) {
310 return false;
311 } else {
312 double f = (start.z() - z) / (start.z() - end.z());
313 if ((f >= 0) && (f <= 1.0)) {
314 results.append((1 - f) * start + f * end);
315 return true;
316 }
317 }
318 return false;
319}
320
321// Returns the intersection of the plane of the map and the camera frustum as a right handed polygon
323{
325 points.reserve(4);
326
327 // The camera is always upright. Tilting angle never reach 90degrees.
328 // Meaning: bottom frustum edges always intersect the map plane, top ones may not.
329
330 // Top Right
331 if (!appendZIntersects(frustum.apex, frustum.topRightFar, 0.0, points))
332 appendZIntersects(frustum.topRightFar, frustum.bottomRightFar, 0.0, points);
333
334 // Bottom Right
335 appendZIntersects(frustum.apex, frustum.bottomRightFar, 0.0, points);
336
337 // Bottom Left
338 appendZIntersects(frustum.apex, frustum.bottomLeftFar, 0.0, points);
339
340 // Top Left
341 if (!appendZIntersects(frustum.apex, frustum.topLeftFar, 0.0, points))
342 appendZIntersects(frustum.topLeftFar, frustum.bottomLeftFar, 0.0, points);
343
344 return points;
345}
346
347QPair<PolygonVector, PolygonVector> QGeoCameraTilesPrivate::splitPolygonAtAxisValue(const PolygonVector &polygon, int axis, double value) const
348{
349 PolygonVector polygonBelow;
350 PolygonVector polygonAbove;
351
352 const qsizetype size = polygon.size();
353
354 if (size == 0)
355 return QPair<PolygonVector, PolygonVector>(polygonBelow, polygonAbove);
356
357 QList<int> comparisons(polygon.size());
358
359 for (qsizetype i = 0; i < size; ++i) {
360 const double v = polygon.at(i).get(axis);
361 if (qFuzzyCompare(v - value + 1.0, 1.0)) {
362 comparisons[i] = 0;
363 } else {
364 if (v < value) {
365 comparisons[i] = -1;
366 } else if (value < v) {
367 comparisons[i] = 1;
368 }
369 }
370 }
371
372 for (qsizetype index = 0; index < size; ++index) {
373 qsizetype prevIndex = index - 1;
374 if (prevIndex < 0)
375 prevIndex += size;
376 const qsizetype nextIndex = (index + 1) % size;
377
378 int prevComp = comparisons[prevIndex];
379 int comp = comparisons[index];
380 int nextComp = comparisons[nextIndex];
381
382 if (comp == 0) {
383 if (prevComp == -1) {
384 polygonBelow.append(polygon.at(index));
385 if (nextComp == 1) {
386 polygonAbove.append(polygon.at(index));
387 }
388 } else if (prevComp == 1) {
389 polygonAbove.append(polygon.at(index));
390 if (nextComp == -1) {
391 polygonBelow.append(polygon.at(index));
392 }
393 } else if (prevComp == 0) {
394 if (nextComp == -1) {
395 polygonBelow.append(polygon.at(index));
396 } else if (nextComp == 1) {
397 polygonAbove.append(polygon.at(index));
398 } else if (nextComp == 0) {
399 // do nothing
400 }
401 }
402 } else {
403 if (comp == -1) {
404 polygonBelow.append(polygon.at(index));
405 } else if (comp == 1) {
406 polygonAbove.append(polygon.at(index));
407 }
408
409 // there is a point between this and the next point
410 // on the polygon that lies on the splitting line
411 // and should be added to both the below and above
412 // polygons
413 if ((nextComp != 0) && (nextComp != comp)) {
415 QDoubleVector3D p2 = polygon.at(nextIndex);
416
417 double p1v = p1.get(axis);
418 double p2v = p2.get(axis);
419
420 double f = (p1v - value) / (p1v - p2v);
421
422 if (((0 <= f) && (f <= 1.0))
423 || qFuzzyCompare(f + 1.0, 1.0)
424 || qFuzzyCompare(f + 1.0, 2.0) ) {
425 QDoubleVector3D midPoint = (1.0 - f) * p1 + f * p2;
426 polygonBelow.append(midPoint);
427 polygonAbove.append(midPoint);
428 }
429 }
430 }
431 }
432
433 return QPair<PolygonVector, PolygonVector>(polygonBelow, polygonAbove);
434}
435
436static void addXOffset(PolygonVector &footprint, double xoff)
437{
438 for (QDoubleVector3D &v: footprint)
439 v.setX(v.x() + xoff);
440}
441
443{
444 bool clipX0 = false;
445 bool clipX1 = false;
446 bool clipY0 = false;
447 bool clipY1 = false;
448
449 double side = 1.0 * m_sideLength;
450 double minX = std::numeric_limits<double>::max();
451 double maxX = std::numeric_limits<double>::lowest();
452
453 for (const QDoubleVector3D &p: footprint) {
454 if (p.y() < 0.0)
455 clipY0 = true;
456 if (p.y() > side)
457 clipY1 = true;
458 }
459
460 PolygonVector results = footprint;
461
462 if (clipY0)
463 results = splitPolygonAtAxisValue(results, 1, 0.0).second;
464
465 if (clipY1)
466 results = splitPolygonAtAxisValue(results, 1, side).first;
467
468 for (const QDoubleVector3D &p : std::as_const(results)) {
469 if ((p.x() < 0.0) || (qFuzzyIsNull(p.x())))
470 clipX0 = true;
471 if ((p.x() > side) || (qFuzzyCompare(side, p.x())))
472 clipX1 = true;
473 }
474
475 for (const QDoubleVector3D &v : std::as_const(results)) {
476 minX = qMin(v.x(), minX);
477 maxX = qMax(v.x(), maxX);
478 }
479
480 double footprintWidth = maxX - minX;
481
482 if (clipX0) {
483 if (clipX1) {
484 if (footprintWidth > side) {
485 PolygonVector rightPart = splitPolygonAtAxisValue(results, 0, side).second;
486 addXOffset(rightPart, -side);
487 rightPart = splitPolygonAtAxisValue(rightPart, 0, side).first; // clip it again, should it tend to infinite or so
488
489 PolygonVector leftPart = splitPolygonAtAxisValue(results, 0, 0).first;
490 addXOffset(leftPart, side);
491 leftPart = splitPolygonAtAxisValue(leftPart, 0, 0).second; // same here
492
493 results = splitPolygonAtAxisValue(results, 0, 0.0).second;
494 results = splitPolygonAtAxisValue(results, 0, side).first;
495 return ClippedFootprint(leftPart, results, rightPart);
496 } else { // fitting the WebMercator square exactly?
497 results = splitPolygonAtAxisValue(results, 0, 0.0).second;
498 results = splitPolygonAtAxisValue(results, 0, side).first;
500 }
501 } else {
502 QPair<PolygonVector, PolygonVector> pair = splitPolygonAtAxisValue(results, 0, 0.0);
503 if (pair.first.isEmpty()) {
504 // if we touched the line but didn't cross it...
505 for (const auto &v : std::as_const(pair.second)) {
506 if (qFuzzyIsNull(v.x()))
507 pair.first.append(v);
508 }
509 if (pair.first.size() == 2) {
510 double y0 = pair.first[0].y();
511 double y1 = pair.first[1].y();
512 pair.first.clear();
513 pair.first.append(QDoubleVector3D(side, y0, 0.0));
514 pair.first.append(QDoubleVector3D(side - 0.001, y0, 0.0));
515 pair.first.append(QDoubleVector3D(side - 0.001, y1, 0.0));
516 pair.first.append(QDoubleVector3D(side, y1, 0.0));
517 } else if (pair.first.size() == 1) {
518 // FIXME this is trickier
519 // - touching at one point on the tile boundary
520 // - probably need to build a triangular polygon across the edge
521 // - don't want to add another y tile if we can help it
522 // - initial version doesn't care
523 double y = pair.first.at(0).y();
524 pair.first.clear();
525 pair.first.append(QDoubleVector3D(side - 0.001, y, 0.0));
526 pair.first.append(QDoubleVector3D(side, y + 0.001, 0.0));
527 pair.first.append(QDoubleVector3D(side, y - 0.001, 0.0));
528 }
529 } else {
530 addXOffset(pair.first, side);
531 if (footprintWidth > side)
532 pair.first = splitPolygonAtAxisValue(pair.first, 0, 0).second;
533 }
534 return ClippedFootprint(pair.first, pair.second, PolygonVector());
535 }
536 } else {
537 if (clipX1) {
538 QPair<PolygonVector, PolygonVector> pair = splitPolygonAtAxisValue(results, 0, side);
539 if (pair.second.isEmpty()) {
540 // if we touched the line but didn't cross it...
541 for (const auto &v : std::as_const(pair.first)) {
542 if (qFuzzyCompare(side, v.x()))
543 pair.second.append(v);
544 }
545 if (pair.second.size() == 2) {
546 double y0 = pair.second[0].y();
547 double y1 = pair.second[1].y();
548 pair.second.clear();
549 pair.second.append(QDoubleVector3D(0, y0, 0.0));
550 pair.second.append(QDoubleVector3D(0.001, y0, 0.0));
551 pair.second.append(QDoubleVector3D(0.001, y1, 0.0));
552 pair.second.append(QDoubleVector3D(0, y1, 0.0));
553 } else if (pair.second.size() == 1) {
554 // FIXME this is trickier
555 // - touching at one point on the tile boundary
556 // - probably need to build a triangular polygon across the edge
557 // - don't want to add another y tile if we can help it
558 // - initial version doesn't care
559 double y = pair.second.at(0).y();
560 pair.second.clear();
561 pair.second.append(QDoubleVector3D(0.001, y, 0.0));
562 pair.second.append(QDoubleVector3D(0.0, y - 0.001, 0.0));
563 pair.second.append(QDoubleVector3D(0.0, y + 0.001, 0.0));
564 }
565 } else {
566 addXOffset(pair.second, -side);
567 if (footprintWidth > side)
568 pair.second = splitPolygonAtAxisValue(pair.second, 0, side).first;
569 }
570 return ClippedFootprint(PolygonVector(), pair.first, pair.second);
571 } else {
573 }
574 }
575
576}
577
578QList<QPair<double, int>> QGeoCameraTilesPrivate::tileIntersections(double p1, int t1, double p2, int t2) const
579{
580 if (t1 == t2) {
581 QList<QPair<double, int>> results = QList<QPair<double, int>>();
582 results.append(QPair<double, int>(0.0, t1));
583 return results;
584 }
585
586 int step = 1;
587 if (t1 > t2)
588 step = -1;
589
590 qsizetype size = 1 + ((t2 - t1) / step);
591
592 QList<QPair<double, int>> results = { QPair<double, int>(0.0, t1) };
593
594 if (step == 1) {
595 for (qsizetype i = 1; i < size; ++i) {
596 double f = (t1 + i - p1) / (p2 - p1);
597 results.append(QPair<double, int>(f, t1 + i));
598 }
599 } else {
600 for (qsizetype i = 1; i < size; ++i) {
601 double f = (t1 - i + 1 - p1) / (p2 - p1);
602 results.append(QPair<double, int>(f, t1 - i));
603 }
604 }
605
606 return results;
607}
608
610{
611 const qsizetype numPoints = polygon.size();
612
613 if (numPoints == 0)
614 return QSet<QGeoTileSpec>();
615
616 QList<int> tilesX(polygon.size());
617 QList<int> tilesY(polygon.size());
618
619 // grab tiles at the corners of the polygon
620 for (qsizetype i = 0; i < numPoints; ++i) {
621
622 const QDoubleVector2D p = polygon.at(i).toVector2D();
623
624 int x = 0;
625 int y = 0;
626
627 if (qFuzzyCompare(p.x(), m_sideLength * 1.0))
628 x = m_sideLength - 1;
629 else {
630 x = static_cast<int>(p.x()) % m_sideLength;
631 if ( !qFuzzyCompare(p.x(), 1.0 * x) && qFuzzyCompare(p.x(), 1.0 * (x + 1)) )
632 x++;
633 }
634
635 if (qFuzzyCompare(p.y(), m_sideLength * 1.0))
636 y = m_sideLength - 1;
637 else {
638 y = static_cast<int>(p.y()) % m_sideLength;
639 if ( !qFuzzyCompare(p.y(), 1.0 * y) && qFuzzyCompare(p.y(), 1.0 * (y + 1)) )
640 y++;
641 }
642
643 tilesX[i] = x;
644 tilesY[i] = y;
645 }
646
648
649 // walk along the edges of the polygon and add all tiles covered by them
650 for (qsizetype i1 = 0; i1 < numPoints; ++i1) {
651 const qsizetype i2 = (i1 + 1) % numPoints;
652
653 const double x1 = polygon.at(i1).get(0);
654 const double x2 = polygon.at(i2).get(0);
655
656 const bool xFixed = qFuzzyCompare(x1, x2);
657 const bool xIntegral = qFuzzyCompare(x1, std::floor(x1)) || qFuzzyCompare(x1 + 1.0, std::floor(x1 + 1.0));
658
659 QList<QPair<double, int> > xIntersects
661 tilesX.at(i1),
662 x2,
663 tilesX.at(i2));
664
665 const double y1 = polygon.at(i1).get(1);
666 const double y2 = polygon.at(i2).get(1);
667
668 const bool yFixed = qFuzzyCompare(y1, y2);
669 const bool yIntegral = qFuzzyCompare(y1, std::floor(y1)) || qFuzzyCompare(y1 + 1.0, std::floor(y1 + 1.0));
670
671 QList<QPair<double, int> > yIntersects
673 tilesY.at(i1),
674 y2,
675 tilesY.at(i2));
676
677 int x = xIntersects.takeFirst().second;
678 int y = yIntersects.takeFirst().second;
679
680
681 /*
682 If the polygon coincides with the tile edges we must be
683 inclusive and grab all tiles on both sides. We also need
684 to handle tiles with corners coindent with the
685 corners of the polygon.
686 e.g. all tiles marked with 'x' will be added
687
688 "+" - tile boundaries
689 "O" - polygon boundary
690
691 + + + + + + + + + + + + + + + + + + + + +
692 + + + + + +
693 + + x + x + x + +
694 + + + + + +
695 + + + + + + + + O O O O O + + + + + + + +
696 + + O 0 + +
697 + + x O x 0 x + +
698 + + O 0 + +
699 + + + + + + + + O 0 0 0 0 + + + + + + + +
700 + + + + + +
701 + + x + x + x + +
702 + + + + + +
703 + + + + + + + + + + + + + + + + + + + + +
704 */
705
706
707 int xOther = x;
708 int yOther = y;
709
710 if (xFixed && xIntegral) {
711 if (y2 < y1) {
712 xOther = qMax(0, x - 1);
713 }
714 }
715
716 if (yFixed && yIntegral) {
717 if (x1 < x2) {
718 yOther = qMax(0, y - 1);
719
720 }
721 }
722
723 if (xIntegral) {
724 map.add(xOther, y);
725 if (yIntegral)
726 map.add(xOther, yOther);
727
728 }
729
730 if (yIntegral)
731 map.add(x, yOther);
732
733 map.add(x,y);
734
735 // top left corner
736 const qsizetype iPrev = (i1 + numPoints - 1) % numPoints;
737 const double xPrevious = polygon.at(iPrev).get(0);
738 const double yPrevious = polygon.at(iPrev).get(1);
739 const bool xPreviousFixed = qFuzzyCompare(xPrevious, x1);
740 if (xIntegral && xPreviousFixed && yIntegral && yFixed) {
741 if ((x2 > x1) && (yPrevious > y1)) {
742 if ((x - 1) > 0 && (y - 1) > 0)
743 map.add(x - 1, y - 1);
744 } else if ((x2 < x1) && (yPrevious < y1)) {
745 // what?
746 }
747 }
748
749 // for the simple case where intersections do not coincide with
750 // the boundaries, we move along the edge and add tiles until
751 // the x and y intersection lists are exhausted
752
753 while (!xIntersects.isEmpty() && !yIntersects.isEmpty()) {
754 const QPair<double, int> nextX = xIntersects.first();
755 const QPair<double, int> nextY = yIntersects.first();
756 if (nextX.first < nextY.first) {
757 x = nextX.second;
758 map.add(x, y);
759 xIntersects.removeFirst();
760
761 } else if (nextX.first > nextY.first) {
762 y = nextY.second;
763 map.add(x, y);
764 yIntersects.removeFirst();
765
766 } else {
767 map.add(x, nextY.second);
768 map.add(nextX.second, y);
769 x = nextX.second;
770 y = nextY.second;
771 map.add(x, y);
772 xIntersects.removeFirst();
773 yIntersects.removeFirst();
774 }
775 }
776
777 while (!xIntersects.isEmpty()) {
778 x = xIntersects.takeFirst().second;
779 map.add(x, y);
780 if (yIntegral && yFixed)
781 map.add(x, yOther);
782
783 }
784
785 while (!yIntersects.isEmpty()) {
786 y = yIntersects.takeFirst().second;
787 map.add(x, y);
788 if (xIntegral && xFixed)
789 map.add(xOther, y);
790 }
791 }
792
793 QSet<QGeoTileSpec> results;
794
795 const int z = m_intZoomLevel;
796 for (auto i = map.data.constBegin(); i != map.data.constEnd(); ++i) {
797 int y = i.key();
798 int minX = i->first;
799 int maxX = i->second;
800 for (int x = minX; x <= maxX; ++x)
802 }
803
804 return results;
805}
806
808
809void QGeoCameraTilesPrivate::TileMap::add(int tileX, int tileY)
810{
811 if (data.contains(tileY)) {
812 int oldMinX = data.value(tileY).first;
813 int oldMaxX = data.value(tileY).second;
814 data.insert(tileY, QPair<int, int>(qMin(tileX, oldMinX), qMax(tileX, oldMaxX)));
815 } else {
816 data.insert(tileY, QPair<int, int>(tileX, tileX));
817 }
818}
819
static QDoubleVector3D normal(const QDoubleVector3D &v1, const QDoubleVector3D &v2)
double zoomLevel() const
double tilt() const
double fieldOfView() const
double bearing() const
QGeoCoordinate center() const
PolygonVector frustumFootprint(const Frustum &frustum) const
Frustum createFrustum(double viewExpansion) const
QSet< QGeoTileSpec > tilesFromPolygon(const PolygonVector &polygon) const
QList< QPair< double, int > > tileIntersections(double p1, int t1, double p2, int t2) const
QPair< PolygonVector, PolygonVector > splitPolygonAtAxisValue(const PolygonVector &polygon, int axis, double value) const
ClippedFootprint clipFootprintToMap(const PolygonVector &footprint) const
QSet< QGeoTileSpec > m_tiles
void setMapType(const QGeoMapType &mapType)
const QSet< QGeoTileSpec > & createTiles()
void setMapVersion(int mapVersion)
QGeoCameraData cameraData() const
QGeoMapType activeMapType() const
std::unique_ptr< QGeoCameraTilesPrivate > d_ptr
void setScreenSize(const QSize &size)
void setViewExpansion(double viewExpansion)
void setTileSize(int tileSize)
void setCameraData(const QGeoCameraData &camera)
void setPluginString(const QString &pluginString)
void setVisibleArea(const QRectF &visibleArea)
int mapId() const
T & first()
Definition qlist.h:645
iterator insert(qsizetype i, parameter_type t)
Definition qlist.h:488
T value(qsizetype i) const
Definition qlist.h:664
void reserve(qsizetype size)
Definition qlist.h:753
void append(parameter_type t)
Definition qlist.h:458
static double radians(double degrees)
T & first()
Definition qmap.h:419
const_iterator constBegin() const
Definition qmap.h:600
const_iterator constEnd() const
Definition qmap.h:604
The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
Definition qmatrix4x4.h:25
void rotate(float angle, const QVector3D &vector)
Multiples this matrix by another that rotates coordinates through angle degrees about vector.
\inmodule QtCore\reentrant
Definition qpoint.h:217
constexpr qreal x() const noexcept
Returns the x coordinate of this point.
Definition qpoint.h:343
constexpr qreal y() const noexcept
Returns the y coordinate of this point.
Definition qpoint.h:348
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr bool isNull() const noexcept
Returns true if the rectangle is a null rectangle, otherwise returns false.
Definition qrect.h:658
constexpr QPointF center() const noexcept
Returns the center point of the rectangle.
Definition qrect.h:699
const_iterator constBegin() const noexcept
Definition qset.h:139
const_iterator constEnd() const noexcept
Definition qset.h:143
void clear()
Definition qset.h:61
QSet< T > & unite(const QSet< T > &other)
Definition qset.h:229
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
QString first(qsizetype n) const &
Definition qstring.h:390
The QVector3D class represents a vector or vertex in 3D space.
Definition qvectornd.h:171
static QDoubleVector2D coordToMercator(const QGeoCoordinate &coord)
QCamera * camera
Definition camera.cpp:19
QMap< QString, QString > map
[6]
QPixmap p2
QPixmap p1
[0]
Combined button and popup list for selecting options.
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter * iter
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
bool qFuzzyIsNull(qfloat16 f) noexcept
Definition qfloat16.h:349
static QDoubleVector3D toDoubleVector3D(const QVector3D &in)
static bool appendZIntersects(const QDoubleVector3D &start, const QDoubleVector3D &end, double z, QList< QDoubleVector3D > &results)
static QVector3D toVector3D(const QDoubleVector3D &in)
static void addXOffset(PolygonVector &footprint, double xoff)
QList< QDoubleVector3D > PolygonVector
static QT_BEGIN_NAMESPACE const int tileSize
Definition qmemrotate.cpp:9
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
GLsizei const GLfloat * v
[13]
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat z
GLint GLint GLint GLint GLint x
[0]
GLuint GLfloat GLfloat GLfloat GLfloat y1
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLuint index
[2]
GLuint GLuint end
GLuint GLfloat GLfloat GLfloat x1
GLdouble GLdouble right
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLfloat GLfloat f
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat t1
[4]
GLuint start
GLuint GLfloat GLfloat y0
GLint y
GLfloat GLfloat GLfloat GLfloat maxX
GLfixed GLfixed GLint GLint GLfixed points
GLfixed GLfixed GLfixed y2
GLfixed GLfixed x2
GLuint in
GLfloat GLfloat p
[1]
#define t2
#define t1
QScreen * screen
[1]
Definition main.cpp:29
ptrdiff_t qsizetype
Definition qtypes.h:165
QQuickView * view
[0]
QDoubleVector3D topRightFar
QDoubleVector3D topRightNear
QDoubleVector3D bottomLeftNear
QDoubleVector3D topLeftNear
QDoubleVector3D bottomLeftFar
QDoubleVector3D bottomRightFar
QDoubleVector3D topLeftFar
QDoubleVector3D bottomRightNear
QDoubleVector3D apex
void add(int tileX, int tileY)