summaryrefslogtreecommitdiffstats
path: root/src/location/declarativemaps
diff options
context:
space:
mode:
authorPaolo Angelelli <paolo.angelelli@qt.io>2017-07-07 15:31:00 +0200
committerPaolo Angelelli <paolo.angelelli@qt.io>2017-07-17 12:40:42 +0000
commit2ab93acd9751b3ffe2c36a4a0e37dc792686a08f (patch)
tree59070747c2225f76754cf292e15ed29b30141d85 /src/location/declarativemaps
parentb02916a5568d57eda767ca930dcdb366179250bc (diff)
Fix dragging items out of map bounds
In 5.9.0 map items are clipped against the visible region. This implies that their geometry is also clipped against the visible region. This is problematic in ::geometryChanged, since the old geometry is always clipped in this way. This patch clips items against a "projectable" region instead, that is the part of the map that is in front of the camera. Since this can produce very large vertices, mapbox earcut 3rd party library is pulled in, to replace qTriangulate that only supports coordinates up to 1<<21. Task-number: QTBUG-61727 Change-Id: I7449e755a4848a2b2107c5de4e27821e3e887bfb Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
Diffstat (limited to 'src/location/declarativemaps')
-rw-r--r--src/location/declarativemaps/qdeclarativepolygonmapitem.cpp53
-rw-r--r--src/location/declarativemaps/qdeclarativepolylinemapitem.cpp2
2 files changed, 38 insertions, 17 deletions
diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
index daa1a9fc..3218f9f1 100644
--- a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp
@@ -53,6 +53,8 @@
/* poly2tri triangulator includes */
#include <clip2tri.h>
+#include <earcut.hpp>
+#include <array>
QT_BEGIN_NAMESPACE
@@ -185,7 +187,7 @@ void QGeoMapPolygonGeometry::updateSourcePoints(const QGeoMap &map,
// 2)
QList<QList<QDoubleVector2D> > clippedPaths;
- const QList<QDoubleVector2D> &visibleRegion = map.geoProjection().visibleRegion();
+ const QList<QDoubleVector2D> &visibleRegion = map.geoProjection().projectableRegion();
if (visibleRegion.size()) {
c2t::clip2tri clipper;
clipper.addSubjectPath(QClipperUtils::qListToPath(wrappedPath), true);
@@ -306,23 +308,42 @@ void QGeoMapPolygonGeometry::updateScreenPoints(const QGeoMap &map)
screenOutline_ = ppi;
- QTriangleSet ts = qTriangulate(ppi);
- qreal *vx = ts.vertices.data();
-
- screenIndices_.reserve(ts.indices.size());
- screenVertices_.reserve(ts.vertices.size());
+ using Coord = double;
+ using N = uint32_t;
+ using Point = std::array<Coord, 2>;
+
+ std::vector<std::vector<Point>> polygon;
+ polygon.push_back(std::vector<Point>());
+ std::vector<Point> &poly = polygon.front();
+ // ... fill polygon structure with actual data
+
+ for (int i = 0; i < ppi.elementCount(); ++i) {
+ const QPainterPath::Element e = ppi.elementAt(i);
+ if (e.isMoveTo() || i == ppi.elementCount() - 1
+ || (qAbs(e.x - poly.front()[0]) < 0.1
+ && qAbs(e.y - poly.front()[1]) < 0.1)) {
+ Point p = { e.x, e.y };
+ poly.push_back( p );
+ } else if (e.isLineTo()) {
+ Point p = { e.x, e.y };
+ poly.push_back( p );
+ } else {
+ qWarning("Unhandled element type in polygon painterpath");
+ }
+ }
- if (ts.indices.type() == QVertexIndexVector::UnsignedInt) {
- const quint32 *ix = reinterpret_cast<const quint32 *>(ts.indices.data());
- for (int i = 0; i < (ts.indices.size()/3*3); ++i)
- screenIndices_ << ix[i];
- } else {
- const quint16 *ix = reinterpret_cast<const quint16 *>(ts.indices.data());
- for (int i = 0; i < (ts.indices.size()/3*3); ++i)
- screenIndices_ << ix[i];
+ if (poly.size() > 2) {
+ // Run tessellation
+ // Returns array of indices that refer to the vertices of the input polygon.
+ // Three subsequent indices form a triangle.
+ screenVertices_.clear();
+ screenIndices_.clear();
+ for (const auto &p : poly)
+ screenVertices_ << QPointF(p[0], p[1]);
+ std::vector<N> indices = mapbox::earcut<N>(polygon);
+ for (const auto &i: indices)
+ screenIndices_ << quint32(i);
}
- for (int i = 0; i < (ts.vertices.size()/2*2); i += 2)
- screenVertices_ << QPointF(vx[i], vx[i + 1]);
screenBounds_ = ppi.boundingRect();
}
diff --git a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
index aedb9811..26f030b0 100644
--- a/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
+++ b/src/location/declarativemaps/qdeclarativepolylinemapitem.cpp
@@ -226,7 +226,7 @@ QList<QList<QDoubleVector2D> > QGeoMapPolylineGeometry::clipPath(const QGeoMap &
// 2)
QList<QList<QDoubleVector2D> > clippedPaths;
- const QList<QDoubleVector2D> &visibleRegion = map.geoProjection().visibleRegion();
+ const QList<QDoubleVector2D> &visibleRegion = map.geoProjection().projectableRegion();
if (visibleRegion.size()) {
c2t::clip2tri clipper;
clipper.addSubjectPath(QClipperUtils::qListToPath(wrappedPath), false);