1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 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 #ifndef QGEOPROJECTION_H
38 #define QGEOPROJECTION_H
39 
40 //
41 //  W A R N I N G
42 //  -------------
43 //
44 // This file is not part of the Qt API.  It exists purely as an
45 // implementation detail.  This header file may change from version to
46 // version without notice, or even be removed.
47 //
48 // We mean it.
49 //
50 
51 #include <QtLocation/private/qlocationglobal_p.h>
52 #include <QtLocation/private/qgeocameradata_p.h>
53 #include <QtPositioning/private/qdoublematrix4x4_p.h>
54 #include <QtPositioning/QGeoShape>
55 #include <QMatrix4x4>
56 #include <QTransform>
57 
58 QT_BEGIN_NAMESPACE
59 
60 class Q_LOCATION_PRIVATE_EXPORT QGeoProjection
61 {
62 public:
63     enum ProjectionGroup {
64         ProjectionOther,
65         ProjectionCylindrical,
66         ProjectionPseudocylindrical,
67         ProjectionAzimuthal,
68         ProjectionPseudoazimuthal,
69         ProjectionConic,
70         ProjectionPseudoconic
71         //Polyhedral
72         //Retroazimuthal
73     };
74 
75     enum Datum {
76         DatumUnknown,
77         DatumWGS84,
78         DatumSphere
79     };
80 
81     enum ProjectionType {
82         ProjectionUnknown,
83         ProjectionGeneralPerspective,
84         ProjectionWebMercator
85     };
86 
87     QGeoProjection();
88     virtual ~QGeoProjection();
89 
90     virtual void setVisibleArea(const QRectF &visibleArea) = 0;
91     virtual void setViewportSize(const QSize &size) = 0;
92     virtual void setCameraData(const QGeoCameraData &cameraData, bool force = true) = 0;
93     virtual QGeoCameraData cameraData() const = 0;
94 
95     // returns the minimum zoom at the current viewport size
96     virtual double minimumZoom() const = 0;
97     virtual double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const = 0;
98     virtual double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const = 0;
99 
100     virtual QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const = 0;
101     virtual QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const = 0;
102 
103     virtual ProjectionGroup projectionGroup() const = 0;
104     virtual Datum datum() const = 0;
105     virtual ProjectionType projectionType() const = 0;
106 
107     // Returns the new map center after anchoring coordinate to anchorPoint on the screen
108     virtual QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const;
109 
110     virtual QGeoShape visibleRegion() const;
111     virtual bool setBearing(qreal bearing, const QGeoCoordinate &coordinate);
112     virtual QMatrix4x4 projectionTransformation() const = 0; // This brings a mercator coord into the correct viewport coordinate.
113     virtual QMatrix4x4 projectionTransformation_centered() const = 0; // Same as projectionTransformation, but the center of the camera is around 0,0.
114                                                                       // Requires subsequent shifting of the geometry to fit such camera.
115     virtual const QMatrix4x4 &qsgTransform() const = 0;
116     virtual QDoubleVector3D centerMercator() const = 0;
117 
118     void setItemToWindowTransform(const QTransform &itemToWindowTransform);
119     virtual QTransform itemToWindowTransform() const;
120 
121     QTransform       m_itemToWindowTransform;
122     mutable bool     m_qsgTransformDirty = true;
123 };
124 
125 class Q_LOCATION_PRIVATE_EXPORT QGeoProjectionWebMercator : public QGeoProjection
126 {
127 public:
128     QGeoProjectionWebMercator();
129     ~QGeoProjectionWebMercator();
130 
131     // From QGeoProjection
132     double minimumZoom() const override;
133     QMatrix4x4 projectionTransformation() const override;
134     QMatrix4x4 projectionTransformation_centered() const override;
135     const QMatrix4x4 &qsgTransform() const override;
136     QDoubleVector3D centerMercator() const override;
137 
138     double maximumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override;
139     double minimumCenterLatitudeAtZoom(const QGeoCameraData &cameraData) const override;
140 
141     void setVisibleArea(const QRectF &visibleArea) override;
142     void setViewportSize(const QSize &size) override;
143     void setCameraData(const QGeoCameraData &cameraData, bool force = true) override;
144     QGeoCameraData cameraData() const override;
145 
146     QGeoCoordinate itemPositionToCoordinate(const QDoubleVector2D &pos, bool clipToViewport = true) const override;
147     QDoubleVector2D coordinateToItemPosition(const QGeoCoordinate &coordinate, bool clipToViewport = true) const override;
148 
149     QGeoProjection::ProjectionGroup projectionGroup() const override;
150     QGeoProjection::Datum datum() const override;
151     QGeoProjection::ProjectionType projectionType() const override;
152 
153     QGeoCoordinate anchorCoordinateToPoint(const QGeoCoordinate &coordinate, const QPointF &anchorPoint) const override;
154     bool setBearing(qreal bearing, const QGeoCoordinate &coordinate) override;
155 
156     QGeoShape visibleRegion() const override;
157 
158     // Specific to QGeoProjectionWebMercator
159     double mapWidth() const; // The size of the underlying map, at the current zoom level.
160     double mapHeight() const;
161 
162     QDoubleVector2D geoToMapProjection(const QGeoCoordinate &coordinate) const;
163     QGeoCoordinate mapProjectionToGeo(const QDoubleVector2D &projection) const;
164 
165     int projectionWrapFactor(const QDoubleVector2D &projection) const;
166     QDoubleVector2D wrapMapProjection(const QDoubleVector2D &projection) const;
167     QDoubleVector2D unwrapMapProjection(const QDoubleVector2D &wrappedProjection) const;
168 
169     QDoubleVector2D wrappedMapProjectionToItemPosition(const QDoubleVector2D &wrappedProjection) const;
170     QDoubleVector2D itemPositionToWrappedMapProjection(const QDoubleVector2D &itemPosition) const;
171 
172     QDoubleVector2D geoToWrappedMapProjection(const QGeoCoordinate &coordinate) const;
173     QGeoCoordinate wrappedMapProjectionToGeo(const QDoubleVector2D &wrappedProjection) const;
174     QMatrix4x4 quickItemTransformation(const QGeoCoordinate &coordinate, const QPointF &anchorPoint, qreal zoomLevel) const;
175 
176     bool isProjectable(const QDoubleVector2D &wrappedProjection) const;
177     QList<QDoubleVector2D> visibleGeometry() const;
178     QList<QDoubleVector2D> visibleGeometryExpanded() const;
179     QList<QDoubleVector2D> projectableGeometry() const;
180 
181     inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition) const;
182     inline QDoubleVector2D viewportToWrappedMapProjection(const QDoubleVector2D &itemPosition, double &s) const;
183 
184     QPair<QGeoCoordinate, qreal> fitViewportToGeoRectangle(const QGeoRectangle &rectangle,
185                                                            const QMargins &margins) const;
186 
187 private:
188     void setupCamera();
189     void updateVisibleRegion();
190 
191 public:
192     struct Line2D
193     {
194         Line2D();
195         Line2D(const QDoubleVector2D &linePoint, const QDoubleVector2D &lineDirection);
196 
197         bool isValid() const;
198 
199         QDoubleVector2D m_point;
200         QDoubleVector2D m_direction;
201     };
202 
203     struct Plane
204     {
205         Plane();
206         Plane(const QDoubleVector3D &planePoint, const QDoubleVector3D &planeNormal);
207 
208         QDoubleVector3D lineIntersection(const QDoubleVector3D &linePoint, const QDoubleVector3D &lineDirection) const;
209         inline QDoubleVector3D lineIntersection(const QDoubleVector3D &linePoint, const QDoubleVector3D &lineDirection, double &s) const;
210         Line2D planeXYIntersection() const;
211         bool isValid() const;
212 
213         QDoubleVector3D m_point;
214         QDoubleVector3D m_normal;
215     };
216 
217 #ifdef QT_LOCATION_DEBUG
218 public:
219 #else
220 protected:
221 #endif
222     QGeoCameraData m_cameraData;
223     double m_mapEdgeSize;
224     double m_minimumZoom;
225     // mercator to camera transform for coordinates (not tiles!)
226     double m_cameraCenterXMercator;
227     double m_cameraCenterYMercator;
228 
229     // cameraToScreen transform
230     double m_viewportWidth; // in pixels
231     double m_viewportHeight; // in pixels
232     double m_1_viewportWidth;
233     double m_1_viewportHeight;
234 
235     QDoubleMatrix4x4 m_cameraMatrix;
236     QDoubleMatrix4x4 m_cameraMatrix0;
237     QDoubleMatrix4x4 m_transformation;
238     QDoubleMatrix4x4 m_transformation0;
239     QDoubleMatrix4x4 m_quickItemTransformation;
240     QDoubleVector3D  m_eye;
241     QDoubleVector3D  m_up;
242     QDoubleVector3D  m_center;
243     QDoubleVector3D  m_view;
244     QDoubleVector3D  m_viewNormalized;
245     QDoubleVector3D  m_side;
246     QDoubleVector3D  m_centerNearPlane;
247     double           m_sideLengthPixels; // map edge size at integer zoom level
248     double           m_aperture;
249     double           m_nearPlane;
250     double           m_farPlane;
251     double           m_halfWidth;
252     double           m_halfHeight;
253     double           m_minimumUnprojectableY;
254     double           m_verticalEstateToSkip;
255 
256     // For the clipping region
257     QDoubleVector3D  m_centerMercator;
258     QDoubleVector3D  m_eyeMercator;
259     QDoubleVector3D  m_eyeMercator0;
260     QDoubleVector3D  m_viewMercator;
261     QDoubleVector3D  m_upMercator;
262     QDoubleVector3D  m_sideMercator;
263     QDoubleVector3D  m_centerNearPlaneMercator;
264     double           m_nearPlaneMercator;
265     Line2D           m_nearPlaneMapIntersection;
266 
267     QList<QDoubleVector2D> m_visibleRegion;
268     QList<QDoubleVector2D> m_visibleRegionExpanded;
269     QList<QDoubleVector2D> m_projectableRegion;
270     bool             m_visibleRegionDirty;
271 
272     mutable QMatrix4x4 m_qsgTransform;
273     QRectF           m_visibleArea;
274 
275     Q_DISABLE_COPY(QGeoProjectionWebMercator)
276 };
277 
278 QT_END_NAMESPACE
279 
280 #endif // QGEOPROJECTION_H
281