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(x: 2.0); |
43 | |
44 | static double zoomLevelTo256(double zoomLevelForTileSize, double tileSize) |
45 | { |
46 | return std::log( x: std::pow(x: 2.0, y: 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 | |
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 | |
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 | |
111 | QGeoCameraCapabilitiesPrivate::~QGeoCameraCapabilitiesPrivate() {} |
112 | |
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 | |
134 | 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 | */ |
169 | QGeoCameraCapabilities::QGeoCameraCapabilities() |
170 | : d(new QGeoCameraCapabilitiesPrivate()) {} |
171 | |
172 | /*! |
173 | Constructs a camera capabilities object from the contents of \a other. |
174 | */ |
175 | QGeoCameraCapabilities::QGeoCameraCapabilities(const QGeoCameraCapabilities &other) |
176 | : d(other.d) {} |
177 | |
178 | /*! |
179 | Destroys this camera capabilities object. |
180 | */ |
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 | */ |
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 | |
196 | bool QGeoCameraCapabilities::operator == (const QGeoCameraCapabilities &rhs) const |
197 | { |
198 | return (*(d.constData()) == *(rhs.d.constData())); |
199 | } |
200 | |
201 | bool QGeoCameraCapabilities::operator != (const QGeoCameraCapabilities &other) const |
202 | { |
203 | return !(operator==(rhs: other)); |
204 | } |
205 | |
206 | void QGeoCameraCapabilities::setTileSize(int tileSize) |
207 | { |
208 | if (tileSize < 1) |
209 | return; |
210 | d->tileSize_ = tileSize; |
211 | } |
212 | |
213 | 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 | */ |
224 | 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 | */ |
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 | */ |
247 | double QGeoCameraCapabilities::minimumZoomLevel() const |
248 | { |
249 | return d->minZoom_; |
250 | } |
251 | |
252 | double QGeoCameraCapabilities::minimumZoomLevelAt256() const |
253 | { |
254 | if (d->tileSize_ == 256) |
255 | return d->minZoom_; |
256 | return qMax<double>(a: 0, b: zoomLevelTo256(zoomLevelForTileSize: d->minZoom_, tileSize: 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 | */ |
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 | */ |
277 | double QGeoCameraCapabilities::maximumZoomLevel() const |
278 | { |
279 | return d->maxZoom_; |
280 | } |
281 | |
282 | double QGeoCameraCapabilities::maximumZoomLevelAt256() const |
283 | { |
284 | if (d->tileSize_ == 256) |
285 | return d->maxZoom_; |
286 | return qMax<double>(a: 0, b: zoomLevelTo256(zoomLevelForTileSize: d->maxZoom_, tileSize: 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 | */ |
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 | */ |
303 | 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 | */ |
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 | */ |
322 | 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 | */ |
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 | */ |
341 | 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 | */ |
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 | */ |
364 | 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 | */ |
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 | */ |
387 | 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 | */ |
398 | void QGeoCameraCapabilities::setMinimumFieldOfView(double minimumFieldOfView) |
399 | { |
400 | d->minimumFieldOfView_ = qBound(min: 1.0, val: minimumFieldOfView, max: 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 | */ |
410 | 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 | */ |
421 | void QGeoCameraCapabilities::setMaximumFieldOfView(double maximumFieldOfView) |
422 | { |
423 | d->maximumFieldOfView_ = qBound(min: 1.0, val: maximumFieldOfView, max: 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 | */ |
433 | 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 | */ |
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 | */ |
462 | bool QGeoCameraCapabilities::overzoomEnabled() const |
463 | { |
464 | return d->overzoomEnabled_; |
465 | } |
466 | |
467 | |
468 | QT_END_NAMESPACE |
469 | |