201Frustum QGeoCameraTilesPrivate::createFrustum(
double viewExpansion)
const
203 double apertureSize = 1.0;
204 if (m_camera.fieldOfView() != 90.0)
205 apertureSize = tan(QLocationUtils::radians(m_camera.fieldOfView()) * 0.5);
206 QDoubleVector3D center = m_sideLength * QWebMercator::coordToMercator(m_camera.center());
207#ifdef QT_LOCATION_DEBUG
208 m_createFrustum_center = center;
212 double f = m_screenSize.height();
214 double z = std::pow(2.0, m_camera.zoomLevel() - m_intZoomLevel) * m_tileSize;
216 double altitude = (f / (2.0 * z)) / apertureSize;
217 QDoubleVector3D eye = center;
220 QDoubleVector3D view = eye - center;
221 QDoubleVector3D side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0));
222 QDoubleVector3D up = QDoubleVector3D::normal(side, view);
227 mBearing.rotate(1.0 * m_camera.bearing(), toVector3D(view));
228 up = toDoubleVector3D(mBearing.map(toVector3D(up)));
231 QDoubleVector3D side2 = QDoubleVector3D::normal(up, view);
233 mTilt.rotate(-1.0 * m_camera.tilt(), toVector3D(side2));
234 eye = toDoubleVector3D((mTilt.map(toVector3D(view))) + toVector3D(center));
237 side = QDoubleVector3D::normal(view, QDoubleVector3D(0.0, 1.0, 0.0));
238 up = QDoubleVector3D::normal(view, side2);
240 double nearPlane = 1.0 / 32.0;
244 double farPlane = altitude + 8.0;
246 double aspectRatio = 1.0 * m_screenSize.width() / m_screenSize.height();
249 double hhn,hwn,hhf,hwf = 0.0;
253 viewExpansion *= apertureSize;
255 hhn = viewExpansion * nearPlane;
256 hwn = hhn * aspectRatio;
258 hhf = viewExpansion * farPlane;
259 hwf = hhf * aspectRatio;
261 QDoubleVector3D d = center - eye;
264 QDoubleVector3D right = QDoubleVector3D::normal(d, up);
266 QDoubleVector3D cf = eye + d * farPlane;
267 QDoubleVector3D cn = eye + d * nearPlane;
272#ifdef QT_LOCATION_DEBUG
273 m_createFrustum_eye = eye;
276 QRectF va = m_visibleArea;
278 va = QRectF(0, 0, m_screenSize.width(), m_screenSize.height());
279 QRectF screen = QRectF(QPointF(0,0),m_screenSize);
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());
286 double wn = (2 * hwn) * xdiffpct;
287 double hn = (2 * hhn) * ydiffpct;
288 double wf = (2 * hwf) * xdiffpct;
289 double hf = (2 * hhf) * ydiffpct;
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));
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));
347QPair<PolygonVector, PolygonVector> QGeoCameraTilesPrivate::splitPolygonAtAxisValue(
const PolygonVector &polygon,
int axis,
double value)
const
349 PolygonVector polygonBelow;
350 PolygonVector polygonAbove;
352 const qsizetype size = polygon.size();
355 return QPair<PolygonVector, PolygonVector>(polygonBelow, polygonAbove);
357 QList<
int> comparisons(polygon.size());
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)) {
366 }
else if (value < v) {
372 for (qsizetype index = 0; index < size; ++index) {
373 qsizetype prevIndex = index - 1;
376 const qsizetype nextIndex = (index + 1) % size;
378 int prevComp = comparisons[prevIndex];
379 int comp = comparisons[index];
380 int nextComp = comparisons[nextIndex];
383 if (prevComp == -1) {
384 polygonBelow.append(polygon.at(index));
386 polygonAbove.append(polygon.at(index));
388 }
else if (prevComp == 1) {
389 polygonAbove.append(polygon.at(index));
390 if (nextComp == -1) {
391 polygonBelow.append(polygon.at(index));
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) {
404 polygonBelow.append(polygon.at(index));
405 }
else if (comp == 1) {
406 polygonAbove.append(polygon.at(index));
413 if ((nextComp != 0) && (nextComp != comp)) {
414 QDoubleVector3D p1 = polygon.at(index);
415 QDoubleVector3D p2 = polygon.at(nextIndex);
417 double p1v = p1.get(axis);
418 double p2v = p2.get(axis);
420 double f = (p1v - value) / (p1v - p2v);
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);
433 return QPair<PolygonVector, PolygonVector>(polygonBelow, polygonAbove);
442QGeoCameraTilesPrivate::ClippedFootprint QGeoCameraTilesPrivate::clipFootprintToMap(
const PolygonVector &footprint)
const
449 double side = 1.0 * m_sideLength;
450 double minX = std::numeric_limits<
double>::max();
451 double maxX = std::numeric_limits<
double>::lowest();
453 for (
const QDoubleVector3D &p: footprint) {
460 PolygonVector results = footprint;
463 results = splitPolygonAtAxisValue(results, 1, 0.0).second;
466 results = splitPolygonAtAxisValue(results, 1, side).first;
468 for (
const QDoubleVector3D &p : std::as_const(results)) {
469 if ((p.x() < 0.0) || (qFuzzyIsNull(p.x())))
471 if ((p.x() > side) || (qFuzzyCompare(side, p.x())))
475 for (
const QDoubleVector3D &v : std::as_const(results)) {
476 minX = qMin(v.x(), minX);
477 maxX = qMax(v.x(), maxX);
480 double footprintWidth = maxX - minX;
484 if (footprintWidth > side) {
485 PolygonVector rightPart = splitPolygonAtAxisValue(results, 0, side).second;
486 addXOffset(rightPart, -side);
487 rightPart = splitPolygonAtAxisValue(rightPart, 0, side).first;
489 PolygonVector leftPart = splitPolygonAtAxisValue(results, 0, 0).first;
490 addXOffset(leftPart, side);
491 leftPart = splitPolygonAtAxisValue(leftPart, 0, 0).second;
493 results = splitPolygonAtAxisValue(results, 0, 0.0).second;
494 results = splitPolygonAtAxisValue(results, 0, side).first;
495 return ClippedFootprint(leftPart, results, rightPart);
497 results = splitPolygonAtAxisValue(results, 0, 0.0).second;
498 results = splitPolygonAtAxisValue(results, 0, side).first;
499 return ClippedFootprint(PolygonVector(), results, PolygonVector());
502 QPair<PolygonVector, PolygonVector> pair = splitPolygonAtAxisValue(results, 0, 0.0);
503 if (pair.first.isEmpty()) {
505 for (
const auto &v : std::as_const(pair.second)) {
506 if (qFuzzyIsNull(v.x()))
507 pair.first.append(v);
509 if (pair.first.size() == 2) {
510 double y0 = pair.first[0].y();
511 double y1 = pair.first[1].y();
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) {
523 double y = pair.first.at(0).y();
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));
530 addXOffset(pair.first, side);
531 if (footprintWidth > side)
532 pair.first = splitPolygonAtAxisValue(pair.first, 0, 0).second;
534 return ClippedFootprint(pair.first, pair.second, PolygonVector());
538 QPair<PolygonVector, PolygonVector> pair = splitPolygonAtAxisValue(results, 0, side);
539 if (pair.second.isEmpty()) {
541 for (
const auto &v : std::as_const(pair.first)) {
542 if (qFuzzyCompare(side, v.x()))
543 pair.second.append(v);
545 if (pair.second.size() == 2) {
546 double y0 = pair.second[0].y();
547 double y1 = pair.second[1].y();
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) {
559 double y = pair.second.at(0).y();
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));
566 addXOffset(pair.second, -side);
567 if (footprintWidth > side)
568 pair.second = splitPolygonAtAxisValue(pair.second, 0, side).first;
570 return ClippedFootprint(PolygonVector(), pair.first, pair.second);
572 return ClippedFootprint(PolygonVector(), results, PolygonVector());
609QSet<QGeoTileSpec> QGeoCameraTilesPrivate::tilesFromPolygon(
const PolygonVector &polygon)
const
611 const qsizetype numPoints = polygon.size();
614 return QSet<QGeoTileSpec>();
616 QList<
int> tilesX(polygon.size());
617 QList<
int> tilesY(polygon.size());
620 for (qsizetype i = 0; i < numPoints; ++i) {
622 const QDoubleVector2D p = polygon.at(i).toVector2D();
627 if (qFuzzyCompare(p.x(), m_sideLength * 1.0))
628 x = m_sideLength - 1;
630 x =
static_cast<
int>(p.x()) % m_sideLength;
631 if ( !qFuzzyCompare(p.x(), 1.0 * x) && qFuzzyCompare(p.x(), 1.0 * (x + 1)) )
635 if (qFuzzyCompare(p.y(), m_sideLength * 1.0))
636 y = m_sideLength - 1;
638 y =
static_cast<
int>(p.y()) % m_sideLength;
639 if ( !qFuzzyCompare(p.y(), 1.0 * y) && qFuzzyCompare(p.y(), 1.0 * (y + 1)) )
647 QGeoCameraTilesPrivate::TileMap map;
650 for (qsizetype i1 = 0; i1 < numPoints; ++i1) {
651 const qsizetype i2 = (i1 + 1) % numPoints;
653 const double x1 = polygon.at(i1).get(0);
654 const double x2 = polygon.at(i2).get(0);
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));
659 QList<QPair<
double,
int> > xIntersects
660 = tileIntersections(x1,
665 const double y1 = polygon.at(i1).get(1);
666 const double y2 = polygon.at(i2).get(1);
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));
671 QList<QPair<
double,
int> > yIntersects
672 = tileIntersections(y1,
677 int x = xIntersects.takeFirst().second;
678 int y = yIntersects.takeFirst().second;
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
710 if (xFixed && xIntegral) {
712 xOther = qMax(0, x - 1);
716 if (yFixed && yIntegral) {
718 yOther = qMax(0, y - 1);
726 map.add(xOther, yOther);
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)) {
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) {
759 xIntersects.removeFirst();
761 }
else if (nextX.first > nextY.first) {
764 yIntersects.removeFirst();
767 map.add(x, nextY.second);
768 map.add(nextX.second, y);
772 xIntersects.removeFirst();
773 yIntersects.removeFirst();
777 while (!xIntersects.isEmpty()) {
778 x = xIntersects.takeFirst().second;
780 if (yIntegral && yFixed)
785 while (!yIntersects.isEmpty()) {
786 y = yIntersects.takeFirst().second;
788 if (xIntegral && xFixed)
793 QSet<QGeoTileSpec> results;
795 const int z = m_intZoomLevel;
796 for (
auto i = map.data.constBegin(); i != map.data.constEnd(); ++i) {
799 int maxX = i->second;
800 for (
int x = minX; x <= maxX; ++x)
801 results.insert(QGeoTileSpec(m_pluginString, m_mapType.mapId(), z, x, y, m_mapVersion));