1/****************************************************************************
2**
3** Copyright (C) 2020 Paolo Angelelli <paolo.angelelli@gmail.com>
4** Copyright (C) 2020 The Qt Company Ltd.
5** Contact: http://www.qt.io/licensing/
6**
7** This file is part of the QtLocation module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL3$
10** Commercial License Usage
11** Licensees holding valid commercial Qt licenses may use this file in
12** accordance with the commercial license agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and The Qt Company. For licensing terms
15** and conditions see http://www.qt.io/terms-conditions. For further
16** information use the contact form at http://www.qt.io/contact-us.
17**
18** GNU Lesser General Public License Usage
19** Alternatively, this file may be used under the terms of the GNU Lesser
20** General Public License version 3 as published by the Free Software
21** Foundation and appearing in the file LICENSE.LGPLv3 included in the
22** packaging of this file. Please review the following information to
23** ensure the GNU Lesser General Public License version 3 requirements
24** will be met: https://www.gnu.org/licenses/lgpl.html.
25**
26** GNU General Public License Usage
27** Alternatively, this file may be used under the terms of the GNU
28** General Public License version 2.0 or later as published by the Free
29** Software Foundation and appearing in the file LICENSE.GPL included in
30** the packaging of this file. Please review the following information to
31** ensure the GNU General Public License version 2.0 requirements will be
32** met: http://www.gnu.org/licenses/gpl-2.0.html.
33**
34** $QT_END_LICENSE$
35**
36****************************************************************************/
37
38#ifndef QDECLARATIVEPOLYGONMAPITEM_P_P_H
39#define QDECLARATIVEPOLYGONMAPITEM_P_P_H
40
41//
42// W A R N I N G
43// -------------
44//
45// This file is not part of the Qt API. It exists purely as an
46// implementation detail. This header file may change from version to
47// version without notice, or even be removed.
48//
49// We mean it.
50//
51
52#include <QtLocation/private/qlocationglobal_p.h>
53#include <QtLocation/private/qgeomapitemgeometry_p.h>
54#include <QtLocation/private/qdeclarativegeomapitembase_p.h>
55#include <QtLocation/private/qdeclarativepolylinemapitem_p.h>
56#include <QtLocation/private/qdeclarativegeomapitemutils_p.h>
57#include <QtLocation/private/qdeclarativepolygonmapitem_p.h>
58#include <QtLocation/private/qdeclarativepolylinemapitem_p_p.h>
59#include <QSGGeometryNode>
60#include <QSGFlatColorMaterial>
61#include <QtPositioning/QGeoPath>
62#include <QtPositioning/QGeoRectangle>
63#include <QtPositioning/QGeoPolygon>
64#include <QtPositioning/private/qdoublevector2d_p.h>
65#include <QSGFlatColorMaterial>
66#include <QSGSimpleMaterial>
67#include <QtGui/QMatrix4x4>
68#include <QColor>
69#include <QList>
70#include <QVector>
71#include <QtCore/QScopedValueRollback>
72
73QT_BEGIN_NAMESPACE
74
75class Q_LOCATION_PRIVATE_EXPORT QGeoMapPolygonGeometry : public QGeoMapItemGeometry
76{
77public:
78 QGeoMapPolygonGeometry();
79
80 inline void setAssumeSimple(bool value) { assumeSimple_ = value; }
81
82 void updateSourcePoints(const QGeoMap &map,
83 const QList<QDoubleVector2D> &path);
84
85 void updateScreenPoints(const QGeoMap &map, qreal strokeWidth = 0.0);
86
87protected:
88 QPainterPath srcPath_;
89 bool assumeSimple_;
90};
91
92#if QT_CONFIG(opengl)
93class Q_LOCATION_PRIVATE_EXPORT QGeoMapPolygonGeometryOpenGL : public QGeoMapItemGeometry
94{
95public:
96 typedef struct {
97 QList<QDoubleVector2D> wrappedBboxes;
98 } WrappedPolygon;
99 QGeoMapPolygonGeometryOpenGL();
100 ~QGeoMapPolygonGeometryOpenGL() override {}
101
102 // Temporary method for compatibility in MapCircleObject. Remove when MapObjects are ported.
103 void updateSourcePoints(const QGeoMap &map,
104 const QList<QDoubleVector2D> &path);
105
106 void updateSourcePoints(const QGeoMap &map,
107 const QList<QGeoCoordinate> &perimeter);
108
109 void updateSourcePoints(const QGeoMap &map,
110 const QGeoPolygon &poly);
111
112 void updateSourcePoints(const QGeoMap &map,
113 const QGeoRectangle &rect);
114
115 void updateScreenPoints(const QGeoMap &map, qreal strokeWidth = 0.0, const QColor &strokeColor = Qt::transparent);
116 void updateQuickGeometry(const QGeoProjectionWebMercator &p, qreal strokeWidth = 0.0);
117
118 void allocateAndFillPolygon(QSGGeometry *geom) const
119 {
120
121
122 const QVector<QDeclarativeGeoMapItemUtils::vec2> &vx = m_screenVertices;
123 const QVector<quint32> &ix = m_screenIndices;
124
125 geom->allocate(vertexCount: vx.size(), indexCount: ix.size());
126 if (geom->indexType() == QSGGeometry::UnsignedShortType) {
127 quint16 *its = geom->indexDataAsUShort();
128 for (int i = 0; i < ix.size(); ++i)
129 its[i] = ix[i];
130 } else if (geom->indexType() == QSGGeometry::UnsignedIntType) {
131 quint32 *its = geom->indexDataAsUInt();
132 for (int i = 0; i < ix.size(); ++i)
133 its[i] = ix[i];
134 }
135
136 QSGGeometry::Point2D *pts = geom->vertexDataAsPoint2D();
137 for (int i = 0; i < vx.size(); ++i)
138 pts[i].set(nx: vx[i].x, ny: vx[i].y);
139 }
140
141 QVector<QDeclarativeGeoMapItemUtils::vec2> m_screenVertices;
142 QVector<quint32> m_screenIndices;
143 QDoubleVector2D m_bboxLeftBoundWrapped;
144 QVector<WrappedPolygon> m_wrappedPolygons;
145 int m_wrapOffset;
146};
147
148class Q_LOCATION_PRIVATE_EXPORT MapPolygonShader : public QSGMaterialShader
149{
150public:
151 MapPolygonShader();
152
153 const char *vertexShader() const override {
154 return
155 "attribute highp vec4 vertex; \n"
156 "uniform highp mat4 qt_Matrix; \n"
157 "uniform highp mat4 mapProjection; \n"
158 "uniform highp vec3 center; \n"
159 "uniform highp vec3 center_lowpart; \n"
160 "uniform lowp float wrapOffset; \n"
161 "vec4 wrapped(in vec4 v) { return vec4(v.x + wrapOffset, v.y, 0.0, 1.0); }\n"
162 "void main() { \n"
163 " vec4 vtx = wrapped(vertex) - vec4(center, 0.0); \n"
164 " vtx = vtx - vec4(center_lowpart, 0.0); \n"
165 " gl_Position = qt_Matrix * mapProjection * vtx; \n"
166 "}";
167 }
168
169 const char *fragmentShader() const override {
170 return
171 "uniform lowp vec4 color; \n"
172 "void main() { \n"
173 " gl_FragColor = color; \n"
174 "}";
175 }
176
177 void updateState(const RenderState &state, QSGMaterial *newEffect, QSGMaterial *oldEffect) override;
178 char const *const *attributeNames() const override
179 {
180 static char const *const attr[] = { "vertex", nullptr };
181 return attr;
182 }
183
184private:
185 void initialize() override
186 {
187 m_matrix_id = program()->uniformLocation(name: "qt_Matrix");
188 m_color_id = program()->uniformLocation(name: "color");
189 m_mapProjection_id = program()->uniformLocation(name: "mapProjection");
190 m_center_id = program()->uniformLocation(name: "center");
191 m_center_lowpart_id = program()->uniformLocation(name: "center_lowpart");
192 m_wrapOffset_id = program()->uniformLocation(name: "wrapOffset");
193 }
194 int m_center_id;
195 int m_center_lowpart_id;
196 int m_mapProjection_id;
197 int m_matrix_id;
198 int m_color_id;
199 int m_wrapOffset_id;
200};
201#endif // QT_CONFIG(opengl)
202
203class Q_LOCATION_PRIVATE_EXPORT MapPolygonMaterial : public QSGFlatColorMaterial
204{
205public:
206 MapPolygonMaterial()
207 : QSGFlatColorMaterial()
208 {
209 // Passing RequiresFullMatrix is essential in order to prevent the
210 // batch renderer from baking in simple, translate-only transforms into
211 // the vertex data. The shader will rely on the fact that
212 // vertexCoord.xy is the Shape-space coordinate and so no modifications
213 // are welcome.
214 setFlag(flags: Blending | RequiresFullMatrix | CustomCompileStep);
215 }
216
217 QSGMaterialShader *createShader() const override;
218
219 void setGeoProjection(const QMatrix4x4 &p)
220 {
221 m_geoProjection = p;
222 }
223
224 QMatrix4x4 geoProjection() const
225 {
226 return m_geoProjection;
227 }
228
229 void setCenter(const QDoubleVector3D &c)
230 {
231 m_center = c;
232 }
233
234 QDoubleVector3D center() const
235 {
236 return m_center;
237 }
238
239 int wrapOffset() const
240 {
241 return m_wrapOffset;
242 }
243
244 void setWrapOffset(int wrapOffset)
245 {
246 m_wrapOffset = wrapOffset;
247 }
248
249 int compare(const QSGMaterial *other) const override;
250 QSGMaterialType *type() const override;
251
252protected:
253 QMatrix4x4 m_geoProjection;
254 QDoubleVector3D m_center;
255 int m_wrapOffset = 0;
256};
257
258class Q_LOCATION_PRIVATE_EXPORT MapPolygonNode : public MapItemGeometryNode
259{
260
261public:
262 MapPolygonNode();
263 ~MapPolygonNode() override;
264
265 void update(const QColor &fillColor, const QColor &borderColor,
266 const QGeoMapItemGeometry *fillShape,
267 const QGeoMapItemGeometry *borderShape);
268private:
269 QSGFlatColorMaterial fill_material_;
270 MapPolylineNode *border_;
271 QSGGeometry geometry_;
272};
273
274#if QT_CONFIG(opengl)
275class Q_LOCATION_PRIVATE_EXPORT MapPolygonNodeGL : public MapItemGeometryNode
276{
277
278public:
279 MapPolygonNodeGL();
280 ~MapPolygonNodeGL() override;
281
282 void update(const QColor &fillColor,
283 const QGeoMapPolygonGeometryOpenGL *fillShape,
284 const QMatrix4x4 &geoProjection,
285 const QDoubleVector3D &center);
286
287 MapPolygonMaterial fill_material_;
288 QSGGeometry geometry_;
289};
290#endif // QT_CONFIG(opengl)
291
292class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolygonMapItemPrivate
293{
294public:
295 QDeclarativePolygonMapItemPrivate(QDeclarativePolygonMapItem &polygon) : m_poly(polygon)
296 {
297
298 }
299 QDeclarativePolygonMapItemPrivate(QDeclarativePolygonMapItemPrivate &other) : m_poly(other.m_poly)
300 {
301 }
302
303 virtual ~QDeclarativePolygonMapItemPrivate();
304 virtual void onLinePropertiesChanged() = 0;
305 virtual void markSourceDirtyAndUpdate() = 0;
306 virtual void onMapSet() = 0;
307 virtual void onGeoGeometryChanged() = 0;
308 virtual void onGeoGeometryUpdated() = 0;
309 virtual void onItemGeometryChanged() = 0;
310 virtual void updatePolish() = 0;
311 virtual void afterViewportChanged() = 0;
312 virtual QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) = 0;
313 virtual bool contains(const QPointF &point) const = 0;
314
315 QDeclarativePolygonMapItem &m_poly;
316};
317
318class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolygonMapItemPrivateCPU: public QDeclarativePolygonMapItemPrivate
319{
320public:
321 QDeclarativePolygonMapItemPrivateCPU(QDeclarativePolygonMapItem &polygon) : QDeclarativePolygonMapItemPrivate(polygon)
322 {
323 }
324
325 QDeclarativePolygonMapItemPrivateCPU(QDeclarativePolygonMapItemPrivate &other)
326 : QDeclarativePolygonMapItemPrivate(other)
327 {
328 }
329
330 ~QDeclarativePolygonMapItemPrivateCPU() override;
331 void onLinePropertiesChanged() override
332 {
333 // mark dirty just in case we're a width change
334 markSourceDirtyAndUpdate();
335 }
336 void markSourceDirtyAndUpdate() override
337 {
338 // preserveGeometry is cleared in updateMapItemPaintNode
339 m_geometry.markSourceDirty();
340 m_borderGeometry.markSourceDirty();
341 m_poly.polishAndUpdate();
342 }
343 void regenerateCache()
344 {
345 if (!m_poly.map() || m_poly.map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
346 return;
347 const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_poly.map()->geoProjection());
348 m_geopathProjected.clear();
349 m_geopathProjected.reserve(alloc: m_poly.m_geopoly.size());
350 for (const QGeoCoordinate &c : m_poly.m_geopoly.path())
351 m_geopathProjected << p.geoToMapProjection(coordinate: c);
352 }
353 void updateCache()
354 {
355 if (!m_poly.map() || m_poly.map()->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
356 return;
357 const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_poly.map()->geoProjection());
358 m_geopathProjected << p.geoToMapProjection(coordinate: m_poly.m_geopoly.path().last());
359 }
360 void preserveGeometry()
361 {
362 m_geometry.setPreserveGeometry(value: true, geoLeftBound: m_poly.m_geopoly.boundingGeoRectangle().topLeft());
363 m_borderGeometry.setPreserveGeometry(value: true, geoLeftBound: m_poly.m_geopoly.boundingGeoRectangle().topLeft());
364 }
365 void afterViewportChanged() override
366 {
367 // preserveGeometry is cleared in updateMapItemPaintNode
368 preserveGeometry();
369 markSourceDirtyAndUpdate();
370 }
371 void onMapSet() override
372 {
373 regenerateCache();
374 markSourceDirtyAndUpdate();
375 }
376 void onGeoGeometryChanged() override
377 {
378 regenerateCache();
379 preserveGeometry();
380 markSourceDirtyAndUpdate();
381 }
382 void onGeoGeometryUpdated() override
383 {
384 updateCache();
385 preserveGeometry();
386 markSourceDirtyAndUpdate();
387 }
388 void onItemGeometryChanged() override
389 {
390 onGeoGeometryChanged();
391 }
392 void updatePolish() override
393 {
394 if (m_poly.m_geopoly.path().length() == 0) { // Possibly cleared
395 m_geometry.clear();
396 m_borderGeometry.clear();
397 m_poly.setWidth(0);
398 m_poly.setHeight(0);
399 return;
400 }
401 const QGeoMap *map = m_poly.map();
402 const qreal borderWidth = m_poly.m_border.width();
403 const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(map->geoProjection());
404 QScopedValueRollback<bool> rollback(m_poly.m_updatingGeometry);
405 m_poly.m_updatingGeometry = true;
406
407 m_geometry.updateSourcePoints(map: *map, path: m_geopathProjected);
408 m_geometry.updateScreenPoints(map: *map, strokeWidth: borderWidth);
409
410 QList<QGeoMapItemGeometry *> geoms;
411 geoms << &m_geometry;
412 m_borderGeometry.clear();
413
414 if (m_poly.m_border.color().alpha() != 0 && borderWidth > 0) {
415 QList<QDoubleVector2D> closedPath = m_geopathProjected;
416 closedPath << closedPath.first();
417
418 m_borderGeometry.setPreserveGeometry(value: true, geoLeftBound: m_poly.m_geopoly.boundingGeoRectangle().topLeft());
419
420 const QGeoCoordinate &geometryOrigin = m_geometry.origin();
421
422 m_borderGeometry.srcPoints_.clear();
423 m_borderGeometry.srcPointTypes_.clear();
424
425 QDoubleVector2D borderLeftBoundWrapped;
426 QList<QList<QDoubleVector2D > > clippedPaths = m_borderGeometry.clipPath(map: *map, path: closedPath, leftBoundWrapped&: borderLeftBoundWrapped);
427 if (clippedPaths.size()) {
428 borderLeftBoundWrapped = p.geoToWrappedMapProjection(coordinate: geometryOrigin);
429 m_borderGeometry.pathToScreen(map: *map, clippedPaths, leftBoundWrapped: borderLeftBoundWrapped);
430 m_borderGeometry.updateScreenPoints(map: *map, strokeWidth: borderWidth);
431
432 geoms << &m_borderGeometry;
433 } else {
434 m_borderGeometry.clear();
435 }
436 }
437
438 QRectF combined = QGeoMapItemGeometry::translateToCommonOrigin(geoms);
439 m_poly.setWidth(combined.width() + 2 * borderWidth);
440 m_poly.setHeight(combined.height() + 2 * borderWidth);
441
442 m_poly.setPositionOnMap(coordinate: m_geometry.origin(), offset: -1 * m_geometry.sourceBoundingBox().topLeft()
443 + QPointF(borderWidth, borderWidth));
444 }
445 QSGNode *updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override
446 {
447 Q_UNUSED(data);
448 if (!m_node || !oldNode) {
449 m_node = new MapPolygonNode();
450 if (oldNode) {
451 delete oldNode;
452 oldNode = nullptr;
453 }
454 } else {
455 m_node = static_cast<MapPolygonNode *>(oldNode);
456 }
457
458 //TODO: update only material
459 if (m_geometry.isScreenDirty()
460 || m_borderGeometry.isScreenDirty()
461 || m_poly.m_dirtyMaterial
462 || !oldNode) {
463 m_node->update(fillColor: m_poly.m_color,
464 borderColor: m_poly.m_border.color(),
465 fillShape: &m_geometry,
466 borderShape: &m_borderGeometry);
467 m_geometry.setPreserveGeometry(value: false);
468 m_borderGeometry.setPreserveGeometry(value: false);
469 m_geometry.markClean();
470 m_borderGeometry.markClean();
471 m_poly.m_dirtyMaterial = false;
472 }
473 return m_node;
474 }
475 bool contains(const QPointF &point) const override
476 {
477 return (m_geometry.contains(screenPoint: point) || m_borderGeometry.contains(point));
478 }
479
480 QList<QDoubleVector2D> m_geopathProjected;
481 QGeoMapPolygonGeometry m_geometry;
482 QGeoMapPolylineGeometry m_borderGeometry;
483 MapPolygonNode *m_node = nullptr;
484};
485
486#if QT_CONFIG(opengl)
487class Q_LOCATION_PRIVATE_EXPORT QDeclarativePolygonMapItemPrivateOpenGL: public QDeclarativePolygonMapItemPrivate
488{
489public:
490 struct RootNode : public QSGNode /*QSGTransformNode*/, public VisibleNode
491 {
492 RootNode() { }
493
494 bool isSubtreeBlocked() const override
495 {
496 return subtreeBlocked();
497 }
498 };
499
500 QDeclarativePolygonMapItemPrivateOpenGL(QDeclarativePolygonMapItem &polygon) : QDeclarativePolygonMapItemPrivate(polygon)
501 {
502 }
503
504 QDeclarativePolygonMapItemPrivateOpenGL(QDeclarativePolygonMapItemPrivate &other)
505 : QDeclarativePolygonMapItemPrivate(other)
506 {
507 }
508
509 ~QDeclarativePolygonMapItemPrivateOpenGL() override;
510
511 void markScreenDirtyAndUpdate()
512 {
513 // preserveGeometry is cleared in updateMapItemPaintNode
514 m_geometry.markScreenDirty();
515 m_borderGeometry.markScreenDirty();
516 m_poly.polishAndUpdate();
517 }
518 void onLinePropertiesChanged() override
519 {
520 m_poly.m_dirtyMaterial = true;
521 afterViewportChanged();
522 }
523 void markSourceDirtyAndUpdate() override
524 {
525 // preserveGeometry is cleared in updateMapItemPaintNode
526 m_geometry.markSourceDirty();
527 m_borderGeometry.markSourceDirty();
528 m_poly.polishAndUpdate();
529 }
530 void preserveGeometry()
531 {
532 m_geometry.setPreserveGeometry(value: true, geoLeftBound: m_poly.m_geopoly.boundingGeoRectangle().topLeft());
533 m_borderGeometry.setPreserveGeometry(value: true, geoLeftBound: m_poly.m_geopoly.boundingGeoRectangle().topLeft());
534 }
535 void afterViewportChanged() override // This is called when the camera changes, or visibleArea changes.
536 {
537 // preserveGeometry is cleared in updateMapItemPaintNode
538 preserveGeometry();
539 markScreenDirtyAndUpdate();
540 }
541 void onMapSet() override
542 {
543 markSourceDirtyAndUpdate();
544 }
545 void onGeoGeometryChanged() override
546 {
547 preserveGeometry();
548 markSourceDirtyAndUpdate();
549 }
550 void onGeoGeometryUpdated() override
551 {
552 preserveGeometry();
553 markSourceDirtyAndUpdate();
554 }
555 void onItemGeometryChanged() override
556 {
557 onGeoGeometryChanged();
558 }
559 void updatePolish() override
560 {
561 if (m_poly.m_geopoly.path().length() == 0) { // Possibly cleared
562 m_geometry.clear();
563 m_borderGeometry.clear();
564 m_poly.setWidth(0);
565 m_poly.setHeight(0);
566 return;
567 }
568
569 QScopedValueRollback<bool> rollback(m_poly.m_updatingGeometry);
570 m_poly.m_updatingGeometry = true;
571 const qreal lineWidth = m_poly.m_border.width();
572 const QColor &lineColor = m_poly.m_border.color();
573 const QColor &fillColor = m_poly.color();
574 if (fillColor.alpha() != 0) {
575 m_geometry.updateSourcePoints(map: *m_poly.map(), poly: m_poly.m_geopoly);
576 m_geometry.markScreenDirty();
577 m_geometry.updateScreenPoints(map: *m_poly.map(), strokeWidth: lineWidth, strokeColor: lineColor);
578 } else {
579 m_geometry.clearBounds();
580 }
581
582 QGeoMapItemGeometry * geom = &m_geometry;
583 m_borderGeometry.clearScreen();
584 if (lineColor.alpha() != 0 && lineWidth > 0) {
585 m_borderGeometry.updateSourcePoints(map: *m_poly.map(), poly: m_poly.m_geopoly);
586 m_borderGeometry.markScreenDirty();
587 m_borderGeometry.updateScreenPoints(map: *m_poly.map(), strokeWidth: lineWidth);
588 geom = &m_borderGeometry;
589 }
590 m_poly.setWidth(geom->sourceBoundingBox().width());
591 m_poly.setHeight(geom->sourceBoundingBox().height());
592 m_poly.setPosition(1.0 * geom->firstPointOffset() - QPointF(lineWidth * 0.5,lineWidth * 0.5));
593 }
594 QSGNode * updateMapItemPaintNode(QSGNode *oldNode, QQuickItem::UpdatePaintNodeData *data) override
595 {
596 Q_UNUSED(data);
597
598 if (!m_rootNode || !oldNode) {
599 m_rootNode = new RootNode();
600 m_node = new MapPolygonNodeGL();
601 m_rootNode->appendChildNode(node: m_node);
602 m_polylinenode = new MapPolylineNodeOpenGLExtruded();
603 m_rootNode->appendChildNode(node: m_polylinenode);
604 m_rootNode->markDirty(bits: QSGNode::DirtyNodeAdded);
605 if (oldNode)
606 delete oldNode;
607 } else {
608 m_rootNode = static_cast<RootNode *>(oldNode);
609 }
610
611 const QGeoMap *map = m_poly.map();
612 const QMatrix4x4 &combinedMatrix = map->geoProjection().qsgTransform();
613 const QDoubleVector3D &cameraCenter = map->geoProjection().centerMercator();
614
615 if (m_borderGeometry.isScreenDirty()) {
616 /* Do the border update first */
617 m_polylinenode->update(fillColor: m_poly.m_border.color(),
618 lineWidth: float(m_poly.m_border.width()),
619 shape: &m_borderGeometry,
620 geoProjection: combinedMatrix,
621 center: cameraCenter,
622 capStyle: Qt::SquareCap,
623 closed: true,
624 zoom: 30); // No LOD for polygons just yet.
625 // First figure out what to do with holes.
626 m_borderGeometry.setPreserveGeometry(value: false);
627 m_borderGeometry.markClean();
628 } else {
629 m_polylinenode->setSubtreeBlocked(true);
630 }
631 if (m_geometry.isScreenDirty()) {
632 m_node->update(fillColor: m_poly.m_color,
633 fillShape: &m_geometry,
634 geoProjection: combinedMatrix,
635 center: cameraCenter);
636 m_geometry.setPreserveGeometry(value: false);
637 m_geometry.markClean();
638 } else {
639 m_node->setSubtreeBlocked(true);
640 }
641
642 m_rootNode->setSubtreeBlocked(false);
643 return m_rootNode;
644 }
645 bool contains(const QPointF &point) const override
646 {
647 const qreal lineWidth = m_poly.m_border.width();
648 const QColor &lineColor = m_poly.m_border.color();
649 const QRectF &bounds = (lineColor.alpha() != 0 && lineWidth > 0) ? m_borderGeometry.sourceBoundingBox() : m_geometry.sourceBoundingBox();
650 if (bounds.contains(p: point)) {
651 QDeclarativeGeoMap *m = m_poly.quickMap();
652 if (m) {
653 const QGeoCoordinate crd = m->toCoordinate(position: m->mapFromItem(item: &m_poly, point));
654 return m_poly.m_geopoly.contains(coordinate: crd) || m_borderGeometry.contains(point: m_poly.mapToItem(item: m_poly.quickMap(), point),
655 lineWidth: m_poly.border()->width(),
656 p: static_cast<const QGeoProjectionWebMercator&>(m_poly.map()->geoProjection()));
657 } else {
658 return true;
659 }
660 }
661 return false;
662 }
663
664 QGeoMapPolygonGeometryOpenGL m_geometry;
665 QGeoMapPolylineGeometryOpenGL m_borderGeometry;
666 RootNode *m_rootNode = nullptr;
667 MapPolygonNodeGL *m_node = nullptr;
668 MapPolylineNodeOpenGLExtruded *m_polylinenode = nullptr;
669};
670#endif // QT_CONFIG(opengl)
671
672QT_END_NAMESPACE
673
674#endif // QDECLARATIVEPOLYGONMAPITEM_P_P_H
675

source code of qtlocation/src/location/declarativemaps/qdeclarativepolygonmapitem_p_p.h