1 /****************************************************************************
2 **
3 ** Copyright (C) 2018 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtLocation module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL3$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPLv3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or later as published by the Free
28 ** Software Foundation and appearing in the file LICENSE.GPL included in
29 ** the packaging of this file. Please review the following information to
30 ** ensure the GNU General Public License version 2.0 requirements will be
31 ** met: http://www.gnu.org/licenses/gpl-2.0.html.
32 **
33 ** $QT_END_LICENSE$
34 **
35 ****************************************************************************/
36 
37 #include "qmappolylineobjectqsg_p_p.h"
38 #include <QtQuick/qsgnode.h>
39 #include <QtQuick/qsgsimplerectnode.h>
40 
41 QT_BEGIN_NAMESPACE
42 
43 /*
44     Note: never use q, since this class is also used inside QMapRouteObjectPrivateQSG!
45 */
46 
QMapPolylineObjectPrivateQSG(QGeoMapObject * q)47 QMapPolylineObjectPrivateQSG::QMapPolylineObjectPrivateQSG(QGeoMapObject *q)
48     : QMapPolylineObjectPrivateDefault(q)
49 {
50 
51 }
52 
QMapPolylineObjectPrivateQSG(const QMapPolylineObjectPrivate & other)53 QMapPolylineObjectPrivateQSG::QMapPolylineObjectPrivateQSG(const QMapPolylineObjectPrivate &other)
54     : QMapPolylineObjectPrivateDefault(other)
55 {
56     // rest of the data already cloned by the *Default copy constructor, but necessary
57     // update operations triggered only by setters overrides
58     markSourceDirty();
59     updateGeometry();
60     if (m_map)
61         emit m_map->sgNodeChanged();
62 }
63 
~QMapPolylineObjectPrivateQSG()64 QMapPolylineObjectPrivateQSG::~QMapPolylineObjectPrivateQSG()
65 {
66     if (m_map)
67         m_map->removeMapObject(q);
68 }
69 
projectPath()70 QList<QDoubleVector2D> QMapPolylineObjectPrivateQSG::projectPath()
71 {
72     QList<QDoubleVector2D> geopathProjected_;
73     if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
74         return geopathProjected_;
75 
76     const QGeoProjectionWebMercator &p =
77             static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
78     geopathProjected_.reserve(m_path.path().size());
79     for (const QGeoCoordinate &c : m_path.path())
80         geopathProjected_ << p.geoToMapProjection(c);
81     return geopathProjected_;
82 }
83 
updateGeometry()84 void QMapPolylineObjectPrivateQSG::updateGeometry()
85 {
86     if (!m_map || m_map->geoProjection().projectionType() != QGeoProjection::ProjectionWebMercator)
87         return;
88 
89     if (m_path.path().length() == 0) { // Possibly cleared
90         m_borderGeometry.clear();
91         return;
92     }
93 
94     const QGeoProjectionWebMercator &p = static_cast<const QGeoProjectionWebMercator&>(m_map->geoProjection());
95     if (m_borderGeometry.isSourceDirty()) {
96         m_borderGeometry.setPreserveGeometry(true, m_path.boundingGeoRectangle().topLeft());
97         m_borderGeometry.m_dataChanged = true;
98         m_borderGeometry.updateSourcePoints(*m_map, m_path);
99         m_leftBoundMercator = p.geoToMapProjection(m_borderGeometry.origin());
100     }
101     m_borderGeometry.markScreenDirty();
102     m_borderGeometry.m_wrapOffset = p.projectionWrapFactor(m_leftBoundMercator) + 1;
103 }
104 
105 /*!
106   \internal
107 */
zoomForLOD(int zoom) const108 unsigned int QMapPolylineObjectPrivateQSG::zoomForLOD(int zoom) const
109 {
110     // LOD Threshold currently fixed to 12 for MapPolylineObject(QSG).
111     // ToDo: Consider allowing to change this via DynamicParameter.
112     if (zoom >= 12)
113         return 30;
114     return uint(zoom);
115 }
116 
updateMapObjectNode(QSGNode * oldNode,VisibleNode ** visibleNode,QSGNode * root,QQuickWindow *)117 QSGNode *QMapPolylineObjectPrivateQSG::updateMapObjectNode(QSGNode *oldNode,
118                                                            VisibleNode **visibleNode,
119                                                            QSGNode *root,
120                                                            QQuickWindow * /*window*/)
121 {
122     if (!m_polylinenode || !oldNode) {
123         m_polylinenode = new MapPolylineNodeOpenGLExtruded();
124         *visibleNode = static_cast<VisibleNode *>(m_polylinenode);
125         if (oldNode)
126             delete oldNode;
127     } else {
128         m_polylinenode = static_cast<MapPolylineNodeOpenGLExtruded *>(oldNode);
129     }
130 
131     const QMatrix4x4 &combinedMatrix = m_map->geoProjection().qsgTransform();
132     const QDoubleVector3D &cameraCenter = m_map->geoProjection().centerMercator();
133 
134     if (m_borderGeometry.isScreenDirty()) {
135         /* Do the border update first */
136         m_polylinenode->update(color(),
137                                float(width()),
138                                &m_borderGeometry,
139                                combinedMatrix,
140                                cameraCenter,
141                                Qt::SquareCap,
142                                true,
143                                zoomForLOD(int(m_map->cameraData().zoomLevel())));
144         m_borderGeometry.setPreserveGeometry(false);
145         m_borderGeometry.markClean();
146     }
147 
148     if (!m_polylinenode->isSubtreeBlocked() ) {
149         m_polylinenode->setSubtreeBlocked(false);
150         root->appendChildNode(m_polylinenode);
151         return m_polylinenode;
152     } else {
153         delete m_polylinenode;
154         m_polylinenode = nullptr;
155         *visibleNode = nullptr;
156         return nullptr;
157     }
158 }
159 
path() const160 QList<QGeoCoordinate> QMapPolylineObjectPrivateQSG::path() const
161 {
162     return m_path.path();
163 }
164 
setPath(const QList<QGeoCoordinate> & path)165 void QMapPolylineObjectPrivateQSG::setPath(const QList<QGeoCoordinate> &path)
166 {
167     m_path.setPath(path);
168     markSourceDirty();
169     updateGeometry();
170     if (m_map)
171         emit m_map->sgNodeChanged();
172 }
173 
setColor(const QColor & color)174 void QMapPolylineObjectPrivateQSG::setColor(const QColor &color)
175 {
176     QMapPolylineObjectPrivateDefault::setColor(color);
177 
178     if (m_map)
179         emit m_map->sgNodeChanged();
180 }
181 
setWidth(qreal width)182 void QMapPolylineObjectPrivateQSG::setWidth(qreal width)
183 {
184     QMapPolylineObjectPrivateDefault::setWidth(width);
185 
186     if (m_map)
187         emit m_map->sgNodeChanged();
188 }
189 
clone()190 QGeoMapObjectPrivate *QMapPolylineObjectPrivateQSG::clone()
191 {
192     return new QMapPolylineObjectPrivateQSG(static_cast<QMapPolylineObjectPrivate &>(*this));
193 }
194 
geoShape() const195 QGeoShape QMapPolylineObjectPrivateQSG::geoShape() const
196 {
197     return m_path;
198 }
199 
markSourceDirty()200 void QMapPolylineObjectPrivateQSG::markSourceDirty()
201 {
202     m_borderGeometry.markSourceDirty();
203 }
204 
205 QT_END_NAMESPACE
206