Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qgeocircle.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qgeocircle.h"
5#include "qgeocircle_p.h"
6
7#include "qgeocoordinate.h"
8#include "qnumeric.h"
9#include "qlocationutils_p.h"
10
11#include "qdoublevector2d_p.h"
12#include "qdoublevector3d_p.h"
13#include <cmath>
15
17
18
67inline QGeoCirclePrivate *QGeoCircle::d_func()
68{
69 return static_cast<QGeoCirclePrivate *>(d_ptr.data());
70}
71
72inline const QGeoCirclePrivate *QGeoCircle::d_func() const
73{
74 return static_cast<const QGeoCirclePrivate *>(d_ptr.constData());
75}
76
84
92
100
110
115
124
126{
127 return m_center.isValid() && !qIsNaN(m_radius) && m_radius >= -1e-7;
128}
129
131{
132 return !isValid() || m_radius <= 1e-7;
133}
134
139{
140 Q_D(QGeoCircle);
141
142 d->setCenter(center);
143}
144
149{
150 Q_D(const QGeoCircle);
151
152 return d->center();
153}
154
159{
160 Q_D(QGeoCircle);
161
162 d->setRadius(radius);
163}
164
169{
170 Q_D(const QGeoCircle);
171
172 return d->m_radius;
173}
174
175bool QGeoCirclePrivate::contains(const QGeoCoordinate &coordinate) const
176{
177 if (!isValid() || !coordinate.isValid())
178 return false;
179
180 // see QTBUG-41447 for details
181 qreal distance = m_center.distanceTo(coordinate);
183 return true;
184
185 return false;
186}
187
192
197
199{
200 if (isEmpty()) {
201 if (m_center.isValid()) {
204 }
205 return;
206 }
207
208 bool crossNorth = crossNorthPole();
209 bool crossSouth = crossSouthPole();
210
211 if (crossNorth && crossSouth) {
212 // Circle crossing both poles fills the whole map
213 m_bbox = QGeoRectangle(QGeoCoordinate(90.0, -180.0), QGeoCoordinate(-90.0, 180.0));
214 } else if (crossNorth) {
215 // Circle crossing one pole fills the map in the longitudinal direction
217 } else if (crossSouth) {
219 } else {
220 // Regular circle not crossing anything
221
222 // Calculate geo bounding box of the circle
223 //
224 // A circle tangential point with a meridian, together with pole and
225 // the circle center create a spherical triangle.
226 // Finding the tangential point with the spherical law of sines:
227 //
228 // * lon_delta_in_rad : delta between the circle center and a tangential
229 // point (absolute value).
230 // * r_in_rad : angular radius of the circle
231 // * lat_in_rad : latitude of the circle center
232 // * alpha_in_rad : angle between meridian and radius of the circle.
233 // At the tangential point, sin(alpha_in_rad) == 1.
234 // * lat_delta_in_rad - absolute delta of latitudes between the circle center and
235 // any of the two points where the great circle going through the circle
236 // center and the pole crosses the circle. In other words, the points
237 // on the circle with azimuth 0 or 180.
238 //
239 // Using:
240 // sin(lon_delta_in_rad)/sin(r_in_rad) = sin(alpha_in_rad)/sin(pi/2 - lat_in_rad)
241
242 double r_in_rad = m_radius / QLocationUtils::earthMeanRadius(); // angular r
243 double lat_delta_in_deg = QLocationUtils::degrees(r_in_rad);
244 double lon_delta_in_deg = QLocationUtils::degrees(std::asin(
245 std::sin(r_in_rad) /
247 ));
248
249 QGeoCoordinate topLeft;
250 topLeft.setLatitude(QLocationUtils::clipLat(m_center.latitude() + lat_delta_in_deg));
251 topLeft.setLongitude(QLocationUtils::wrapLong(m_center.longitude() - lon_delta_in_deg));
252 QGeoCoordinate bottomRight;
253 bottomRight.setLatitude(QLocationUtils::clipLat(m_center.latitude() - lat_delta_in_deg));
254 bottomRight.setLongitude(QLocationUtils::wrapLong(m_center.longitude() + lon_delta_in_deg));
255
256 m_bbox = QGeoRectangle(topLeft, bottomRight);
257 }
258}
259
265
271
273{
274 const QGeoCoordinate northPole(90.0, m_center.longitude());
275 qreal distanceToPole = m_center.distanceTo(northPole);
276 if (distanceToPole < m_radius)
277 return true;
278 return false;
279}
280
282{
283 const QGeoCoordinate southPole(-90.0, m_center.longitude());
284 qreal distanceToPole = m_center.distanceTo(southPole);
285 if (distanceToPole < m_radius)
286 return true;
287 return false;
288}
289
290/*
291 Extends the circle to include \a coordinate.
292*/
294{
295 if (!isValid() || !coordinate.isValid() || contains(coordinate))
296 return;
297
298 setRadius(m_center.distanceTo(coordinate));
299}
300
307void QGeoCircle::translate(double degreesLatitude, double degreesLongitude)
308{
309 // TODO handle dlat, dlon larger than 360 degrees
310
311 Q_D(QGeoCircle);
312
313 double lat = d->m_center.latitude();
314 double lon = d->m_center.longitude();
315
316 lat += degreesLatitude;
317 lon += degreesLongitude;
318 lon = QLocationUtils::wrapLong(lon);
319
320 // TODO: remove this and simply clip latitude.
321 if (lat > 90.0) {
322 lat = 180.0 - lat;
323 if (lon < 0.0)
324 lon = 180.0;
325 else
326 lon -= 180;
327 }
328
329 if (lat < -90.0) {
330 lat = 180.0 + lat;
331 if (lon < 0.0)
332 lon = 180.0;
333 else
334 lon -= 180;
335 }
336
337 d->setCenter(QGeoCoordinate(lat, lon));
338}
339
349QGeoCircle QGeoCircle::translated(double degreesLatitude, double degreesLongitude) const
350{
351 QGeoCircle result(*this);
352 result.translate(degreesLatitude, degreesLongitude);
353 return result;
354}
355
362{
363 Q_D(QGeoCircle);
364 d->extendCircle(coordinate);
365}
366
374{
375 if (type() != QGeoShape::CircleType) {
376 qWarning("Not a circle");
377 return QStringLiteral("QGeoCircle(not a circle)");
378 }
379
380 return QStringLiteral("QGeoCircle({%1, %2}, %3)")
381 .arg(center().latitude())
382 .arg(center().longitude())
383 .arg(radius());
384}
385
386/*******************************************************************************
387*******************************************************************************/
388
390: QGeoShapePrivate(QGeoShape::CircleType), m_radius(-1.0)
391{
392}
393
395: QGeoShapePrivate(QGeoShape::CircleType), m_center(center), m_radius(radius)
396{
398}
399
401: QGeoShapePrivate(QGeoShape::CircleType), m_center(other.m_center),
402 m_radius(other.m_radius), m_bbox(other.m_bbox)
403{
404}
405
407
409{
410 return new QGeoCirclePrivate(*this);
411}
412
414{
415 if (!QGeoShapePrivate::operator==(other))
416 return false;
417
418 const QGeoCirclePrivate &otherCircle = static_cast<const QGeoCirclePrivate &>(other);
419
420 return m_radius == otherCircle.m_radius && m_center == otherCircle.m_center;
421}
422
423size_t QGeoCirclePrivate::hash(size_t seed) const
424{
426}
427
429
430#include "moc_qgeocircle.cpp"
bool crossNorthPole() const
QGeoCoordinate center() const override
QGeoRectangle m_bbox
QGeoShapePrivate * clone() const override
QGeoRectangle boundingGeoRectangle() const override
bool operator==(const QGeoShapePrivate &other) const override
void setRadius(const qreal r)
bool crossSouthPole() const
bool isValid() const override
void extendCircle(const QGeoCoordinate &coordinate)
bool isEmpty() const override
QGeoCoordinate m_center
size_t hash(size_t seed) const override
void setCenter(const QGeoCoordinate &c)
bool contains(const QGeoCoordinate &coordinate) const override
\inmodule QtPositioning
Definition qgeocircle.h:15
Q_INVOKABLE QGeoCircle translated(double degreesLatitude, double degreesLongitude) const
Returns a copy of this geo circle translated by degreesLatitude northwards and degreesLongitude eastw...
~QGeoCircle()
Destroys this geo circle.
void setCenter(const QGeoCoordinate &center)
Sets the center coordinate of this geo circle to center.
Q_INVOKABLE void extendCircle(const QGeoCoordinate &coordinate)
Extends the geo circle to also cover the coordinate coordinate.
Q_INVOKABLE void translate(double degreesLatitude, double degreesLongitude)
Translates this geo circle by degreesLatitude northwards and degreesLongitude eastwards.
QGeoCircle & operator=(const QGeoCircle &other)
Assigns other to this geo circle and returns a reference to this geo circle.
QGeoCoordinate center
This property holds the center coordinate for the geo circle.
Definition qgeocircle.h:17
Q_INVOKABLE QString toString() const
Returns the geo circle properties as a string.
qreal radius
This property holds the circle radius in meters.
Definition qgeocircle.h:18
void setRadius(qreal radius)
Sets the radius in meters of this geo circle to radius.
QGeoCircle()
Constructs a new, invalid geo circle.
\inmodule QtPositioning
double longitude
This property holds the longitude in decimal degrees.
double latitude
This property holds the latitude in decimal degrees.
Q_INVOKABLE QGeoCoordinate atDistanceAndAzimuth(qreal distance, qreal azimuth, qreal distanceUp=0.0) const
Returns the coordinate that is reached by traveling distance meters from the current coordinate at az...
void setLatitude(double latitude)
Sets the latitude (in decimal degrees) to latitude.
void setLongitude(double longitude)
Sets the longitude (in decimal degrees) to longitude.
Q_INVOKABLE qreal distanceTo(const QGeoCoordinate &other) const
Returns the distance (in meters) from this coordinate to the coordinate specified by other.
bool isValid
This property holds the validity of this geo coordinate.
\inmodule QtPositioning
void setTopLeft(const QGeoCoordinate &topLeft)
Sets the top left coordinate of this geo rectangle to topLeft.
void setBottomRight(const QGeoCoordinate &bottomRight)
Sets the bottom right coordinate of this geo rectangle to bottomRight.
\inmodule QtPositioning
Definition qgeoshape.h:17
QGeoShape & operator=(const QGeoShape &other)
Assigns other to this geo shape and returns a reference to this geo shape.
QSharedDataPointer< QGeoShapePrivate > d_ptr
Definition qgeoshape.h:61
ShapeType type
This property holds the type of this geo shape.
Definition qgeoshape.h:19
static double radians(double degrees)
static double degrees(double radians)
static double earthMeanRadius()
static double wrapLong(double lng)
static double clipLat(double lat, double clipValue=90.0)
const T * constData() const noexcept
Returns a const pointer to the shared data object.
Definition qshareddata.h:51
T * data()
Returns a pointer to the shared data object.
Definition qshareddata.h:47
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
Combined button and popup list for selecting options.
bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) noexcept
Definition qfloat16.h:333
bool qIsNaN(qfloat16 f) noexcept
Definition qfloat16.h:284
constexpr QtPrivate::QHashMultiReturnType< T... > qHashMulti(size_t seed, const T &... args) noexcept(std::conjunction_v< QtPrivate::QNothrowHashable< T >... >)
#define qWarning
Definition qlogging.h:166
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1390
GLboolean r
[2]
GLsizei GLsizei GLfloat distance
const GLubyte * c
GLuint64EXT * result
[6]
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
#define QStringLiteral(str)
double qreal
Definition qtypes.h:187
QSharedPointer< T > other(t)
[5]