1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 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 "qgeocameracapabilities_p.h"
38 
39 #include <QSharedData>
40 #include <cmath>
41 
42 static const double invLog2 = 1.0 / std::log(2.0);
43 
zoomLevelTo256(double zoomLevelForTileSize,double tileSize)44 static double zoomLevelTo256(double zoomLevelForTileSize, double tileSize)
45 {
46     return std::log( std::pow(2.0, zoomLevelForTileSize) * tileSize / 256.0 ) * invLog2;
47 }
48 
49 QT_BEGIN_NAMESPACE
50 
51 class QGeoCameraCapabilitiesPrivate : public QSharedData
52 {
53 public:
54     QGeoCameraCapabilitiesPrivate();
55     QGeoCameraCapabilitiesPrivate(const QGeoCameraCapabilitiesPrivate &other);
56     ~QGeoCameraCapabilitiesPrivate();
57 
58     QGeoCameraCapabilitiesPrivate &operator = (const QGeoCameraCapabilitiesPrivate &other);
59 
60     bool operator == (const QGeoCameraCapabilitiesPrivate &rhs) const;
61 
62     bool supportsBearing_;
63     bool supportsRolling_;
64     bool supportsTilting_;
65 
66     // this is mutable so that it can be set from accessor functions that are const
67     // TODO: remove the mutable here
68     mutable bool valid_;
69 
70     double minZoom_;
71     double maxZoom_;
72     double minTilt_;
73     double maxTilt_;
74     int tileSize_;
75     double minimumFieldOfView_;
76     double maximumFieldOfView_;
77     bool overzoomEnabled_;
78 };
79 
QGeoCameraCapabilitiesPrivate()80 QGeoCameraCapabilitiesPrivate::QGeoCameraCapabilitiesPrivate()
81     : supportsBearing_(false),
82       supportsRolling_(false),
83       supportsTilting_(false),
84       valid_(false),
85       minZoom_(0.0),
86       maxZoom_(0.0),
87       minTilt_(0.0),
88       maxTilt_(0.0),
89       tileSize_(256),
90       minimumFieldOfView_(45.0),  // Defaulting to a fixed FOV of 45 degrees. Too large FOVs cause the loading of too many tiles
91       maximumFieldOfView_(45.0),
92       overzoomEnabled_(false) {}
93 
94 
QGeoCameraCapabilitiesPrivate(const QGeoCameraCapabilitiesPrivate & other)95 QGeoCameraCapabilitiesPrivate::QGeoCameraCapabilitiesPrivate(const QGeoCameraCapabilitiesPrivate &other)
96     : QSharedData(other),
97       supportsBearing_(other.supportsBearing_),
98       supportsRolling_(other.supportsRolling_),
99       supportsTilting_(other.supportsTilting_),
100       valid_(other.valid_),
101       minZoom_(other.minZoom_),
102       maxZoom_(other.maxZoom_),
103       minTilt_(other.minTilt_),
104       maxTilt_(other.maxTilt_),
105       tileSize_(other.tileSize_),
106       minimumFieldOfView_(other.minimumFieldOfView_),
107       maximumFieldOfView_(other.maximumFieldOfView_),
108       overzoomEnabled_(other.overzoomEnabled_){}
109 
110 
~QGeoCameraCapabilitiesPrivate()111 QGeoCameraCapabilitiesPrivate::~QGeoCameraCapabilitiesPrivate() {}
112 
operator =(const QGeoCameraCapabilitiesPrivate & other)113 QGeoCameraCapabilitiesPrivate &QGeoCameraCapabilitiesPrivate::operator = (const QGeoCameraCapabilitiesPrivate &other)
114 {
115     if (this == &other)
116         return *this;
117 
118     supportsBearing_ = other.supportsBearing_;
119     supportsRolling_ = other.supportsRolling_;
120     supportsTilting_ = other.supportsTilting_;
121     valid_ = other.valid_;
122     minZoom_ = other.minZoom_;
123     maxZoom_ = other.maxZoom_;
124     minTilt_ = other.minTilt_;
125     maxTilt_ = other.maxTilt_;
126     tileSize_ = other.tileSize_;
127     minimumFieldOfView_ = other.minimumFieldOfView_;
128     maximumFieldOfView_ = other.maximumFieldOfView_;
129     overzoomEnabled_ = other.overzoomEnabled_;
130 
131     return *this;
132 }
133 
operator ==(const QGeoCameraCapabilitiesPrivate & rhs) const134 bool QGeoCameraCapabilitiesPrivate::operator == (const QGeoCameraCapabilitiesPrivate &rhs) const
135 {
136     return ((supportsBearing_ == rhs.supportsBearing_)
137             && (supportsRolling_ == rhs.supportsRolling_)
138             && (supportsTilting_ == rhs.supportsTilting_)
139             && (valid_ == rhs.valid_)
140             && (minZoom_ == rhs.minZoom_)
141             && (maxZoom_ == rhs.maxZoom_)
142             && (minTilt_ == rhs.minTilt_)
143             && (maxTilt_ == rhs.maxTilt_)
144             && (tileSize_ == rhs.tileSize_)
145             && (minimumFieldOfView_ == rhs.minimumFieldOfView_)
146             && (maximumFieldOfView_ == rhs.maximumFieldOfView_)
147             && (overzoomEnabled_ == rhs.overzoomEnabled_));
148 }
149 
150 /*!
151     \class QGeoCameraCapabilities
152     \inmodule QtLocation
153     \ingroup QtLocation-impl
154     \since 5.6
155     \internal
156 
157     \brief The QGeoCameraCapabilities class describes the limitations on camera settings imposed by a mapping plugin.
158 
159     Different mapping plugins will support different ranges of zoom levels, and not all mapping plugins will
160     be able to support, bearing, tilting and rolling of the camera.
161 
162     This class describes what the plugin supports, and is used to restrict changes to the camera information
163     associated with a \l QGeoMap such that the camera information stays within these limits.
164 */
165 
166 /*!
167     Constructs a camera capabilities object.
168 */
QGeoCameraCapabilities()169 QGeoCameraCapabilities::QGeoCameraCapabilities()
170     : d(new QGeoCameraCapabilitiesPrivate()) {}
171 
172 /*!
173     Constructs a camera capabilities object from the contents of \a other.
174 */
QGeoCameraCapabilities(const QGeoCameraCapabilities & other)175 QGeoCameraCapabilities::QGeoCameraCapabilities(const QGeoCameraCapabilities &other)
176     : d(other.d) {}
177 
178 /*!
179     Destroys this camera capabilities object.
180 */
~QGeoCameraCapabilities()181 QGeoCameraCapabilities::~QGeoCameraCapabilities() {}
182 
183 /*!
184     Assigns the contents of \a other to this camera capabilities object and
185     returns a reference to this camera capabilities object.
186 */
operator =(const QGeoCameraCapabilities & other)187 QGeoCameraCapabilities &QGeoCameraCapabilities::operator = (const QGeoCameraCapabilities &other)
188 {
189     if (this == &other)
190         return *this;
191 
192     d = other.d;
193     return *this;
194 }
195 
operator ==(const QGeoCameraCapabilities & rhs) const196 bool QGeoCameraCapabilities::operator == (const QGeoCameraCapabilities &rhs) const
197 {
198     return (*(d.constData()) == *(rhs.d.constData()));
199 }
200 
operator !=(const QGeoCameraCapabilities & other) const201 bool QGeoCameraCapabilities::operator != (const QGeoCameraCapabilities &other) const
202 {
203     return !(operator==(other));
204 }
205 
setTileSize(int tileSize)206 void QGeoCameraCapabilities::setTileSize(int tileSize)
207 {
208     if (tileSize < 1)
209         return;
210     d->tileSize_ = tileSize;
211 }
212 
tileSize() const213 int QGeoCameraCapabilities::tileSize() const
214 {
215     return d->tileSize_;
216 }
217 
218 /*!
219     Returns whether this instance of the class is considered "valid". To be
220     valid, the instance must have had at least one capability set (to either
221     true or false) using a set method, or copied from another instance
222     (such as by the assignment operator).
223 */
isValid() const224 bool QGeoCameraCapabilities::isValid() const
225 {
226     return d->valid_;
227 }
228 
229 /*!
230     Sets the minimum zoom level supported by the associated plugin to \a maximumZoomLevel.
231 
232     Larger values of the zoom level correspond to more detailed views of the
233     map.
234 */
setMinimumZoomLevel(double minimumZoomLevel)235 void QGeoCameraCapabilities::setMinimumZoomLevel(double minimumZoomLevel)
236 {
237     d->minZoom_ = minimumZoomLevel;
238     d->valid_ = true;
239 }
240 
241 /*!
242     Returns the minimum zoom level supported by the associated plugin.
243 
244     Larger values of the zoom level correspond to more detailed views of the
245     map.
246 */
minimumZoomLevel() const247 double QGeoCameraCapabilities::minimumZoomLevel() const
248 {
249     return d->minZoom_;
250 }
251 
minimumZoomLevelAt256() const252 double QGeoCameraCapabilities::minimumZoomLevelAt256() const
253 {
254     if (d->tileSize_ == 256)
255         return d->minZoom_;
256     return qMax<double>(0, zoomLevelTo256(d->minZoom_, d->tileSize_));
257 }
258 
259 /*!
260     Sets the maximum zoom level supported by the associated plugin to \a maximumZoomLevel.
261 
262     Larger values of the zoom level correspond to more detailed views of the
263     map.
264 */
setMaximumZoomLevel(double maximumZoomLevel)265 void QGeoCameraCapabilities::setMaximumZoomLevel(double maximumZoomLevel)
266 {
267     d->maxZoom_ = maximumZoomLevel;
268     d->valid_ = true;
269 }
270 
271 /*!
272     Returns the maximum zoom level supported by the associated plugin.
273 
274     Larger values of the zoom level correspond to more detailed views of the
275     map.
276 */
maximumZoomLevel() const277 double QGeoCameraCapabilities::maximumZoomLevel() const
278 {
279     return d->maxZoom_;
280 }
281 
maximumZoomLevelAt256() const282 double QGeoCameraCapabilities::maximumZoomLevelAt256() const
283 {
284     if (d->tileSize_ == 256)
285         return d->maxZoom_;
286     return qMax<double>(0, zoomLevelTo256(d->maxZoom_, d->tileSize_));
287 }
288 
289 /*!
290     Sets whether the associated plugin can render a map when the camera
291     has an arbitrary bearing to \a supportsBearing.
292 */
setSupportsBearing(bool supportsBearing)293 void QGeoCameraCapabilities::setSupportsBearing(bool supportsBearing)
294 {
295     d->supportsBearing_ = supportsBearing;
296     d->valid_ = true;
297 }
298 
299 /*!
300     Returns whether the associated plugin can render a map when the camera
301     has an arbitrary bearing.
302 */
supportsBearing() const303 bool QGeoCameraCapabilities::supportsBearing() const
304 {
305     return d->supportsBearing_;
306 }
307 
308 /*!
309     Sets whether the associated plugin can render a map when the
310     camera is rolled to \a supportsRolling.
311 */
setSupportsRolling(bool supportsRolling)312 void QGeoCameraCapabilities::setSupportsRolling(bool supportsRolling)
313 {
314     d->supportsRolling_ = supportsRolling;
315     d->valid_ = true;
316 }
317 
318 /*!
319     Returns whether the associated plugin can render a map when the
320     camera is rolled.
321 */
supportsRolling() const322 bool QGeoCameraCapabilities::supportsRolling() const
323 {
324     return d->supportsRolling_;
325 }
326 
327 /*!
328     Sets whether the associated plugin can render a map when the
329     camera is tilted to \a supportsTilting.
330 */
setSupportsTilting(bool supportsTilting)331 void QGeoCameraCapabilities::setSupportsTilting(bool supportsTilting)
332 {
333     d->supportsTilting_ = supportsTilting;
334     d->valid_ = true;
335 }
336 
337 /*!
338     Returns whether the associated plugin can render a map when the
339     camera is tilted.
340 */
supportsTilting() const341 bool QGeoCameraCapabilities::supportsTilting() const
342 {
343     return d->supportsTilting_;
344 }
345 
346 /*!
347     Sets the minimum tilt supported by the associated plugin to \a minimumTilt.
348 
349     The value is in degrees where 0 is equivalent to 90 degrees between
350     the line of view and earth's surface, that is, looking straight down to earth.
351 */
setMinimumTilt(double minimumTilt)352 void QGeoCameraCapabilities::setMinimumTilt(double minimumTilt)
353 {
354     d->minTilt_ = minimumTilt;
355     d->valid_ = true;
356 }
357 
358 /*!
359     Returns the minimum tilt supported by the associated plugin.
360 
361     The value is in degrees where 0 is equivalent to 90 degrees between
362     the line of view and earth's surface, that is, looking straight down to earth.
363 */
minimumTilt() const364 double QGeoCameraCapabilities::minimumTilt() const
365 {
366     return d->minTilt_;
367 }
368 
369 /*!
370     Sets the maximum tilt supported by the associated plugin to \a maximumTilt.
371 
372     The value is in degrees where 0 is equivalent to 90 degrees between
373     the line of view and earth's surface, that is, looking straight down to earth.
374 */
setMaximumTilt(double maximumTilt)375 void QGeoCameraCapabilities::setMaximumTilt(double maximumTilt)
376 {
377     d->maxTilt_ = maximumTilt;
378     d->valid_ = true;
379 }
380 
381 /*!
382     Returns the maximum tilt supported by the associated plugin.
383 
384     The value is in degrees where 0 is equivalent to 90 degrees between
385     the line of view and earth's surface, that is, looking straight down to earth.
386 */
maximumTilt() const387 double QGeoCameraCapabilities::maximumTilt() const
388 {
389     return d->maxTilt_;
390 }
391 
392 /*!
393     Sets the minimum field of view supported by the associated plugin to \a minimumFieldOfView.
394     The value is in degrees and is clamped against a [1, 179] range.
395 
396     \since 5.9
397 */
setMinimumFieldOfView(double minimumFieldOfView)398 void QGeoCameraCapabilities::setMinimumFieldOfView(double minimumFieldOfView)
399 {
400     d->minimumFieldOfView_ = qBound(1.0, minimumFieldOfView, 179.0);
401     d->valid_ = true;
402 }
403 
404 /*!
405     Returns the minimum field of view supported by the associated plugin.
406     The value is in degrees.
407 
408     \since 5.9
409 */
minimumFieldOfView() const410 double QGeoCameraCapabilities::minimumFieldOfView() const
411 {
412     return d->minimumFieldOfView_;
413 }
414 
415 /*!
416     Sets the maximum field of view supported by the associated plugin to \a maximumFieldOfView.
417     The value is in degrees and is clamped against a [1, 179] range.
418 
419     \since 5.9
420 */
setMaximumFieldOfView(double maximumFieldOfView)421 void QGeoCameraCapabilities::setMaximumFieldOfView(double maximumFieldOfView)
422 {
423     d->maximumFieldOfView_ = qBound(1.0, maximumFieldOfView, 179.0);
424     d->valid_ = true;
425 }
426 
427 /*!
428     Returns the maximum field of view supported by the associated plugin.
429     The value is in degrees.
430 
431     \since 5.9
432 */
maximumFieldOfView() const433 double QGeoCameraCapabilities::maximumFieldOfView() const
434 {
435     return d->maximumFieldOfView_;
436 }
437 
438 /*!
439     Sets whether overzooming is supported by the associated plugin.
440 
441     Overzooming means that zoom levels outside the [minimumZL, maximumZL] range can be set,
442     and if tiles aren't available for those zoom levels, either tiles from other zoom levels
443     will be used, or nothing will be shown.
444 
445     Set this value to false if the plugin is not capable of that. For example if using
446     a mapping engine that always clamp the zoomLevel value, which may cause misalignment in case
447     of stacked map elements.
448 
449     \since 5.9
450 */
setOverzoomEnabled(bool overzoomEnabled)451 void QGeoCameraCapabilities::setOverzoomEnabled(bool overzoomEnabled)
452 {
453     d->overzoomEnabled_ = overzoomEnabled;
454     d->valid_ = true;
455 }
456 
457 /*!
458     Returns whether overzooming is supported by the associated plugin.
459 
460     \since 5.9
461 */
overzoomEnabled() const462 bool QGeoCameraCapabilities::overzoomEnabled() const
463 {
464     return d->overzoomEnabled_;
465 }
466 
467 
468 QT_END_NAMESPACE
469