195QGeoRectangle::QGeoRectangle(
const QList<QGeoCoordinate> &coordinates)
197 if (coordinates.isEmpty()) {
198 d_ptr =
new QGeoRectanglePrivate;
200 const QGeoCoordinate &startCoordinate = coordinates.first();
201 d_ptr =
new QGeoRectanglePrivate(startCoordinate, startCoordinate);
203 for (
const QGeoCoordinate &coordinate : coordinates)
204 d_func()->extendRectangle(coordinate);
363void QGeoRectangle::setCenter(
const QGeoCoordinate ¢er)
369 d->bottomRight = center;
372 double width =
this->width();
373 double height =
this->height();
375 double tlLat = center.latitude() + height / 2.0;
376 double tlLon = center.longitude() - width / 2.0;
377 double brLat = center.latitude() - height / 2.0;
378 double brLon = center.longitude() + width / 2.0;
379 tlLon = QLocationUtils::wrapLong(tlLon);
380 brLon = QLocationUtils::wrapLong(brLon);
383 brLat = 2 * center.latitude() - 90.0;
398 tlLat = 2 * center.latitude() + 90.0;
402 if (width == 360.0) {
407 d->topLeft = QGeoCoordinate(tlLat, tlLon);
408 d->bottomRight = QGeoCoordinate(brLat, brLon);
424void QGeoRectangle::setWidth(
double degreesWidth)
429 if (degreesWidth < 0.0)
434 if (degreesWidth >= 360.0) {
435 d->topLeft.setLongitude(-180.0);
436 d->bottomRight.setLongitude(180.0);
440 double tlLat = d->topLeft.latitude();
441 double brLat = d->bottomRight.latitude();
443 QGeoCoordinate c = center();
445 double tlLon = c.longitude() - degreesWidth / 2.0;
446 tlLon = QLocationUtils::wrapLong(tlLon);
448 double brLon = c.longitude() + degreesWidth / 2.0;
449 brLon = QLocationUtils::wrapLong(brLon);
451 d->topLeft = QGeoCoordinate(tlLat, tlLon);
452 d->bottomRight = QGeoCoordinate(brLat, brLon);
479void QGeoRectangle::setHeight(
double degreesHeight)
484 if (degreesHeight < 0.0)
487 if (degreesHeight >= 180.0) {
488 degreesHeight = 180.0;
493 double tlLon = d->topLeft.longitude();
494 double brLon = d->bottomRight.longitude();
496 QGeoCoordinate c = center();
498 double tlLat = c.latitude() + degreesHeight / 2.0;
499 double brLat = c.latitude() - degreesHeight / 2.0;
502 brLat = 2* c.latitude() - 90.0;
517 tlLat = 2 * c.latitude() + 90.0;
521 d->topLeft = QGeoCoordinate(tlLat, tlLon);
522 d->bottomRight = QGeoCoordinate(brLat, brLon);
540bool QGeoRectanglePrivate::contains(
const QGeoCoordinate &coordinate)
const
542 if (!isValid() || !coordinate.isValid())
545 double left = topLeft.longitude();
546 double right = bottomRight.longitude();
547 double top = topLeft.latitude();
548 double bottom = bottomRight.latitude();
550 double lon = coordinate.longitude();
551 double lat = coordinate.latitude();
558 if ((lat == 90.0) && (top == 90.0))
561 if ((lat == -90.0) && (bottom == -90.0))
565 if ((lon < left) || (lon > right))
568 if ((lon < left) && (lon > right))
575QGeoCoordinate QGeoRectanglePrivate::center()
const
578 return QGeoCoordinate();
580 double cLat = (topLeft.latitude() + bottomRight.latitude()) / 2.0;
581 double cLon = (bottomRight.longitude() + topLeft.longitude()) / 2.0;
583 if (topLeft.longitude() > bottomRight.longitude())
586 cLon = QLocationUtils::wrapLong(cLon);
587 return QGeoCoordinate(cLat, cLon);
599bool QGeoRectangle::contains(
const QGeoRectangle &rectangle)
const
601 Q_D(
const QGeoRectangle);
603 return (d->contains(rectangle.topLeft())
604 && d->contains(rectangle.topRight())
605 && d->contains(rectangle.bottomLeft())
606 && d->contains(rectangle.bottomRight()));
616bool QGeoRectangle::intersects(
const QGeoRectangle &rectangle)
const
618 Q_D(
const QGeoRectangle);
620 double left1 = d->topLeft.longitude();
621 double right1 = d->bottomRight.longitude();
622 double top1 = d->topLeft.latitude();
623 double bottom1 = d->bottomRight.latitude();
625 double left2 = rectangle.d_func()->topLeft.longitude();
626 double right2 = rectangle.d_func()->bottomRight.longitude();
627 double top2 = rectangle.d_func()->topLeft.latitude();
628 double bottom2 = rectangle.d_func()->bottomRight.latitude();
636 if ((top1 == 90.0) && (top1 == top2))
639 if ((bottom1 == -90.0) && (bottom1 == bottom2))
642 if (left1 < right1) {
643 if (left2 < right2) {
644 if ((left1 > right2) || (right1 < left2))
647 if ((left1 > right2) && (right1 < left2))
651 if (left2 < right2) {
652 if ((left2 > right1) && (right2 < left1))
673void QGeoRectangle::translate(
double degreesLatitude,
double degreesLongitude)
679 double tlLat = d->topLeft.latitude();
680 double tlLon = d->topLeft.longitude();
681 double brLat = d->bottomRight.latitude();
682 double brLon = d->bottomRight.longitude();
684 if (degreesLatitude >= 0.0)
685 degreesLatitude = qMin(degreesLatitude, 90.0 - tlLat);
687 degreesLatitude = qMax(degreesLatitude, -90.0 - brLat);
689 if ( (tlLon != -180.0) || (brLon != 180.0) ) {
690 tlLon = QLocationUtils::wrapLong(tlLon + degreesLongitude);
691 brLon = QLocationUtils::wrapLong(brLon + degreesLongitude);
694 tlLat += degreesLatitude;
695 brLat += degreesLatitude;
697 d->topLeft = QGeoCoordinate(tlLat, tlLon);
698 d->bottomRight = QGeoCoordinate(brLat, brLon);
753void QGeoRectanglePrivate::extendRectangle(
const QGeoCoordinate &coordinate)
755 if (!isValid() || !coordinate.isValid() || contains(coordinate))
758 double left = topLeft.longitude();
759 double right = bottomRight.longitude();
760 double top = topLeft.latitude();
761 double bottom = bottomRight.latitude();
763 double inputLat = coordinate.latitude();
764 double inputLon = coordinate.longitude();
766 top = qMax(top, inputLat);
767 bottom = qMin(bottom, inputLat);
769 bool wrap = left > right;
771 if (wrap && inputLon > right && inputLon < left) {
772 if (qAbs(left - inputLon) < qAbs(right - inputLon))
777 if (inputLon < left) {
778 if (360 - (right - inputLon) < left - inputLon)
782 }
else if (inputLon > right) {
783 if (360 - (inputLon - left) < inputLon - right)
789 topLeft = QGeoCoordinate(top, left);
790 bottomRight = QGeoCoordinate(bottom, right);
814QGeoRectangle &QGeoRectangle::operator|=(
const QGeoRectangle &rectangle)
820 double top = qMax(d->topLeft.latitude(), rectangle.d_func()->topLeft.latitude());
821 double bottom = qMin(d->bottomRight.latitude(), rectangle.d_func()->bottomRight.latitude());
823 QGeoRectangle candidate(
824 {top, d->topLeft.longitude()},
825 {bottom, rectangle.d_func()->bottomRight.longitude()}
827 QGeoRectangle otherCandidate(
828 {top, rectangle.d_func()->topLeft.longitude()},
829 {bottom, d->bottomRight.longitude()}
831 double unwrappedWidth = (candidate.width() < rectangle.width() ? 360 : 0) + candidate.width();
832 double otherUnwrappedWidth = (otherCandidate.width() < width() ? 360 : 0) + otherCandidate.width();
833 if (otherUnwrappedWidth < unwrappedWidth) {
834 candidate = otherCandidate;
835 unwrappedWidth = otherUnwrappedWidth;
837 if (360 <= unwrappedWidth) {
838 candidate.d_func()->topLeft.setLongitude(-180.0);
839 candidate.d_func()->bottomRight.setLongitude(180.0);
842 candidate = (candidate.width() < width() ? *
this : candidate);
843 candidate = (candidate.width() < rectangle.width() ? rectangle : candidate);
845 double middle1 = center().longitude();
846 double middle2 = rectangle.center().longitude();
847 if ((middle1 <= middle2 ? 0 : 360) + middle2 - middle1 == 180) {
848 candidate.d_func()->topLeft.setLongitude(-180.0);
849 candidate.d_func()->bottomRight.setLongitude(180.0);
853 this->d_func()->topLeft.setLatitude(top);
854 this->d_func()->bottomRight.setLatitude(bottom);
864QString QGeoRectangle::toString()
const
866 if (type() != QGeoShape::RectangleType) {
867 qWarning(
"Not a rectangle a %d\n", type());
868 return QStringLiteral(
"QGeoRectangle(not a rectangle)");
871 return QStringLiteral(
"QGeoRectangle({%1, %2}, {%3, %4})")
872 .arg(topLeft().latitude())
873 .arg(topLeft().longitude())
874 .arg(bottomRight().latitude())
875 .arg(bottomRight().longitude());
892QGeoRectanglePrivate::QGeoRectanglePrivate(
const QGeoRectanglePrivate &other)
893: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(other.topLeft),
894 bottomRight(other.bottomRight)
905bool QGeoRectanglePrivate::operator==(
const QGeoShapePrivate &other)
const
907 if (!QGeoShapePrivate::operator==(other))
910 const QGeoRectanglePrivate &otherBox =
static_cast<
const QGeoRectanglePrivate &>(other);
912 return topLeft == otherBox.topLeft && bottomRight == otherBox.bottomRight;