summaryrefslogtreecommitdiff
path: root/src/location/declarativemaps/qdeclarativepolygonmapitem_p_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/location/declarativemaps/qdeclarativepolygonmapitem_p_p.h')
-rw-r--r--src/location/declarativemaps/qdeclarativepolygonmapitem_p_p.h668
1 files changed, 668 insertions, 0 deletions
diff --git a/src/location/declarativemaps/qdeclarativepolygonmapitem_p_p.h b/src/location/declarativemaps/qdeclarativepolygonmapitem_p_p.h
new file mode 100644
index 00000000..8d566e69
--- /dev/null
+++ b/src/location/declarativemaps/qdeclarativepolygonmapitem_p_p.h
@@ -0,0 +1,668 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Paolo Angelelli <paolo.angelelli@gmail.com>
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtLocation module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL3$
+** 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 http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free
+** Software Foundation and appearing in the file LICENSE.GPL included in
+** the packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 2.0 requirements will be
+** met: http://www.gnu.org/licenses/gpl-2.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVEPOLYGONMAPITEM_P_P_H
+#define QDECLARATIVEPOLYGONMAPITEM_P_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/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 <QSGGeometryNode>
+#include <QSGFlatColorMaterial>
+#include <QtPositioning/QGeoPath>
+#include <QtPositioning/QGeoRectangle>
+#include <QtPositioning/QGeoPolygon>
+#include <QtPositioning/private/qdoublevector2d_p.h>
+#include <QSGFlatColorMaterial>
+#include <QSGSimpleMaterial>
+#include <QtGui/QMatrix4x4>
+#include <QColor>
+#include <QList>
+#include <QVector>
+#include <QtCore/QScopedValueRollback>
+
+QT_BEGIN_NAMESPACE
+
+class Q_LOCATION_PRIVATE_EXPORT QGeoMapPolygonGeometry : public QGeoMapItemGeometry
+{
+public:
+ QGeoMapPolygonGeometry();
+
+ inline void setAssumeSimple(bool value) { assumeSimple_ = value; }
+
+ void updateSourcePoints(const QGeoMap &map,
+ const QList<QDoubleVector2D> &path);
+
+ void updateScreenPoints(const QGeoMap &map, qreal strokeWidth = 0.0);
+
+protected:
+ QPainterPath srcPath_;
+ bool assumeSimple_;
+};
+
+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 QVector<QDeclarativeGeoMapItemUtils::vec2> &vx = m_screenVertices;
+ const QVector<quint32> &ix = m_screenIndices;
+
+ geom->allocate(vx.size(), ix.size());
+ if (geom->indexType() == QSGGeometry::UnsignedShortType) {
+ quint16 *its = geom->indexDataAsUShort();
+ for (int i = 0; i < ix.size(); ++i)
+ its[i] = ix[i];
+ } else if (geom->indexType() == QSGGeometry::UnsignedIntType) {
+ quint32 *its = geom->indexDataAsUInt();
+ for (int i = 0; i < ix.size(); ++i)
+ its[i] = ix[i];
+ }
+
+ QSGGeometry::Point2D *pts = geom->vertexDataAsPoint2D();
+ for (int i = 0; i < vx.size(); ++i)
+ pts[i].set(vx[i].x, vx[i].y);
+ }
+
+ QVector<QDeclarativeGeoMapItemUtils::vec2> m_screenVertices;
+ QVector<quint32> m_screenIndices;
+ QDoubleVector2D m_bboxLeftBoundWrapped;
+ QVector<WrappedPolygon> m_wrappedPolygons;
+ int m_wrapOffset;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT MapPolygonShader : public QSGMaterialShader
+{
+public:
+ MapPolygonShader();
+
+ const char *vertexShader() const override {
+ return
+ "attribute highp vec4 vertex; \n"
+ "uniform highp mat4 qt_Matrix; \n"
+ "uniform highp mat4 mapProjection; \n"
+ "uniform highp vec3 center; \n"
+ "uniform highp vec3 center_lowpart; \n"
+ "uniform lowp float wrapOffset; \n"
+ "vec4 wrapped(in vec4 v) { return vec4(v.x + wrapOffset, v.y, 0.0, 1.0); }\n"
+ "void main() { \n"
+ " vec4 vtx = wrapped(vertex) - vec4(center, 0.0); \n"
+ " vtx = vtx - vec4(center_lowpart, 0.0); \n"
+ " gl_Position = qt_Matrix * mapProjection * vtx; \n"
+ "}";
+ }
+
+ const char *fragmentShader() const override {
+ return
+ "uniform lowp vec4 color; \n"
+ "void main() { \n"
+ " gl_FragColor = color; \n"
+ "}";
+ }
+
+ void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
+ char const *const *attributeNames() const override
+ {
+ static char const *const attr[] = { "vertex", nullptr };
+ return attr;
+ }
+
+private:
+ void initialize() override
+ {
+ m_matrix_id = program()->uniformLocation("qt_Matrix");
+ m_color_id = program()->uniformLocation("color");
+ m_mapProjection_id = program()->uniformLocation("mapProjection");
+ m_center_id = program()->uniformLocation("center");
+ m_center_lowpart_id = program()->uniformLocation("center_lowpart");
+ m_wrapOffset_id = program()->uniformLocation("wrapOffset");
+ }
+ int m_center_id;
+ int m_center_lowpart_id;
+ int m_mapProjection_id;
+ int m_matrix_id;
+ int m_color_id;
+ int m_wrapOffset_id;
+};
+
+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 | CustomCompileStep);
+ }
+
+ QSGMaterialShader *createShader() 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
+{
+
+public:
+ MapPolygonNode();
+ ~MapPolygonNode() override;
+
+ void update(const QColor &fillColor, const QColor &borderColor,
+ const QGeoMapItemGeometry *fillShape,
+ const QGeoMapItemGeometry *borderShape);
+private:
+ QSGFlatColorMaterial fill_material_;
+ MapPolylineNode *border_;
+ 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:
+ QDeclarativePolygonMapItemPrivate(QDeclarativePolygonMapItem &polygon) : m_poly(polygon)
+ {
+
+ }
+ QDeclarativePolygonMapItemPrivate(QDeclarativePolygonMapItemPrivate &other) : m_poly(other.m_poly)
+ {
+ }
+
+ virtual ~QDeclarativePolygonMapItemPrivate();
+ virtual void onLinePropertiesChanged() = 0;
+ virtual void markSourceDirtyAndUpdate() = 0;
+ virtual void onMapSet() = 0;
+ virtual void onGeoGeometryChanged() = 0;
+ virtual void onGeoGeometryUpdated() = 0;
+ virtual void onItemGeometryChanged() = 0;
+ virtual void updatePolish() = 0;
+ virtual void afterViewportChanged() = 0;
+ virtual QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) = 0;
+ virtual bool contains(const QPointF &point) const = 0;
+
+ QDeclarativePolygonMapItem &m_poly;
+};
+
+class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolygonMapItemPrivateCPU: public QDeclarativePolygonMapItemPrivate
+{
+public:
+ QDeclarativePolygonMapItemPrivateCPU(QDeclarativePolygonMapItem &polygon) : QDeclarativePolygonMapItemPrivate(polygon)
+ {
+ }
+
+ QDeclarativePolygonMapItemPrivateCPU(QDeclarativePolygonMapItemPrivate &other)
+ : QDeclarativePolygonMapItemPrivate(other)
+ {
+ }
+
+ ~QDeclarativePolygonMapItemPrivateCPU() override;
+ void onLinePropertiesChanged() override
+ {
+ // mark dirty just in case we're a width change
+ markSourceDirtyAndUpdate();
+ }
+ void markSourceDirtyAndUpdate() override
+ {
+ // preserveGeometry is cleared in updateMapItemPaintNode
+ m_geometry.markSourceDirty();
+ m_borderGeometry.markSourceDirty();
+ m_poly.polishAndUpdate();
+ }
+ void regenerateCache()
+ {
+ if (!m_poly.map() || m_poly.map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
+ return;
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_poly.map()->geoProjection());
+ m_geopathProjected.clear();
+ m_geopathProjected.reserve(m_poly.m_geopoly.size());
+ for (const QGeoCoordinate &c : m_poly.m_geopoly.path())
+ m_geopathProjected << p.geoToMapProjection(c);
+ }
+ void updateCache()
+ {
+ if (!m_poly.map() || m_poly.map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
+ return;
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_poly.map()->geoProjection());
+ m_geopathProjected << p.geoToMapProjection(m_poly.m_geopoly.path().last());
+ }
+ 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
+ {
+ // preserveGeometry is cleared in updateMapItemPaintNode
+ preserveGeometry();
+ markSourceDirtyAndUpdate();
+ }
+ void onMapSet() override
+ {
+ regenerateCache();
+ markSourceDirtyAndUpdate();
+ }
+ void onGeoGeometryChanged() override
+ {
+ regenerateCache();
+ preserveGeometry();
+ markSourceDirtyAndUpdate();
+ }
+ void onGeoGeometryUpdated() override
+ {
+ updateCache();
+ preserveGeometry();
+ markSourceDirtyAndUpdate();
+ }
+ void onItemGeometryChanged() override
+ {
+ onGeoGeometryChanged();
+ }
+ void updatePolish() override
+ {
+ if (m_poly.m_geopoly.path().length() == 0) { // Possibly cleared
+ m_geometry.clear();
+ m_borderGeometry.clear();
+ m_poly.setWidth(0);
+ m_poly.setHeight(0);
+ return;
+ }
+ const QGeoMap *map = m_poly.map();
+ const qreal borderWidth = m_poly.m_border.width();
+ const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map->geoProjection());
+ QScopedValueRollback<bool> rollback(m_poly.m_updatingGeometry);
+ m_poly.m_updatingGeometry = true;
+
+ m_geometry.updateSourcePoints(*map, m_geopathProjected);
+ m_geometry.updateScreenPoints(*map, borderWidth);
+
+ QList<QGeoMapItemGeometry *> geoms;
+ geoms << &m_geometry;
+ m_borderGeometry.clear();
+
+ if (m_poly.m_border.color().alpha() != 0 && borderWidth > 0) {
+ QList<QDoubleVector2D> closedPath = m_geopathProjected;
+ closedPath << closedPath.first();
+
+ m_borderGeometry.setPreserveGeometry(true, m_poly.m_geopoly.boundingGeoRectangle().topLeft());
+
+ const QGeoCoordinate &geometryOrigin = m_geometry.origin();
+
+ m_borderGeometry.srcPoints_.clear();
+ m_borderGeometry.srcPointTypes_.clear();
+
+ QDoubleVector2D borderLeftBoundWrapped;
+ QList<QList<QDoubleVector2D > > clippedPaths = m_borderGeometry.clipPath(*map, closedPath, borderLeftBoundWrapped);
+ if (clippedPaths.size()) {
+ borderLeftBoundWrapped = p.geoToWrappedMapProjection(geometryOrigin);
+ m_borderGeometry.pathToScreen(*map, clippedPaths, borderLeftBoundWrapped);
+ m_borderGeometry.updateScreenPoints(*map, borderWidth);
+
+ geoms << &m_borderGeometry;
+ } else {
+ m_borderGeometry.clear();
+ }
+ }
+
+ QRectF combined = QGeoMapItemGeometry::translateToCommonOrigin(geoms);
+ m_poly.setWidth(combined.width() + 2 * borderWidth);
+ m_poly.setHeight(combined.height() + 2 * borderWidth);
+
+ m_poly.setPositionOnMap(m_geometry.origin(), -1 * m_geometry.sourceBoundingBox().topLeft()
+ + QPointF(borderWidth, borderWidth));
+ }
+ QSGNode *updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override
+ {
+ Q_UNUSED(data);
+ if (!m_node || !oldNode) {
+ m_node = new MapPolygonNode();
+ if (oldNode) {
+ delete oldNode;
+ oldNode = nullptr;
+ }
+ } else {
+ m_node = static_cast<MapPolygonNode *>(oldNode);
+ }
+
+ //TODO: update only material
+ if (m_geometry.isScreenDirty()
+ || m_borderGeometry.isScreenDirty()
+ || m_poly.m_dirtyMaterial
+ || !oldNode) {
+ m_node->update(m_poly.m_color,
+ m_poly.m_border.color(),
+ &m_geometry,
+ &m_borderGeometry);
+ m_geometry.setPreserveGeometry(false);
+ m_borderGeometry.setPreserveGeometry(false);
+ m_geometry.markClean();
+ m_borderGeometry.markClean();
+ m_poly.m_dirtyMaterial = false;
+ }
+ return m_node;
+ }
+ bool contains(const QPointF &point) const override
+ {
+ return (m_geometry.contains(point) || m_borderGeometry.contains(point));
+ }
+
+ QList<QDoubleVector2D> m_geopathProjected;
+ QGeoMapPolygonGeometry m_geometry;
+ QGeoMapPolylineGeometry m_borderGeometry;
+ 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.path().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