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
qgeorectangle.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 "qgeorectangle.h"
5#include "qgeorectangle_p.h"
6
7#include "qwebmercator_p.h"
8#include "qdoublevector2d_p.h"
9#include "qgeocoordinate.h"
10#include "qnumeric.h"
11#include "qlocationutils_p.h"
12#include <QList>
14
16
17
148inline QGeoRectanglePrivate *QGeoRectangle::d_func()
149{
150 return static_cast<QGeoRectanglePrivate *>(d_ptr.data());
151}
152
153inline const QGeoRectanglePrivate *QGeoRectangle::d_func() const
154{
155 return static_cast<const QGeoRectanglePrivate *>(d_ptr.constData());
156}
157
165
176QGeoRectangle::QGeoRectangle(const QGeoCoordinate &center, double degreesWidth, double degreesHeight)
177{
179 setWidth(degreesWidth);
180 setHeight(degreesHeight);
181}
182
191
195QGeoRectangle::QGeoRectangle(const QList<QGeoCoordinate> &coordinates)
196{
197 if (coordinates.isEmpty()) {
199 } else {
200 const QGeoCoordinate &startCoordinate = coordinates.first();
201 d_ptr = new QGeoRectanglePrivate(startCoordinate, startCoordinate);
202
203 for (const QGeoCoordinate &coordinate : coordinates)
204 d_func()->extendRectangle(coordinate);
205 }
206}
207
215
225
232
241
247
249{
250 if (!isValid())
251 return true;
252
253 return topLeft.latitude() == bottomRight.latitude() ||
255}
256
261{
262 Q_D(QGeoRectangle);
263
264 d->topLeft = topLeft;
265}
266
271{
272 Q_D(const QGeoRectangle);
273
274 return d->topLeft;
275}
276
281{
282 Q_D(QGeoRectangle);
283
284 d->topLeft.setLatitude(topRight.latitude());
285 d->bottomRight.setLongitude(topRight.longitude());
286}
287
292{
293 // TODO remove?
294 if (!isValid())
295 return QGeoCoordinate();
296
297 Q_D(const QGeoRectangle);
298
299 return QGeoCoordinate(d->topLeft.latitude(), d->bottomRight.longitude());
300}
301
306{
307 Q_D(QGeoRectangle);
308
309 d->bottomRight.setLatitude(bottomLeft.latitude());
310 d->topLeft.setLongitude(bottomLeft.longitude());
311}
312
317{
318 // TODO remove?
319 if (!isValid())
320 return QGeoCoordinate();
321
322 Q_D(const QGeoRectangle);
323
324 return QGeoCoordinate(d->bottomRight.latitude(), d->topLeft.longitude());
325}
326
331{
332 Q_D(QGeoRectangle);
333
334 d->bottomRight = bottomRight;
335}
336
341{
342 Q_D(const QGeoRectangle);
343
344 return d->bottomRight;
345}
346
358{
359 Q_D(QGeoRectangle);
360
361 if (!isValid()) {
362 d->topLeft = center;
363 d->bottomRight = center;
364 return;
365 }
366 double width = this->width();
367 double height = this->height();
368
369 double tlLat = center.latitude() + height / 2.0;
370 double tlLon = center.longitude() - width / 2.0;
371 double brLat = center.latitude() - height / 2.0;
372 double brLon = center.longitude() + width / 2.0;
373 tlLon = QLocationUtils::wrapLong(tlLon);
374 brLon = QLocationUtils::wrapLong(brLon);
375
376 if (tlLat > 90.0) {
377 brLat = 2 * center.latitude() - 90.0;
378 tlLat = 90.0;
379 }
380
381 if (tlLat < -90.0) {
382 brLat = -90.0;
383 tlLat = -90.0;
384 }
385
386 if (brLat > 90.0) {
387 tlLat = 90.0;
388 brLat = 90.0;
389 }
390
391 if (brLat < -90.0) {
392 tlLat = 2 * center.latitude() + 90.0;
393 brLat = -90.0;
394 }
395
396 if (width == 360.0) {
397 tlLon = -180.0;
398 brLon = 180.0;
399 }
400
401 d->topLeft = QGeoCoordinate(tlLat, tlLon);
402 d->bottomRight = QGeoCoordinate(brLat, brLon);
403}
404
409{
410 Q_D(const QGeoRectangle);
411
412 return d->center();
413}
414
418void QGeoRectangle::setWidth(double degreesWidth)
419{
420 if (!isValid())
421 return;
422
423 if (degreesWidth < 0.0)
424 return;
425
426 Q_D(QGeoRectangle);
427
428 if (degreesWidth >= 360.0) {
429 d->topLeft.setLongitude(-180.0);
430 d->bottomRight.setLongitude(180.0);
431 return;
432 }
433
434 double tlLat = d->topLeft.latitude();
435 double brLat = d->bottomRight.latitude();
436
438
439 double tlLon = c.longitude() - degreesWidth / 2.0;
440 tlLon = QLocationUtils::wrapLong(tlLon);
441
442 double brLon = c.longitude() + degreesWidth / 2.0;
443 brLon = QLocationUtils::wrapLong(brLon);
444
445 d->topLeft = QGeoCoordinate(tlLat, tlLon);
446 d->bottomRight = QGeoCoordinate(brLat, brLon);
447}
448
455{
456 if (!isValid())
457 return qQNaN();
458
459 Q_D(const QGeoRectangle);
460
461 double result = d->bottomRight.longitude() - d->topLeft.longitude();
462 if (result < 0.0)
463 result += 360.0;
464 if (result > 360.0)
465 result -= 360.0;
466
467 return result;
468}
469
473void QGeoRectangle::setHeight(double degreesHeight)
474{
475 if (!isValid())
476 return;
477
478 if (degreesHeight < 0.0)
479 return;
480
481 if (degreesHeight >= 180.0) {
482 degreesHeight = 180.0;
483 }
484
485 Q_D(QGeoRectangle);
486
487 double tlLon = d->topLeft.longitude();
488 double brLon = d->bottomRight.longitude();
489
491
492 double tlLat = c.latitude() + degreesHeight / 2.0;
493 double brLat = c.latitude() - degreesHeight / 2.0;
494
495 if (tlLat > 90.0) {
496 brLat = 2* c.latitude() - 90.0;
497 tlLat = 90.0;
498 }
499
500 if (tlLat < -90.0) {
501 brLat = -90.0;
502 tlLat = -90.0;
503 }
504
505 if (brLat > 90.0) {
506 tlLat = 90.0;
507 brLat = 90.0;
508 }
509
510 if (brLat < -90.0) {
511 tlLat = 2 * c.latitude() + 90.0;
512 brLat = -90.0;
513 }
514
515 d->topLeft = QGeoCoordinate(tlLat, tlLon);
516 d->bottomRight = QGeoCoordinate(brLat, brLon);
517}
518
525{
526 if (!isValid())
527 return qQNaN();
528
529 Q_D(const QGeoRectangle);
530
531 return d->topLeft.latitude() - d->bottomRight.latitude();
532}
533
535{
536 if (!isValid() || !coordinate.isValid())
537 return false;
538
539 double left = topLeft.longitude();
540 double right = bottomRight.longitude();
541 double top = topLeft.latitude();
542 double bottom = bottomRight.latitude();
543
544 double lon = coordinate.longitude();
545 double lat = coordinate.latitude();
546
547 if (lat > top)
548 return false;
549 if (lat < bottom)
550 return false;
551
552 if ((lat == 90.0) && (top == 90.0))
553 return true;
554
555 if ((lat == -90.0) && (bottom == -90.0))
556 return true;
557
558 if (left <= right) {
559 if ((lon < left) || (lon > right))
560 return false;
561 } else {
562 if ((lon < left) && (lon > right))
563 return false;
564 }
565
566 return true;
567}
568
570{
571 if (!isValid())
572 return QGeoCoordinate();
573
574 double cLat = (topLeft.latitude() + bottomRight.latitude()) / 2.0;
575 double cLon = (bottomRight.longitude() + topLeft.longitude()) / 2.0;
576
578 cLon = cLon - 180.0;
579
580 cLon = QLocationUtils::wrapLong(cLon);
581 return QGeoCoordinate(cLat, cLon);
582}
583
588
593bool QGeoRectangle::contains(const QGeoRectangle &rectangle) const
594{
595 Q_D(const QGeoRectangle);
596
597 return (d->contains(rectangle.topLeft())
598 && d->contains(rectangle.topRight())
599 && d->contains(rectangle.bottomLeft())
600 && d->contains(rectangle.bottomRight()));
601}
602
610bool QGeoRectangle::intersects(const QGeoRectangle &rectangle) const
611{
612 Q_D(const QGeoRectangle);
613
614 double left1 = d->topLeft.longitude();
615 double right1 = d->bottomRight.longitude();
616 double top1 = d->topLeft.latitude();
617 double bottom1 = d->bottomRight.latitude();
618
619 double left2 = rectangle.d_func()->topLeft.longitude();
620 double right2 = rectangle.d_func()->bottomRight.longitude();
621 double top2 = rectangle.d_func()->topLeft.latitude();
622 double bottom2 = rectangle.d_func()->bottomRight.latitude();
623
624 if (top1 < bottom2)
625 return false;
626
627 if (bottom1 > top2)
628 return false;
629
630 if ((top1 == 90.0) && (top1 == top2))
631 return true;
632
633 if ((bottom1 == -90.0) && (bottom1 == bottom2))
634 return true;
635
636 if (left1 < right1) {
637 if (left2 < right2) {
638 if ((left1 > right2) || (right1 < left2))
639 return false;
640 } else {
641 if ((left1 > right2) && (right1 < left2))
642 return false;
643 }
644 } else {
645 if (left2 < right2) {
646 if ((left2 > right1) && (right2 < left1))
647 return false;
648 } else {
649 // if both wrap then they have to intersect
650 }
651 }
652
653 return true;
654}
655
667void QGeoRectangle::translate(double degreesLatitude, double degreesLongitude)
668{
669 // TODO handle dlat, dlon larger than 360 degrees
670
671 Q_D(QGeoRectangle);
672
673 double tlLat = d->topLeft.latitude();
674 double tlLon = d->topLeft.longitude();
675 double brLat = d->bottomRight.latitude();
676 double brLon = d->bottomRight.longitude();
677
678 if (degreesLatitude >= 0.0)
679 degreesLatitude = qMin(degreesLatitude, 90.0 - tlLat);
680 else
681 degreesLatitude = qMax(degreesLatitude, -90.0 - brLat);
682
683 if ( (tlLon != -180.0) || (brLon != 180.0) ) {
684 tlLon = QLocationUtils::wrapLong(tlLon + degreesLongitude);
685 brLon = QLocationUtils::wrapLong(brLon + degreesLongitude);
686 }
687
688 tlLat += degreesLatitude;
689 brLat += degreesLatitude;
690
691 d->topLeft = QGeoCoordinate(tlLat, tlLon);
692 d->bottomRight = QGeoCoordinate(brLat, brLon);
693}
694
704QGeoRectangle QGeoRectangle::translated(double degreesLatitude, double degreesLongitude) const
705{
706 QGeoRectangle result(*this);
707 result.translate(degreesLatitude, degreesLongitude);
708 return result;
709}
710
717{
718 Q_D(QGeoRectangle);
719 d->extendRectangle(coordinate);
720}
721
732{
733 QGeoRectangle result(*this);
734 if (rectangle.isValid())
735 result |= rectangle;
736 return result;
737}
738
748{
749 if (!isValid() || !coordinate.isValid() || contains(coordinate))
750 return;
751
752 double left = topLeft.longitude();
753 double right = bottomRight.longitude();
754 double top = topLeft.latitude();
755 double bottom = bottomRight.latitude();
756
757 double inputLat = coordinate.latitude();
758 double inputLon = coordinate.longitude();
759
760 top = qMax(top, inputLat);
761 bottom = qMin(bottom, inputLat);
762
763 bool wrap = left > right;
764
765 if (wrap && inputLon > right && inputLon < left) {
766 if (qAbs(left - inputLon) < qAbs(right - inputLon))
767 left = inputLon;
768 else
769 right = inputLon;
770 } else if (!wrap) {
771 if (inputLon < left) {
772 if (360 - (right - inputLon) < left - inputLon)
773 right = inputLon;
774 else
775 left = inputLon;
776 } else if (inputLon > right) {
777 if (360 - (inputLon - left) < inputLon - right)
778 left = inputLon;
779 else
780 right = inputLon;
781 }
782 }
785}
786
809{
810 // If non-intersecting goes for most narrow box
811
812 Q_D(QGeoRectangle);
813
814 double top = qMax(d->topLeft.latitude(), rectangle.d_func()->topLeft.latitude());
815 double bottom = qMin(d->bottomRight.latitude(), rectangle.d_func()->bottomRight.latitude());
816
817 QGeoRectangle candidate(
818 {top, d->topLeft.longitude()},
819 {bottom, rectangle.d_func()->bottomRight.longitude()}
820 );
821 QGeoRectangle otherCandidate(
822 {top, rectangle.d_func()->topLeft.longitude()},
823 {bottom, d->bottomRight.longitude()}
824 );
825 double unwrappedWidth = (candidate.width() < rectangle.width() ? 360 : 0) + candidate.width();
826 double otherUnwrappedWidth = (otherCandidate.width() < width() ? 360 : 0) + otherCandidate.width();
827 if (otherUnwrappedWidth < unwrappedWidth) {
828 candidate = otherCandidate;
829 unwrappedWidth = otherUnwrappedWidth;
830 }
831 if (360 <= unwrappedWidth) {
832 candidate.d_func()->topLeft.setLongitude(-180.0);
833 candidate.d_func()->bottomRight.setLongitude(180.0);
834 }
835
836 candidate = (candidate.width() < width() ? *this : candidate);
837 candidate = (candidate.width() < rectangle.width() ? rectangle : candidate);
838
839 double middle1 = center().longitude();
840 double middle2 = rectangle.center().longitude();
841 if ((middle1 <= middle2 ? 0 : 360) + middle2 - middle1 == 180) {
842 candidate.d_func()->topLeft.setLongitude(-180.0);
843 candidate.d_func()->bottomRight.setLongitude(180.0);
844 }
845
846 *this = candidate;
847 this->d_func()->topLeft.setLatitude(top);
848 this->d_func()->bottomRight.setLatitude(bottom);
849
850 return *this;
851}
852
859{
861 qWarning("Not a rectangle a %d\n", type());
862 return QStringLiteral("QGeoRectangle(not a rectangle)");
863 }
864
865 return QStringLiteral("QGeoRectangle({%1, %2}, {%3, %4})")
866 .arg(topLeft().latitude())
867 .arg(topLeft().longitude())
868 .arg(bottomRight().latitude())
869 .arg(bottomRight().longitude());
870}
871
872/*******************************************************************************
873*******************************************************************************/
874
879
881 const QGeoCoordinate &bottomRight)
882: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(topLeft), bottomRight(bottomRight)
883{
884}
885
887: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(other.topLeft),
888 bottomRight(other.bottomRight)
889{
890}
891
893
895{
896 return new QGeoRectanglePrivate(*this);
897}
898
900{
901 if (!QGeoShapePrivate::operator==(other))
902 return false;
903
904 const QGeoRectanglePrivate &otherBox = static_cast<const QGeoRectanglePrivate &>(other);
905
906 return topLeft == otherBox.topLeft && bottomRight == otherBox.bottomRight;
907}
908
910{
912}
913
915
916#include "moc_qgeorectangle.cpp"
\inmodule QtPositioning
double longitude
This property holds the longitude in decimal degrees.
double latitude
This property holds the latitude in decimal degrees.
void setLatitude(double latitude)
Sets the latitude (in decimal degrees) to latitude.
bool isValid
This property holds the validity of this geo coordinate.
QGeoCoordinate bottomRight
QGeoShapePrivate * clone() const override
QGeoCoordinate topLeft
void extendRectangle(const QGeoCoordinate &coordinate)
Extends the rectangle in the smallest possible way to include coordinate in the shape.
bool isEmpty() const override
QGeoRectangle boundingGeoRectangle() const override
bool operator==(const QGeoShapePrivate &other) const override
size_t hash(size_t seed) const override
bool contains(const QGeoCoordinate &coordinate) const override
bool isValid() const override
QGeoCoordinate center() const override
\inmodule QtPositioning
double height
This property holds the height of this geo rectangle in degrees.
Q_INVOKABLE bool intersects(const QGeoRectangle &rectangle) const
Returns whether the geo rectangle rectangle intersects this geo rectangle.
QGeoCoordinate topLeft
This property holds the top left coordinate of this geo rectangle.
QGeoCoordinate bottomRight
This property holds the bottom right coordinate of this geo rectangle.
void setTopLeft(const QGeoCoordinate &topLeft)
Sets the top left coordinate of this geo rectangle to topLeft.
Q_INVOKABLE QGeoRectangle united(const QGeoRectangle &rectangle) const
Returns the smallest geo rectangle which contains both this geo rectangle and rectangle.
void setBottomRight(const QGeoCoordinate &bottomRight)
Sets the bottom right coordinate of this geo rectangle to bottomRight.
bool contains(const QGeoRectangle &rectangle) const
Returns whether the geo rectangle rectangle is contained within this geo rectangle.
QGeoRectangle & operator=(const QGeoRectangle &other)
Assigns other to this geo rectangle and returns a reference to this geo rectangle.
QGeoCoordinate center
This property holds the center of this geo rectangle.
void setTopRight(const QGeoCoordinate &topRight)
Sets the top right coordinate of this geo rectangle to topRight.
QGeoRectangle()
Constructs a new, invalid geo rectangle.
void setCenter(const QGeoCoordinate &center)
Sets the center of this geo rectangle to center.
Q_INVOKABLE QString toString() const
Returns the geo rectangle properties as a string.
void setWidth(double degreesWidth)
Sets the width of this geo rectangle in degrees to degreesWidth.
void setHeight(double degreesHeight)
Sets the height of this geo rectangle in degrees to degreesHeight.
QGeoRectangle & operator|=(const QGeoRectangle &rectangle)
Returns the smallest geo rectangle which contains both this geo rectangle and rectangle.
~QGeoRectangle()
Destroys this geo rectangle.
Q_INVOKABLE QGeoRectangle translated(double degreesLatitude, double degreesLongitude) const
Returns a copy of this geo rectangle translated by degreesLatitude northwards and degreesLongitude ea...
QGeoCoordinate bottomLeft
This property holds the bottom left coorindate of this geo rectangle.
Q_INVOKABLE void extendRectangle(const QGeoCoordinate &coordinate)
Extends the geo rectangle to also cover the coordinate coordinate.
QGeoCoordinate topRight
This property holds the top right coordinate of this geo rectangle.
double width
This property holds the width of this geo rectangle in degrees.
void setBottomLeft(const QGeoCoordinate &bottomLeft)
Sets the bottom left coordinate of this geo rectangle to bottomLeft.
Q_INVOKABLE void translate(double degreesLatitude, double degreesLongitude)
Translates this geo rectangle by degreesLatitude northwards and degreesLongitude eastwards.
\inmodule QtPositioning
Definition qgeoshape.h:17
bool isValid
This property holds the validity of the geo shape.
Definition qgeoshape.h:20
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
@ RectangleType
Definition qgeoshape.h:32
static double wrapLong(double lng)
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
#define this
Definition dialogs.cpp:9
Combined button and popup list for selecting options.
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
constexpr const T & qMin(const T &a, const T &b)
Definition qminmax.h:40
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
constexpr T qAbs(const T &t)
Definition qnumeric.h:328
Q_CORE_EXPORT Q_DECL_CONST_FUNCTION double qQNaN()
GLint GLsizei GLsizei height
GLdouble GLdouble GLdouble GLdouble top
GLdouble GLdouble right
GLint GLsizei width
GLint left
GLint GLint bottom
const GLubyte * c
GLuint64EXT * result
[6]
static Q_CONSTINIT QBasicAtomicInteger< unsigned > seed
Definition qrandom.cpp:196
static QT_BEGIN_NAMESPACE QAsn1Element wrap(quint8 type, const QAsn1Element &child)
#define QStringLiteral(str)
QSharedPointer< T > other(t)
[5]