diff options
author | Paolo Angelelli <paolo.angelelli@qt.io> | 2017-07-07 15:31:00 +0200 |
---|---|---|
committer | Paolo Angelelli <paolo.angelelli@qt.io> | 2017-07-28 12:13:56 +0000 |
commit | 763d5977e7758adb232e1ecd091f926e6f54e75a (patch) | |
tree | dcc9ccf70b9214ba8857963750322cded5db42d2 /src/location/declarativemaps | |
parent | 3ac051c4549575634cecc706175b019f4ed4c3bf (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.
This patch also contains a fix for earcut.hpp to make it
build also on QNX6.6
Task-number: QTBUG-61727
Change-Id: Iffc95fdae88fef982c1eb86db567b326b5e51057
Reviewed-by: Ville Voutilainen <ville.voutilainen@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Paolo Angelelli <paolo.angelelli@qt.io>
Diffstat (limited to 'src/location/declarativemaps')
-rw-r--r-- | src/location/declarativemaps/qdeclarativepolygonmapitem.cpp | 53 | ||||
-rw-r--r-- | src/location/declarativemaps/qdeclarativepolylinemapitem.cpp | 2 |
2 files changed, 38 insertions, 17 deletions
diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp b/src/location/declarativemaps/qdeclarativepolygonmapitem.cpp index e2c83186..48f66423 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); @@ -270,23 +272,42 @@ void QGeoMapPolygonGeometry::updateScreenPoints(const QGeoMap &map) ppi.closeSubpath(); 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 3e22c0d7..2c6d3ba4 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); |