summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorVolker Hilsheimer <volker.hilsheimer@qt.io>2022-10-05 00:08:40 +0200
committerVolker Hilsheimer <volker.hilsheimer@qt.io>2022-10-06 22:58:12 +0200
commit26a2e42c34b0effac4ffcba59a07df238980282e (patch)
treebcf466bf4e96e06bde09428dc631494e56da8c46 /src
parent04320df9f53eae8b5895a9a5767e8434ff36be8d (diff)
downloadqtlocation-26a2e42c34b0effac4ffcba59a07df238980282e.tar.gz
Move the RHI implementation into separate folder
Makes it easier to work with the code, the implementations have little in common that is not anyway abstracted into the common private base class. Change-Id: I4d957833f5a881e1b445ff6e912ffa036d10321a Reviewed-by: Ivan Solovev <ivan.solovev@qt.io>
Diffstat (limited to 'src')
-rw-r--r--src/location/CMakeLists.txt23
-rw-r--r--src/location/quickmapitems/qdeclarativecirclemapitem.cpp5
-rw-r--r--src/location/quickmapitems/qdeclarativecirclemapitem_p_p.h169
-rw-r--r--src/location/quickmapitems/qdeclarativepolygonmapitem.cpp390
-rw-r--r--src/location/quickmapitems/qdeclarativepolygonmapitem_p_p.h326
-rw-r--r--src/location/quickmapitems/qdeclarativepolylinemapitem.cpp712
-rw-r--r--src/location/quickmapitems/qdeclarativepolylinemapitem_p_p.h508
-rw-r--r--src/location/quickmapitems/qdeclarativerectanglemapitem.cpp3
-rw-r--r--src/location/quickmapitems/qdeclarativerectanglemapitem_p_p.h167
-rw-r--r--src/location/quickmapitems/rhi/qdeclarativecirclemapitem_rhi.cpp158
-rw-r--r--src/location/quickmapitems/rhi/qdeclarativecirclemapitem_rhi_p.h133
-rw-r--r--src/location/quickmapitems/rhi/qdeclarativepolygonmapitem_rhi.cpp303
-rw-r--r--src/location/quickmapitems/rhi/qdeclarativepolygonmapitem_rhi_p.h243
-rw-r--r--src/location/quickmapitems/rhi/qdeclarativepolylinemapitem_rhi.cpp517
-rw-r--r--src/location/quickmapitems/rhi/qdeclarativepolylinemapitem_rhi_p.h333
-rw-r--r--src/location/quickmapitems/rhi/qdeclarativerectanglemapitem_rhi.cpp159
-rw-r--r--src/location/quickmapitems/rhi/qdeclarativerectanglemapitem_rhi_p.h131
-rw-r--r--src/location/quickmapitems/rhi/qgeomapitemgeometry_rhi.cpp729
-rw-r--r--src/location/quickmapitems/rhi/qgeomapitemgeometry_rhi_p.h221
-rw-r--r--src/location/quickmapitems/rhi/qgeosimplify.cpp (renamed from src/location/quickmapitems/qgeosimplify.cpp)0
-rw-r--r--src/location/quickmapitems/rhi/qgeosimplify_p.h (renamed from src/location/quickmapitems/qgeosimplify_p.h)0
-rw-r--r--src/location/quickmapitems/rhi/shaders/polygon.frag (renamed from src/location/quickmapitems/shaders/polygon.frag)0
-rw-r--r--src/location/quickmapitems/rhi/shaders/polygon.vert (renamed from src/location/quickmapitems/shaders/polygon.vert)0
-rw-r--r--src/location/quickmapitems/rhi/shaders/polyline_extruded.frag (renamed from src/location/quickmapitems/shaders/polyline_extruded.frag)0
-rw-r--r--src/location/quickmapitems/rhi/shaders/polyline_extruded.vert (renamed from src/location/quickmapitems/shaders/polyline_extruded.vert)0
-rw-r--r--src/location/quickmapitems/rhi/shaders/polyline_linestrip.frag (renamed from src/location/quickmapitems/shaders/polyline_linestrip.frag)0
-rw-r--r--src/location/quickmapitems/rhi/shaders/polyline_linestrip.vert (renamed from src/location/quickmapitems/shaders/polyline_linestrip.vert)0
27 files changed, 2950 insertions, 2280 deletions
diff --git a/src/location/CMakeLists.txt b/src/location/CMakeLists.txt
index 19a029ad..bfddbc5c 100644
--- a/src/location/CMakeLists.txt
+++ b/src/location/CMakeLists.txt
@@ -131,7 +131,6 @@ qt_internal_add_qml_module(Location
quickmapitems/qdeclarativegeomapitembase.cpp
quickmapitems/qdeclarativegeomapitemview_p.h
quickmapitems/qdeclarativegeomapitemview.cpp
- quickmapitems/qgeosimplify.cpp quickmapitems/qgeosimplify_p.h
quickmapitems/qdeclarativegeomapitemutils.cpp quickmapitems/qdeclarativegeomapitemutils_p.h
quickmapitems/qdeclarativegeomapquickitem_p.h
quickmapitems/qdeclarativegeomapquickitem.cpp
@@ -154,6 +153,16 @@ qt_internal_add_qml_module(Location
quickmapitems/qdeclarativegeomapcopyrightsnotice.cpp
quickmapitems/qdeclarativegeomapitemtransitionmanager_p.h
quickmapitems/qdeclarativegeomapitemtransitionmanager.cpp
+ quickmapitems/rhi/qdeclarativepolygonmapitem_rhi_p.h
+ quickmapitems/rhi/qdeclarativepolygonmapitem_rhi.cpp
+ quickmapitems/rhi/qdeclarativepolylinemapitem_rhi_p.h
+ quickmapitems/rhi/qdeclarativepolylinemapitem_rhi.cpp
+ quickmapitems/rhi/qdeclarativerectanglemapitem_rhi_p.h
+ quickmapitems/rhi/qdeclarativerectanglemapitem_rhi.cpp
+ quickmapitems/rhi/qdeclarativecirclemapitem_rhi_p.h
+ quickmapitems/rhi/qdeclarativecirclemapitem_rhi.cpp
+ quickmapitems/rhi/qgeomapitemgeometry_rhi_p.h quickmapitems/rhi/qgeomapitemgeometry_rhi.cpp
+ quickmapitems/rhi/qgeosimplify.cpp quickmapitems/rhi/qgeosimplify_p.h
declarativeplaces/qdeclarativecategory.cpp
declarativeplaces/qdeclarativecategory_p.h
declarativeplaces/qdeclarativecontactdetails.cpp
@@ -181,12 +190,12 @@ qt_internal_add_shaders(Location "declarative_location_shaders"
PREFIX
"/location"
FILES
- "quickmapitems/shaders/polyline_linestrip.vert"
- "quickmapitems/shaders/polyline_linestrip.frag"
- "quickmapitems/shaders/polyline_extruded.vert"
- "quickmapitems/shaders/polyline_extruded.frag"
- "quickmapitems/shaders/polygon.vert"
- "quickmapitems/shaders/polygon.frag"
+ "quickmapitems/rhi/shaders/polyline_linestrip.vert"
+ "quickmapitems/rhi/shaders/polyline_linestrip.frag"
+ "quickmapitems/rhi/shaders/polyline_extruded.vert"
+ "quickmapitems/rhi/shaders/polyline_extruded.frag"
+ "quickmapitems/rhi/shaders/polygon.vert"
+ "quickmapitems/rhi/shaders/polygon.frag"
)
qt_internal_add_docs(Location
diff --git a/src/location/quickmapitems/qdeclarativecirclemapitem.cpp b/src/location/quickmapitems/qdeclarativecirclemapitem.cpp
index 8f0ba330..927ce6ae 100644
--- a/src/location/quickmapitems/qdeclarativecirclemapitem.cpp
+++ b/src/location/quickmapitems/qdeclarativecirclemapitem.cpp
@@ -38,12 +38,11 @@
****************************************************************************/
#include "qdeclarativecirclemapitem_p.h"
-#include "qdeclarativepolygonmapitem_p.h"
#include "qdeclarativecirclemapitem_p_p.h"
+#include "rhi/qdeclarativecirclemapitem_rhi_p.h"
#include <QtCore/QScopedValueRollback>
#include <QPen>
-#include <QPainter>
#include <qgeocircle.h>
#include <QtGui/private/qtriangulator_p.h>
@@ -561,8 +560,6 @@ QDeclarativeCircleMapItemPrivate::~QDeclarativeCircleMapItemPrivate() {}
QDeclarativeCircleMapItemPrivateCPU::~QDeclarativeCircleMapItemPrivateCPU() {}
-QDeclarativeCircleMapItemPrivateOpenGL::~QDeclarativeCircleMapItemPrivateOpenGL() {}
-
bool QDeclarativeCircleMapItemPrivate::preserveCircleGeometry (QList<QDoubleVector2D> &path,
const QGeoCoordinate &center, qreal distance, const QGeoProjectionWebMercator &p)
{
diff --git a/src/location/quickmapitems/qdeclarativecirclemapitem_p_p.h b/src/location/quickmapitems/qdeclarativecirclemapitem_p_p.h
index 49677e2a..319ff635 100644
--- a/src/location/quickmapitems/qdeclarativecirclemapitem_p_p.h
+++ b/src/location/quickmapitems/qdeclarativecirclemapitem_p_p.h
@@ -172,175 +172,6 @@ public:
MapPolygonNode *m_node = nullptr;
};
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativeCircleMapItemPrivateOpenGL: public QDeclarativeCircleMapItemPrivate
-{
-public:
- QDeclarativeCircleMapItemPrivateOpenGL(QDeclarativeCircleMapItem &circle) : QDeclarativeCircleMapItemPrivate(circle)
- {
- }
-
- QDeclarativeCircleMapItemPrivateOpenGL(QDeclarativeCircleMapItemPrivate &other)
- : QDeclarativeCircleMapItemPrivate(other)
- {
- }
-
- ~QDeclarativeCircleMapItemPrivateOpenGL() override;
-
- void onLinePropertiesChanged() override
- {
- m_circle.m_dirtyMaterial = true;
- afterViewportChanged();
- }
- void markScreenDirtyAndUpdate()
- {
- // preserveGeometry is cleared in updateMapItemPaintNode
- m_geometry.markScreenDirty();
- m_borderGeometry.markScreenDirty();
- m_circle.polishAndUpdate();
- }
- void markSourceDirtyAndUpdate() override
- {
- updateCirclePath();
- preserveGeometry();
- m_geometry.markSourceDirty();
- m_borderGeometry.markSourceDirty();
- m_circle.polishAndUpdate();
- }
- void preserveGeometry()
- {
- m_geometry.setPreserveGeometry(true, m_leftBound);
- m_borderGeometry.setPreserveGeometry(true, m_leftBound);
- }
- void onMapSet() override
- {
- markSourceDirtyAndUpdate();
- }
- void onGeoGeometryChanged() override
- {
-
- markSourceDirtyAndUpdate();
- }
- void onItemGeometryChanged() override
- {
- onGeoGeometryChanged();
- }
- void afterViewportChanged() override
- {
- preserveGeometry();
- markScreenDirtyAndUpdate();
- }
- void updatePolish() override
- {
- if (m_circle.m_circle.isEmpty()) {
- m_geometry.clear();
- m_borderGeometry.clear();
- m_circle.setWidth(0);
- m_circle.setHeight(0);
- return;
- }
-
- QScopedValueRollback<bool> rollback(m_circle.m_updatingGeometry);
- m_circle.m_updatingGeometry = true;
- const qreal lineWidth = m_circle.m_border.width();
- const QColor &lineColor = m_circle.m_border.color();
- const QColor &fillColor = m_circle.color();
- if (fillColor.alpha() != 0) {
- m_geometry.updateSourcePoints(*m_circle.map(), m_circlePath);
- m_geometry.markScreenDirty();
- m_geometry.updateScreenPoints(*m_circle.map(), lineWidth, lineColor);
- } else {
- m_geometry.clearBounds();
- }
-
- QGeoMapItemGeometry * geom = &m_geometry;
- m_borderGeometry.clearScreen();
- if (lineColor.alpha() != 0 && lineWidth > 0) {
- m_borderGeometry.updateSourcePoints(*m_circle.map(), m_circle.m_circle);
- m_borderGeometry.markScreenDirty();
- m_borderGeometry.updateScreenPoints(*m_circle.map(), lineWidth);
- geom = &m_borderGeometry;
- }
- m_circle.setWidth(geom->sourceBoundingBox().width());
- m_circle.setHeight(geom->sourceBoundingBox().height());
- m_circle.setPosition(1.0 * geom->firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
- }
-
- QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override
- {
- Q_UNUSED(data);
-
- if (!m_rootNode || !oldNode) {
- m_rootNode = new QDeclarativePolygonMapItemPrivateOpenGL::RootNode();
- m_node = new MapPolygonNodeGL();
- m_rootNode->appendChildNode(m_node);
- m_polylinenode = new MapPolylineNodeOpenGLExtruded();
- m_rootNode->appendChildNode(m_polylinenode);
- m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
- if (oldNode)
- delete oldNode;
- } else {
- m_rootNode = static_cast<QDeclarativePolygonMapItemPrivateOpenGL::RootNode *>(oldNode);
- }
-
- const QGeoMap *map = m_circle.map();
- const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
- const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
-
- if (m_borderGeometry.isScreenDirty()) {
- /* Do the border update first */
- m_polylinenode->update(m_circle.m_border.color(),
- float(m_circle.m_border.width()),
- &m_borderGeometry,
- combinedMatrix,
- cameraCenter,
- Qt::SquareCap,
- true,
- 30); // No LOD for circles
- m_borderGeometry.setPreserveGeometry(false);
- m_borderGeometry.markClean();
- } else {
- m_polylinenode->setSubtreeBlocked(true);
- }
- if (m_geometry.isScreenDirty()) {
- m_node->update(m_circle.m_color,
- &m_geometry,
- combinedMatrix,
- cameraCenter);
- m_geometry.setPreserveGeometry(false);
- m_geometry.markClean();
- } else {
- m_node->setSubtreeBlocked(true);
- }
-
- m_rootNode->setSubtreeBlocked(false);
- return m_rootNode;
- }
- bool contains(const QPointF &point) const override
- {
- const qreal lineWidth = m_circle.m_border.width();
- const QColor &lineColor = m_circle.m_border.color();
- const QRectF &bounds = (lineColor.alpha() != 0 && lineWidth > 0) ? m_borderGeometry.sourceBoundingBox() : m_geometry.sourceBoundingBox();
- if (bounds.contains(point)) {
- QDeclarativeGeoMap *m = m_circle.quickMap();
- if (m) {
- const QGeoCoordinate crd = m->toCoordinate(m->mapFromItem(&m_circle, point));
- return m_circle.m_circle.contains(crd) || m_borderGeometry.contains(m_circle.mapToItem(m_circle.quickMap(), point),
- m_circle.border()->width(),
- static_cast<const QGeoProjectionWebMercator&>(m_circle.map()->geoProjection()));
- } else {
- return true;
- }
- }
- return false;
- }
-
- QGeoMapPolygonGeometryOpenGL m_geometry;
- QGeoMapPolylineGeometryOpenGL m_borderGeometry;
- QDeclarativePolygonMapItemPrivateOpenGL::RootNode *m_rootNode = nullptr;
- MapPolygonNodeGL *m_node = nullptr;
- MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
-};
-
QT_END_NAMESPACE
#endif // QDECLARATIVECIRCLEMAPITEM_P_P_H
diff --git a/src/location/quickmapitems/qdeclarativepolygonmapitem.cpp b/src/location/quickmapitems/qdeclarativepolygonmapitem.cpp
index 53a9f8f5..f8125ddb 100644
--- a/src/location/quickmapitems/qdeclarativepolygonmapitem.cpp
+++ b/src/location/quickmapitems/qdeclarativepolygonmapitem.cpp
@@ -39,19 +39,13 @@
#include "qdeclarativegeomapitemutils_p.h"
#include "qdeclarativepolygonmapitem_p.h"
-#include "qdeclarativepolylinemapitem_p_p.h"
#include "qdeclarativepolygonmapitem_p_p.h"
-#include "qdeclarativerectanglemapitem_p_p.h"
-#include "error_messages_p.h"
+#include "rhi/qdeclarativepolygonmapitem_rhi_p.h"
#include <QtCore/QScopedValueRollback>
#include <qnumeric.h>
-#include <QPainter>
#include <QPainterPath>
-#include <QtQml/QQmlInfo>
-#include <QtQuick/qsgnode.h>
-#include <QtQuick/private/qsgmaterialshader_p.h>
#include <QtLocation/private/qgeomap_p.h>
#include <QtPositioning/private/qlocationutils_p.h>
#include <QtPositioning/private/qdoublevector2d_p.h>
@@ -427,267 +421,6 @@ bool QDeclarativePolygonMapItemPrivateCPU::contains(const QPointF &point) const
return (m_geometry.contains(point) || m_borderGeometry.contains(point));
}
-
-QGeoMapPolygonGeometryOpenGL::QGeoMapPolygonGeometryOpenGL()
-{
-}
-
-void QGeoMapPolygonGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QList<QDoubleVector2D> &path)
-{
- QList<QGeoCoordinate> geopath;
- for (const auto &c: path)
- geopath.append(QWebMercator::mercatorToCoord(c));
- updateSourcePoints(map, geopath);
-}
-
-// wrapPath always preserves the geometry
-// This one handles holes
-static void wrapPath(const QGeoPolygon &poly
- ,const QGeoCoordinate &geoLeftBound
- ,const QGeoProjectionWebMercator &p
- ,QList<QList<QDoubleVector2D> > &wrappedPaths
- ,QDoubleVector2D *leftBoundWrapped = nullptr)
-{
- QList<QList<QDoubleVector2D> > paths;
- for (qsizetype i = 0; i < 1 + poly.holesCount(); ++i) {
- QList<QDoubleVector2D> path;
- if (!i) {
- for (const QGeoCoordinate &c : poly.perimeter())
- path << p.geoToMapProjection(c);
- } else {
- for (const QGeoCoordinate &c : poly.holePath(i-1))
- path << p.geoToMapProjection(c);
- }
- paths.append(path);
- }
-
- const QDoubleVector2D leftBound = p.geoToMapProjection(geoLeftBound);
- wrappedPaths.clear();
-
- QList<QDoubleVector2D> wrappedPath;
- // compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
- for (const auto &path : paths) {
- wrappedPath.clear();
- for (QDoubleVector2D coord : path) {
- // 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(coord.x()) || !qIsFinite(coord.y())) {
- wrappedPaths.clear();
- return;
- }
-
- const bool isPointLessThanUnwrapBelowX = (coord.x() < leftBound.x());
- // unwrap x to preserve geometry if moved to border of map
- if (isPointLessThanUnwrapBelowX)
- coord.setX(coord.x() + 1.0);
- wrappedPath.append(coord);
- }
- wrappedPaths.append(wrappedPath);
- }
-
- if (leftBoundWrapped)
- *leftBoundWrapped = leftBound;
-}
-
-static void cutPathEars(const QList<QList<QDoubleVector2D>> &wrappedPaths,
- QList<QDeclarativeGeoMapItemUtils::vec2> &screenVertices,
- QList<quint32> &screenIndices)
-{
- using Coord = double;
- using N = uint32_t;
- using Point = std::array<Coord, 2>;
- screenVertices.clear();
- screenIndices.clear();
-
- std::vector<std::vector<Point>> polygon;
- std::vector<Point> poly;
-
- for (const QList<QDoubleVector2D> &wrappedPath: wrappedPaths) {
- poly.clear();
- for (const QDoubleVector2D &v: wrappedPath) {
- screenVertices << v;
- Point pt = {{ v.x(), v.y() }};
- poly.push_back( pt );
- }
- polygon.push_back(poly);
- }
-
- std::vector<N> indices = qt_mapbox::earcut<N>(polygon);
-
- for (const auto &i: indices)
- screenIndices << quint32(i);
-}
-
-static void cutPathEars(const QList<QDoubleVector2D> &wrappedPath,
- QList<QDeclarativeGeoMapItemUtils::vec2> &screenVertices,
- QList<quint32> &screenIndices)
-{
- using Coord = double;
- using N = uint32_t;
- using Point = std::array<Coord, 2>;
- screenVertices.clear();
- screenIndices.clear();
-
- std::vector<std::vector<Point>> polygon;
- std::vector<Point> poly;
-
- for (const QDoubleVector2D &v: wrappedPath) {
- screenVertices << v;
- Point pt = {{ v.x(), v.y() }};
- poly.push_back( pt );
- }
- polygon.push_back(poly);
-
- std::vector<N> indices = qt_mapbox::earcut<N>(polygon);
-
- for (const auto &i: indices)
- screenIndices << quint32(i);
-}
-
-/*!
- \internal
-*/
-// This one does only a perimeter
-void QGeoMapPolygonGeometryOpenGL::updateSourcePoints(const QGeoMap &map,
- const QList<QGeoCoordinate> &perimeter)
-{
- if (!sourceDirty_)
- return;
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
-
- // build the actual path
- // The approach is the same as described in QGeoMapPolylineGeometry::updateSourcePoints
- srcOrigin_ = geoLeftBound_;
-
- QDoubleVector2D leftBoundWrapped;
- // 1) pre-compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
- QList<QDoubleVector2D> wrappedPath;
- QDeclarativeGeoMapItemUtils::wrapPath(perimeter, geoLeftBound_, p,
- wrappedPath, &leftBoundWrapped);
-
- // 1.1) do the same for the bbox
- QList<QDoubleVector2D> wrappedBbox, wrappedBboxPlus1, wrappedBboxMinus1;
- QGeoPolygon bbox(QGeoPath(perimeter).boundingGeoRectangle());
- QDeclarativeGeoMapItemUtils::wrapPath(bbox.perimeter(), bbox.boundingGeoRectangle().topLeft(), p,
- wrappedBbox, wrappedBboxMinus1, wrappedBboxPlus1, &m_bboxLeftBoundWrapped);
-
- // 2) Store the triangulated polygon, and the wrapped bbox paths.
- // the triangulations can be used as they are, as they "bypass" the QtQuick display chain
- // the bbox wraps have to be however clipped, and then projected, in order to figure out the geometry.
- // Note that this might still cause the geometryChange method to fail under some extreme conditions.
- cutPathEars(wrappedPath, m_screenVertices, m_screenIndices);
-
- m_wrappedPolygons.resize(3);
- m_wrappedPolygons[0].wrappedBboxes = wrappedBboxMinus1;
- m_wrappedPolygons[1].wrappedBboxes = wrappedBbox;
- m_wrappedPolygons[2].wrappedBboxes = wrappedBboxPlus1;
-}
-
-// This one handles whole QGeoPolygon w. holes
-void QGeoMapPolygonGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoPolygon &poly)
-{
- if (!sourceDirty_)
- return;
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
-
- // build the actual path
- // The approach is the same as described in QGeoMapPolylineGeometry::updateSourcePoints
- srcOrigin_ = geoLeftBound_;
-
- QDoubleVector2D leftBoundWrapped;
- QList<QList<QDoubleVector2D>> wrappedPath;
- // 1) pre-compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
- wrapPath(poly, geoLeftBound_, p,
- wrappedPath, &leftBoundWrapped);
-
- // 1.1) do the same for the bbox
- QList<QDoubleVector2D> wrappedBbox, wrappedBboxPlus1, wrappedBboxMinus1;
- QGeoPolygon bbox(poly.boundingGeoRectangle());
- QDeclarativeGeoMapItemUtils::wrapPath(bbox.perimeter(), bbox.boundingGeoRectangle().topLeft(), p,
- wrappedBbox, wrappedBboxMinus1, wrappedBboxPlus1, &m_bboxLeftBoundWrapped);
-
- // 2) Store the triangulated polygon, and the wrapped bbox paths.
- // the triangulations can be used as they are, as they "bypass" the QtQuick display chain
- // the bbox wraps have to be however clipped, and then projected, in order to figure out the geometry.
- // Note that this might still cause the geometryChange method to fail under some extreme conditions.
- cutPathEars(wrappedPath, m_screenVertices, m_screenIndices);
- m_wrappedPolygons.resize(3);
- m_wrappedPolygons[0].wrappedBboxes = wrappedBboxMinus1;
- m_wrappedPolygons[1].wrappedBboxes = wrappedBbox;
- m_wrappedPolygons[2].wrappedBboxes = wrappedBboxPlus1;
-}
-
-void QGeoMapPolygonGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoRectangle &rect)
-{
- if (!sourceDirty_)
- return;
- const QList<QGeoCoordinate> perimeter = QGeoMapItemGeometry::path(rect);
- updateSourcePoints(map, perimeter);
-}
-
-/*!
- \internal
-*/
-void QGeoMapPolygonGeometryOpenGL::updateScreenPoints(const QGeoMap &map, qreal strokeWidth , const QColor &strokeColor)
-{
- if (map.viewportWidth() == 0 || map.viewportHeight() == 0) {
- clear();
- return;
- }
-
- // 1) identify which set to use: std, +1 or -1
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
- const QDoubleVector2D leftBoundMercator = p.geoToMapProjection(srcOrigin_);
- m_wrapOffset = p.projectionWrapFactor(leftBoundMercator) + 1; // +1 to get the offset into QLists
-
- // 1.1) select geometry set
- // This could theoretically be skipped for those polygons whose bbox is not even projectable.
- // However, such optimization could only be introduced if not calculating bboxes lazily.
- // Hence not doing it.
- if (sourceDirty_) {
- m_dataChanged = true;
- }
-
- if (strokeWidth == 0.0 || strokeColor.alpha() == 0) // or else the geometry of the border is used, so no point in calculating 2 of them
- updateQuickGeometry(p, strokeWidth);
-}
-
-void QGeoMapPolygonGeometryOpenGL::updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal /*strokeWidth*/)
-{
- // 2) clip bbox
- // BBox handling -- this is related to the bounding box geometry
- // that has to inevitably follow the old projection codepath
- // As it needs to provide projected coordinates for QtQuick interaction.
- // This could be futher optimized to be updated in a lazy fashion.
- const QList<QDoubleVector2D> &wrappedBbox = m_wrappedPolygons.at(m_wrapOffset).wrappedBboxes;
- QList<QList<QDoubleVector2D> > clippedBbox;
- QDoubleVector2D bboxLeftBoundWrapped = m_bboxLeftBoundWrapped;
- bboxLeftBoundWrapped.setX(bboxLeftBoundWrapped.x() + double(m_wrapOffset - 1));
- QDeclarativeGeoMapItemUtils::clipPolygon(wrappedBbox, p, clippedBbox, &bboxLeftBoundWrapped);
-
- // 3) project bbox
- QPainterPath ppi;
- if (!clippedBbox.size() || clippedBbox.first().size() < 3) {
- sourceBounds_ = screenBounds_ = QRectF();
- firstPointOffset_ = QPointF();
- screenOutline_ = ppi;
- return;
- }
-
- QDeclarativeGeoMapItemUtils::projectBbox(clippedBbox.first(), p, ppi); // Using first because a clipped box should always result in one polygon
- const QRectF brect = ppi.boundingRect();
- firstPointOffset_ = QPointF(brect.topLeft());
- screenOutline_ = ppi;
-
- // 4) Set Screen bbox
- screenBounds_ = brect;
- sourceBounds_.setX(0);
- sourceBounds_.setY(0);
- sourceBounds_.setWidth(brect.width());
- sourceBounds_.setHeight(brect.height());
-}
-
-QDeclarativePolygonMapItemPrivateOpenGL::~QDeclarativePolygonMapItemPrivateOpenGL() {}
/*
* QDeclarativePolygonMapItem Implementation
*/
@@ -980,26 +713,6 @@ void QDeclarativePolygonMapItem::geometryChange(const QRectF &newGeometry, const
//////////////////////////////////////////////////////////////////////
-QSGMaterialShader *MapPolygonMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
-{
- Q_UNUSED(renderMode);
- return new MapPolygonShader();
-}
-
-int MapPolygonMaterial::compare(const QSGMaterial *other) const
-{
- const MapPolygonMaterial &o = *static_cast<const MapPolygonMaterial *>(other);
- if (o.m_center == m_center && o.m_geoProjection == m_geoProjection && o.m_wrapOffset == m_wrapOffset)
- return QSGFlatColorMaterial::compare(other);
- return -1;
-}
-
-QSGMaterialType *MapPolygonMaterial::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
MapPolygonNode::MapPolygonNode()
: border_(new MapPolylineNode()),
geometry_(QSGGeometry::defaultAttributes_Point2D(), 0)
@@ -1050,106 +763,5 @@ void MapPolygonNode::update(const QColor &fillColor, const QColor &borderColor,
}
}
-MapPolygonNodeGL::MapPolygonNodeGL() :
- //fill_material_(this),
- fill_material_(),
- geometry_(QSGGeometry::defaultAttributes_Point2D(), 0)
-{
- geometry_.setDrawingMode(QSGGeometry::DrawTriangles);
- QSGGeometryNode::setMaterial(&fill_material_);
- QSGGeometryNode::setGeometry(&geometry_);
-}
-
-MapPolygonNodeGL::~MapPolygonNodeGL()
-{
-}
-
-/*!
- \internal
-*/
-void MapPolygonNodeGL::update(const QColor &fillColor,
- const QGeoMapPolygonGeometryOpenGL *fillShape,
- const QMatrix4x4 &geoProjection,
- const QDoubleVector3D &center)
-{
- if (fillShape->m_screenIndices.size() < 3 || fillColor.alpha() == 0) {
- setSubtreeBlocked(true);
- return;
- }
- setSubtreeBlocked(false);
-
- QSGGeometry *fill = QSGGeometryNode::geometry();
- if (fillShape->m_dataChanged || !fill->vertexCount()) {
- fillShape->allocateAndFillPolygon(fill);
- markDirty(DirtyGeometry);
- fillShape->m_dataChanged = false;
- }
-
- //if (fillColor != fill_material_.color()) // Any point in optimizing this?
- {
- fill_material_.setColor(fillColor);
- fill_material_.setGeoProjection(geoProjection);
- fill_material_.setCenter(center);
- fill_material_.setWrapOffset(fillShape->m_wrapOffset - 1);
- setMaterial(&fill_material_);
- markDirty(DirtyMaterial);
- }
-}
-
-MapPolygonShader::MapPolygonShader() : QSGMaterialShader(*new QSGMaterialShaderPrivate(this))
-{
- setShaderFileName(VertexStage, QLatin1String(":/location/quickmapitems/shaders/polygon.vert.qsb"));
- setShaderFileName(FragmentStage, QLatin1String(":/location/quickmapitems/shaders/polygon.frag.qsb"));
-}
-
-bool MapPolygonShader::updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type());
- MapPolygonMaterial *oldMaterial = static_cast<MapPolygonMaterial *>(oldEffect);
- MapPolygonMaterial *newMaterial = static_cast<MapPolygonMaterial *>(newEffect);
-
- const QColor &c = newMaterial->color();
- const QMatrix4x4 &geoProjection = newMaterial->geoProjection();
- const QDoubleVector3D &center = newMaterial->center();
-
- // It is safer to use vec4 instead on vec3, as described in:
- // https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)#Memory_layout
- QVector4D vecCenter, vecCenter_lowpart;
- for (int i = 0; i < 3; i++)
- QLocationUtils::split_double(center.get(i), &vecCenter[i], &vecCenter_lowpart[i]);
- vecCenter[3] = 0;
- vecCenter_lowpart[3] = 0;
-
- int offset = 0;
- char *buf_p = state.uniformData()->data();
-
- if (state.isMatrixDirty()) {
- const QMatrix4x4 m = state.projectionMatrix();
- memcpy(buf_p + offset, m.constData(), 4*4*4);
- }
- offset += 4*4*4;
-
- memcpy(buf_p + offset, geoProjection.constData(), 4*4*4); offset+=4*4*4;
-
- memcpy(buf_p + offset, &vecCenter, 4*4); offset += 4*4;
-
- memcpy(buf_p + offset, &vecCenter_lowpart, 4*4); offset+=4*4;
-
- const float wrapOffset = newMaterial->wrapOffset();
- memcpy(buf_p + offset, &wrapOffset, 4); offset+=4;
- offset += 4+4+4; // Padding
-
- if (oldMaterial == nullptr || c != oldMaterial->color() || state.isOpacityDirty()) {
- float opacity = state.opacity() * c.alphaF();
- QVector4D v(c.redF() * opacity,
- c.greenF() * opacity,
- c.blueF() * opacity,
- opacity);
- memcpy(buf_p + offset, &v, 4*4);
- }
- offset+=4*4;
-
- return true;
-}
QT_END_NAMESPACE
diff --git a/src/location/quickmapitems/qdeclarativepolygonmapitem_p_p.h b/src/location/quickmapitems/qdeclarativepolygonmapitem_p_p.h
index 7c5eb9ac..20871847 100644
--- a/src/location/quickmapitems/qdeclarativepolygonmapitem_p_p.h
+++ b/src/location/quickmapitems/qdeclarativepolygonmapitem_p_p.h
@@ -57,20 +57,13 @@
#include <QtGui/QMatrix4x4>
#include <QtGui/QColor>
-#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>
-#include <QtPositioning/QGeoPath>
-#include <QtPositioning/QGeoRectangle>
-#include <QtPositioning/QGeoPolygon>
-
#include <QtLocation/private/qlocationglobal_p.h>
#include <QtLocation/private/qgeomapitemgeometry_p.h>
-#include <QtLocation/private/qdeclarativegeomapitembase_p.h>
-#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
-#include <QtLocation/private/qdeclarativegeomapitemutils_p.h>
#include <QtLocation/private/qdeclarativepolygonmapitem_p.h>
#include <QtLocation/private/qdeclarativepolylinemapitem_p_p.h>
+
#include <QtPositioning/private/qdoublevector2d_p.h>
QT_BEGIN_NAMESPACE
@@ -92,123 +85,6 @@ protected:
bool assumeSimple_ = false;
};
-class Q_LOCATION_PRIVATE_EXPORT QGeoMapPolygonGeometryOpenGL : public QGeoMapItemGeometry
-{
-public:
- typedef struct {
- QList<QDoubleVector2D> wrappedBboxes;
- } WrappedPolygon;
- QGeoMapPolygonGeometryOpenGL();
- ~QGeoMapPolygonGeometryOpenGL() override {}
-
- // Temporary method for compatibility in MapCircleObject. Remove when MapObjects are ported.
- void updateSourcePoints(const QGeoMap &map,
- const QList<QDoubleVector2D> &path);
-
- void updateSourcePoints(const QGeoMap &map,
- const QList<QGeoCoordinate> &perimeter);
-
- void updateSourcePoints(const QGeoMap &map,
- const QGeoPolygon &poly);
-
- void updateSourcePoints(const QGeoMap &map,
- const QGeoRectangle &rect);
-
- void updateScreenPoints(const QGeoMap &map, qreal strokeWidth = 0.0, const QColor &strokeColor = Qt::transparent);
- void updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal strokeWidth = 0.0);
-
- void allocateAndFillPolygon(QSGGeometry *geom) const
- {
-
- const QList<QDeclarativeGeoMapItemUtils::vec2> &vx = m_screenVertices;
- const QList<quint32> &ix = m_screenIndices;
-
- geom->allocate(vx.size(), ix.size());
- if (geom->indexType() == QSGGeometry::UnsignedShortType) {
- quint16 *its = geom->indexDataAsUShort();
- for (qsizetype i = 0; i < ix.size(); ++i)
- its[i] = ix[i];
- } else if (geom->indexType() == QSGGeometry::UnsignedIntType) {
- quint32 *its = geom->indexDataAsUInt();
- for (qsizetype i = 0; i < ix.size(); ++i)
- its[i] = ix[i];
- }
-
- QSGGeometry::Point2D *pts = geom->vertexDataAsPoint2D();
- for (qsizetype i = 0; i < vx.size(); ++i)
- pts[i].set(vx[i].x, vx[i].y);
- }
-
- QList<QDeclarativeGeoMapItemUtils::vec2> m_screenVertices;
- QList<quint32> m_screenIndices;
- QDoubleVector2D m_bboxLeftBoundWrapped;
- QList<WrappedPolygon> m_wrappedPolygons;
- int m_wrapOffset = 0;
-};
-
-class Q_LOCATION_PRIVATE_EXPORT MapPolygonShader : public QSGMaterialShader
-{
-public:
- MapPolygonShader();
-
- bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
-};
-
-class Q_LOCATION_PRIVATE_EXPORT MapPolygonMaterial : public QSGFlatColorMaterial
-{
-public:
- MapPolygonMaterial()
- : QSGFlatColorMaterial()
- {
- // Passing RequiresFullMatrix is essential in order to prevent the
- // batch renderer from baking in simple, translate-only transforms into
- // the vertex data. The shader will rely on the fact that
- // vertexCoord.xy is the Shape-space coordinate and so no modifications
- // are welcome.
- setFlag(Blending | RequiresFullMatrix);
- }
-
- QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
-
- void setGeoProjection(const QMatrix4x4 &p)
- {
- m_geoProjection = p;
- }
-
- QMatrix4x4 geoProjection() const
- {
- return m_geoProjection;
- }
-
- void setCenter(const QDoubleVector3D &c)
- {
- m_center = c;
- }
-
- QDoubleVector3D center() const
- {
- return m_center;
- }
-
- int wrapOffset() const
- {
- return m_wrapOffset;
- }
-
- void setWrapOffset(int wrapOffset)
- {
- m_wrapOffset = wrapOffset;
- }
-
- int compare(const QSGMaterial *other) const override;
- QSGMaterialType *type() const override;
-
-protected:
- QMatrix4x4 m_geoProjection;
- QDoubleVector3D m_center;
- int m_wrapOffset = 0;
-};
-
class Q_LOCATION_PRIVATE_EXPORT MapPolygonNode : public MapItemGeometryNode
{
@@ -225,22 +101,6 @@ private:
QSGGeometry geometry_;
};
-class Q_LOCATION_PRIVATE_EXPORT MapPolygonNodeGL : public MapItemGeometryNode
-{
-
-public:
- MapPolygonNodeGL();
- ~MapPolygonNodeGL() override;
-
- void update(const QColor &fillColor,
- const QGeoMapPolygonGeometryOpenGL *fillShape,
- const QMatrix4x4 &geoProjection,
- const QDoubleVector3D &center);
-
- MapPolygonMaterial fill_material_;
- QSGGeometry geometry_;
-};
-
class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolygonMapItemPrivate
{
public:
@@ -352,190 +212,6 @@ public:
MapPolygonNode *m_node = nullptr;
};
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolygonMapItemPrivateOpenGL: public QDeclarativePolygonMapItemPrivate
-{
-public:
- struct RootNode : public QSGNode /*QSGTransformNode*/, public VisibleNode
- {
- RootNode() { }
-
- bool isSubtreeBlocked() const override
- {
- return subtreeBlocked();
- }
- };
-
- QDeclarativePolygonMapItemPrivateOpenGL(QDeclarativePolygonMapItem &polygon) : QDeclarativePolygonMapItemPrivate(polygon)
- {
- }
-
- QDeclarativePolygonMapItemPrivateOpenGL(QDeclarativePolygonMapItemPrivate &other)
- : QDeclarativePolygonMapItemPrivate(other)
- {
- }
-
- ~QDeclarativePolygonMapItemPrivateOpenGL() override;
-
- void markScreenDirtyAndUpdate()
- {
- // preserveGeometry is cleared in updateMapItemPaintNode
- m_geometry.markScreenDirty();
- m_borderGeometry.markScreenDirty();
- m_poly.polishAndUpdate();
- }
- void onLinePropertiesChanged() override
- {
- m_poly.m_dirtyMaterial = true;
- afterViewportChanged();
- }
- void markSourceDirtyAndUpdate() override
- {
- // preserveGeometry is cleared in updateMapItemPaintNode
- m_geometry.markSourceDirty();
- m_borderGeometry.markSourceDirty();
- m_poly.polishAndUpdate();
- }
- void preserveGeometry()
- {
- m_geometry.setPreserveGeometry(true, m_poly.m_geopoly.boundingGeoRectangle().topLeft());
- m_borderGeometry.setPreserveGeometry(true, m_poly.m_geopoly.boundingGeoRectangle().topLeft());
- }
- void afterViewportChanged() override // This is called when the camera changes, or visibleArea changes.
- {
- // preserveGeometry is cleared in updateMapItemPaintNode
- preserveGeometry();
- markScreenDirtyAndUpdate();
- }
- void onMapSet() override
- {
- markSourceDirtyAndUpdate();
- }
- void onGeoGeometryChanged() override
- {
- preserveGeometry();
- markSourceDirtyAndUpdate();
- }
- void onGeoGeometryUpdated() override
- {
- preserveGeometry();
- markSourceDirtyAndUpdate();
- }
- void onItemGeometryChanged() override
- {
- onGeoGeometryChanged();
- }
- void updatePolish() override
- {
- if (m_poly.m_geopoly.perimeter().length() == 0) { // Possibly cleared
- m_geometry.clear();
- m_borderGeometry.clear();
- m_poly.setWidth(0);
- m_poly.setHeight(0);
- return;
- }
-
- QScopedValueRollback<bool> rollback(m_poly.m_updatingGeometry);
- m_poly.m_updatingGeometry = true;
- const qreal lineWidth = m_poly.m_border.width();
- const QColor &lineColor = m_poly.m_border.color();
- const QColor &fillColor = m_poly.color();
- if (fillColor.alpha() != 0) {
- m_geometry.updateSourcePoints(*m_poly.map(), m_poly.m_geopoly);
- m_geometry.markScreenDirty();
- m_geometry.updateScreenPoints(*m_poly.map(), lineWidth, lineColor);
- } else {
- m_geometry.clearBounds();
- }
-
- QGeoMapItemGeometry * geom = &m_geometry;
- m_borderGeometry.clearScreen();
- if (lineColor.alpha() != 0 && lineWidth > 0) {
- m_borderGeometry.updateSourcePoints(*m_poly.map(), m_poly.m_geopoly);
- m_borderGeometry.markScreenDirty();
- m_borderGeometry.updateScreenPoints(*m_poly.map(), lineWidth);
- geom = &m_borderGeometry;
- }
- m_poly.setWidth(geom->sourceBoundingBox().width());
- m_poly.setHeight(geom->sourceBoundingBox().height());
- m_poly.setPosition(1.0 * geom->firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
- }
- QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override
- {
- Q_UNUSED(data);
-
- if (!m_rootNode || !oldNode) {
- m_rootNode = new RootNode();
- m_node = new MapPolygonNodeGL();
- m_rootNode->appendChildNode(m_node);
- m_polylinenode = new MapPolylineNodeOpenGLExtruded();
- m_rootNode->appendChildNode(m_polylinenode);
- m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
- if (oldNode)
- delete oldNode;
- } else {
- m_rootNode = static_cast<RootNode *>(oldNode);
- }
-
- const QGeoMap *map = m_poly.map();
- const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
- const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
-
- if (m_borderGeometry.isScreenDirty()) {
- /* Do the border update first */
- m_polylinenode->update(m_poly.m_border.color(),
- float(m_poly.m_border.width()),
- &m_borderGeometry,
- combinedMatrix,
- cameraCenter,
- Qt::SquareCap,
- true,
- 30); // No LOD for polygons just yet.
- // First figure out what to do with holes.
- m_borderGeometry.setPreserveGeometry(false);
- m_borderGeometry.markClean();
- } else {
- m_polylinenode->setSubtreeBlocked(true);
- }
- if (m_geometry.isScreenDirty()) {
- m_node->update(m_poly.m_color,
- &m_geometry,
- combinedMatrix,
- cameraCenter);
- m_geometry.setPreserveGeometry(false);
- m_geometry.markClean();
- } else {
- m_node->setSubtreeBlocked(true);
- }
-
- m_rootNode->setSubtreeBlocked(false);
- return m_rootNode;
- }
- bool contains(const QPointF &point) const override
- {
- const qreal lineWidth = m_poly.m_border.width();
- const QColor &lineColor = m_poly.m_border.color();
- const QRectF &bounds = (lineColor.alpha() != 0 && lineWidth > 0) ? m_borderGeometry.sourceBoundingBox() : m_geometry.sourceBoundingBox();
- if (bounds.contains(point)) {
- QDeclarativeGeoMap *m = m_poly.quickMap();
- if (m) {
- const QGeoCoordinate crd = m->toCoordinate(m->mapFromItem(&m_poly, point));
- return m_poly.m_geopoly.contains(crd) || m_borderGeometry.contains(m_poly.mapToItem(m_poly.quickMap(), point),
- m_poly.border()->width(),
- static_cast<const QGeoProjectionWebMercator&>(m_poly.map()->geoProjection()));
- } else {
- return true;
- }
- }
- return false;
- }
-
- QGeoMapPolygonGeometryOpenGL m_geometry;
- QGeoMapPolylineGeometryOpenGL m_borderGeometry;
- RootNode *m_rootNode = nullptr;
- MapPolygonNodeGL *m_node = nullptr;
- MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
-};
-
QT_END_NAMESPACE
#endif // QDECLARATIVEPOLYGONMAPITEM_P_P_H
diff --git a/src/location/quickmapitems/qdeclarativepolylinemapitem.cpp b/src/location/quickmapitems/qdeclarativepolylinemapitem.cpp
index 5a4e06c3..fb0e7d79 100644
--- a/src/location/quickmapitems/qdeclarativepolylinemapitem.cpp
+++ b/src/location/quickmapitems/qdeclarativepolylinemapitem.cpp
@@ -39,52 +39,25 @@
#include "qdeclarativepolylinemapitem_p.h"
#include "qdeclarativepolylinemapitem_p_p.h"
-#include "qdeclarativerectanglemapitem_p_p.h"
-#include "qdeclarativecirclemapitem_p_p.h"
+#include "rhi/qdeclarativepolylinemapitem_rhi_p.h"
#include "qdeclarativegeomapitemutils_p.h"
-#include "error_messages_p.h"
-#include "qgeosimplify_p.h"
#include <QtCore/QScopedValueRollback>
#include <qnumeric.h>
-#include <QThreadPool>
-#include <QRunnable>
-#include <QPainter>
#include <QPainterPath>
-#include <QtQml/QQmlInfo>
#include <QtGui/private/qtriangulatingstroker_p.h>
-#include <QtGui/private/qtriangulator_p.h>
-#include <QtQuick/private/qsgmaterialshader_p.h>
#include <QtPositioning/private/qlocationutils_p.h>
#include <QtPositioning/private/qdoublevector2d_p.h>
#include <QtPositioning/private/qwebmercator_p.h>
#include <QtPositioning/private/qclipperutils_p.h>
#include <QtPositioning/private/qgeopath_p.h>
-#include <QtLocation/private/qgeomapparameter_p.h>
#include <QtLocation/private/qgeomap_p.h>
#include <array>
QT_BEGIN_NAMESPACE
-struct ThreadPool // to have a thread pool with max 1 thread for geometry processing
-{
- ThreadPool ()
- {
- m_threadPool.setMaxThreadCount(1);
- }
-
- void start(QRunnable *runnable, int priority = 0)
- {
- m_threadPool.start(runnable, priority);
- }
-
- QThreadPool m_threadPool;
-};
-
-Q_GLOBAL_STATIC(ThreadPool, threadPool)
-
static bool get_line_intersection(const double p0_x,
const double p0_y,
@@ -822,165 +795,6 @@ bool QDeclarativePolylineMapItemPrivateCPU::contains(const QPointF &point) const
return m_geometry.contains(point);
}
-
-void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoPolygon &poly)
-{
- if (!sourceDirty_)
- return;
- QGeoPath p(poly.perimeter());
- if (poly.perimeter().size() && poly.perimeter().last() != poly.perimeter().first())
- p.addCoordinate(poly.perimeter().first());
- updateSourcePoints(map, p);
-}
-
-void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoPath &poly)
-{
- if (!sourceDirty_)
- return;
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
-
- // build the actual path
- // The approach is the same as described in QGeoMapPolylineGeometry::updateSourcePoints
-
-
- QDoubleVector2D leftBoundWrapped;
- // 1) pre-compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
- QList<QDoubleVector2D> wrappedPath;
- QDeclarativeGeoMapItemUtils::wrapPath(poly.path(), geoLeftBound_, p,
- wrappedPath, &leftBoundWrapped);
-
- const QGeoRectangle &boundingRectangle = poly.boundingGeoRectangle();
- updateSourcePoints(p, wrappedPath, boundingRectangle);
-}
-
-void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoProjectionWebMercator &p,
- const QList<QDoubleVector2D> &wrappedPath,
- const QGeoRectangle &boundingRectangle) {
- if (!sourceDirty_)
- return;
- // 1.1) do the same for the bbox
- // Beware: vertical lines (or horizontal lines) might have an "empty" bbox. Check for that
-
- QGeoCoordinate topLeft = boundingRectangle.topLeft();
- QGeoCoordinate bottomRight = boundingRectangle.bottomRight();
- const qreal epsilon = 0.000001;
- if (qFuzzyCompare(topLeft.latitude(), bottomRight.latitude())) {
- topLeft.setLatitude(qBound(-90.0, topLeft.latitude() + epsilon ,90.0));
- bottomRight.setLatitude(qBound(-90.0, bottomRight.latitude() - epsilon ,90.0));
- }
- if (qFuzzyCompare(topLeft.longitude(), bottomRight.longitude())) {
- topLeft.setLongitude(QLocationUtils::wrapLong(topLeft.longitude() - epsilon));
- bottomRight.setLongitude(QLocationUtils::wrapLong(bottomRight.longitude() + epsilon));
- }
- QGeoPolygon bbox(QGeoRectangle(topLeft, bottomRight));
- QList<QDoubleVector2D> wrappedBbox, wrappedBboxPlus1, wrappedBboxMinus1;
- QDeclarativeGeoMapItemUtils::wrapPath(bbox.perimeter(), bbox.boundingGeoRectangle().topLeft(), p,
- wrappedBbox, wrappedBboxMinus1, wrappedBboxPlus1, &m_bboxLeftBoundWrapped);
-
- // New pointers, some old LOD task might still be running and operating on the old pointers.
- resetLOD();
-
- for (const auto &v: qAsConst(wrappedPath)) m_screenVertices->append(v);
-
- m_wrappedPolygons.resize(3);
- m_wrappedPolygons[0].wrappedBboxes = wrappedBboxMinus1;
- m_wrappedPolygons[1].wrappedBboxes = wrappedBbox;
- m_wrappedPolygons[2].wrappedBboxes = wrappedBboxPlus1;
- srcOrigin_ = geoLeftBound_;
-}
-
-void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoRectangle &rect)
-{
- const QList<QGeoCoordinate> perimeter = QGeoMapItemGeometry::perimeter(rect);
- updateSourcePoints(map, QGeoPath(perimeter));
-}
-
-void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoCircle &circle)
-{
- if (!sourceDirty_)
- return;
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
-
- QDoubleVector2D leftBoundWrapped;
- // 1) pre-compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
- QList<QGeoCoordinate> path;
- QGeoCoordinate leftBound;
- QList<QDoubleVector2D> wrappedPath;
- QDeclarativeCircleMapItemPrivateCPU::calculatePeripheralPoints(path, circle.center(), circle.radius(), QDeclarativeCircleMapItemPrivateCPU::CircleSamples, leftBound);
- path << path.first();
- geoLeftBound_ = leftBound;
- QDeclarativeGeoMapItemUtils::wrapPath(path, leftBound, p, wrappedPath, &leftBoundWrapped);
- const QGeoRectangle &boundingRectangle = circle.boundingGeoRectangle();
- updateSourcePoints(p, wrappedPath, boundingRectangle);
-}
-
-void QGeoMapPolylineGeometryOpenGL::updateScreenPoints(const QGeoMap &map, qreal strokeWidth, bool /*adjustTranslation*/)
-{
- if (map.viewportWidth() == 0 || map.viewportHeight() == 0) {
- clear();
- return;
- }
-
- // 1) identify which set to use: std, +1 or -1
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
- const QDoubleVector2D leftBoundMercator = p.geoToMapProjection(srcOrigin_);
- m_wrapOffset = p.projectionWrapFactor(leftBoundMercator) + 1; // +1 to get the offset into QLists
-
- if (sourceDirty_) {
- // 1.1) select geometry set
- // This could theoretically be skipped for those polylines whose bbox is not even projectable.
- // However, such optimization could only be introduced if not calculating bboxes lazily.
- // Hence not doing it.
-// if (m_screenVertices.size() > 1)
- m_dataChanged = true;
- }
-
- updateQuickGeometry(p, strokeWidth);
-}
-
-void QGeoMapPolylineGeometryOpenGL::updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal strokeWidth)
-{
- // 2) clip bbox
- // BBox handling -- this is related to the bounding box geometry
- // that has to inevitably follow the old projection codepath
- // As it needs to provide projected coordinates for QtQuick interaction.
- // This could be futher optimized to be updated in a lazy fashion.
- const QList<QDoubleVector2D> &wrappedBbox = m_wrappedPolygons.at(m_wrapOffset).wrappedBboxes;
- QList<QList<QDoubleVector2D> > clippedBbox;
- QDoubleVector2D bboxLeftBoundWrapped = m_bboxLeftBoundWrapped;
- bboxLeftBoundWrapped.setX(bboxLeftBoundWrapped.x() + double(m_wrapOffset - 1));
- QDeclarativeGeoMapItemUtils::clipPolygon(wrappedBbox, p, clippedBbox, &bboxLeftBoundWrapped, false);
-
- // 3) project bbox
- QPainterPath ppi;
-
- if ( !clippedBbox.size() ||
- clippedBbox.first().size() < 3) {
- sourceBounds_ = screenBounds_ = QRectF();
- firstPointOffset_ = QPointF();
- screenOutline_ = ppi;
- return;
- }
-
- QDeclarativeGeoMapItemUtils::projectBbox(clippedBbox.first(), p, ppi); // Using first because a clipped box should always result in one polygon
- const QRectF brect = ppi.boundingRect();
- firstPointOffset_ = QPointF(brect.topLeft());
- sourceBounds_ = brect;
- screenOutline_ = ppi;
-
- // 4) Set Screen bbox
- screenBounds_ = brect;
- sourceBounds_.setX(0);
- sourceBounds_.setY(0);
- sourceBounds_.setWidth(brect.width() + strokeWidth);
- sourceBounds_.setHeight(brect.height() + strokeWidth);
-}
-
-
-QDeclarativePolylineMapItemPrivateOpenGLLineStrip::~QDeclarativePolylineMapItemPrivateOpenGLLineStrip() {}
-
-QDeclarativePolylineMapItemPrivateOpenGLExtruded::~QDeclarativePolylineMapItemPrivateOpenGLExtruded() {}
-
/*
* QDeclarativePolygonMapItem Implementation
*/
@@ -1465,528 +1279,4 @@ void MapPolylineNode::update(const QColor &fillColor,
}
}
-MapPolylineNodeOpenGLLineStrip::MapPolylineNodeOpenGLLineStrip()
-: geometry_(QSGGeometry::defaultAttributes_Point2D(), 0)
-{
- geometry_.setDrawingMode(QSGGeometry::DrawLineStrip);
- QSGGeometryNode::setMaterial(&fill_material_);
- QSGGeometryNode::setGeometry(&geometry_);
-}
-
-MapPolylineNodeOpenGLLineStrip::~MapPolylineNodeOpenGLLineStrip()
-{
-
-}
-
-void MapPolylineNodeOpenGLLineStrip::update(const QColor &fillColor,
- const qreal lineWidth,
- const QGeoMapPolylineGeometryOpenGL *shape,
- const QMatrix4x4 &geoProjection,
- const QDoubleVector3D &center,
- const Qt::PenCapStyle /*capStyle*/)
-{
- if (shape->m_screenVertices->size() < 2) {
- setSubtreeBlocked(true);
- return;
- } else {
- setSubtreeBlocked(false);
- }
-
- QSGGeometry *fill = QSGGeometryNode::geometry();
- if (shape->m_dataChanged) {
- shape->allocateAndFillLineStrip(fill);
- markDirty(DirtyGeometry);
- shape->m_dataChanged = false;
- }
- fill->setLineWidth(lineWidth);
- fill_material_.setLineWidth(lineWidth); // to make the material not compare equal if linewidth changes
-
-// if (fillColor != fill_material_.color())
- {
- fill_material_.setWrapOffset(shape->m_wrapOffset - 1);
- fill_material_.setColor(fillColor);
- fill_material_.setGeoProjection(geoProjection);
- fill_material_.setCenter(center);
- setMaterial(&fill_material_);
- markDirty(DirtyMaterial);
- }
-}
-
-MapPolylineShaderLineStrip::MapPolylineShaderLineStrip() : QSGMaterialShader(*new QSGMaterialShaderPrivate(this))
-{
- setShaderFileName(VertexStage, QLatin1String(":/location/quickmapitems/shaders/polyline_linestrip.vert.qsb"));
- setShaderFileName(FragmentStage, QLatin1String(":/location/quickmapitems/shaders/polyline_linestrip.frag.qsb"));
-}
-
-bool MapPolylineShaderLineStrip::updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type());
- MapPolylineMaterial *oldMaterial = static_cast<MapPolylineMaterial *>(oldEffect);
- MapPolylineMaterial *newMaterial = static_cast<MapPolylineMaterial *>(newEffect);
-
- const QColor &c = newMaterial->color();
- const QMatrix4x4 &geoProjection = newMaterial->geoProjection();
- const QDoubleVector3D &center = newMaterial->center();
-
- QVector4D vecCenter, vecCenter_lowpart;
- for (int i = 0; i < 3; i++)
- QLocationUtils::split_double(center.get(i), &vecCenter[i], &vecCenter_lowpart[i]);
- vecCenter[3] = 0;
- vecCenter_lowpart[3] = 0;
-
- int offset = 0;
- char *buf_p = state.uniformData()->data();
-
- if (state.isMatrixDirty()) {
- const QMatrix4x4 m = state.projectionMatrix();
- memcpy(buf_p + offset, m.constData(), 4*4*4);
- }
- offset += 4*4*4;
-
- memcpy(buf_p + offset, geoProjection.constData(), 4*4*4); offset+=4*4*4;
-
- memcpy(buf_p + offset, &vecCenter, 4*4); offset += 4*4;
-
- memcpy(buf_p + offset, &vecCenter_lowpart, 4*4); offset+=4*4;
-
- if (state.isOpacityDirty()) {
- const float opacity = state.opacity();
- memcpy(buf_p + offset, &opacity, 4);
- }
- offset += 4;
-
- float wrapOffset = newMaterial->wrapOffset();
- memcpy(buf_p + offset, &wrapOffset, 4); offset+=4;
-
- offset+=8; // float padding
-
- if (oldMaterial == nullptr || c != oldMaterial->color() || state.isOpacityDirty()) {
- float opacity = state.opacity() * c.alphaF();
- QVector4D v(c.redF() * opacity,
- c.greenF() * opacity,
- c.blueF() * opacity,
- opacity);
- memcpy(buf_p + offset, &v, 4*4);
- }
- offset+=4*4;
-
- return true;
-}
-
-QSGMaterialShader *MapPolylineMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
-{
- Q_UNUSED(renderMode);
- return new MapPolylineShaderLineStrip();
-}
-
-QSGMaterialType *MapPolylineMaterial::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
-int MapPolylineMaterial::compare(const QSGMaterial *other) const
-{
- const MapPolylineMaterial &o = *static_cast<const MapPolylineMaterial *>(other);
- if (o.m_center == m_center && o.m_geoProjection == m_geoProjection && o.m_wrapOffset == m_wrapOffset && o.m_lineWidth == m_lineWidth)
- return QSGFlatColorMaterial::compare(other);
- return -1;
-}
-
-const QSGGeometry::AttributeSet &MapPolylineNodeOpenGLExtruded::attributesMapPolylineTriangulated()
-{
- return MapPolylineEntry::attributes();
-}
-
-MapPolylineNodeOpenGLExtruded::MapPolylineNodeOpenGLExtruded()
-: m_geometryTriangulating(MapPolylineNodeOpenGLExtruded::attributesMapPolylineTriangulated(),
- 0 /* vtx cnt */, 0 /* index cnt */, QSGGeometry::UnsignedIntType /* index type */)
-{
- m_geometryTriangulating.setDrawingMode(QSGGeometry::DrawTriangles);
- QSGGeometryNode::setMaterial(&fill_material_);
- QSGGeometryNode::setGeometry(&m_geometryTriangulating);
-}
-
-MapPolylineNodeOpenGLExtruded::~MapPolylineNodeOpenGLExtruded()
-{
-
-}
-
-bool QGeoMapPolylineGeometryOpenGL::allocateAndFillEntries(QSGGeometry *geom,
- bool closed,
- unsigned int zoom) const
-{
- // Select LOD. Generate if not present. Assign it to m_screenVertices;
- if (m_dataChanged) {
- // it means that the data really changed.
- // So synchronously produce LOD 1, and enqueue the requested one if != 0 or 1.
- // Select 0 if 0 is requested, or 1 in all other cases.
- selectLODOnDataChanged(zoom, m_bboxLeftBoundWrapped.x());
- } else {
- // Data has not changed, but active LOD != requested LOD.
- // So, if there are no active tasks, try to change to the correct one.
- if (!selectLODOnLODMismatch(zoom, m_bboxLeftBoundWrapped.x(), closed))
- return false;
- }
-
- const QList<QDeclarativeGeoMapItemUtils::vec2> &v = *m_screenVertices;
- if (v.size() < 2) {
- geom->allocate(0, 0);
- return true;
- }
- const int numSegments = (v.size() - 1);
-
- const int numIndices = numSegments * 6; // six vertices per line segment
- geom->allocate(numIndices);
- MapPolylineNodeOpenGLExtruded::MapPolylineEntry *vertices =
- static_cast<MapPolylineNodeOpenGLExtruded::MapPolylineEntry *>(geom->vertexData());
-
- for (int i = 0; i < numSegments; ++i) {
- MapPolylineNodeOpenGLExtruded::MapPolylineEntry e;
- const QDeclarativeGeoMapItemUtils::vec2 &cur = v[i];
- const QDeclarativeGeoMapItemUtils::vec2 &next = v[i+1];
- e.triangletype = 1.0;
- e.next = next;
- e.prev = cur;
- e.pos = cur;
- e.direction = 1.0;
- e.vertextype = -1.0;
- vertices[i*6] = e;
- e.direction = -1.0;
- vertices[i*6+1] = e;
- e.pos = next;
- e.vertextype = 1.0;
- vertices[i*6+2] = e;
-
- // Second tri
- e.triangletype = -1.0;
- e.direction = -1.0;
- vertices[i*6+3] = e;
- e.direction = 1.0;
- vertices[i*6+4] = e;
- e.pos = cur;
- e.vertextype = -1.0;
- vertices[i*6+5] = e;
-
- if (i != 0) {
- vertices[i*6].prev = vertices[i*6+1].prev = vertices[i*6+5].prev = v[i-1];
- } else {
- if (closed) {
- vertices[i*6].prev = vertices[i*6+1].prev = vertices[i*6+5].prev = v[numSegments - 1];
- } else {
- vertices[i*6].triangletype = vertices[i*6+1].triangletype = vertices[i*6+5].triangletype = 2.0;
- }
- }
- if (i != numSegments - 1) {
- vertices[i*6+2].next = vertices[i*6+3].next = vertices[i*6+4].next = v[i+2];
- } else {
- if (closed) {
- vertices[i*6+2].next = vertices[i*6+3].next = vertices[i*6+4].next = v[1];
- } else {
- vertices[i*6+2].triangletype = vertices[i*6+3].triangletype = vertices[i*6+4].triangletype = 3.0;
- }
- }
- }
- return true;
-}
-
-void QGeoMapPolylineGeometryOpenGL::allocateAndFillLineStrip(QSGGeometry *geom,
- int lod) const
-{
- // Select LOD. Generate if not present. Assign it to m_screenVertices;
- Q_UNUSED(lod);
-
- const QList<QDeclarativeGeoMapItemUtils::vec2> &vx = *m_screenVertices;
- geom->allocate(vx.size());
-
- QSGGeometry::Point2D *pts = geom->vertexDataAsPoint2D();
- for (qsizetype i = 0; i < vx.size(); ++i)
- pts[i].set(vx[i].x, vx[i].y);
-}
-
-void MapPolylineNodeOpenGLExtruded::update(const QColor &fillColor,
- float lineWidth,
- const QGeoMapPolylineGeometryOpenGL *shape,
- const QMatrix4x4 &geoProjection,
- const QDoubleVector3D &center,
- const Qt::PenCapStyle capStyle,
- bool closed,
- unsigned int zoom)
-{
- // shape->size() == number of triangles
- if (shape->m_screenVertices->size() < 2
- || lineWidth < 0.5 || fillColor.alpha() == 0) { // number of points
- setSubtreeBlocked(true);
- return;
- } else {
- setSubtreeBlocked(false);
- }
-
- QSGGeometry *fill = QSGGeometryNode::geometry();
- if (shape->m_dataChanged || !shape->isLODActive(zoom) || !fill->vertexCount()) { // fill->vertexCount for when node gets destroyed by MapItemBase bcoz of opacity, then recreated.
- if (shape->allocateAndFillEntries(fill, closed, zoom)) {
- markDirty(DirtyGeometry);
- shape->m_dataChanged = false;
- }
- }
-
- // Update this
-// if (fillColor != fill_material_.color())
- {
- fill_material_.setWrapOffset(shape->m_wrapOffset - 1);
- fill_material_.setColor(fillColor);
- fill_material_.setGeoProjection(geoProjection);
- fill_material_.setCenter(center);
- fill_material_.setLineWidth(lineWidth);
- fill_material_.setMiter(capStyle != Qt::FlatCap);
- setMaterial(&fill_material_);
- markDirty(DirtyMaterial);
- }
-}
-
-MapPolylineShaderExtruded::MapPolylineShaderExtruded() : QSGMaterialShader(*new QSGMaterialShaderPrivate(this))
-{
- // Heavily adapted from https://github.com/mattdesl/webgl-lines/blob/master/projected/vert.glsl,
- // that is (c) Matt DesLauriers, and released under the MIT license.
- setShaderFileName(VertexStage, QLatin1String(":/location/quickmapitems/shaders/polyline_extruded.vert.qsb"));
- setShaderFileName(FragmentStage, QLatin1String(":/location/quickmapitems/shaders/polyline_extruded.frag.qsb"));
-}
-
-bool MapPolylineShaderExtruded::updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
-{
- Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type());
- MapPolylineMaterialExtruded *oldMaterial = static_cast<MapPolylineMaterialExtruded *>(oldEffect);
- MapPolylineMaterialExtruded *newMaterial = static_cast<MapPolylineMaterialExtruded *>(newEffect);
-
- const QColor &c = newMaterial->color();
- const QMatrix4x4 &geoProjection = newMaterial->geoProjection();
- const QDoubleVector3D &center = newMaterial->center();
-
- // It is safer to use vec4 instead on vec3, as described in:
- // https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)#Memory_layout
- QVector4D vecCenter, vecCenter_lowpart;
- for (int i = 0; i < 3; i++)
- QLocationUtils::split_double(center.get(i), &vecCenter[i], &vecCenter_lowpart[i]);
- vecCenter[3] = 0;
- vecCenter_lowpart[3] = 0;
-
- int offset = 0;
- char *buf_p = state.uniformData()->data();
-
- if (state.isMatrixDirty()) {
- const QMatrix4x4 m = state.projectionMatrix();
- memcpy(buf_p + offset, m.constData(), 4*4*4);
- }
- offset += 4*4*4;
-
- memcpy(buf_p + offset, geoProjection.constData(), 4*4*4); offset+=4*4*4;
-
- memcpy(buf_p + offset, &vecCenter, 4*4); offset += 4*4;
-
- memcpy(buf_p + offset, &vecCenter_lowpart, 4*4); offset+=4*4;
-
- const float lineWidth = newMaterial->lineWidth();
- memcpy(buf_p + offset, &lineWidth, 4); offset+=4;
-
- const QRectF viewportRect = state.viewportRect();
- const float aspect = float(viewportRect.width() / viewportRect.height());
- memcpy(buf_p + offset, &aspect, 4); offset+=4;
-
- offset += 4; // Padding
-
- int miter = newMaterial->miter();
- memcpy(buf_p + offset, &miter, 4); offset+=4;
-
- if (oldMaterial == nullptr || c != oldMaterial->color() || state.isOpacityDirty()) {
- float opacity = state.opacity() * c.alphaF();
- QVector4D v(c.redF() * opacity,
- c.greenF() * opacity,
- c.blueF() * opacity,
- opacity);
- memcpy(buf_p + offset, &v, 4*4);
- }
- offset+=4*4;
-
- const float wrapOffset = newMaterial->wrapOffset();
- memcpy(buf_p + offset, &wrapOffset, 4); offset+=4;
-
- return true;
-}
-
-QSGMaterialShader *MapPolylineMaterialExtruded::createShader(QSGRendererInterface::RenderMode renderMode) const
-{
- Q_UNUSED(renderMode);
- return new MapPolylineShaderExtruded();
-}
-
-QSGMaterialType *MapPolylineMaterialExtruded::type() const
-{
- static QSGMaterialType type;
- return &type;
-}
-
-int MapPolylineMaterialExtruded::compare(const QSGMaterial *other) const
-{
- const MapPolylineMaterialExtruded &o = *static_cast<const MapPolylineMaterialExtruded *>(other);
- if (o.m_miter == m_miter)
- return MapPolylineMaterial::compare(other);
- return -1;
-}
-
-QList<QDeclarativeGeoMapItemUtils::vec2> QGeoMapItemLODGeometry::getSimplified(
- QList<QDeclarativeGeoMapItemUtils::vec2>
- &wrappedPath, // reference as it gets copied in the nested call
- double leftBoundWrapped, unsigned int zoom)
-{
- // Try a simplify step
- QList<QDoubleVector2D> data;
- for (auto e: wrappedPath)
- data << e.toDoubleVector2D();
- const QList<QDoubleVector2D> simplified = QGeoSimplify::geoSimplifyZL(data,
- leftBoundWrapped,
- zoom);
-
- data.clear();
- QList<QDeclarativeGeoMapItemUtils::vec2> simple;
- for (auto e: simplified)
- simple << e;
- return simple;
-}
-
-
-bool QGeoMapItemLODGeometry::isLODActive(unsigned int lod) const
-{
- return m_screenVertices == m_verticesLOD[zoomToLOD(lod)].data();
-}
-
-class PolylineSimplifyTask : public QRunnable
-{
-public:
- PolylineSimplifyTask(const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>
- &input, // reference as it gets copied in the nested call
- const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> &output,
- double leftBound, unsigned int zoom, QSharedPointer<unsigned int> &working)
- : m_zoom(zoom), m_leftBound(leftBound), m_input(input), m_output(output), m_working(working)
- {
- Q_ASSERT(!input.isNull());
- Q_ASSERT(!output.isNull());
- }
-
- ~PolylineSimplifyTask() override;
-
- void run() override
- {
- // Skip sending notifications for now. Updated data will be picked up eventually.
- // ToDo: figure out how to connect a signal from here to a slot in the item.
- *m_working = QGeoMapPolylineGeometryOpenGL::zoomToLOD(m_zoom);
- const QList<QDeclarativeGeoMapItemUtils::vec2> res =
- QGeoMapPolylineGeometryOpenGL::getSimplified(
- *m_input, m_leftBound, QGeoMapPolylineGeometryOpenGL::zoomForLOD(m_zoom));
- *m_output = res;
- *m_working = 0;
- }
-
- unsigned int m_zoom;
- double m_leftBound;
- QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> m_input, m_output;
- QSharedPointer<unsigned int> m_working;
-};
-
-void QGeoMapItemLODGeometry::enqueueSimplificationTask(
- const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> &input,
- const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> &output, double leftBound,
- unsigned int zoom, QSharedPointer<unsigned int> &working)
-{
- Q_ASSERT(!input.isNull());
- Q_ASSERT(!output.isNull());
- PolylineSimplifyTask *task = new PolylineSimplifyTask(input,
- output,
- leftBound,
- zoom,
- working);
- threadPool->start(task);
-}
-
-PolylineSimplifyTask::~PolylineSimplifyTask() {}
-
-void QGeoMapItemLODGeometry::selectLOD(unsigned int zoom, double leftBound, bool /* closed */) // closed to tell if this is a polygon or a polyline.
-{
- unsigned int requestedLod = zoomToLOD(zoom);
- if (!m_verticesLOD[requestedLod].isNull()) {
- m_screenVertices = m_verticesLOD[requestedLod].data();
- } else if (!m_verticesLOD.at(0)->isEmpty()) {
- // if here, zoomToLOD != 0 and no current working task.
- // So select the last filled LOD != m_working (lower-bounded by 1,
- // guaranteed to exist), and enqueue the right one
- m_verticesLOD[requestedLod] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
- new QList<QDeclarativeGeoMapItemUtils::vec2>);
-
- for (unsigned int i = requestedLod - 1; i >= 1; i--) {
- if (*m_working != i && !m_verticesLOD[i].isNull()) {
- m_screenVertices = m_verticesLOD[i].data();
- break;
- } else if (i == 1) {
- // get 1 synchronously if not computed already
- m_verticesLOD[1] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
- new QList<QDeclarativeGeoMapItemUtils::vec2>);
- *m_verticesLOD[1] = getSimplified( *m_verticesLOD[0],
- leftBound,
- zoomForLOD(0));
- if (requestedLod == 1)
- return;
- }
- }
-
- enqueueSimplificationTask( m_verticesLOD.at(0),
- m_verticesLOD[requestedLod],
- leftBound,
- zoom,
- m_working);
-
- }
-}
-
-void QGeoMapItemLODGeometry::selectLODOnDataChanged(unsigned int zoom, double leftBound) const
-{
- unsigned int lod = zoomToLOD(zoom);
- if (lod > 0) {
- // Generate ZL 1 as fallback for all cases != 0. Do not do if 0 is requested
- // (= old behavior, LOD disabled)
- m_verticesLOD[1] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
- new QList<QDeclarativeGeoMapItemUtils::vec2>);
- *m_verticesLOD[1] = getSimplified( *m_verticesLOD[0],
- leftBound,
- zoomForLOD(0));
- }
- if (lod > 1) {
- if (!m_verticesLOD[lod])
- m_verticesLOD[lod] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
- new QList<QDeclarativeGeoMapItemUtils::vec2>);
- enqueueSimplificationTask( m_verticesLOD.at(0),
- m_verticesLOD[lod],
- leftBound,
- zoom,
- m_working);
- }
- m_screenVertices = m_verticesLOD[qMin<unsigned int>(lod, 1)].data(); // return only 0,1 synchronously
-}
-
-unsigned int QGeoMapItemLODGeometry::zoomToLOD(unsigned int zoom)
-{
- unsigned int res;
- if (zoom > 20)
- res = 0;
- else
- res = qBound<unsigned int>(3, zoom, 20) / 3; // bound LOD'ing between ZL 3 and 20. Every 3 ZoomLevels
- return res;
-}
-
-unsigned int QGeoMapItemLODGeometry::zoomForLOD(unsigned int zoom)
-{
- unsigned int res = (qBound<unsigned int>(3, zoom, 20) / 3) * 3;
- if (zoom < 6)
- return res;
- return res + 1; // give more resolution when closing in
-}
-
QT_END_NAMESPACE
diff --git a/src/location/quickmapitems/qdeclarativepolylinemapitem_p_p.h b/src/location/quickmapitems/qdeclarativepolylinemapitem_p_p.h
index 3a446a10..676e6f71 100644
--- a/src/location/quickmapitems/qdeclarativepolylinemapitem_p_p.h
+++ b/src/location/quickmapitems/qdeclarativepolylinemapitem_p_p.h
@@ -52,28 +52,20 @@
// We mean it.
//
-#include <QSharedPointer>
#include <QtCore/QScopedValueRollback>
#include <QSGGeometryNode>
#include <QSGFlatColorMaterial>
-#include <QSGMaterialShader>
-#include <QtPositioning/QGeoPath>
-#include <QtPositioning/QGeoPolygon>
-#include <QtPositioning/QGeoRectangle>
-#include <QtPositioning/QGeoCircle>
#include <QtLocation/private/qlocationglobal_p.h>
#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
-#include <QtLocation/private/qdeclarativegeomapitemutils_p.h>
-#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
#include <QtLocation/private/qgeomapitemgeometry_p.h>
#include <QtPositioning/private/qdoublevector2d_p.h>
-#include <array>
-
QT_BEGIN_NAMESPACE
+class QSGMaterialShader;
+
class Q_LOCATION_PRIVATE_EXPORT QGeoMapPolylineGeometry : public QGeoMapItemGeometry
{
public:
@@ -135,72 +127,6 @@ public:
bool isSubtreeBlocked() const override;
};
-class Q_LOCATION_PRIVATE_EXPORT MapPolylineMaterial : public QSGFlatColorMaterial
-{
-public:
- MapPolylineMaterial()
- : QSGFlatColorMaterial()
- {
- // Passing RequiresFullMatrix is essential in order to prevent the
- // batch renderer from baking in simple, translate-only transforms into
- // the vertex data. The shader will rely on the fact that
- // vertexCoord.xy is the Shape-space coordinate and so no modifications
- // are welcome.
- setFlag(Blending | RequiresFullMatrix);
- }
-
- QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
-
- void setGeoProjection(const QMatrix4x4 &p)
- {
- m_geoProjection = p;
- }
-
- QMatrix4x4 geoProjection() const
- {
- return m_geoProjection;
- }
-
- void setCenter(const QDoubleVector3D &c)
- {
- m_center = c;
- }
-
- QDoubleVector3D center() const
- {
- return m_center;
- }
-
- int wrapOffset() const
- {
- return m_wrapOffset;
- }
-
- void setWrapOffset(int wrapOffset)
- {
- m_wrapOffset = wrapOffset;
- }
-
- void setLineWidth(float lw)
- {
- m_lineWidth = lw;
- }
-
- float lineWidth() const
- {
- return m_lineWidth;
- }
-
- QSGMaterialType *type() const override;
- int compare(const QSGMaterial *other) const override;
-
-protected:
- QMatrix4x4 m_geoProjection;
- QDoubleVector3D m_center;
- int m_wrapOffset = 0;
- float m_lineWidth = 1.0;
-};
-
class Q_LOCATION_PRIVATE_EXPORT MapPolylineNode : public MapItemGeometryNode
{
public:
@@ -214,272 +140,6 @@ protected:
QSGGeometry geometry_;
};
-class Q_LOCATION_PRIVATE_EXPORT QGeoMapItemLODGeometry
-{
-public:
- mutable std::array<QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>, 7>
- m_verticesLOD; // fix it to 7,
- // do not allow simplifications beyond ZL 20. This could actually be
- // limited even further
- mutable QList<QDeclarativeGeoMapItemUtils::vec2> *m_screenVertices;
- mutable QSharedPointer<unsigned int> m_working;
-
- QGeoMapItemLODGeometry()
- {
- resetLOD();
- }
-
- void resetLOD()
- {
- // New pointer, some old LOD task might still be running and operating on the old pointers.
- m_verticesLOD[0] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
- new QList<QDeclarativeGeoMapItemUtils::vec2>);
- for (unsigned int i = 1; i < m_verticesLOD.size(); ++i)
- m_verticesLOD[i] = nullptr; // allocate on first use
- m_screenVertices = m_verticesLOD.front().data(); // resetting pointer to data to be LOD 0
- }
-
- static unsigned int zoomToLOD(unsigned int zoom);
-
- static unsigned int zoomForLOD(unsigned int zoom);
-
- bool isLODActive(unsigned int lod) const;
-
- void selectLOD(unsigned int zoom, double leftBound, bool /*closed*/);
-
- static QList<QDeclarativeGeoMapItemUtils::vec2>
- getSimplified(QList<QDeclarativeGeoMapItemUtils::vec2> &wrappedPath, double leftBoundWrapped,
- unsigned int zoom);
-
- static void enqueueSimplificationTask(
- const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>
- &input, // reference as it gets copied in the nested call
- const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> &output,
- double leftBound, unsigned int zoom, QSharedPointer<unsigned int> &working);
-
- void selectLODOnDataChanged(unsigned int zoom, double leftBound) const;
-
- bool selectLODOnLODMismatch(unsigned int zoom, double leftBound, bool closed) const
- {
- if (*m_working > 0) {
- return false;
- }
- const_cast<QGeoMapItemLODGeometry *>(this)->selectLOD(zoom,
- leftBound,
- closed);
- return true;
- }
-};
-
-class Q_LOCATION_PRIVATE_EXPORT QGeoMapPolylineGeometryOpenGL : public QGeoMapItemGeometry, public QGeoMapItemLODGeometry
-{
-public:
- typedef struct {
- QList<QDoubleVector2D> wrappedBboxes;
- } WrappedPolyline;
-
- QGeoMapPolylineGeometryOpenGL()
- {
- m_working = QSharedPointer<unsigned int>(new unsigned int(0));
- }
-
- void updateSourcePoints(const QGeoMap &map,
- const QGeoPolygon &poly);
-
- void updateSourcePoints(const QGeoMap &map,
- const QGeoPath &poly);
-
- void updateSourcePoints(const QGeoProjectionWebMercator &p,
- const QList<QDoubleVector2D> &wrappedPath,
- const QGeoRectangle &boundingRectangle);
-
- void updateSourcePoints(const QGeoMap &map,
- const QGeoRectangle &rect);
-
- void updateSourcePoints(const QGeoMap &map,
- const QGeoCircle &circle);
-
- void updateScreenPoints(const QGeoMap &map,
- qreal strokeWidth,
- bool adjustTranslation = true);
-
- void updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal strokeWidth = 0.0);
-
- bool allocateAndFillEntries(QSGGeometry *geom,
- bool closed = false,
- unsigned int zoom = 0) const;
- void allocateAndFillLineStrip(QSGGeometry *geom,
- int lod = 0) const;
-
- bool contains(const QPointF &point) const override
- {
- Q_UNUSED(point);
- return false;
- }
-
- static double distanceTo(const QDoubleVector2D &a, const QDoubleVector2D &b, const QDoubleVector2D &p)
- {
- double u = ((p.x() - a.x()) * (b.x() - a.x()) + (p.y() - a.y()) * (b.y() - a.y()) ) / (b - a).lengthSquared();
- QDoubleVector2D intersection(a.x() + u * (b.x() - a.x()) , a.y() + u * (b.y() - a.y()) );
-
- QDoubleVector2D candidate = ( (p-a).length() < (p-b).length() ) ? a : b;
-
- if (u > 0 && u < 1
- && (p-intersection).length() < (p-candidate).length() ) // And it falls in the segment
- candidate = intersection;
-
- return qAbs((candidate - p).length());
- }
- // Note: this is also slightly incorrect on joins and in the beginning/end of the line
- bool contains(const QPointF &point, qreal lineWidth, const QGeoProjectionWebMercator &p) const
- {
- const double lineHalfWidth = lineWidth * 0.5;
- const QDoubleVector2D pt(point);
- QDoubleVector2D a;
- if (m_screenVertices->size())
- a = p.wrappedMapProjectionToItemPosition(p.wrapMapProjection(m_screenVertices->first().toDoubleVector2D()));
- QDoubleVector2D b;
- for (qsizetype i = 1; i < m_screenVertices->size(); ++i) {
- const auto &screenVertice = m_screenVertices->at(i);
- if (!a.isFinite()) {
- a = p.wrappedMapProjectionToItemPosition(p.wrapMapProjection(screenVertice.toDoubleVector2D()));
- continue;
- }
-
- b = p.wrappedMapProjectionToItemPosition(p.wrapMapProjection(screenVertice.toDoubleVector2D()));
- if (!b.isFinite()) {
- a = b;
- continue;
- }
-
- if (b == a)
- continue;
-
- // Heavily simplifying it here: if a point is not projectable, skip the segment.
- // For a correct solution, the segment should be clipped instead.
- if (distanceTo(a, b, pt) <= lineHalfWidth)
- return true;
-
- a = b;
- }
- return false;
- }
-
-public:
- QDoubleVector2D m_bboxLeftBoundWrapped;
- QList<WrappedPolyline> m_wrappedPolygons;
- int m_wrapOffset;
-
- friend class QDeclarativeCircleMapItem;
- friend class QDeclarativePolygonMapItem;
- friend class QDeclarativeRectangleMapItem;
-};
-
-class Q_LOCATION_PRIVATE_EXPORT MapPolylineShaderLineStrip : public QSGMaterialShader
-{
-public:
- MapPolylineShaderLineStrip();
-
- bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
-};
-
-class Q_LOCATION_PRIVATE_EXPORT MapPolylineShaderExtruded : public QSGMaterialShader
-{
-public:
- MapPolylineShaderExtruded();
-
- bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
-};
-
-class Q_LOCATION_PRIVATE_EXPORT MapPolylineNodeOpenGLLineStrip : public MapItemGeometryNode
-{
-public:
- MapPolylineNodeOpenGLLineStrip();
- ~MapPolylineNodeOpenGLLineStrip() override;
-
- void update(const QColor &fillColor,
- const qreal lineWidth,
- const QGeoMapPolylineGeometryOpenGL *shape,
- const QMatrix4x4 &geoProjection,
- const QDoubleVector3D &center,
- const Qt::PenCapStyle capStyle = Qt::SquareCap);
-
-protected:
- MapPolylineMaterial fill_material_;
- QSGGeometry geometry_;
-};
-
-class Q_LOCATION_PRIVATE_EXPORT MapPolylineMaterialExtruded : public MapPolylineMaterial
-{
-public:
- MapPolylineMaterialExtruded() : MapPolylineMaterial()
- {
-
- }
- QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
-
- void setMiter(int m)
- {
- m_miter = m;
- }
-
- int miter() const
- {
- return m_miter;
- }
-
- QSGMaterialType *type() const override;
- int compare(const QSGMaterial *other) const override;
-
- int m_miter = 0;
-};
-
-class Q_LOCATION_PRIVATE_EXPORT MapPolylineNodeOpenGLExtruded : public MapItemGeometryNode
-{
-public:
-
- typedef struct MapPolylineEntry {
- QDeclarativeGeoMapItemUtils::vec2 pos;
- QDeclarativeGeoMapItemUtils::vec2 prev;
- QDeclarativeGeoMapItemUtils::vec2 next;
- float direction;
- float triangletype; // es2 does not support int attribs
- float vertextype;
-
- static const QSGGeometry::AttributeSet &attributes()
- {
- static const QSGGeometry::Attribute dataTri[] = {
- QSGGeometry::Attribute::createWithAttributeType(0, 2, QSGGeometry::FloatType, QSGGeometry::PositionAttribute) // pos
- ,QSGGeometry::Attribute::createWithAttributeType(1, 2, QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // next
- ,QSGGeometry::Attribute::createWithAttributeType(2, 2, QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // previous
- ,QSGGeometry::Attribute::createWithAttributeType(3, 1, QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // direction
- ,QSGGeometry::Attribute::createWithAttributeType(4, 1, QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // triangletype
- ,QSGGeometry::Attribute::createWithAttributeType(5, 1, QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // vertextype
- };
- static const QSGGeometry::AttributeSet attrsTri = { 6, sizeof(MapPolylineNodeOpenGLExtruded::MapPolylineEntry), dataTri };
- return attrsTri;
- }
- } MapPolylineEntry;
-
- MapPolylineNodeOpenGLExtruded();
- ~MapPolylineNodeOpenGLExtruded() override;
-
- void update(const QColor &fillColor,
- float lineWidth,
- const QGeoMapPolylineGeometryOpenGL *shape,
- const QMatrix4x4 &geoProjection,
- const QDoubleVector3D &center,
- const Qt::PenCapStyle capStyle = Qt::FlatCap,
- bool closed = false,
- unsigned int zoom = 30);
-
- static const QSGGeometry::AttributeSet &attributesMapPolylineTriangulated();
-
-protected:
- MapPolylineMaterialExtruded fill_material_;
- QSGGeometry m_geometryTriangulating;
-};
-
class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolylineMapItemPrivate
{
public:
@@ -571,170 +231,6 @@ public:
MapPolylineNode *m_node = nullptr;
};
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolylineMapItemPrivateOpenGLLineStrip: public QDeclarativePolylineMapItemPrivate
-{
-public:
-
- QDeclarativePolylineMapItemPrivateOpenGLLineStrip(QDeclarativePolylineMapItem &poly) : QDeclarativePolylineMapItemPrivate(poly)
- {
- }
-
- QDeclarativePolylineMapItemPrivateOpenGLLineStrip(QDeclarativePolylineMapItemPrivate &other)
- : QDeclarativePolylineMapItemPrivate(other)
- {
- }
-
- ~QDeclarativePolylineMapItemPrivateOpenGLLineStrip() override;
- void onLinePropertiesChanged() override
- {
- afterViewportChanged();
- }
- void markSourceDirtyAndUpdate() override
- {
- m_geometry.markSourceDirty();
- m_poly.polishAndUpdate();
- }
- void preserveGeometry()
- {
- m_geometry.setPreserveGeometry(true, m_poly.m_geopath.boundingGeoRectangle().topLeft());
- }
- void onMapSet() override
- {
- markSourceDirtyAndUpdate();
- }
- void onGeoGeometryChanged() override
- {
- preserveGeometry();
- markSourceDirtyAndUpdate();
- }
- void onGeoGeometryUpdated() override
- {
- preserveGeometry();
- markSourceDirtyAndUpdate();
- }
- void onItemGeometryChanged() override
- {
- onGeoGeometryChanged();
- }
- void afterViewportChanged() override
- {
- preserveGeometry();
- m_poly.polishAndUpdate();
- }
- bool contains(const QPointF &point) const override
- {
- return m_geometry.contains(m_poly.mapToItem(m_poly.quickMap(), point),
- m_poly.line()->width(),
- static_cast<const QGeoProjectionWebMercator&>(m_poly.map()->geoProjection()));
- }
- void updatePolish() override
- {
- if (m_poly.m_geopath.path().length() == 0) { // Possibly cleared
- m_geometry.clear();
- m_geometry.clear();
- m_poly.setWidth(0);
- m_poly.setHeight(0);
- return;
- }
-
- QScopedValueRollback<bool> rollback(m_poly.m_updatingGeometry);
- m_poly.m_updatingGeometry = true;
- const qreal lineWidth = m_poly.m_line.width();
- m_geometry.updateSourcePoints(*m_poly.map(), m_poly.m_geopath);
- m_geometry.markScreenDirty();
- m_geometry.updateScreenPoints(*m_poly.map(), lineWidth);
-
- m_poly.setWidth(m_geometry.sourceBoundingBox().width());
- m_poly.setHeight(m_geometry.sourceBoundingBox().height());
- m_poly.setPosition(1.0 * m_geometry.firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
- }
- QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override
- {
- Q_UNUSED(data);
-
- if (!m_node || !oldNode) {
- m_node = new MapPolylineNodeOpenGLLineStrip();
- if (oldNode)
- delete oldNode;
- } else {
- m_node = static_cast<MapPolylineNodeOpenGLLineStrip *>(oldNode);
- }
-
- if (m_geometry.isScreenDirty() || m_poly.m_dirtyMaterial) {
- const QGeoMap *map = m_poly.map();
- const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
- const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
- m_node->update(m_poly.m_line.color(), // This updates only the material if the geometry is unchanged
- m_poly.m_line.width(),
- &m_geometry,
- combinedMatrix,
- cameraCenter);
- m_geometry.setPreserveGeometry(false);
- m_geometry.markClean();
- m_poly.m_dirtyMaterial = false;
- }
- return m_node;
- }
-
- QGeoMapPolylineGeometryOpenGL m_geometry;
- MapPolylineNodeOpenGLLineStrip *m_node = nullptr;
-};
-
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolylineMapItemPrivateOpenGLExtruded: public QDeclarativePolylineMapItemPrivateOpenGLLineStrip
-{
-public:
-
- QDeclarativePolylineMapItemPrivateOpenGLExtruded(QDeclarativePolylineMapItem &poly)
- : QDeclarativePolylineMapItemPrivateOpenGLLineStrip(poly)
- {
- }
-
- QDeclarativePolylineMapItemPrivateOpenGLExtruded(QDeclarativePolylineMapItemPrivate &other)
- : QDeclarativePolylineMapItemPrivateOpenGLLineStrip(other)
- {
- }
-
- ~QDeclarativePolylineMapItemPrivateOpenGLExtruded() override;
-
- QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override
- {
- Q_UNUSED(data);
- const QGeoMap *map = m_poly.map();
- const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map->geoProjection());
- const QMatrix4x4 &combinedMatrix = p.qsgTransform();
- const QDoubleVector3D &cameraCenter = p.centerMercator();
- const QColor &color = m_poly.m_line.color();
- const float lineWidth = m_poly.m_line.width();
-
- MapPolylineNodeOpenGLExtruded *nodeTri = nullptr;
- if (!m_nodeTri || !oldNode) {
- if (oldNode)
- delete oldNode;
- nodeTri = new MapPolylineNodeOpenGLExtruded();
- } else {
- nodeTri = static_cast<MapPolylineNodeOpenGLExtruded *>(oldNode);
- }
-
- //TODO: update only material
- if (m_geometry.isScreenDirty() || m_poly.m_dirtyMaterial) {
- nodeTri->update(color,
- lineWidth ,
- &m_geometry,
- combinedMatrix,
- cameraCenter,
- Qt::FlatCap,
- false,
- m_poly.zoomForLOD(int(map->cameraData().zoomLevel())));
- m_geometry.setPreserveGeometry(false);
- m_geometry.markClean();
- m_poly.m_dirtyMaterial = false;
- }
- m_nodeTri = nodeTri;
- return nodeTri;
- }
-
- MapPolylineNodeOpenGLExtruded *m_nodeTri = nullptr;
-};
QT_END_NAMESPACE
#endif // QDECLARATIVEPOLYLINEMAPITEM_P_P_H
diff --git a/src/location/quickmapitems/qdeclarativerectanglemapitem.cpp b/src/location/quickmapitems/qdeclarativerectanglemapitem.cpp
index dcce6f42..20930d40 100644
--- a/src/location/quickmapitems/qdeclarativerectanglemapitem.cpp
+++ b/src/location/quickmapitems/qdeclarativerectanglemapitem.cpp
@@ -39,6 +39,7 @@
#include "qdeclarativerectanglemapitem_p.h"
#include "qdeclarativerectanglemapitem_p_p.h"
+#include "rhi/qdeclarativerectanglemapitem_rhi_p.h"
#include "qdeclarativepolygonmapitem_p.h"
#include <QtCore/QScopedValueRollback>
@@ -491,6 +492,4 @@ bool QDeclarativeRectangleMapItemPrivateCPU::contains(const QPointF &point) cons
return (m_geometry.contains(point) || m_borderGeometry.contains(point));
}
-QDeclarativeRectangleMapItemPrivateOpenGL::~QDeclarativeRectangleMapItemPrivateOpenGL() {}
-
QT_END_NAMESPACE
diff --git a/src/location/quickmapitems/qdeclarativerectanglemapitem_p_p.h b/src/location/quickmapitems/qdeclarativerectanglemapitem_p_p.h
index 1c4d2bc0..4f76d445 100644
--- a/src/location/quickmapitems/qdeclarativerectanglemapitem_p_p.h
+++ b/src/location/quickmapitems/qdeclarativerectanglemapitem_p_p.h
@@ -138,173 +138,6 @@ public:
MapPolygonNode *m_node = nullptr;
};
-class Q_LOCATION_PRIVATE_EXPORT QDeclarativeRectangleMapItemPrivateOpenGL: public QDeclarativeRectangleMapItemPrivate
-{
-public:
- QDeclarativeRectangleMapItemPrivateOpenGL(QDeclarativeRectangleMapItem &rect) : QDeclarativeRectangleMapItemPrivate(rect)
- {
- }
-
- QDeclarativeRectangleMapItemPrivateOpenGL(QDeclarativeRectangleMapItemPrivate &other)
- : QDeclarativeRectangleMapItemPrivate(other)
- {
- }
-
- ~QDeclarativeRectangleMapItemPrivateOpenGL() override;
-
- void markScreenDirtyAndUpdate()
- {
- // preserveGeometry is cleared in updateMapItemPaintNode
- m_geometry.markScreenDirty();
- m_borderGeometry.markScreenDirty();
- m_rect.polishAndUpdate();
- }
- void onLinePropertiesChanged() override
- {
- m_rect.m_dirtyMaterial = true;
- afterViewportChanged();
- }
- void markSourceDirtyAndUpdate() override
- {
- m_geometry.markSourceDirty();
- m_borderGeometry.markSourceDirty();
- m_rect.polishAndUpdate();
- }
- void preserveGeometry()
- {
- m_geometry.setPreserveGeometry(true, m_rect.m_rectangle.topLeft());
- m_borderGeometry.setPreserveGeometry(true, m_rect.m_rectangle.topLeft());
- }
- void onMapSet() override
- {
- markSourceDirtyAndUpdate();
- }
- void onGeoGeometryChanged() override
- {
- preserveGeometry();
- markSourceDirtyAndUpdate();
- }
- void onItemGeometryChanged() override
- {
- onGeoGeometryChanged();
- }
- void afterViewportChanged() override
- {
- preserveGeometry();
- markScreenDirtyAndUpdate();
- }
- void updatePolish() override
- {
- if (!m_rect.topLeft().isValid() || !m_rect.bottomRight().isValid()) {
- m_geometry.clear();
- m_borderGeometry.clear();
- m_rect.setWidth(0);
- m_rect.setHeight(0);
- return;
- }
-
- QScopedValueRollback<bool> rollback(m_rect.m_updatingGeometry);
- m_rect.m_updatingGeometry = true;
- const qreal lineWidth = m_rect.m_border.width();
- const QColor &lineColor = m_rect.m_border.color();
- const QColor &fillColor = m_rect.color();
- if (fillColor.alpha() != 0) {
- m_geometry.updateSourcePoints(*m_rect.map(), m_rect.m_rectangle);
- m_geometry.markScreenDirty();
- m_geometry.updateScreenPoints(*m_rect.map(), lineWidth, lineColor);
- } else {
- m_geometry.clearBounds();
- }
-
- QGeoMapItemGeometry * geom = &m_geometry;
- m_borderGeometry.clearScreen();
- if (lineColor.alpha() != 0 && lineWidth > 0) {
- m_borderGeometry.updateSourcePoints(*m_rect.map(), m_rect.m_rectangle);
- m_borderGeometry.markScreenDirty();
- m_borderGeometry.updateScreenPoints(*m_rect.map(), lineWidth);
- geom = &m_borderGeometry;
- }
- m_rect.setWidth(geom->sourceBoundingBox().width());
- m_rect.setHeight(geom->sourceBoundingBox().height());
- m_rect.setPosition(1.0 * geom->firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
- }
-
- QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override
- {
- Q_UNUSED(data);
-
- if (!m_rootNode || !oldNode) {
- m_rootNode = new QDeclarativePolygonMapItemPrivateOpenGL::RootNode();
- m_node = new MapPolygonNodeGL();
- m_rootNode->appendChildNode(m_node);
- m_polylinenode = new MapPolylineNodeOpenGLExtruded();
- m_rootNode->appendChildNode(m_polylinenode);
- m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
- if (oldNode)
- delete oldNode;
- } else {
- m_rootNode = static_cast<QDeclarativePolygonMapItemPrivateOpenGL::RootNode *>(oldNode);
- }
-
- const QGeoMap *map = m_rect.map();
- const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
- const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
-
- if (m_borderGeometry.isScreenDirty()) {
- /* Do the border update first */
- m_polylinenode->update(m_rect.m_border.color(),
- float(m_rect.m_border.width()),
- &m_borderGeometry,
- combinedMatrix,
- cameraCenter,
- Qt::SquareCap,
- true,
- 30); // No LOD for rectangles
- m_borderGeometry.setPreserveGeometry(false);
- m_borderGeometry.markClean();
- } else {
- m_polylinenode->setSubtreeBlocked(true);
- }
- if (m_geometry.isScreenDirty()) {
- m_node->update(m_rect.m_color,
- &m_geometry,
- combinedMatrix,
- cameraCenter);
- m_geometry.setPreserveGeometry(false);
- m_geometry.markClean();
- } else {
- m_node->setSubtreeBlocked(true);
- }
-
- m_rootNode->setSubtreeBlocked(false);
- return m_rootNode;
- }
- bool contains(const QPointF &point) const override
- {
- const qreal lineWidth = m_rect.m_border.width();
- const QColor &lineColor = m_rect.m_border.color();
- const QRectF &bounds = (lineColor.alpha() != 0 && lineWidth > 0) ? m_borderGeometry.sourceBoundingBox() : m_geometry.sourceBoundingBox();
- if (bounds.contains(point)) {
- QDeclarativeGeoMap *m = m_rect.quickMap();
- if (m) {
- const QGeoCoordinate crd = m->toCoordinate(m->mapFromItem(&m_rect, point));
- return m_rect.m_rectangle.contains(crd) || m_borderGeometry.contains(m_rect.mapToItem(m_rect.quickMap(), point),
- m_rect.border()->width(),
- static_cast<const QGeoProjectionWebMercator&>(m_rect.map()->geoProjection()));
- } else {
- return true;
- }
- }
- return false;
- }
-
- QGeoMapPolygonGeometryOpenGL m_geometry;
- QGeoMapPolylineGeometryOpenGL m_borderGeometry;
- QDeclarativePolygonMapItemPrivateOpenGL::RootNode *m_rootNode = nullptr;
- MapPolygonNodeGL *m_node = nullptr;
- MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
-};
-
QT_END_NAMESPACE
#endif // QDECLARATIVERECTANGLEMAPITEM_P_P_H
diff --git a/src/location/quickmapitems/rhi/qdeclarativecirclemapitem_rhi.cpp b/src/location/quickmapitems/rhi/qdeclarativecirclemapitem_rhi.cpp
new file mode 100644
index 00000000..0a09aa4e
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qdeclarativecirclemapitem_rhi.cpp
@@ -0,0 +1,158 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2022 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtLocation module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL3 included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 3 requirements
+ ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 2.0 or (at your option) the GNU General
+ ** Public license version 3 or any later version approved by the KDE Free
+ ** Qt Foundation. The licenses are as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+ ** https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qdeclarativecirclemapitem_rhi_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeCircleMapItemPrivateOpenGL::~QDeclarativeCircleMapItemPrivateOpenGL() {}
+
+void QDeclarativeCircleMapItemPrivateOpenGL::updatePolish()
+{
+ if (m_circle.m_circle.isEmpty()) {
+ m_geometry.clear();
+ m_borderGeometry.clear();
+ m_circle.setWidth(0);
+ m_circle.setHeight(0);
+ return;
+ }
+
+ QScopedValueRollback<bool> rollback(m_circle.m_updatingGeometry);
+ m_circle.m_updatingGeometry = true;
+ const qreal lineWidth = m_circle.m_border.width();
+ const QColor &lineColor = m_circle.m_border.color();
+ const QColor &fillColor = m_circle.color();
+ if (fillColor.alpha() != 0) {
+ m_geometry.updateSourcePoints(*m_circle.map(), m_circlePath);
+ m_geometry.markScreenDirty();
+ m_geometry.updateScreenPoints(*m_circle.map(), lineWidth, lineColor);
+ } else {
+ m_geometry.clearBounds();
+ }
+
+ QGeoMapItemGeometry * geom = &m_geometry;
+ m_borderGeometry.clearScreen();
+ if (lineColor.alpha() != 0 && lineWidth > 0) {
+ m_borderGeometry.updateSourcePoints(*m_circle.map(), m_circle.m_circle);
+ m_borderGeometry.markScreenDirty();
+ m_borderGeometry.updateScreenPoints(*m_circle.map(), lineWidth);
+ geom = &m_borderGeometry;
+ }
+ m_circle.setWidth(geom->sourceBoundingBox().width());
+ m_circle.setHeight(geom->sourceBoundingBox().height());
+ m_circle.setPosition(1.0 * geom->firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
+}
+
+QSGNode *QDeclarativeCircleMapItemPrivateOpenGL::updateMapItemPaintNode(QSGNode *oldNode,
+ QQuickItem::UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+
+ if (!m_rootNode || !oldNode) {
+ m_rootNode = new QDeclarativePolygonMapItemPrivateOpenGL::RootNode();
+ m_node = new MapPolygonNodeGL();
+ m_rootNode->appendChildNode(m_node);
+ m_polylinenode = new MapPolylineNodeOpenGLExtruded();
+ m_rootNode->appendChildNode(m_polylinenode);
+ m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
+ if (oldNode)
+ delete oldNode;
+ } else {
+ m_rootNode = static_cast<QDeclarativePolygonMapItemPrivateOpenGL::RootNode *>(oldNode);
+ }
+
+ const QGeoMap *map = m_circle.map();
+ const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
+ const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
+
+ if (m_borderGeometry.isScreenDirty()) {
+ /* Do the border update first */
+ m_polylinenode->update(m_circle.m_border.color(),
+ float(m_circle.m_border.width()),
+ &m_borderGeometry,
+ combinedMatrix,
+ cameraCenter,
+ Qt::SquareCap,
+ true,
+ 30); // No LOD for circles
+ m_borderGeometry.setPreserveGeometry(false);
+ m_borderGeometry.markClean();
+ } else {
+ m_polylinenode->setSubtreeBlocked(true);
+ }
+ if (m_geometry.isScreenDirty()) {
+ m_node->update(m_circle.m_color,
+ &m_geometry,
+ combinedMatrix,
+ cameraCenter);
+ m_geometry.setPreserveGeometry(false);
+ m_geometry.markClean();
+ } else {
+ m_node->setSubtreeBlocked(true);
+ }
+
+ m_rootNode->setSubtreeBlocked(false);
+ return m_rootNode;
+}
+
+bool QDeclarativeCircleMapItemPrivateOpenGL::contains(const QPointF &point) const
+{
+ const qreal lineWidth = m_circle.m_border.width();
+ const QColor &lineColor = m_circle.m_border.color();
+ const QRectF &bounds = (lineColor.alpha() != 0 && lineWidth > 0)
+ ? m_borderGeometry.sourceBoundingBox()
+ : m_geometry.sourceBoundingBox();
+ if (bounds.contains(point)) {
+ QDeclarativeGeoMap *m = m_circle.quickMap();
+ if (m) {
+ const QGeoCoordinate crd = m->toCoordinate(m->mapFromItem(&m_circle, point));
+ const auto &projection = static_cast<const QGeoProjectionWebMercator&>(
+ m_circle.map()->geoProjection());
+ return m_circle.m_circle.contains(crd)
+ || m_borderGeometry.contains(m_circle.mapToItem(m_circle.quickMap(), point),
+ m_circle.border()->width(), projection);
+ } else {
+ return true;
+ }
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/location/quickmapitems/rhi/qdeclarativecirclemapitem_rhi_p.h b/src/location/quickmapitems/rhi/qdeclarativecirclemapitem_rhi_p.h
new file mode 100644
index 00000000..9bf60106
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qdeclarativecirclemapitem_rhi_p.h
@@ -0,0 +1,133 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Paolo Angelelli <paolo.angelelli@gmail.com>
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVECIRCLEMAPITEM_RHI_P_H
+#define QDECLARATIVECIRCLEMAPITEM_RHI_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativecirclemapitem_p_p.h>
+#include <QtLocation/private/qdeclarativepolygonmapitem_p_p.h>
+
+#include "qdeclarativepolygonmapitem_rhi_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeCircleMapItemPrivateOpenGL: public QDeclarativeCircleMapItemPrivate
+{
+public:
+ QDeclarativeCircleMapItemPrivateOpenGL(QDeclarativeCircleMapItem &circle) : QDeclarativeCircleMapItemPrivate(circle)
+ {
+ }
+
+ QDeclarativeCircleMapItemPrivateOpenGL(QDeclarativeCircleMapItemPrivate &other)
+ : QDeclarativeCircleMapItemPrivate(other)
+ {
+ }
+
+ ~QDeclarativeCircleMapItemPrivateOpenGL() override;
+
+ void onLinePropertiesChanged() override
+ {
+ m_circle.m_dirtyMaterial = true;
+ afterViewportChanged();
+ }
+ void markScreenDirtyAndUpdate()
+ {
+ // preserveGeometry is cleared in updateMapItemPaintNode
+ m_geometry.markScreenDirty();
+ m_borderGeometry.markScreenDirty();
+ m_circle.polishAndUpdate();
+ }
+ void markSourceDirtyAndUpdate() override
+ {
+ updateCirclePath();
+ preserveGeometry();
+ m_geometry.markSourceDirty();
+ m_borderGeometry.markSourceDirty();
+ m_circle.polishAndUpdate();
+ }
+ void preserveGeometry()
+ {
+ m_geometry.setPreserveGeometry(true, m_leftBound);
+ m_borderGeometry.setPreserveGeometry(true, m_leftBound);
+ }
+ void onMapSet() override
+ {
+ markSourceDirtyAndUpdate();
+ }
+ void onGeoGeometryChanged() override
+ {
+
+ markSourceDirtyAndUpdate();
+ }
+ void onItemGeometryChanged() override
+ {
+ onGeoGeometryChanged();
+ }
+ void afterViewportChanged() override
+ {
+ preserveGeometry();
+ markScreenDirtyAndUpdate();
+ }
+ void updatePolish() override;
+ QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override;
+ bool contains(const QPointF &point) const override;
+
+ QGeoMapPolygonGeometryOpenGL m_geometry;
+ QGeoMapPolylineGeometryOpenGL m_borderGeometry;
+ QDeclarativePolygonMapItemPrivateOpenGL::RootNode *m_rootNode = nullptr;
+ MapPolygonNodeGL *m_node = nullptr;
+ MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVECIRCLEMAPITEM_RHI_P_H
diff --git a/src/location/quickmapitems/rhi/qdeclarativepolygonmapitem_rhi.cpp b/src/location/quickmapitems/rhi/qdeclarativepolygonmapitem_rhi.cpp
new file mode 100644
index 00000000..1dd5efea
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qdeclarativepolygonmapitem_rhi.cpp
@@ -0,0 +1,303 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2022 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtLocation module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL3 included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 3 requirements
+ ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 2.0 or (at your option) the GNU General
+ ** Public license version 3 or any later version approved by the KDE Free
+ ** Qt Foundation. The licenses are as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+ ** https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qdeclarativegeomapitemutils_p.h"
+#include "qdeclarativepolygonmapitem_p.h"
+#include "qdeclarativepolylinemapitem_p_p.h"
+#include "qdeclarativepolygonmapitem_p_p.h"
+#include "qdeclarativepolygonmapitem_rhi_p.h"
+#include "qdeclarativerectanglemapitem_p_p.h"
+#include "error_messages_p.h"
+
+#include <QtCore/QScopedValueRollback>
+#include <qnumeric.h>
+#include <QPainter>
+#include <QPainterPath>
+#include <QtQml/QQmlInfo>
+#include <QtQuick/qsgnode.h>
+
+#include <QtQuick/private/qsgmaterialshader_p.h>
+#include <QtLocation/private/qgeomap_p.h>
+#include <QtPositioning/private/qlocationutils_p.h>
+#include <QtPositioning/private/qdoublevector2d_p.h>
+#include <QtPositioning/private/qclipperutils_p.h>
+#include <QtPositioning/private/qgeopolygon_p.h>
+#include <QtPositioning/private/qwebmercator_p.h>
+
+QT_BEGIN_NAMESPACE
+
+MapPolygonShader::MapPolygonShader() : QSGMaterialShader(*new QSGMaterialShaderPrivate(this))
+{
+ setShaderFileName(VertexStage, QLatin1String(":/location/quickmapitems/rhi/shaders/polygon.vert.qsb"));
+ setShaderFileName(FragmentStage, QLatin1String(":/location/quickmapitems/rhi/shaders/polygon.frag.qsb"));
+}
+
+bool MapPolygonShader::updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type());
+ MapPolygonMaterial *oldMaterial = static_cast<MapPolygonMaterial *>(oldEffect);
+ MapPolygonMaterial *newMaterial = static_cast<MapPolygonMaterial *>(newEffect);
+
+ const QColor &c = newMaterial->color();
+ const QMatrix4x4 &geoProjection = newMaterial->geoProjection();
+ const QDoubleVector3D &center = newMaterial->center();
+
+ // It is safer to use vec4 instead on vec3, as described in:
+ // https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)#Memory_layout
+ QVector4D vecCenter, vecCenter_lowpart;
+ for (int i = 0; i < 3; i++)
+ QLocationUtils::split_double(center.get(i), &vecCenter[i], &vecCenter_lowpart[i]);
+ vecCenter[3] = 0;
+ vecCenter_lowpart[3] = 0;
+
+ int offset = 0;
+ char *buf_p = state.uniformData()->data();
+
+ if (state.isMatrixDirty()) {
+ const QMatrix4x4 m = state.projectionMatrix();
+ memcpy(buf_p + offset, m.constData(), 4*4*4);
+ }
+ offset += 4*4*4;
+
+ memcpy(buf_p + offset, geoProjection.constData(), 4*4*4); offset+=4*4*4;
+
+ memcpy(buf_p + offset, &vecCenter, 4*4); offset += 4*4;
+
+ memcpy(buf_p + offset, &vecCenter_lowpart, 4*4); offset+=4*4;
+
+ const float wrapOffset = newMaterial->wrapOffset();
+ memcpy(buf_p + offset, &wrapOffset, 4); offset+=4;
+
+ offset += 4+4+4; // Padding
+
+ if (oldMaterial == nullptr || c != oldMaterial->color() || state.isOpacityDirty()) {
+ float opacity = state.opacity() * c.alphaF();
+ QVector4D v(c.redF() * opacity,
+ c.greenF() * opacity,
+ c.blueF() * opacity,
+ opacity);
+ memcpy(buf_p + offset, &v, 4*4);
+ }
+ offset+=4*4;
+
+ return true;
+}
+
+QSGMaterialShader *MapPolygonMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
+{
+ Q_UNUSED(renderMode);
+ return new MapPolygonShader();
+}
+
+int MapPolygonMaterial::compare(const QSGMaterial *other) const
+{
+ const MapPolygonMaterial &o = *static_cast<const MapPolygonMaterial *>(other);
+ if (o.m_center == m_center && o.m_geoProjection == m_geoProjection && o.m_wrapOffset == m_wrapOffset)
+ return QSGFlatColorMaterial::compare(other);
+ return -1;
+}
+
+QSGMaterialType *MapPolygonMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+MapPolygonNodeGL::MapPolygonNodeGL() :
+ //fill_material_(this),
+ fill_material_(),
+ geometry_(QSGGeometry::defaultAttributes_Point2D(), 0)
+{
+ geometry_.setDrawingMode(QSGGeometry::DrawTriangles);
+ QSGGeometryNode::setMaterial(&fill_material_);
+ QSGGeometryNode::setGeometry(&geometry_);
+}
+
+MapPolygonNodeGL::~MapPolygonNodeGL()
+{
+}
+
+/*!
+ \internal
+*/
+void MapPolygonNodeGL::update(const QColor &fillColor,
+ const QGeoMapPolygonGeometryOpenGL *fillShape,
+ const QMatrix4x4 &geoProjection,
+ const QDoubleVector3D &center)
+{
+ if (fillShape->m_screenIndices.size() < 3 || fillColor.alpha() == 0) {
+ setSubtreeBlocked(true);
+ return;
+ }
+ setSubtreeBlocked(false);
+
+ QSGGeometry *fill = QSGGeometryNode::geometry();
+ if (fillShape->m_dataChanged || !fill->vertexCount()) {
+ fillShape->allocateAndFillPolygon(fill);
+ markDirty(DirtyGeometry);
+ fillShape->m_dataChanged = false;
+ }
+
+ //if (fillColor != fill_material_.color()) // Any point in optimizing this?
+ {
+ fill_material_.setColor(fillColor);
+ fill_material_.setGeoProjection(geoProjection);
+ fill_material_.setCenter(center);
+ fill_material_.setWrapOffset(fillShape->m_wrapOffset - 1);
+ setMaterial(&fill_material_);
+ markDirty(DirtyMaterial);
+ }
+}
+
+QDeclarativePolygonMapItemPrivateOpenGL::~QDeclarativePolygonMapItemPrivateOpenGL() {}
+
+
+void QDeclarativePolygonMapItemPrivateOpenGL::updatePolish()
+{
+ if (m_poly.m_geopoly.perimeter().length() == 0) { // Possibly cleared
+ m_geometry.clear();
+ m_borderGeometry.clear();
+ m_poly.setWidth(0);
+ m_poly.setHeight(0);
+ return;
+ }
+
+ QScopedValueRollback<bool> rollback(m_poly.m_updatingGeometry);
+ m_poly.m_updatingGeometry = true;
+ const qreal lineWidth = m_poly.m_border.width();
+ const QColor &lineColor = m_poly.m_border.color();
+ const QColor &fillColor = m_poly.color();
+ if (fillColor.alpha() != 0) {
+ m_geometry.updateSourcePoints(*m_poly.map(), m_poly.m_geopoly);
+ m_geometry.markScreenDirty();
+ m_geometry.updateScreenPoints(*m_poly.map(), lineWidth, lineColor);
+ } else {
+ m_geometry.clearBounds();
+ }
+
+ QGeoMapItemGeometry * geom = &m_geometry;
+ m_borderGeometry.clearScreen();
+ if (lineColor.alpha() != 0 && lineWidth > 0) {
+ m_borderGeometry.updateSourcePoints(*m_poly.map(), m_poly.m_geopoly);
+ m_borderGeometry.markScreenDirty();
+ m_borderGeometry.updateScreenPoints(*m_poly.map(), lineWidth);
+ geom = &m_borderGeometry;
+ }
+ m_poly.setWidth(geom->sourceBoundingBox().width());
+ m_poly.setHeight(geom->sourceBoundingBox().height());
+ m_poly.setPosition(1.0 * geom->firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
+}
+
+QSGNode *QDeclarativePolygonMapItemPrivateOpenGL::updateMapItemPaintNode(QSGNode *oldNode,
+ QQuickItem::UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+
+ if (!m_rootNode || !oldNode) {
+ m_rootNode = new RootNode();
+ m_node = new MapPolygonNodeGL();
+ m_rootNode->appendChildNode(m_node);
+ m_polylinenode = new MapPolylineNodeOpenGLExtruded();
+ m_rootNode->appendChildNode(m_polylinenode);
+ m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
+ if (oldNode)
+ delete oldNode;
+ } else {
+ m_rootNode = static_cast<RootNode *>(oldNode);
+ }
+
+ const QGeoMap *map = m_poly.map();
+ const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
+ const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
+
+ if (m_borderGeometry.isScreenDirty()) {
+ /* Do the border update first */
+ m_polylinenode->update(m_poly.m_border.color(),
+ float(m_poly.m_border.width()),
+ &m_borderGeometry,
+ combinedMatrix,
+ cameraCenter,
+ Qt::SquareCap,
+ true,
+ 30); // No LOD for polygons just yet.
+ // First figure out what to do with holes.
+ m_borderGeometry.setPreserveGeometry(false);
+ m_borderGeometry.markClean();
+ } else {
+ m_polylinenode->setSubtreeBlocked(true);
+ }
+ if (m_geometry.isScreenDirty()) {
+ m_node->update(m_poly.m_color,
+ &m_geometry,
+ combinedMatrix,
+ cameraCenter);
+ m_geometry.setPreserveGeometry(false);
+ m_geometry.markClean();
+ } else {
+ m_node->setSubtreeBlocked(true);
+ }
+
+ m_rootNode->setSubtreeBlocked(false);
+ return m_rootNode;
+}
+
+bool QDeclarativePolygonMapItemPrivateOpenGL::contains(const QPointF &point) const
+{
+ const qreal lineWidth = m_poly.m_border.width();
+ const QColor &lineColor = m_poly.m_border.color();
+ const QRectF &bounds = (lineColor.alpha() != 0 && lineWidth > 0)
+ ? m_borderGeometry.sourceBoundingBox()
+ : m_geometry.sourceBoundingBox();
+ if (bounds.contains(point)) {
+ QDeclarativeGeoMap *m = m_poly.quickMap();
+ if (m) {
+ const QGeoCoordinate crd = m->toCoordinate(m->mapFromItem(&m_poly, point));
+ const auto &projection = static_cast<const QGeoProjectionWebMercator&>(
+ m_poly.map()->geoProjection());
+ return m_poly.m_geopoly.contains(crd)
+ || m_borderGeometry.contains(m_poly.mapToItem(m_poly.quickMap(), point),
+ m_poly.border()->width(), projection);
+ } else {
+ return true;
+ }
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/quickmapitems/rhi/qdeclarativepolygonmapitem_rhi_p.h b/src/location/quickmapitems/rhi/qdeclarativepolygonmapitem_rhi_p.h
new file mode 100644
index 00000000..5d178aad
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qdeclarativepolygonmapitem_rhi_p.h
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Paolo Angelelli <paolo.angelelli@gmail.com>
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPOLYGONMAPITEM_RHI_P_H
+#define QDECLARATIVEPOLYGONMAPITEM_RHI_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QList>
+#include <QtCore/QScopedValueRollback>
+#include <QtGui/QMatrix4x4>
+#include <QColor>
+
+#include <QSGGeometryNode>
+#include <QSGFlatColorMaterial>
+
+#include <QtPositioning/QGeoPath>
+#include <QtPositioning/QGeoRectangle>
+#include <QtPositioning/QGeoPolygon>
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qgeomapitemgeometry_p.h>
+#include <QtLocation/private/qdeclarativegeomapitembase_p.h>
+#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
+#include <QtLocation/private/qdeclarativepolygonmapitem_p.h>
+#include <QtLocation/private/qdeclarativepolygonmapitem_p_p.h>
+#include <QtLocation/private/qdeclarativepolylinemapitem_rhi_p.h>
+#include <QtPositioning/private/qdoublevector2d_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolygonMaterial : public QSGFlatColorMaterial
+{
+public:
+ MapPolygonMaterial()
+ : QSGFlatColorMaterial()
+ {
+ // Passing RequiresFullMatrix is essential in order to prevent the
+ // batch renderer from baking in simple, translate-only transforms into
+ // the vertex data. The shader will rely on the fact that
+ // vertexCoord.xy is the Shape-space coordinate and so no modifications
+ // are welcome.
+ setFlag(Blending | RequiresFullMatrix);
+ }
+
+ QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
+
+ void setGeoProjection(const QMatrix4x4 &p)
+ {
+ m_geoProjection = p;
+ }
+
+ QMatrix4x4 geoProjection() const
+ {
+ return m_geoProjection;
+ }
+
+ void setCenter(const QDoubleVector3D &c)
+ {
+ m_center = c;
+ }
+
+ QDoubleVector3D center() const
+ {
+ return m_center;
+ }
+
+ int wrapOffset() const
+ {
+ return m_wrapOffset;
+ }
+
+ void setWrapOffset(int wrapOffset)
+ {
+ m_wrapOffset = wrapOffset;
+ }
+
+ int compare(const QSGMaterial *other) const override;
+ QSGMaterialType *type() const override;
+
+protected:
+ QMatrix4x4 m_geoProjection;
+ QDoubleVector3D m_center;
+ int m_wrapOffset = 0;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolygonShader : public QSGMaterialShader
+{
+public:
+ MapPolygonShader();
+
+ bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolygonNodeGL : public MapItemGeometryNode
+{
+
+public:
+ MapPolygonNodeGL();
+ ~MapPolygonNodeGL() override;
+
+ void update(const QColor &fillColor,
+ const QGeoMapPolygonGeometryOpenGL *fillShape,
+ const QMatrix4x4 &geoProjection,
+ const QDoubleVector3D &center);
+
+ MapPolygonMaterial fill_material_;
+ QSGGeometry geometry_;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolygonMapItemPrivateOpenGL: public QDeclarativePolygonMapItemPrivate
+{
+public:
+ struct RootNode : public QSGNode /*QSGTransformNode*/, public VisibleNode
+ {
+ RootNode() { }
+
+ bool isSubtreeBlocked() const override
+ {
+ return subtreeBlocked();
+ }
+ };
+
+ QDeclarativePolygonMapItemPrivateOpenGL(QDeclarativePolygonMapItem &polygon) : QDeclarativePolygonMapItemPrivate(polygon)
+ {
+ }
+
+ QDeclarativePolygonMapItemPrivateOpenGL(QDeclarativePolygonMapItemPrivate &other)
+ : QDeclarativePolygonMapItemPrivate(other)
+ {
+ }
+
+ ~QDeclarativePolygonMapItemPrivateOpenGL() override;
+
+ void markScreenDirtyAndUpdate()
+ {
+ // preserveGeometry is cleared in updateMapItemPaintNode
+ m_geometry.markScreenDirty();
+ m_borderGeometry.markScreenDirty();
+ m_poly.polishAndUpdate();
+ }
+ void onLinePropertiesChanged() override
+ {
+ m_poly.m_dirtyMaterial = true;
+ afterViewportChanged();
+ }
+ void markSourceDirtyAndUpdate() override
+ {
+ // preserveGeometry is cleared in updateMapItemPaintNode
+ m_geometry.markSourceDirty();
+ m_borderGeometry.markSourceDirty();
+ m_poly.polishAndUpdate();
+ }
+ void preserveGeometry()
+ {
+ m_geometry.setPreserveGeometry(true, m_poly.m_geopoly.boundingGeoRectangle().topLeft());
+ m_borderGeometry.setPreserveGeometry(true, m_poly.m_geopoly.boundingGeoRectangle().topLeft());
+ }
+ void afterViewportChanged() override // This is called when the camera changes, or visibleArea changes.
+ {
+ // preserveGeometry is cleared in updateMapItemPaintNode
+ preserveGeometry();
+ markScreenDirtyAndUpdate();
+ }
+ void onMapSet() override
+ {
+ markSourceDirtyAndUpdate();
+ }
+ void onGeoGeometryChanged() override
+ {
+ preserveGeometry();
+ markSourceDirtyAndUpdate();
+ }
+ void onGeoGeometryUpdated() override
+ {
+ preserveGeometry();
+ markSourceDirtyAndUpdate();
+ }
+ void onItemGeometryChanged() override
+ {
+ onGeoGeometryChanged();
+ }
+ void updatePolish() override;
+ QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override;
+ bool contains(const QPointF &point) const override;
+
+ QGeoMapPolygonGeometryOpenGL m_geometry;
+ QGeoMapPolylineGeometryOpenGL m_borderGeometry;
+ RootNode *m_rootNode = nullptr;
+ MapPolygonNodeGL *m_node = nullptr;
+ MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
+};
+
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEPOLYGONMAPITEM_RHI_P_H
diff --git a/src/location/quickmapitems/rhi/qdeclarativepolylinemapitem_rhi.cpp b/src/location/quickmapitems/rhi/qdeclarativepolylinemapitem_rhi.cpp
new file mode 100644
index 00000000..b7ddf22a
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qdeclarativepolylinemapitem_rhi.cpp
@@ -0,0 +1,517 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2022 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtLocation module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL3 included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 3 requirements
+ ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 2.0 or (at your option) the GNU General
+ ** Public license version 3 or any later version approved by the KDE Free
+ ** Qt Foundation. The licenses are as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+ ** https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qdeclarativepolygonmapitem_rhi_p.h"
+
+#include <QtQuick/private/qsgmaterialshader_p.h>
+#include <QtPositioning/private/qlocationutils_p.h>
+
+QT_BEGIN_NAMESPACE
+
+MapPolylineNodeOpenGLLineStrip::MapPolylineNodeOpenGLLineStrip()
+: geometry_(QSGGeometry::defaultAttributes_Point2D(), 0)
+{
+ geometry_.setDrawingMode(QSGGeometry::DrawLineStrip);
+ QSGGeometryNode::setMaterial(&fill_material_);
+ QSGGeometryNode::setGeometry(&geometry_);
+}
+
+MapPolylineNodeOpenGLLineStrip::~MapPolylineNodeOpenGLLineStrip()
+{
+
+}
+
+void MapPolylineNodeOpenGLLineStrip::update(const QColor &fillColor,
+ const qreal lineWidth,
+ const QGeoMapPolylineGeometryOpenGL *shape,
+ const QMatrix4x4 &geoProjection,
+ const QDoubleVector3D &center,
+ const Qt::PenCapStyle /*capStyle*/)
+{
+ if (shape->m_screenVertices->size() < 2) {
+ setSubtreeBlocked(true);
+ return;
+ } else {
+ setSubtreeBlocked(false);
+ }
+
+ QSGGeometry *fill = QSGGeometryNode::geometry();
+ if (shape->m_dataChanged) {
+ shape->allocateAndFillLineStrip(fill);
+ markDirty(DirtyGeometry);
+ shape->m_dataChanged = false;
+ }
+ fill->setLineWidth(lineWidth);
+ fill_material_.setLineWidth(lineWidth); // to make the material not compare equal if linewidth changes
+
+// if (fillColor != fill_material_.color())
+ {
+ fill_material_.setWrapOffset(shape->m_wrapOffset - 1);
+ fill_material_.setColor(fillColor);
+ fill_material_.setGeoProjection(geoProjection);
+ fill_material_.setCenter(center);
+ setMaterial(&fill_material_);
+ markDirty(DirtyMaterial);
+ }
+}
+
+MapPolylineShaderLineStrip::MapPolylineShaderLineStrip() : QSGMaterialShader(*new QSGMaterialShaderPrivate(this))
+{
+ setShaderFileName(VertexStage, QLatin1String(":/location/quickmapitems/rhi/shaders/polyline_linestrip.vert.qsb"));
+ setShaderFileName(FragmentStage, QLatin1String(":/location/quickmapitems/rhi/shaders/polyline_linestrip.frag.qsb"));
+}
+
+bool MapPolylineShaderLineStrip::updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type());
+ MapPolylineMaterial *oldMaterial = static_cast<MapPolylineMaterial *>(oldEffect);
+ MapPolylineMaterial *newMaterial = static_cast<MapPolylineMaterial *>(newEffect);
+
+ const QColor &c = newMaterial->color();
+ const QMatrix4x4 &geoProjection = newMaterial->geoProjection();
+ const QDoubleVector3D &center = newMaterial->center();
+
+ QVector4D vecCenter, vecCenter_lowpart;
+ for (int i = 0; i < 3; i++)
+ QLocationUtils::split_double(center.get(i), &vecCenter[i], &vecCenter_lowpart[i]);
+ vecCenter[3] = 0;
+ vecCenter_lowpart[3] = 0;
+
+ int offset = 0;
+ char *buf_p = state.uniformData()->data();
+
+ if (state.isMatrixDirty()) {
+ const QMatrix4x4 m = state.projectionMatrix();
+ memcpy(buf_p + offset, m.constData(), 4*4*4);
+ }
+ offset += 4*4*4;
+
+ memcpy(buf_p + offset, geoProjection.constData(), 4*4*4); offset+=4*4*4;
+
+ memcpy(buf_p + offset, &vecCenter, 4*4); offset += 4*4;
+
+ memcpy(buf_p + offset, &vecCenter_lowpart, 4*4); offset+=4*4;
+
+ if (state.isOpacityDirty()) {
+ const float opacity = state.opacity();
+ memcpy(buf_p + offset, &opacity, 4);
+ }
+ offset += 4;
+
+ float wrapOffset = newMaterial->wrapOffset();
+ memcpy(buf_p + offset, &wrapOffset, 4); offset+=4;
+
+ offset+=8; // float padding
+
+ if (oldMaterial == nullptr || c != oldMaterial->color() || state.isOpacityDirty()) {
+ float opacity = state.opacity() * c.alphaF();
+ QVector4D v(c.redF() * opacity,
+ c.greenF() * opacity,
+ c.blueF() * opacity,
+ opacity);
+ memcpy(buf_p + offset, &v, 4*4);
+ }
+ offset+=4*4;
+
+ return true;
+}
+
+QSGMaterialShader *MapPolylineMaterial::createShader(QSGRendererInterface::RenderMode renderMode) const
+{
+ Q_UNUSED(renderMode);
+ return new MapPolylineShaderLineStrip();
+}
+
+QSGMaterialType *MapPolylineMaterial::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+int MapPolylineMaterial::compare(const QSGMaterial *other) const
+{
+ const MapPolylineMaterial &o = *static_cast<const MapPolylineMaterial *>(other);
+ if (o.m_center == m_center && o.m_geoProjection == m_geoProjection && o.m_wrapOffset == m_wrapOffset && o.m_lineWidth == m_lineWidth)
+ return QSGFlatColorMaterial::compare(other);
+ return -1;
+}
+
+
+const QSGGeometry::AttributeSet &MapPolylineNodeOpenGLExtruded::attributesMapPolylineTriangulated()
+{
+ return MapPolylineEntry::attributes();
+}
+
+MapPolylineNodeOpenGLExtruded::MapPolylineNodeOpenGLExtruded()
+: m_geometryTriangulating(MapPolylineNodeOpenGLExtruded::attributesMapPolylineTriangulated(),
+ 0 /* vtx cnt */, 0 /* index cnt */, QSGGeometry::UnsignedIntType /* index type */)
+{
+ m_geometryTriangulating.setDrawingMode(QSGGeometry::DrawTriangles);
+ QSGGeometryNode::setMaterial(&fill_material_);
+ QSGGeometryNode::setGeometry(&m_geometryTriangulating);
+}
+
+MapPolylineNodeOpenGLExtruded::~MapPolylineNodeOpenGLExtruded()
+{
+
+}
+
+bool QGeoMapPolylineGeometryOpenGL::allocateAndFillEntries(QSGGeometry *geom,
+ bool closed,
+ unsigned int zoom) const
+{
+ // Select LOD. Generate if not present. Assign it to m_screenVertices;
+ if (m_dataChanged) {
+ // it means that the data really changed.
+ // So synchronously produce LOD 1, and enqueue the requested one if != 0 or 1.
+ // Select 0 if 0 is requested, or 1 in all other cases.
+ selectLODOnDataChanged(zoom, m_bboxLeftBoundWrapped.x());
+ } else {
+ // Data has not changed, but active LOD != requested LOD.
+ // So, if there are no active tasks, try to change to the correct one.
+ if (!selectLODOnLODMismatch(zoom, m_bboxLeftBoundWrapped.x(), closed))
+ return false;
+ }
+
+ const QList<QDeclarativeGeoMapItemUtils::vec2> &v = *m_screenVertices;
+ if (v.size() < 2) {
+ geom->allocate(0, 0);
+ return true;
+ }
+ const int numSegments = (v.size() - 1);
+
+ const int numIndices = numSegments * 6; // six vertices per line segment
+ geom->allocate(numIndices);
+ MapPolylineNodeOpenGLExtruded::MapPolylineEntry *vertices =
+ static_cast<MapPolylineNodeOpenGLExtruded::MapPolylineEntry *>(geom->vertexData());
+
+ for (int i = 0; i < numSegments; ++i) {
+ MapPolylineNodeOpenGLExtruded::MapPolylineEntry e;
+ const QDeclarativeGeoMapItemUtils::vec2 &cur = v[i];
+ const QDeclarativeGeoMapItemUtils::vec2 &next = v[i+1];
+ e.triangletype = 1.0;
+ e.next = next;
+ e.prev = cur;
+ e.pos = cur;
+ e.direction = 1.0;
+ e.vertextype = -1.0;
+ vertices[i*6] = e;
+ e.direction = -1.0;
+ vertices[i*6+1] = e;
+ e.pos = next;
+ e.vertextype = 1.0;
+ vertices[i*6+2] = e;
+
+ // Second tri
+ e.triangletype = -1.0;
+ e.direction = -1.0;
+ vertices[i*6+3] = e;
+ e.direction = 1.0;
+ vertices[i*6+4] = e;
+ e.pos = cur;
+ e.vertextype = -1.0;
+ vertices[i*6+5] = e;
+
+ if (i != 0) {
+ vertices[i*6].prev = vertices[i*6+1].prev = vertices[i*6+5].prev = v[i-1];
+ } else {
+ if (closed) {
+ vertices[i*6].prev = vertices[i*6+1].prev = vertices[i*6+5].prev = v[numSegments - 1];
+ } else {
+ vertices[i*6].triangletype = vertices[i*6+1].triangletype = vertices[i*6+5].triangletype = 2.0;
+ }
+ }
+ if (i != numSegments - 1) {
+ vertices[i*6+2].next = vertices[i*6+3].next = vertices[i*6+4].next = v[i+2];
+ } else {
+ if (closed) {
+ vertices[i*6+2].next = vertices[i*6+3].next = vertices[i*6+4].next = v[1];
+ } else {
+ vertices[i*6+2].triangletype = vertices[i*6+3].triangletype = vertices[i*6+4].triangletype = 3.0;
+ }
+ }
+ }
+ return true;
+}
+
+void QGeoMapPolylineGeometryOpenGL::allocateAndFillLineStrip(QSGGeometry *geom,
+ int lod) const
+{
+ // Select LOD. Generate if not present. Assign it to m_screenVertices;
+ Q_UNUSED(lod);
+
+ const QList<QDeclarativeGeoMapItemUtils::vec2> &vx = *m_screenVertices;
+ geom->allocate(vx.size());
+
+ QSGGeometry::Point2D *pts = geom->vertexDataAsPoint2D();
+ for (qsizetype i = 0; i < vx.size(); ++i)
+ pts[i].set(vx[i].x, vx[i].y);
+}
+
+void MapPolylineNodeOpenGLExtruded::update(const QColor &fillColor,
+ float lineWidth,
+ const QGeoMapPolylineGeometryOpenGL *shape,
+ const QMatrix4x4 &geoProjection,
+ const QDoubleVector3D &center,
+ const Qt::PenCapStyle capStyle,
+ bool closed,
+ unsigned int zoom)
+{
+ // shape->size() == number of triangles
+ if (shape->m_screenVertices->size() < 2
+ || lineWidth < 0.5 || fillColor.alpha() == 0) { // number of points
+ setSubtreeBlocked(true);
+ return;
+ } else {
+ setSubtreeBlocked(false);
+ }
+
+ QSGGeometry *fill = QSGGeometryNode::geometry();
+ if (shape->m_dataChanged || !shape->isLODActive(zoom) || !fill->vertexCount()) { // fill->vertexCount for when node gets destroyed by MapItemBase bcoz of opacity, then recreated.
+ if (shape->allocateAndFillEntries(fill, closed, zoom)) {
+ markDirty(DirtyGeometry);
+ shape->m_dataChanged = false;
+ }
+ }
+
+ // Update this
+// if (fillColor != fill_material_.color())
+ {
+ fill_material_.setWrapOffset(shape->m_wrapOffset - 1);
+ fill_material_.setColor(fillColor);
+ fill_material_.setGeoProjection(geoProjection);
+ fill_material_.setCenter(center);
+ fill_material_.setLineWidth(lineWidth);
+ fill_material_.setMiter(capStyle != Qt::FlatCap);
+ setMaterial(&fill_material_);
+ markDirty(DirtyMaterial);
+ }
+}
+
+MapPolylineShaderExtruded::MapPolylineShaderExtruded() : QSGMaterialShader(*new QSGMaterialShaderPrivate(this))
+{
+ // Heavily adapted from https://github.com/mattdesl/webgl-lines/blob/master/projected/vert.glsl,
+ // that is (c) Matt DesLauriers, and released under the MIT license.
+ setShaderFileName(VertexStage, QLatin1String(":/location/quickmapitems/rhi/shaders/polyline_extruded.vert.qsb"));
+ setShaderFileName(FragmentStage, QLatin1String(":/location/quickmapitems/rhi/shaders/polyline_extruded.frag.qsb"));
+}
+
+bool MapPolylineShaderExtruded::updateUniformData(QSGMaterialShader::RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect)
+{
+ Q_ASSERT(oldEffect == nullptr || newEffect->type() == oldEffect->type());
+ MapPolylineMaterialExtruded *oldMaterial = static_cast<MapPolylineMaterialExtruded *>(oldEffect);
+ MapPolylineMaterialExtruded *newMaterial = static_cast<MapPolylineMaterialExtruded *>(newEffect);
+
+ const QColor &c = newMaterial->color();
+ const QMatrix4x4 &geoProjection = newMaterial->geoProjection();
+ const QDoubleVector3D &center = newMaterial->center();
+
+ // It is safer to use vec4 instead on vec3, as described in:
+ // https://www.khronos.org/opengl/wiki/Interface_Block_(GLSL)#Memory_layout
+ QVector4D vecCenter, vecCenter_lowpart;
+ for (int i = 0; i < 3; i++)
+ QLocationUtils::split_double(center.get(i), &vecCenter[i], &vecCenter_lowpart[i]);
+ vecCenter[3] = 0;
+ vecCenter_lowpart[3] = 0;
+
+ int offset = 0;
+ char *buf_p = state.uniformData()->data();
+
+ if (state.isMatrixDirty()) {
+ const QMatrix4x4 m = state.projectionMatrix();
+ memcpy(buf_p + offset, m.constData(), 4*4*4);
+ }
+ offset += 4*4*4;
+
+ memcpy(buf_p + offset, geoProjection.constData(), 4*4*4); offset+=4*4*4;
+
+ memcpy(buf_p + offset, &vecCenter, 4*4); offset += 4*4;
+
+ memcpy(buf_p + offset, &vecCenter_lowpart, 4*4); offset+=4*4;
+
+ const float lineWidth = newMaterial->lineWidth();
+ memcpy(buf_p + offset, &lineWidth, 4); offset+=4;
+
+ const QRectF viewportRect = state.viewportRect();
+ const float aspect = float(viewportRect.width() / viewportRect.height());
+ memcpy(buf_p + offset, &aspect, 4); offset+=4;
+
+ offset += 4; // Padding
+
+ int miter = newMaterial->miter();
+ memcpy(buf_p + offset, &miter, 4); offset+=4;
+
+ if (oldMaterial == nullptr || c != oldMaterial->color() || state.isOpacityDirty()) {
+ float opacity = state.opacity() * c.alphaF();
+ QVector4D v(c.redF() * opacity,
+ c.greenF() * opacity,
+ c.blueF() * opacity,
+ opacity);
+ memcpy(buf_p + offset, &v, 4*4);
+ }
+ offset+=4*4;
+
+ const float wrapOffset = newMaterial->wrapOffset();
+ memcpy(buf_p + offset, &wrapOffset, 4); offset+=4;
+
+ return true;
+}
+
+QSGMaterialShader *MapPolylineMaterialExtruded::createShader(QSGRendererInterface::RenderMode renderMode) const
+{
+ Q_UNUSED(renderMode);
+ return new MapPolylineShaderExtruded();
+}
+
+QSGMaterialType *MapPolylineMaterialExtruded::type() const
+{
+ static QSGMaterialType type;
+ return &type;
+}
+
+int MapPolylineMaterialExtruded::compare(const QSGMaterial *other) const
+{
+ const MapPolylineMaterialExtruded &o = *static_cast<const MapPolylineMaterialExtruded *>(other);
+ if (o.m_miter == m_miter)
+ return MapPolylineMaterial::compare(other);
+ return -1;
+}
+
+QDeclarativePolylineMapItemPrivateOpenGLLineStrip::~QDeclarativePolylineMapItemPrivateOpenGLLineStrip() {}
+
+bool QDeclarativePolylineMapItemPrivateOpenGLLineStrip::contains(const QPointF &point) const
+{
+ return m_geometry.contains(m_poly.mapToItem(m_poly.quickMap(), point),
+ m_poly.line()->width(),
+ static_cast<const QGeoProjectionWebMercator&>(m_poly.map()->geoProjection()));
+}
+
+void QDeclarativePolylineMapItemPrivateOpenGLLineStrip::updatePolish()
+{
+ if (m_poly.m_geopath.path().length() == 0) { // Possibly cleared
+ m_geometry.clear();
+ m_geometry.clear();
+ m_poly.setWidth(0);
+ m_poly.setHeight(0);
+ return;
+ }
+
+ QScopedValueRollback<bool> rollback(m_poly.m_updatingGeometry);
+ m_poly.m_updatingGeometry = true;
+ const qreal lineWidth = m_poly.m_line.width();
+ m_geometry.updateSourcePoints(*m_poly.map(), m_poly.m_geopath);
+ m_geometry.markScreenDirty();
+ m_geometry.updateScreenPoints(*m_poly.map(), lineWidth);
+
+ m_poly.setWidth(m_geometry.sourceBoundingBox().width());
+ m_poly.setHeight(m_geometry.sourceBoundingBox().height());
+ m_poly.setPosition(1.0 * m_geometry.firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
+}
+
+QSGNode *QDeclarativePolylineMapItemPrivateOpenGLLineStrip::updateMapItemPaintNode(QSGNode *oldNode,
+ QQuickItem::UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+
+ if (!m_node || !oldNode) {
+ m_node = new MapPolylineNodeOpenGLLineStrip();
+ if (oldNode)
+ delete oldNode;
+ } else {
+ m_node = static_cast<MapPolylineNodeOpenGLLineStrip *>(oldNode);
+ }
+
+ if (m_geometry.isScreenDirty() || m_poly.m_dirtyMaterial) {
+ const QGeoMap *map = m_poly.map();
+ const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
+ const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
+ m_node->update(m_poly.m_line.color(), // This updates only the material if the geometry is unchanged
+ m_poly.m_line.width(),
+ &m_geometry,
+ combinedMatrix,
+ cameraCenter);
+ m_geometry.setPreserveGeometry(false);
+ m_geometry.markClean();
+ m_poly.m_dirtyMaterial = false;
+ }
+ return m_node;
+}
+
+QDeclarativePolylineMapItemPrivateOpenGLExtruded::~QDeclarativePolylineMapItemPrivateOpenGLExtruded() {}
+
+QSGNode *QDeclarativePolylineMapItemPrivateOpenGLExtruded::updateMapItemPaintNode(QSGNode *oldNode,
+ QQuickItem::UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+ const QGeoMap *map = m_poly.map();
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map->geoProjection());
+ const QMatrix4x4 &combinedMatrix = p.qsgTransform();
+ const QDoubleVector3D &cameraCenter = p.centerMercator();
+ const QColor &color = m_poly.m_line.color();
+ const float lineWidth = m_poly.m_line.width();
+
+ MapPolylineNodeOpenGLExtruded *nodeTri = nullptr;
+ if (!m_nodeTri || !oldNode) {
+ if (oldNode)
+ delete oldNode;
+ nodeTri = new MapPolylineNodeOpenGLExtruded();
+ } else {
+ nodeTri = static_cast<MapPolylineNodeOpenGLExtruded *>(oldNode);
+ }
+
+ //TODO: update only material
+ if (m_geometry.isScreenDirty() || m_poly.m_dirtyMaterial) {
+ nodeTri->update(color,
+ lineWidth ,
+ &m_geometry,
+ combinedMatrix,
+ cameraCenter,
+ Qt::FlatCap,
+ false,
+ m_poly.zoomForLOD(int(map->cameraData().zoomLevel())));
+ m_geometry.setPreserveGeometry(false);
+ m_geometry.markClean();
+ m_poly.m_dirtyMaterial = false;
+ }
+ m_nodeTri = nodeTri;
+ return nodeTri;
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/location/quickmapitems/rhi/qdeclarativepolylinemapitem_rhi_p.h b/src/location/quickmapitems/rhi/qdeclarativepolylinemapitem_rhi_p.h
new file mode 100644
index 00000000..8387eae6
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qdeclarativepolylinemapitem_rhi_p.h
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Paolo Angelelli <paolo.angelelli@gmail.com>
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPOLYLINEMAPITEM_RHI_P_H
+#define QDECLARATIVEPOLYLINEMAPITEM_RHI_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QScopedValueRollback>
+#include <QSGMaterialShader>
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
+#include <QtLocation/private/qdeclarativepolylinemapitem_p_p.h>
+#include <QtLocation/private/qgeomapitemgeometry_p.h>
+#include <QtLocation/private/qgeomapitemgeometry_rhi_p.h>
+
+#include <QtPositioning/private/qdoublevector2d_p.h>
+
+#include <array>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolylineShaderLineStrip : public QSGMaterialShader
+{
+public:
+ MapPolylineShaderLineStrip();
+
+ bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolylineMaterial : public QSGFlatColorMaterial
+{
+public:
+ MapPolylineMaterial()
+ : QSGFlatColorMaterial()
+ {
+ // Passing RequiresFullMatrix is essential in order to prevent the
+ // batch renderer from baking in simple, translate-only transforms into
+ // the vertex data. The shader will rely on the fact that
+ // vertexCoord.xy is the Shape-space coordinate and so no modifications
+ // are welcome.
+ setFlag(Blending | RequiresFullMatrix);
+ }
+
+ QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
+
+ void setGeoProjection(const QMatrix4x4 &p)
+ {
+ m_geoProjection = p;
+ }
+
+ QMatrix4x4 geoProjection() const
+ {
+ return m_geoProjection;
+ }
+
+ void setCenter(const QDoubleVector3D &c)
+ {
+ m_center = c;
+ }
+
+ QDoubleVector3D center() const
+ {
+ return m_center;
+ }
+
+ int wrapOffset() const
+ {
+ return m_wrapOffset;
+ }
+
+ void setWrapOffset(int wrapOffset)
+ {
+ m_wrapOffset = wrapOffset;
+ }
+
+ void setLineWidth(float lw)
+ {
+ m_lineWidth = lw;
+ }
+
+ float lineWidth() const
+ {
+ return m_lineWidth;
+ }
+
+ QSGMaterialType *type() const override;
+ int compare(const QSGMaterial *other) const override;
+
+protected:
+ QMatrix4x4 m_geoProjection;
+ QDoubleVector3D m_center;
+ int m_wrapOffset = 0;
+ float m_lineWidth = 1.0;
+};
+
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolylineShaderExtruded : public QSGMaterialShader
+{
+public:
+ MapPolylineShaderExtruded();
+
+ bool updateUniformData(RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolylineNodeOpenGLLineStrip : public MapItemGeometryNode
+{
+public:
+ MapPolylineNodeOpenGLLineStrip();
+ ~MapPolylineNodeOpenGLLineStrip() override;
+
+ void update(const QColor &fillColor,
+ const qreal lineWidth,
+ const QGeoMapPolylineGeometryOpenGL *shape,
+ const QMatrix4x4 &geoProjection,
+ const QDoubleVector3D &center,
+ const Qt::PenCapStyle capStyle = Qt::SquareCap);
+
+protected:
+ MapPolylineMaterial fill_material_;
+ QSGGeometry geometry_;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolylineMaterialExtruded : public MapPolylineMaterial
+{
+public:
+ MapPolylineMaterialExtruded() : MapPolylineMaterial()
+ {
+
+ }
+ QSGMaterialShader *createShader(QSGRendererInterface::RenderMode renderMode) const override;
+
+ void setMiter(int m)
+ {
+ m_miter = m;
+ }
+
+ int miter() const
+ {
+ return m_miter;
+ }
+
+ QSGMaterialType *type() const override;
+ int compare(const QSGMaterial *other) const override;
+
+ int m_miter = 0;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolylineNodeOpenGLExtruded : public MapItemGeometryNode
+{
+public:
+
+ typedef struct MapPolylineEntry {
+ QDeclarativeGeoMapItemUtils::vec2 pos;
+ QDeclarativeGeoMapItemUtils::vec2 prev;
+ QDeclarativeGeoMapItemUtils::vec2 next;
+ float direction;
+ float triangletype; // es2 does not support int attribs
+ float vertextype;
+
+ static const QSGGeometry::AttributeSet &attributes()
+ {
+ static const QSGGeometry::Attribute dataTri[] = {
+ QSGGeometry::Attribute::createWithAttributeType(0, 2,
+ QSGGeometry::FloatType, QSGGeometry::PositionAttribute) // pos
+ ,QSGGeometry::Attribute::createWithAttributeType(1, 2,
+ QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // next
+ ,QSGGeometry::Attribute::createWithAttributeType(2, 2,
+ QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // previous
+ ,QSGGeometry::Attribute::createWithAttributeType(3, 1,
+ QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // direction
+ ,QSGGeometry::Attribute::createWithAttributeType(4, 1,
+ QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // triangletype
+ ,QSGGeometry::Attribute::createWithAttributeType(5, 1,
+ QSGGeometry::FloatType, QSGGeometry::UnknownAttribute) // vertextype
+ };
+ static const QSGGeometry::AttributeSet attrsTri = {
+ 6,
+ sizeof(MapPolylineNodeOpenGLExtruded::MapPolylineEntry),
+ dataTri
+ };
+ return attrsTri;
+ }
+ } MapPolylineEntry;
+
+ MapPolylineNodeOpenGLExtruded();
+ ~MapPolylineNodeOpenGLExtruded() override;
+
+ void update(const QColor &fillColor,
+ float lineWidth,
+ const QGeoMapPolylineGeometryOpenGL *shape,
+ const QMatrix4x4 &geoProjection,
+ const QDoubleVector3D &center,
+ const Qt::PenCapStyle capStyle = Qt::FlatCap,
+ bool closed = false,
+ unsigned int zoom = 30);
+
+ static const QSGGeometry::AttributeSet &attributesMapPolylineTriangulated();
+
+protected:
+ MapPolylineMaterialExtruded fill_material_;
+ QSGGeometry m_geometryTriangulating;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolylineMapItemPrivateOpenGLLineStrip: public QDeclarativePolylineMapItemPrivate
+{
+public:
+
+ QDeclarativePolylineMapItemPrivateOpenGLLineStrip(QDeclarativePolylineMapItem &poly) : QDeclarativePolylineMapItemPrivate(poly)
+ {
+ }
+
+ QDeclarativePolylineMapItemPrivateOpenGLLineStrip(QDeclarativePolylineMapItemPrivate &other)
+ : QDeclarativePolylineMapItemPrivate(other)
+ {
+ }
+
+ ~QDeclarativePolylineMapItemPrivateOpenGLLineStrip() override;
+ void onLinePropertiesChanged() override
+ {
+ afterViewportChanged();
+ }
+ void markSourceDirtyAndUpdate() override
+ {
+ m_geometry.markSourceDirty();
+ m_poly.polishAndUpdate();
+ }
+ void preserveGeometry()
+ {
+ m_geometry.setPreserveGeometry(true, m_poly.m_geopath.boundingGeoRectangle().topLeft());
+ }
+ void onMapSet() override
+ {
+ markSourceDirtyAndUpdate();
+ }
+ void onGeoGeometryChanged() override
+ {
+ preserveGeometry();
+ markSourceDirtyAndUpdate();
+ }
+ void onGeoGeometryUpdated() override
+ {
+ preserveGeometry();
+ markSourceDirtyAndUpdate();
+ }
+ void onItemGeometryChanged() override
+ {
+ onGeoGeometryChanged();
+ }
+ void afterViewportChanged() override
+ {
+ preserveGeometry();
+ m_poly.polishAndUpdate();
+ }
+ bool contains(const QPointF &point) const override;
+ void updatePolish() override;
+ QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override;
+
+ QGeoMapPolylineGeometryOpenGL m_geometry;
+ MapPolylineNodeOpenGLLineStrip *m_node = nullptr;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolylineMapItemPrivateOpenGLExtruded: public QDeclarativePolylineMapItemPrivateOpenGLLineStrip
+{
+public:
+
+ QDeclarativePolylineMapItemPrivateOpenGLExtruded(QDeclarativePolylineMapItem &poly)
+ : QDeclarativePolylineMapItemPrivateOpenGLLineStrip(poly)
+ {
+ }
+
+ QDeclarativePolylineMapItemPrivateOpenGLExtruded(QDeclarativePolylineMapItemPrivate &other)
+ : QDeclarativePolylineMapItemPrivateOpenGLLineStrip(other)
+ {
+ }
+
+ ~QDeclarativePolylineMapItemPrivateOpenGLExtruded() override;
+
+ QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override;
+
+ MapPolylineNodeOpenGLExtruded *m_nodeTri = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVEPOLYLINEMAPITEM_RHI_P_H
diff --git a/src/location/quickmapitems/rhi/qdeclarativerectanglemapitem_rhi.cpp b/src/location/quickmapitems/rhi/qdeclarativerectanglemapitem_rhi.cpp
new file mode 100644
index 00000000..9125aca9
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qdeclarativerectanglemapitem_rhi.cpp
@@ -0,0 +1,159 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2022 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtLocation module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL3 included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 3 requirements
+ ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 2.0 or (at your option) the GNU General
+ ** Public license version 3 or any later version approved by the KDE Free
+ ** Qt Foundation. The licenses are as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+ ** https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qdeclarativerectanglemapitem_rhi_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QDeclarativeRectangleMapItemPrivateOpenGL::~QDeclarativeRectangleMapItemPrivateOpenGL() {}
+
+
+void QDeclarativeRectangleMapItemPrivateOpenGL::updatePolish()
+{
+ if (!m_rect.topLeft().isValid() || !m_rect.bottomRight().isValid()) {
+ m_geometry.clear();
+ m_borderGeometry.clear();
+ m_rect.setWidth(0);
+ m_rect.setHeight(0);
+ return;
+ }
+
+ QScopedValueRollback<bool> rollback(m_rect.m_updatingGeometry);
+ m_rect.m_updatingGeometry = true;
+ const qreal lineWidth = m_rect.m_border.width();
+ const QColor &lineColor = m_rect.m_border.color();
+ const QColor &fillColor = m_rect.color();
+ if (fillColor.alpha() != 0) {
+ m_geometry.updateSourcePoints(*m_rect.map(), m_rect.m_rectangle);
+ m_geometry.markScreenDirty();
+ m_geometry.updateScreenPoints(*m_rect.map(), lineWidth, lineColor);
+ } else {
+ m_geometry.clearBounds();
+ }
+
+ QGeoMapItemGeometry * geom = &m_geometry;
+ m_borderGeometry.clearScreen();
+ if (lineColor.alpha() != 0 && lineWidth > 0) {
+ m_borderGeometry.updateSourcePoints(*m_rect.map(), m_rect.m_rectangle);
+ m_borderGeometry.markScreenDirty();
+ m_borderGeometry.updateScreenPoints(*m_rect.map(), lineWidth);
+ geom = &m_borderGeometry;
+ }
+ m_rect.setWidth(geom->sourceBoundingBox().width());
+ m_rect.setHeight(geom->sourceBoundingBox().height());
+ m_rect.setPosition(1.0 * geom->firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
+}
+
+QSGNode *QDeclarativeRectangleMapItemPrivateOpenGL::updateMapItemPaintNode(QSGNode *oldNode,
+ QQuickItem::UpdatePaintNodeData *data)
+{
+ Q_UNUSED(data);
+
+ if (!m_rootNode || !oldNode) {
+ m_rootNode = new QDeclarativePolygonMapItemPrivateOpenGL::RootNode();
+ m_node = new MapPolygonNodeGL();
+ m_rootNode->appendChildNode(m_node);
+ m_polylinenode = new MapPolylineNodeOpenGLExtruded();
+ m_rootNode->appendChildNode(m_polylinenode);
+ m_rootNode->markDirty(QSGNode::DirtyNodeAdded);
+ if (oldNode)
+ delete oldNode;
+ } else {
+ m_rootNode = static_cast<QDeclarativePolygonMapItemPrivateOpenGL::RootNode *>(oldNode);
+ }
+
+ const QGeoMap *map = m_rect.map();
+ const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
+ const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
+
+ if (m_borderGeometry.isScreenDirty()) {
+ /* Do the border update first */
+ m_polylinenode->update(m_rect.m_border.color(),
+ float(m_rect.m_border.width()),
+ &m_borderGeometry,
+ combinedMatrix,
+ cameraCenter,
+ Qt::SquareCap,
+ true,
+ 30); // No LOD for rectangles
+ m_borderGeometry.setPreserveGeometry(false);
+ m_borderGeometry.markClean();
+ } else {
+ m_polylinenode->setSubtreeBlocked(true);
+ }
+ if (m_geometry.isScreenDirty()) {
+ m_node->update(m_rect.m_color,
+ &m_geometry,
+ combinedMatrix,
+ cameraCenter);
+ m_geometry.setPreserveGeometry(false);
+ m_geometry.markClean();
+ } else {
+ m_node->setSubtreeBlocked(true);
+ }
+
+ m_rootNode->setSubtreeBlocked(false);
+ return m_rootNode;
+}
+
+bool QDeclarativeRectangleMapItemPrivateOpenGL::contains(const QPointF &point) const
+{
+ const qreal lineWidth = m_rect.m_border.width();
+ const QColor &lineColor = m_rect.m_border.color();
+ const QRectF &bounds = (lineColor.alpha() != 0 && lineWidth > 0)
+ ? m_borderGeometry.sourceBoundingBox()
+ : m_geometry.sourceBoundingBox();
+ if (bounds.contains(point)) {
+ QDeclarativeGeoMap *m = m_rect.quickMap();
+ if (m) {
+ const QGeoCoordinate crd = m->toCoordinate(m->mapFromItem(&m_rect, point));
+ const auto &projection = static_cast<const QGeoProjectionWebMercator&>(
+ m_rect.map()->geoProjection());
+ return m_rect.m_rectangle.contains(crd)
+ || m_borderGeometry.contains(m_rect.mapToItem(m_rect.quickMap(), point),
+ m_rect.border()->width(), projection);
+ } else {
+ return true;
+ }
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/location/quickmapitems/rhi/qdeclarativerectanglemapitem_rhi_p.h b/src/location/quickmapitems/rhi/qdeclarativerectanglemapitem_rhi_p.h
new file mode 100644
index 00000000..65cf682f
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qdeclarativerectanglemapitem_rhi_p.h
@@ -0,0 +1,131 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Paolo Angelelli <paolo.angelelli@gmail.com>
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVERECTANGLEMAPITEM_RHI_P_H
+#define QDECLARATIVERECTANGLEMAPITEM_RHI_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtLocation/private/qlocationglobal_p.h>
+#include <QtLocation/private/qdeclarativerectanglemapitem_p_p.h>
+#include <QtLocation/private/qdeclarativepolygonmapitem_p_p.h>
+
+#include "qdeclarativepolygonmapitem_rhi_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativeRectangleMapItemPrivateOpenGL: public QDeclarativeRectangleMapItemPrivate
+{
+public:
+ QDeclarativeRectangleMapItemPrivateOpenGL(QDeclarativeRectangleMapItem &rect) : QDeclarativeRectangleMapItemPrivate(rect)
+ {
+ }
+
+ QDeclarativeRectangleMapItemPrivateOpenGL(QDeclarativeRectangleMapItemPrivate &other)
+ : QDeclarativeRectangleMapItemPrivate(other)
+ {
+ }
+
+ ~QDeclarativeRectangleMapItemPrivateOpenGL() override;
+
+ void markScreenDirtyAndUpdate()
+ {
+ // preserveGeometry is cleared in updateMapItemPaintNode
+ m_geometry.markScreenDirty();
+ m_borderGeometry.markScreenDirty();
+ m_rect.polishAndUpdate();
+ }
+ void onLinePropertiesChanged() override
+ {
+ m_rect.m_dirtyMaterial = true;
+ afterViewportChanged();
+ }
+ void markSourceDirtyAndUpdate() override
+ {
+ m_geometry.markSourceDirty();
+ m_borderGeometry.markSourceDirty();
+ m_rect.polishAndUpdate();
+ }
+ void preserveGeometry()
+ {
+ m_geometry.setPreserveGeometry(true, m_rect.m_rectangle.topLeft());
+ m_borderGeometry.setPreserveGeometry(true, m_rect.m_rectangle.topLeft());
+ }
+ void onMapSet() override
+ {
+ markSourceDirtyAndUpdate();
+ }
+ void onGeoGeometryChanged() override
+ {
+ preserveGeometry();
+ markSourceDirtyAndUpdate();
+ }
+ void onItemGeometryChanged() override
+ {
+ onGeoGeometryChanged();
+ }
+ void afterViewportChanged() override
+ {
+ preserveGeometry();
+ markScreenDirtyAndUpdate();
+ }
+ void updatePolish() override;
+ QSGNode *updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override;
+ bool contains(const QPointF &point) const override;
+
+ QGeoMapPolygonGeometryOpenGL m_geometry;
+ QGeoMapPolylineGeometryOpenGL m_borderGeometry;
+ QDeclarativePolygonMapItemPrivateOpenGL::RootNode *m_rootNode = nullptr;
+ MapPolygonNodeGL *m_node = nullptr;
+ MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVERECTANGLEMAPITEM_RHI_P_H
diff --git a/src/location/quickmapitems/rhi/qgeomapitemgeometry_rhi.cpp b/src/location/quickmapitems/rhi/qgeomapitemgeometry_rhi.cpp
new file mode 100644
index 00000000..dddd9d07
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qgeomapitemgeometry_rhi.cpp
@@ -0,0 +1,729 @@
+/****************************************************************************
+ **
+ ** Copyright (C) 2022 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtLocation module of the Qt Toolkit.
+ **
+ ** $QT_BEGIN_LICENSE:LGPL$
+ ** Commercial License Usage
+ ** Licensees holding valid commercial Qt licenses may use this file in
+ ** accordance with the commercial license agreement provided with the
+ ** Software or, alternatively, in accordance with the terms contained in
+ ** a written agreement between you and The Qt Company. For licensing terms
+ ** and conditions see https://www.qt.io/terms-conditions. For further
+ ** information use the contact form at https://www.qt.io/contact-us.
+ **
+ ** GNU Lesser General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU Lesser
+ ** General Public License version 3 as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.LGPL3 included in the
+ ** packaging of this file. Please review the following information to
+ ** ensure the GNU Lesser General Public License version 3 requirements
+ ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+ **
+ ** GNU General Public License Usage
+ ** Alternatively, this file may be used under the terms of the GNU
+ ** General Public License version 2.0 or (at your option) the GNU General
+ ** Public license version 3 or any later version approved by the KDE Free
+ ** Qt Foundation. The licenses are as published by the Free Software
+ ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+ ** included in the packaging of this file. Please review the following
+ ** information to ensure the GNU General Public License requirements will
+ ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+ ** https://www.gnu.org/licenses/gpl-3.0.html.
+ **
+ ** $QT_END_LICENSE$
+ **
+ ****************************************************************************/
+
+#include "qgeomapitemgeometry_rhi_p.h"
+
+#include <QThreadPool>
+#include <QRunnable>
+
+#include <QtQuick/QSGGeometry>
+#include <QtPositioning/private/qwebmercator_p.h>
+#include <QtPositioning/private/qlocationutils_p.h>
+#include <QtPositioning/QGeoCircle>
+#include <QtPositioning/QGeoPolygon>
+#include <QtPositioning/QGeoPath>
+#include <QtPositioning/QGeoRectangle>
+
+#include <QtLocation/private/qgeomap_p.h>
+#include <QtLocation/private/qdeclarativecirclemapitem_p_p.h>
+#include <QtLocation/private/qgeosimplify_p.h>
+
+/* poly2tri triangulator includes */
+#include <earcut.hpp>
+#include <array>
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ Implementation of QGeoMapItemLODGeometry
+*/
+
+struct ThreadPool // to have a thread pool with max 1 thread for geometry processing
+{
+ ThreadPool ()
+ {
+ m_threadPool.setMaxThreadCount(1);
+ }
+
+ void start(QRunnable *runnable, int priority = 0)
+ {
+ m_threadPool.start(runnable, priority);
+ }
+
+ QThreadPool m_threadPool;
+};
+
+Q_GLOBAL_STATIC(ThreadPool, threadPool)
+
+class PolylineSimplifyTask : public QRunnable
+{
+public:
+ PolylineSimplifyTask(const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>
+ &input, // reference as it gets copied in the nested call
+ const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> &output,
+ double leftBound, unsigned int zoom, QSharedPointer<unsigned int> &working)
+ : m_zoom(zoom), m_leftBound(leftBound), m_input(input), m_output(output), m_working(working)
+ {
+ Q_ASSERT(!input.isNull());
+ Q_ASSERT(!output.isNull());
+ }
+
+ void run() override
+ {
+ // Skip sending notifications for now. Updated data will be picked up eventually.
+ // ToDo: figure out how to connect a signal from here to a slot in the item.
+ *m_working = QGeoMapItemLODGeometry::zoomToLOD(m_zoom);
+ const QList<QDeclarativeGeoMapItemUtils::vec2> res =
+ QGeoMapItemLODGeometry::getSimplified(
+ *m_input, m_leftBound, QGeoMapItemLODGeometry::zoomForLOD(m_zoom));
+ *m_output = res;
+ *m_working = 0;
+ }
+
+ unsigned int m_zoom;
+ double m_leftBound;
+ QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> m_input, m_output;
+ QSharedPointer<unsigned int> m_working;
+};
+
+
+QGeoMapItemLODGeometry::QGeoMapItemLODGeometry()
+{
+ resetLOD();
+}
+
+void QGeoMapItemLODGeometry::resetLOD()
+{
+ // New pointer, some old LOD task might still be running and operating on the old pointers.
+ m_verticesLOD[0] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
+ new QList<QDeclarativeGeoMapItemUtils::vec2>);
+ for (unsigned int i = 1; i < m_verticesLOD.size(); ++i)
+ m_verticesLOD[i] = nullptr; // allocate on first use
+ m_screenVertices = m_verticesLOD.front().data(); // resetting pointer to data to be LOD 0
+}
+
+QList<QDeclarativeGeoMapItemUtils::vec2> QGeoMapItemLODGeometry::getSimplified(
+ QList<QDeclarativeGeoMapItemUtils::vec2>
+ &wrappedPath, // reference as it gets copied in the nested call
+ double leftBoundWrapped, unsigned int zoom)
+{
+ // Try a simplify step
+ QList<QDoubleVector2D> data;
+ for (auto e: wrappedPath)
+ data << e.toDoubleVector2D();
+ const QList<QDoubleVector2D> simplified = QGeoSimplify::geoSimplifyZL(data,
+ leftBoundWrapped,
+ zoom);
+
+ data.clear();
+ QList<QDeclarativeGeoMapItemUtils::vec2> simple;
+ for (auto e: simplified)
+ simple << e;
+ return simple;
+}
+
+bool QGeoMapItemLODGeometry::isLODActive(unsigned int lod) const
+{
+ return m_screenVertices == m_verticesLOD[zoomToLOD(lod)].data();
+}
+
+bool QGeoMapItemLODGeometry::selectLODOnLODMismatch(unsigned int zoom, double leftBound,
+ bool closed) const
+{
+ if (*m_working > 0)
+ return false;
+ const_cast<QGeoMapItemLODGeometry *>(this)->selectLOD(zoom, leftBound, closed);
+ return true;
+}
+
+void QGeoMapItemLODGeometry::enqueueSimplificationTask(
+ const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> &input,
+ const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> &output, double leftBound,
+ unsigned int zoom, QSharedPointer<unsigned int> &working)
+{
+ Q_ASSERT(!input.isNull());
+ Q_ASSERT(!output.isNull());
+ PolylineSimplifyTask *task = new PolylineSimplifyTask(input,
+ output,
+ leftBound,
+ zoom,
+ working);
+ threadPool->start(task);
+}
+
+void QGeoMapItemLODGeometry::selectLOD(unsigned int zoom, double leftBound, bool /* closed */) // closed to tell if this is a polygon or a polyline.
+{
+ unsigned int requestedLod = zoomToLOD(zoom);
+ if (!m_verticesLOD[requestedLod].isNull()) {
+ m_screenVertices = m_verticesLOD[requestedLod].data();
+ } else if (!m_verticesLOD.at(0)->isEmpty()) {
+ // if here, zoomToLOD != 0 and no current working task.
+ // So select the last filled LOD != m_working (lower-bounded by 1,
+ // guaranteed to exist), and enqueue the right one
+ m_verticesLOD[requestedLod] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
+ new QList<QDeclarativeGeoMapItemUtils::vec2>);
+
+ for (unsigned int i = requestedLod - 1; i >= 1; i--) {
+ if (*m_working != i && !m_verticesLOD[i].isNull()) {
+ m_screenVertices = m_verticesLOD[i].data();
+ break;
+ } else if (i == 1) {
+ // get 1 synchronously if not computed already
+ m_verticesLOD[1] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
+ new QList<QDeclarativeGeoMapItemUtils::vec2>);
+ *m_verticesLOD[1] = getSimplified(*m_verticesLOD[0], leftBound, zoomForLOD(0));
+ if (requestedLod == 1)
+ return;
+ }
+ }
+
+ enqueueSimplificationTask(m_verticesLOD.at(0),
+ m_verticesLOD[requestedLod],
+ leftBound,
+ zoom,
+ m_working);
+
+ }
+}
+
+void QGeoMapItemLODGeometry::selectLODOnDataChanged(unsigned int zoom, double leftBound) const
+{
+ unsigned int lod = zoomToLOD(zoom);
+ if (lod > 0) {
+ // Generate ZL 1 as fallback for all cases != 0. Do not do if 0 is requested
+ // (= old behavior, LOD disabled)
+ m_verticesLOD[1] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
+ new QList<QDeclarativeGeoMapItemUtils::vec2>);
+ *m_verticesLOD[1] = getSimplified( *m_verticesLOD[0], leftBound, zoomForLOD(0));
+ }
+ if (lod > 1) {
+ if (!m_verticesLOD[lod]) {
+ m_verticesLOD[lod] = QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>(
+ new QList<QDeclarativeGeoMapItemUtils::vec2>);
+ }
+ enqueueSimplificationTask(m_verticesLOD.at(0),
+ m_verticesLOD[lod],
+ leftBound,
+ zoom,
+ m_working);
+ }
+ m_screenVertices = m_verticesLOD[qMin<unsigned int>(lod, 1)].data(); // return only 0,1 synchronously
+}
+
+unsigned int QGeoMapItemLODGeometry::zoomToLOD(unsigned int zoom)
+{
+ unsigned int res;
+ if (zoom > 20)
+ res = 0;
+ else
+ res = qBound<unsigned int>(3, zoom, 20) / 3; // bound LOD'ing between ZL 3 and 20. Every 3 ZoomLevels
+ return res;
+}
+
+unsigned int QGeoMapItemLODGeometry::zoomForLOD(unsigned int zoom)
+{
+ unsigned int res = (qBound<unsigned int>(3, zoom, 20) / 3) * 3;
+ if (zoom < 6)
+ return res;
+ return res + 1; // give more resolution when closing in
+}
+
+// wrapPath always preserves the geometry
+// This one handles holes
+static void wrapPath(const QGeoPolygon &poly
+ ,const QGeoCoordinate &geoLeftBound
+ ,const QGeoProjectionWebMercator &p
+ ,QList<QList<QDoubleVector2D> > &wrappedPaths
+ ,QDoubleVector2D *leftBoundWrapped = nullptr)
+{
+ QList<QList<QDoubleVector2D> > paths;
+ for (qsizetype i = 0; i < 1 + poly.holesCount(); ++i) {
+ QList<QDoubleVector2D> path;
+ if (!i) {
+ for (const QGeoCoordinate &c : poly.perimeter())
+ path << p.geoToMapProjection(c);
+ } else {
+ for (const QGeoCoordinate &c : poly.holePath(i-1))
+ path << p.geoToMapProjection(c);
+ }
+ paths.append(path);
+ }
+
+ const QDoubleVector2D leftBound = p.geoToMapProjection(geoLeftBound);
+ wrappedPaths.clear();
+
+ QList<QDoubleVector2D> wrappedPath;
+ // compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
+ for (const auto &path : paths) {
+ wrappedPath.clear();
+ for (QDoubleVector2D coord : path) {
+ // 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(coord.x()) || !qIsFinite(coord.y())) {
+ wrappedPaths.clear();
+ return;
+ }
+
+ const bool isPointLessThanUnwrapBelowX = (coord.x() < leftBound.x());
+ // unwrap x to preserve geometry if moved to border of map
+ if (isPointLessThanUnwrapBelowX)
+ coord.setX(coord.x() + 1.0);
+ wrappedPath.append(coord);
+ }
+ wrappedPaths.append(wrappedPath);
+ }
+
+ if (leftBoundWrapped)
+ *leftBoundWrapped = leftBound;
+}
+
+static void cutPathEars(const QList<QList<QDoubleVector2D>> &wrappedPaths,
+ QList<QDeclarativeGeoMapItemUtils::vec2> &screenVertices,
+ QList<quint32> &screenIndices)
+{
+ using Coord = double;
+ using N = uint32_t;
+ using Point = std::array<Coord, 2>;
+ screenVertices.clear();
+ screenIndices.clear();
+
+ std::vector<std::vector<Point>> polygon;
+ std::vector<Point> poly;
+
+ for (const QList<QDoubleVector2D> &wrappedPath: wrappedPaths) {
+ poly.clear();
+ for (const QDoubleVector2D &v: wrappedPath) {
+ screenVertices << v;
+ Point pt = {{ v.x(), v.y() }};
+ poly.push_back( pt );
+ }
+ polygon.push_back(poly);
+ }
+
+ std::vector<N> indices = qt_mapbox::earcut<N>(polygon);
+
+ for (const auto &i: indices)
+ screenIndices << quint32(i);
+}
+
+static void cutPathEars(const QList<QDoubleVector2D> &wrappedPath,
+ QList<QDeclarativeGeoMapItemUtils::vec2> &screenVertices,
+ QList<quint32> &screenIndices)
+{
+ using Coord = double;
+ using N = uint32_t;
+ using Point = std::array<Coord, 2>;
+ screenVertices.clear();
+ screenIndices.clear();
+
+ std::vector<std::vector<Point>> polygon;
+ std::vector<Point> poly;
+
+ for (const QDoubleVector2D &v: wrappedPath) {
+ screenVertices << v;
+ Point pt = {{ v.x(), v.y() }};
+ poly.push_back( pt );
+ }
+ polygon.push_back(poly);
+
+ std::vector<N> indices = qt_mapbox::earcut<N>(polygon);
+
+ for (const auto &i: indices)
+ screenIndices << quint32(i);
+}
+
+void QGeoMapPolygonGeometryOpenGL::allocateAndFillPolygon(QSGGeometry *geom) const
+{
+
+ const QList<QDeclarativeGeoMapItemUtils::vec2> &vx = m_screenVertices;
+ const QList<quint32> &ix = m_screenIndices;
+
+ geom->allocate(vx.size(), ix.size());
+ if (geom->indexType() == QSGGeometry::UnsignedShortType) {
+ quint16 *its = geom->indexDataAsUShort();
+ for (qsizetype i = 0; i < ix.size(); ++i)
+ its[i] = ix[i];
+ } else if (geom->indexType() == QSGGeometry::UnsignedIntType) {
+ quint32 *its = geom->indexDataAsUInt();
+ for (qsizetype i = 0; i < ix.size(); ++i)
+ its[i] = ix[i];
+ }
+
+ QSGGeometry::Point2D *pts = geom->vertexDataAsPoint2D();
+ for (qsizetype i = 0; i < vx.size(); ++i)
+ pts[i].set(vx[i].x, vx[i].y);
+}
+
+
+QGeoMapPolygonGeometryOpenGL::QGeoMapPolygonGeometryOpenGL()
+{
+}
+
+void QGeoMapPolygonGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QList<QDoubleVector2D> &path)
+{
+ QList<QGeoCoordinate> geopath;
+ for (const auto &c: path)
+ geopath.append(QWebMercator::mercatorToCoord(c));
+ updateSourcePoints(map, geopath);
+}
+
+/*!
+ \internal
+*/
+// This one does only a perimeter
+void QGeoMapPolygonGeometryOpenGL::updateSourcePoints(const QGeoMap &map,
+ const QList<QGeoCoordinate> &perimeter)
+{
+ if (!sourceDirty_)
+ return;
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
+
+ // build the actual path
+ // The approach is the same as described in QGeoMapPolylineGeometry::updateSourcePoints
+ srcOrigin_ = geoLeftBound_;
+
+ QDoubleVector2D leftBoundWrapped;
+ // 1) pre-compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
+ QList<QDoubleVector2D> wrappedPath;
+ QDeclarativeGeoMapItemUtils::wrapPath(perimeter, geoLeftBound_, p,
+ wrappedPath, &leftBoundWrapped);
+
+ // 1.1) do the same for the bbox
+ QList<QDoubleVector2D> wrappedBbox, wrappedBboxPlus1, wrappedBboxMinus1;
+ QGeoPolygon bbox(QGeoPath(perimeter).boundingGeoRectangle());
+ QDeclarativeGeoMapItemUtils::wrapPath(bbox.perimeter(), bbox.boundingGeoRectangle().topLeft(), p,
+ wrappedBbox, wrappedBboxMinus1, wrappedBboxPlus1, &m_bboxLeftBoundWrapped);
+
+ // 2) Store the triangulated polygon, and the wrapped bbox paths.
+ // the triangulations can be used as they are, as they "bypass" the QtQuick display chain
+ // the bbox wraps have to be however clipped, and then projected, in order to figure out the geometry.
+ // Note that this might still cause the geometryChange method to fail under some extreme conditions.
+ cutPathEars(wrappedPath, m_screenVertices, m_screenIndices);
+
+ m_wrappedPolygons.resize(3);
+ m_wrappedPolygons[0].wrappedBboxes = wrappedBboxMinus1;
+ m_wrappedPolygons[1].wrappedBboxes = wrappedBbox;
+ m_wrappedPolygons[2].wrappedBboxes = wrappedBboxPlus1;
+}
+
+// This one handles whole QGeoPolygon w. holes
+void QGeoMapPolygonGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoPolygon &poly)
+{
+ if (!sourceDirty_)
+ return;
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
+
+ // build the actual path
+ // The approach is the same as described in QGeoMapPolylineGeometry::updateSourcePoints
+ srcOrigin_ = geoLeftBound_;
+
+ QDoubleVector2D leftBoundWrapped;
+ QList<QList<QDoubleVector2D>> wrappedPath;
+ // 1) pre-compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
+ wrapPath(poly, geoLeftBound_, p,
+ wrappedPath, &leftBoundWrapped);
+
+ // 1.1) do the same for the bbox
+ QList<QDoubleVector2D> wrappedBbox, wrappedBboxPlus1, wrappedBboxMinus1;
+ QGeoPolygon bbox(poly.boundingGeoRectangle());
+ QDeclarativeGeoMapItemUtils::wrapPath(bbox.perimeter(), bbox.boundingGeoRectangle().topLeft(), p,
+ wrappedBbox, wrappedBboxMinus1, wrappedBboxPlus1, &m_bboxLeftBoundWrapped);
+
+ // 2) Store the triangulated polygon, and the wrapped bbox paths.
+ // the triangulations can be used as they are, as they "bypass" the QtQuick display chain
+ // the bbox wraps have to be however clipped, and then projected, in order to figure out the geometry.
+ // Note that this might still cause the geometryChange method to fail under some extreme conditions.
+ cutPathEars(wrappedPath, m_screenVertices, m_screenIndices);
+ m_wrappedPolygons.resize(3);
+ m_wrappedPolygons[0].wrappedBboxes = wrappedBboxMinus1;
+ m_wrappedPolygons[1].wrappedBboxes = wrappedBbox;
+ m_wrappedPolygons[2].wrappedBboxes = wrappedBboxPlus1;
+}
+
+void QGeoMapPolygonGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoRectangle &rect)
+{
+ if (!sourceDirty_)
+ return;
+ const QList<QGeoCoordinate> perimeter = QGeoMapItemGeometry::path(rect);
+ updateSourcePoints(map, perimeter);
+}
+
+/*!
+ \internal
+*/
+void QGeoMapPolygonGeometryOpenGL::updateScreenPoints(const QGeoMap &map, qreal strokeWidth , const QColor &strokeColor)
+{
+ if (map.viewportWidth() == 0 || map.viewportHeight() == 0) {
+ clear();
+ return;
+ }
+
+ // 1) identify which set to use: std, +1 or -1
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
+ const QDoubleVector2D leftBoundMercator = p.geoToMapProjection(srcOrigin_);
+ m_wrapOffset = p.projectionWrapFactor(leftBoundMercator) + 1; // +1 to get the offset into QLists
+
+ // 1.1) select geometry set
+ // This could theoretically be skipped for those polygons whose bbox is not even projectable.
+ // However, such optimization could only be introduced if not calculating bboxes lazily.
+ // Hence not doing it.
+ if (sourceDirty_) {
+ m_dataChanged = true;
+ }
+
+ if (strokeWidth == 0.0 || strokeColor.alpha() == 0) // or else the geometry of the border is used, so no point in calculating 2 of them
+ updateQuickGeometry(p, strokeWidth);
+}
+
+void QGeoMapPolygonGeometryOpenGL::updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal /*strokeWidth*/)
+{
+ // 2) clip bbox
+ // BBox handling -- this is related to the bounding box geometry
+ // that has to inevitably follow the old projection codepath
+ // As it needs to provide projected coordinates for QtQuick interaction.
+ // This could be futher optimized to be updated in a lazy fashion.
+ const QList<QDoubleVector2D> &wrappedBbox = m_wrappedPolygons.at(m_wrapOffset).wrappedBboxes;
+ QList<QList<QDoubleVector2D> > clippedBbox;
+ QDoubleVector2D bboxLeftBoundWrapped = m_bboxLeftBoundWrapped;
+ bboxLeftBoundWrapped.setX(bboxLeftBoundWrapped.x() + double(m_wrapOffset - 1));
+ QDeclarativeGeoMapItemUtils::clipPolygon(wrappedBbox, p, clippedBbox, &bboxLeftBoundWrapped);
+
+ // 3) project bbox
+ QPainterPath ppi;
+ if (!clippedBbox.size() || clippedBbox.first().size() < 3) {
+ sourceBounds_ = screenBounds_ = QRectF();
+ firstPointOffset_ = QPointF();
+ screenOutline_ = ppi;
+ return;
+ }
+
+ QDeclarativeGeoMapItemUtils::projectBbox(clippedBbox.first(), p, ppi); // Using first because a clipped box should always result in one polygon
+ const QRectF brect = ppi.boundingRect();
+ firstPointOffset_ = QPointF(brect.topLeft());
+ screenOutline_ = ppi;
+
+ // 4) Set Screen bbox
+ screenBounds_ = brect;
+ sourceBounds_.setX(0);
+ sourceBounds_.setY(0);
+ sourceBounds_.setWidth(brect.width());
+ sourceBounds_.setHeight(brect.height());
+}
+
+
+void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoPolygon &poly)
+{
+ if (!sourceDirty_)
+ return;
+ QGeoPath p(poly.perimeter());
+ if (poly.perimeter().size() && poly.perimeter().last() != poly.perimeter().first())
+ p.addCoordinate(poly.perimeter().first());
+ updateSourcePoints(map, p);
+}
+
+void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoPath &poly)
+{
+ if (!sourceDirty_)
+ return;
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
+
+ // build the actual path
+ // The approach is the same as described in QGeoMapPolylineGeometry::updateSourcePoints
+
+
+ QDoubleVector2D leftBoundWrapped;
+ // 1) pre-compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
+ QList<QDoubleVector2D> wrappedPath;
+ QDeclarativeGeoMapItemUtils::wrapPath(poly.path(), geoLeftBound_, p,
+ wrappedPath, &leftBoundWrapped);
+
+ const QGeoRectangle &boundingRectangle = poly.boundingGeoRectangle();
+ updateSourcePoints(p, wrappedPath, boundingRectangle);
+}
+
+void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoProjectionWebMercator &p,
+ const QList<QDoubleVector2D> &wrappedPath,
+ const QGeoRectangle &boundingRectangle) {
+ if (!sourceDirty_)
+ return;
+ // 1.1) do the same for the bbox
+ // Beware: vertical lines (or horizontal lines) might have an "empty" bbox. Check for that
+
+ QGeoCoordinate topLeft = boundingRectangle.topLeft();
+ QGeoCoordinate bottomRight = boundingRectangle.bottomRight();
+ const qreal epsilon = 0.000001;
+ if (qFuzzyCompare(topLeft.latitude(), bottomRight.latitude())) {
+ topLeft.setLatitude(qBound(-90.0, topLeft.latitude() + epsilon ,90.0));
+ bottomRight.setLatitude(qBound(-90.0, bottomRight.latitude() - epsilon ,90.0));
+ }
+ if (qFuzzyCompare(topLeft.longitude(), bottomRight.longitude())) {
+ topLeft.setLongitude(QLocationUtils::wrapLong(topLeft.longitude() - epsilon));
+ bottomRight.setLongitude(QLocationUtils::wrapLong(bottomRight.longitude() + epsilon));
+ }
+ QGeoPolygon bbox(QGeoRectangle(topLeft, bottomRight));
+ QList<QDoubleVector2D> wrappedBbox, wrappedBboxPlus1, wrappedBboxMinus1;
+ QDeclarativeGeoMapItemUtils::wrapPath(bbox.perimeter(), bbox.boundingGeoRectangle().topLeft(), p,
+ wrappedBbox, wrappedBboxMinus1, wrappedBboxPlus1, &m_bboxLeftBoundWrapped);
+
+ // New pointers, some old LOD task might still be running and operating on the old pointers.
+ resetLOD();
+
+ for (const auto &v: qAsConst(wrappedPath)) m_screenVertices->append(v);
+
+ m_wrappedPolygons.resize(3);
+ m_wrappedPolygons[0].wrappedBboxes = wrappedBboxMinus1;
+ m_wrappedPolygons[1].wrappedBboxes = wrappedBbox;
+ m_wrappedPolygons[2].wrappedBboxes = wrappedBboxPlus1;
+ srcOrigin_ = geoLeftBound_;
+}
+
+void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoRectangle &rect)
+{
+ const QList<QGeoCoordinate> perimeter = QGeoMapItemGeometry::perimeter(rect);
+ updateSourcePoints(map, QGeoPath(perimeter));
+}
+
+void QGeoMapPolylineGeometryOpenGL::updateSourcePoints(const QGeoMap &map, const QGeoCircle &circle)
+{
+ if (!sourceDirty_)
+ return;
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
+
+ QDoubleVector2D leftBoundWrapped;
+ // 1) pre-compute 3 sets of "wrapped" coordinates: one w regular mercator, one w regular mercator +- 1.0
+ QList<QGeoCoordinate> path;
+ QGeoCoordinate leftBound;
+ QList<QDoubleVector2D> wrappedPath;
+ QDeclarativeCircleMapItemPrivate::calculatePeripheralPoints(path, circle.center(), circle.radius(), QDeclarativeCircleMapItemPrivate::CircleSamples, leftBound);
+ path << path.first();
+ geoLeftBound_ = leftBound;
+ QDeclarativeGeoMapItemUtils::wrapPath(path, leftBound, p, wrappedPath, &leftBoundWrapped);
+ const QGeoRectangle &boundingRectangle = circle.boundingGeoRectangle();
+ updateSourcePoints(p, wrappedPath, boundingRectangle);
+}
+
+void QGeoMapPolylineGeometryOpenGL::updateScreenPoints(const QGeoMap &map, qreal strokeWidth, bool /*adjustTranslation*/)
+{
+ if (map.viewportWidth() == 0 || map.viewportHeight() == 0) {
+ clear();
+ return;
+ }
+
+ // 1) identify which set to use: std, +1 or -1
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map.geoProjection());
+ const QDoubleVector2D leftBoundMercator = p.geoToMapProjection(srcOrigin_);
+ m_wrapOffset = p.projectionWrapFactor(leftBoundMercator) + 1; // +1 to get the offset into QLists
+
+ if (sourceDirty_) {
+ // 1.1) select geometry set
+ // This could theoretically be skipped for those polylines whose bbox is not even projectable.
+ // However, such optimization could only be introduced if not calculating bboxes lazily.
+ // Hence not doing it.
+// if (m_screenVertices.size() > 1)
+ m_dataChanged = true;
+ }
+
+ updateQuickGeometry(p, strokeWidth);
+}
+
+void QGeoMapPolylineGeometryOpenGL::updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal strokeWidth)
+{
+ // 2) clip bbox
+ // BBox handling -- this is related to the bounding box geometry
+ // that has to inevitably follow the old projection codepath
+ // As it needs to provide projected coordinates for QtQuick interaction.
+ // This could be futher optimized to be updated in a lazy fashion.
+ const QList<QDoubleVector2D> &wrappedBbox = m_wrappedPolygons.at(m_wrapOffset).wrappedBboxes;
+ QList<QList<QDoubleVector2D> > clippedBbox;
+ QDoubleVector2D bboxLeftBoundWrapped = m_bboxLeftBoundWrapped;
+ bboxLeftBoundWrapped.setX(bboxLeftBoundWrapped.x() + double(m_wrapOffset - 1));
+ QDeclarativeGeoMapItemUtils::clipPolygon(wrappedBbox, p, clippedBbox, &bboxLeftBoundWrapped, false);
+
+ // 3) project bbox
+ QPainterPath ppi;
+
+ if ( !clippedBbox.size() ||
+ clippedBbox.first().size() < 3) {
+ sourceBounds_ = screenBounds_ = QRectF();
+ firstPointOffset_ = QPointF();
+ screenOutline_ = ppi;
+ return;
+ }
+
+ QDeclarativeGeoMapItemUtils::projectBbox(clippedBbox.first(), p, ppi); // Using first because a clipped box should always result in one polygon
+ const QRectF brect = ppi.boundingRect();
+ firstPointOffset_ = QPointF(brect.topLeft());
+ sourceBounds_ = brect;
+ screenOutline_ = ppi;
+
+ // 4) Set Screen bbox
+ screenBounds_ = brect;
+ sourceBounds_.setX(0);
+ sourceBounds_.setY(0);
+ sourceBounds_.setWidth(brect.width() + strokeWidth);
+ sourceBounds_.setHeight(brect.height() + strokeWidth);
+}
+
+// Note: this is also slightly incorrect on joins and in the beginning/end of the line
+bool QGeoMapPolylineGeometryOpenGL::contains(const QPointF &point, qreal lineWidth, const QGeoProjectionWebMercator &p) const
+{
+ const double lineHalfWidth = lineWidth * 0.5;
+ const QDoubleVector2D pt(point);
+ QDoubleVector2D a;
+ if (m_screenVertices->size())
+ a = p.wrappedMapProjectionToItemPosition(p.wrapMapProjection(m_screenVertices->first().toDoubleVector2D()));
+ QDoubleVector2D b;
+ for (qsizetype i = 1; i < m_screenVertices->size(); ++i) {
+ const auto &screenVertice = m_screenVertices->at(i);
+ if (!a.isFinite()) {
+ a = p.wrappedMapProjectionToItemPosition(p.wrapMapProjection(screenVertice.toDoubleVector2D()));
+ continue;
+ }
+
+ b = p.wrappedMapProjectionToItemPosition(p.wrapMapProjection(screenVertice.toDoubleVector2D()));
+ if (!b.isFinite()) {
+ a = b;
+ continue;
+ }
+
+ if (b == a)
+ continue;
+
+ // Heavily simplifying it here: if a point is not projectable, skip the segment.
+ // For a correct solution, the segment should be clipped instead.
+ if (distanceTo(a, b, pt) <= lineHalfWidth)
+ return true;
+
+ a = b;
+ }
+ return false;
+}
+
+QT_END_NAMESPACE
diff --git a/src/location/quickmapitems/rhi/qgeomapitemgeometry_rhi_p.h b/src/location/quickmapitems/rhi/qgeomapitemgeometry_rhi_p.h
new file mode 100644
index 00000000..27fb8835
--- /dev/null
+++ b/src/location/quickmapitems/rhi/qgeomapitemgeometry_rhi_p.h
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2022 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGEOMAPITEMGEOMETRY_RHI_P_H
+#define QGEOMAPITEMGEOMETRY_RHI_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/QList>
+#include <QtCore/QSharedPointer>
+#include <QtGui/QColor>
+#include <QtPositioning/private/qdoublevector2d_p.h>
+#include <QtLocation/private/qdeclarativegeomapitemutils_p.h>
+#include <QtLocation/private/qgeomapitemgeometry_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QPointF;
+class QSGGeometry;
+class QGeoCircle;
+class QGeoMap;
+class QGeoPath;
+class QGeoPolygon;
+class QGeoProjectionWebMercator;
+class QGeoRectangle;
+
+class QGeoMapItemLODGeometry
+{
+ Q_DISABLE_COPY(QGeoMapItemLODGeometry);
+public:
+ mutable std::array<QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>, 7>
+ m_verticesLOD; // fix it to 7,
+ // do not allow simplifications beyond ZL 20. This could actually be
+ // limited even further
+ mutable QList<QDeclarativeGeoMapItemUtils::vec2> *m_screenVertices;
+ mutable QSharedPointer<unsigned int> m_working;
+
+ QGeoMapItemLODGeometry();
+
+ void resetLOD();
+
+ static unsigned int zoomToLOD(unsigned int zoom);
+
+ static unsigned int zoomForLOD(unsigned int zoom);
+
+ bool isLODActive(unsigned int lod) const;
+
+ void selectLOD(unsigned int zoom, double leftBound, bool /*closed*/);
+
+ static QList<QDeclarativeGeoMapItemUtils::vec2>
+ getSimplified(QList<QDeclarativeGeoMapItemUtils::vec2> &wrappedPath, double leftBoundWrapped,
+ unsigned int zoom);
+
+ static void enqueueSimplificationTask(
+ const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>>
+ &input, // reference as it gets copied in the nested call
+ const QSharedPointer<QList<QDeclarativeGeoMapItemUtils::vec2>> &output,
+ double leftBound, unsigned int zoom, QSharedPointer<unsigned int> &working);
+
+ void selectLODOnDataChanged(unsigned int zoom, double leftBound) const;
+ bool selectLODOnLODMismatch(unsigned int zoom, double leftBound, bool closed) const;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QGeoMapPolylineGeometryOpenGL : public QGeoMapItemGeometry,
+ public QGeoMapItemLODGeometry
+{
+public:
+ typedef struct {
+ QList<QDoubleVector2D> wrappedBboxes;
+ } WrappedPolyline;
+
+ QGeoMapPolylineGeometryOpenGL()
+ {
+ m_working = QSharedPointer<unsigned int>(new unsigned int(0));
+ }
+
+ void updateSourcePoints(const QGeoMap &map,
+ const QGeoPolygon &poly);
+
+ void updateSourcePoints(const QGeoMap &map,
+ const QGeoPath &poly);
+
+ void updateSourcePoints(const QGeoProjectionWebMercator &p,
+ const QList<QDoubleVector2D> &wrappedPath,
+ const QGeoRectangle &boundingRectangle);
+
+ void updateSourcePoints(const QGeoMap &map,
+ const QGeoRectangle &rect);
+
+ void updateSourcePoints(const QGeoMap &map,
+ const QGeoCircle &circle);
+
+ void updateScreenPoints(const QGeoMap &map,
+ qreal strokeWidth,
+ bool adjustTranslation = true);
+
+ void updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal strokeWidth = 0.0);
+
+ bool allocateAndFillEntries(QSGGeometry *geom,
+ bool closed = false,
+ unsigned int zoom = 0) const;
+ void allocateAndFillLineStrip(QSGGeometry *geom,
+ int lod = 0) const;
+
+ bool contains(const QPointF &point) const override
+ {
+ Q_UNUSED(point);
+ return false;
+ }
+
+ static double distanceTo(const QDoubleVector2D &a, const QDoubleVector2D &b, const QDoubleVector2D &p)
+ {
+ double u = ((p.x() - a.x()) * (b.x() - a.x()) + (p.y() - a.y()) * (b.y() - a.y()))
+ / (b - a).lengthSquared();
+ QDoubleVector2D intersection(a.x() + u * (b.x() - a.x()) , a.y() + u * (b.y() - a.y()));
+
+ QDoubleVector2D candidate = ( (p-a).length() < (p-b).length() ) ? a : b;
+
+ // And it falls in the segment
+ if (u > 0 && u < 1 && (p-intersection).length() < (p-candidate).length()) {
+ candidate = intersection;
+ }
+
+ return qAbs((candidate - p).length());
+ }
+ // Note: this is also slightly incorrect on joins and in the beginning/end of the line
+ bool contains(const QPointF &point, qreal lineWidth, const QGeoProjectionWebMercator &p) const;
+
+public:
+ QDoubleVector2D m_bboxLeftBoundWrapped;
+ QList<WrappedPolyline> m_wrappedPolygons;
+ int m_wrapOffset;
+
+ friend class QDeclarativeCircleMapItem;
+ friend class QDeclarativePolygonMapItem;
+ friend class QDeclarativeRectangleMapItem;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QGeoMapPolygonGeometryOpenGL : public QGeoMapItemGeometry
+{
+public:
+ typedef struct {
+ QList<QDoubleVector2D> wrappedBboxes;
+ } WrappedPolygon;
+ QGeoMapPolygonGeometryOpenGL();
+ ~QGeoMapPolygonGeometryOpenGL() override {}
+
+ // Temporary method for compatibility in MapCircleObject. Remove when MapObjects are ported.
+ void updateSourcePoints(const QGeoMap &map,
+ const QList<QDoubleVector2D> &path);
+
+ void updateSourcePoints(const QGeoMap &map,
+ const QList<QGeoCoordinate> &perimeter);
+
+ void updateSourcePoints(const QGeoMap &map,
+ const QGeoPolygon &poly);
+
+ void updateSourcePoints(const QGeoMap &map,
+ const QGeoRectangle &rect);
+
+ void updateScreenPoints(const QGeoMap &map, qreal strokeWidth = 0.0,
+ const QColor &strokeColor = Qt::transparent);
+ void updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal strokeWidth = 0.0);
+
+ void allocateAndFillPolygon(QSGGeometry *geom) const;
+
+ QList<QDeclarativeGeoMapItemUtils::vec2> m_screenVertices;
+ QList<quint32> m_screenIndices;
+ QDoubleVector2D m_bboxLeftBoundWrapped;
+ QList<WrappedPolygon> m_wrappedPolygons;
+ int m_wrapOffset = 0;
+};
+
+QT_END_NAMESPACE
+
+#endif // QGEOMAPITEMGEOMETRY_RHI_P_H
diff --git a/src/location/quickmapitems/qgeosimplify.cpp b/src/location/quickmapitems/rhi/qgeosimplify.cpp
index ad5a3c5d..ad5a3c5d 100644
--- a/src/location/quickmapitems/qgeosimplify.cpp
+++ b/src/location/quickmapitems/rhi/qgeosimplify.cpp
diff --git a/src/location/quickmapitems/qgeosimplify_p.h b/src/location/quickmapitems/rhi/qgeosimplify_p.h
index 1f5c9783..1f5c9783 100644
--- a/src/location/quickmapitems/qgeosimplify_p.h
+++ b/src/location/quickmapitems/rhi/qgeosimplify_p.h
diff --git a/src/location/quickmapitems/shaders/polygon.frag b/src/location/quickmapitems/rhi/shaders/polygon.frag
index 9b9727b6..9b9727b6 100644
--- a/src/location/quickmapitems/shaders/polygon.frag
+++ b/src/location/quickmapitems/rhi/shaders/polygon.frag
diff --git a/src/location/quickmapitems/shaders/polygon.vert b/src/location/quickmapitems/rhi/shaders/polygon.vert
index 06dab03e..06dab03e 100644
--- a/src/location/quickmapitems/shaders/polygon.vert
+++ b/src/location/quickmapitems/rhi/shaders/polygon.vert
diff --git a/src/location/quickmapitems/shaders/polyline_extruded.frag b/src/location/quickmapitems/rhi/shaders/polyline_extruded.frag
index 3530f093..3530f093 100644
--- a/src/location/quickmapitems/shaders/polyline_extruded.frag
+++ b/src/location/quickmapitems/rhi/shaders/polyline_extruded.frag
diff --git a/src/location/quickmapitems/shaders/polyline_extruded.vert b/src/location/quickmapitems/rhi/shaders/polyline_extruded.vert
index 27b69b60..27b69b60 100644
--- a/src/location/quickmapitems/shaders/polyline_extruded.vert
+++ b/src/location/quickmapitems/rhi/shaders/polyline_extruded.vert
diff --git a/src/location/quickmapitems/shaders/polyline_linestrip.frag b/src/location/quickmapitems/rhi/shaders/polyline_linestrip.frag
index e9124d27..e9124d27 100644
--- a/src/location/quickmapitems/shaders/polyline_linestrip.frag
+++ b/src/location/quickmapitems/rhi/shaders/polyline_linestrip.frag
diff --git a/src/location/quickmapitems/shaders/polyline_linestrip.vert b/src/location/quickmapitems/rhi/shaders/polyline_linestrip.vert
index 86b4f3a3..86b4f3a3 100644
--- a/src/location/quickmapitems/shaders/polyline_linestrip.vert
+++ b/src/location/quickmapitems/rhi/shaders/polyline_linestrip.vert