diff options
author | Paolo Angelelli <paolo.angelelli@qt.io> | 2016-12-11 20:44:17 +0100 |
---|---|---|
committer | Paolo Angelelli <paolo.angelelli@qt.io> | 2017-01-26 14:45:48 +0000 |
commit | c57d42b47004623db9b934d0688180ec6dc1a73e (patch) | |
tree | ba4cd0bb2f332db2ad2ad4d144cc2fa3227f3fc2 /src/imports/location/qdeclarativerectanglemapitem.cpp | |
parent | a33f9131a3f5b07831ea9565cb0dc22e078f9475 (diff) | |
download | qtlocation-c57d42b47004623db9b934d0688180ec6dc1a73e.tar.gz |
Add clipping for rotated/tilted Map Items
This patch adds proper rotation/tilting support to Map Items.
To do so, clipping is now performed in wrapped mercator space
instead of screen space.
This prevents projection of geo coordinates that ended behind
the camera, and that would be projected incorrectly by the
projection transformation.
This patch therefore does not use the screen clipping code
any longer (clipPathToRect), since the geometry has already
been clipped.
The downside is that updateSourcePoints is now necessary for
any viewport change.
This would be necessary anyway in presence of tilt or rotation.
NB: Handling of MapQuickItems with zoomLevel set is still TODO.
Future work:
1) Optimize updateSourcePoints by pre-computing the mercator
projection of the geometry, and let updateSourcePoints do only
the wrapping/clipping/projection-to-screen operations.
2) Remove updateScreenPoints altogether
Change-Id: Ie0d3dbef68d48ac97a596d40240d0ac126c0efaf
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
Reviewed-by: Eskil Abrahamsen Blomfeldt <eskil.abrahamsen-blomfeldt@qt.io>
Diffstat (limited to 'src/imports/location/qdeclarativerectanglemapitem.cpp')
-rw-r--r-- | src/imports/location/qdeclarativerectanglemapitem.cpp | 128 |
1 files changed, 37 insertions, 91 deletions
diff --git a/src/imports/location/qdeclarativerectanglemapitem.cpp b/src/imports/location/qdeclarativerectanglemapitem.cpp index a3b8db90..5b6a8914 100644 --- a/src/imports/location/qdeclarativerectanglemapitem.cpp +++ b/src/imports/location/qdeclarativerectanglemapitem.cpp @@ -112,65 +112,6 @@ QT_BEGIN_NAMESPACE \image api-maprectangle.png */ -struct Vertex -{ - QVector2D position; -}; - -QGeoMapRectangleGeometry::QGeoMapRectangleGeometry() -{ -} - -/*! - \internal -*/ -void QGeoMapRectangleGeometry::updatePoints(const QGeoMap &map, - const QGeoCoordinate &topLeft, - const QGeoCoordinate &bottomRight) -{ - if (!screenDirty_ && !sourceDirty_) - return; - - QDoubleVector2D tl = map.geoProjection().coordinateToItemPosition(topLeft, false); - QDoubleVector2D br = map.geoProjection().coordinateToItemPosition(bottomRight, false); - - // We can get NaN if the map isn't set up correctly, or the projection - // is faulty -- probably best thing to do is abort - if (!qIsFinite(tl.x()) || !qIsFinite(tl.y())) - return; - if (!qIsFinite(br.x()) || !qIsFinite(br.y())) - return; - - if ( preserveGeometry_ ) { - double unwrapBelowX = map.geoProjection().coordinateToItemPosition(geoLeftBound_, false).x(); - if (br.x() < unwrapBelowX) - br.setX(tl.x() + screenBounds_.width()); - } - - QRectF re(tl.toPointF(), br.toPointF()); - re.translate(-1 * tl.toPointF()); - - clear(); - screenVertices_.reserve(6); - - screenVertices_ << re.topLeft(); - screenVertices_ << re.topRight(); - screenVertices_ << re.bottomLeft(); - - screenVertices_ << re.topRight(); - screenVertices_ << re.bottomLeft(); - screenVertices_ << re.bottomRight(); - - firstPointOffset_ = QPointF(0,0); - srcOrigin_ = topLeft; - screenBounds_ = re; - - screenOutline_ = QPainterPath(); - screenOutline_.addRect(re); - - geoLeftBound_ = topLeft; -} - QDeclarativeRectangleMapItem::QDeclarativeRectangleMapItem(QQuickItem *parent) : QDeclarativeGeoMapItemBase(parent), color_(Qt::transparent), dirtyMaterial_(true), updatingGeometry_(false) @@ -334,33 +275,49 @@ void QDeclarativeRectangleMapItem::updatePolish() QScopedValueRollback<bool> rollback(updatingGeometry_); updatingGeometry_ = true; - geometry_.updatePoints(*map(), topLeft_, bottomRight_); + QList<QGeoCoordinate> path; + path << topLeft_; + path << QGeoCoordinate(topLeft_.latitude(), bottomRight_.longitude()); + path << bottomRight_; + path << QGeoCoordinate(bottomRight_.latitude(), topLeft_.longitude()); + + geometry_.setPreserveGeometry(true, topLeft_); + geometry_.updateSourcePoints(*map(), path); + geometry_.updateScreenPoints(*map()); - QList<QGeoCoordinate> pathClosed; - pathClosed << topLeft_; - pathClosed << QGeoCoordinate(topLeft_.latitude(), bottomRight_.longitude()); - pathClosed << bottomRight_; - pathClosed << QGeoCoordinate(bottomRight_.latitude(), topLeft_.longitude()); - pathClosed << pathClosed.first(); + QList<QGeoMapItemGeometry *> geoms; + geoms << &geometry_; + borderGeometry_.clear(); if (border_.color() != Qt::transparent && border_.width() > 0) { - borderGeometry_.updateSourcePoints(*map(), pathClosed, topLeft_); - borderGeometry_.updateScreenPoints(*map(), border_.width()); + QList<QGeoCoordinate> closedPath = path; + closedPath << closedPath.first(); + + borderGeometry_.setPreserveGeometry(true, topLeft_); - QList<QGeoMapItemGeometry *> geoms; - geoms << &geometry_ << &borderGeometry_; - QRectF combined = QGeoMapItemGeometry::translateToCommonOrigin(geoms); + const QGeoCoordinate &geometryOrigin = geometry_.origin(); - setWidth(combined.width()); - setHeight(combined.height()); - } else { - borderGeometry_.clear(); + borderGeometry_.srcPoints_.clear(); + borderGeometry_.srcPointTypes_.clear(); - setWidth(geometry_.screenBoundingBox().width()); - setHeight(geometry_.screenBoundingBox().height()); + QDoubleVector2D borderLeftBoundWrapped; + QList<QList<QDoubleVector2D > > clippedPaths = borderGeometry_.clipPath(*map(), closedPath, borderLeftBoundWrapped); + if (clippedPaths.size()) { + borderLeftBoundWrapped = map()->geoProjection().geoToWrappedMapProjection(geometryOrigin); + borderGeometry_.pathToScreen(*map(), clippedPaths, borderLeftBoundWrapped); + borderGeometry_.updateScreenPoints(*map(), border_.width()); + + geoms << &borderGeometry_; + } else { + borderGeometry_.clear(); + } } - setPositionOnMap(pathClosed.at(0), geometry_.firstPointOffset()); + QRectF combined = QGeoMapItemGeometry::translateToCommonOrigin(geoms); + setWidth(combined.width()); + setHeight(combined.height()); + + setPositionOnMap(geometry_.origin(), geometry_.firstPointOffset()); } /*! @@ -371,21 +328,10 @@ void QDeclarativeRectangleMapItem::afterViewportChanged(const QGeoMapViewportCha if (event.mapSize.width() <= 0 || event.mapSize.height() <= 0) return; - // if the scene is tilted, we must regenerate our geometry every frame - if ((event.cameraData.tilt() > 0.0 || event.tiltChanged) && map()->cameraCapabilities().supportsTilting()) { - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - } - - // otherwise, only regen on rotate, resize and zoom - if (event.bearingChanged || event.mapSizeChanged || event.zoomLevelChanged) { - geometry_.markSourceDirty(); - borderGeometry_.markSourceDirty(); - } geometry_.setPreserveGeometry(true, topLeft_); borderGeometry_.setPreserveGeometry(true, topLeft_); - geometry_.markScreenDirty(); - borderGeometry_.markScreenDirty(); + geometry_.markSourceDirty(); + borderGeometry_.markSourceDirty(); polishAndUpdate(); } |