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);
357void QGeoRectangle::setCenter(
const QGeoCoordinate ¢er)
363 d->bottomRight = center;
366 double width =
this->width();
367 double height =
this->height();
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);
377 brLat = 2 * center.latitude() - 90.0;
392 tlLat = 2 * center.latitude() + 90.0;
396 if (width == 360.0) {
401 d->topLeft = QGeoCoordinate(tlLat, tlLon);
402 d->bottomRight = QGeoCoordinate(brLat, brLon);
418void QGeoRectangle::setWidth(
double degreesWidth)
423 if (degreesWidth < 0.0)
428 if (degreesWidth >= 360.0) {
429 d->topLeft.setLongitude(-180.0);
430 d->bottomRight.setLongitude(180.0);
434 double tlLat = d->topLeft.latitude();
435 double brLat = d->bottomRight.latitude();
437 QGeoCoordinate c = center();
439 double tlLon = c.longitude() - degreesWidth / 2.0;
440 tlLon = QLocationUtils::wrapLong(tlLon);
442 double brLon = c.longitude() + degreesWidth / 2.0;
443 brLon = QLocationUtils::wrapLong(brLon);
445 d->topLeft = QGeoCoordinate(tlLat, tlLon);
446 d->bottomRight = QGeoCoordinate(brLat, brLon);
473void QGeoRectangle::setHeight(
double degreesHeight)
478 if (degreesHeight < 0.0)
481 if (degreesHeight >= 180.0) {
482 degreesHeight = 180.0;
487 double tlLon = d->topLeft.longitude();
488 double brLon = d->bottomRight.longitude();
490 QGeoCoordinate c = center();
492 double tlLat = c.latitude() + degreesHeight / 2.0;
493 double brLat = c.latitude() - degreesHeight / 2.0;
496 brLat = 2* c.latitude() - 90.0;
511 tlLat = 2 * c.latitude() + 90.0;
515 d->topLeft = QGeoCoordinate(tlLat, tlLon);
516 d->bottomRight = QGeoCoordinate(brLat, brLon);
534bool QGeoRectanglePrivate::contains(
const QGeoCoordinate &coordinate)
const
536 if (!isValid() || !coordinate.isValid())
539 double left = topLeft.longitude();
540 double right = bottomRight.longitude();
541 double top = topLeft.latitude();
542 double bottom = bottomRight.latitude();
544 double lon = coordinate.longitude();
545 double lat = coordinate.latitude();
552 if ((lat == 90.0) && (top == 90.0))
555 if ((lat == -90.0) && (bottom == -90.0))
559 if ((lon < left) || (lon > right))
562 if ((lon < left) && (lon > right))
569QGeoCoordinate QGeoRectanglePrivate::center()
const
572 return QGeoCoordinate();
574 double cLat = (topLeft.latitude() + bottomRight.latitude()) / 2.0;
575 double cLon = (bottomRight.longitude() + topLeft.longitude()) / 2.0;
577 if (topLeft.longitude() > bottomRight.longitude())
580 cLon = QLocationUtils::wrapLong(cLon);
581 return QGeoCoordinate(cLat, cLon);
593bool QGeoRectangle::contains(
const QGeoRectangle &rectangle)
const
595 Q_D(
const QGeoRectangle);
597 return (d->contains(rectangle.topLeft())
598 && d->contains(rectangle.topRight())
599 && d->contains(rectangle.bottomLeft())
600 && d->contains(rectangle.bottomRight()));
610bool QGeoRectangle::intersects(
const QGeoRectangle &rectangle)
const
612 Q_D(
const QGeoRectangle);
614 double left1 = d->topLeft.longitude();
615 double right1 = d->bottomRight.longitude();
616 double top1 = d->topLeft.latitude();
617 double bottom1 = d->bottomRight.latitude();
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();
630 if ((top1 == 90.0) && (top1 == top2))
633 if ((bottom1 == -90.0) && (bottom1 == bottom2))
636 if (left1 < right1) {
637 if (left2 < right2) {
638 if ((left1 > right2) || (right1 < left2))
641 if ((left1 > right2) && (right1 < left2))
645 if (left2 < right2) {
646 if ((left2 > right1) && (right2 < left1))
667void QGeoRectangle::translate(
double degreesLatitude,
double degreesLongitude)
673 double tlLat = d->topLeft.latitude();
674 double tlLon = d->topLeft.longitude();
675 double brLat = d->bottomRight.latitude();
676 double brLon = d->bottomRight.longitude();
678 if (degreesLatitude >= 0.0)
679 degreesLatitude = qMin(degreesLatitude, 90.0 - tlLat);
681 degreesLatitude = qMax(degreesLatitude, -90.0 - brLat);
683 if ( (tlLon != -180.0) || (brLon != 180.0) ) {
684 tlLon = QLocationUtils::wrapLong(tlLon + degreesLongitude);
685 brLon = QLocationUtils::wrapLong(brLon + degreesLongitude);
688 tlLat += degreesLatitude;
689 brLat += degreesLatitude;
691 d->topLeft = QGeoCoordinate(tlLat, tlLon);
692 d->bottomRight = QGeoCoordinate(brLat, brLon);
747void QGeoRectanglePrivate::extendRectangle(
const QGeoCoordinate &coordinate)
749 if (!isValid() || !coordinate.isValid() || contains(coordinate))
752 double left = topLeft.longitude();
753 double right = bottomRight.longitude();
754 double top = topLeft.latitude();
755 double bottom = bottomRight.latitude();
757 double inputLat = coordinate.latitude();
758 double inputLon = coordinate.longitude();
760 top = qMax(top, inputLat);
761 bottom = qMin(bottom, inputLat);
763 bool wrap = left > right;
765 if (wrap && inputLon > right && inputLon < left) {
766 if (qAbs(left - inputLon) < qAbs(right - inputLon))
771 if (inputLon < left) {
772 if (360 - (right - inputLon) < left - inputLon)
776 }
else if (inputLon > right) {
777 if (360 - (inputLon - left) < inputLon - right)
783 topLeft = QGeoCoordinate(top, left);
784 bottomRight = QGeoCoordinate(bottom, right);
808QGeoRectangle &QGeoRectangle::operator|=(
const QGeoRectangle &rectangle)
814 double top = qMax(d->topLeft.latitude(), rectangle.d_func()->topLeft.latitude());
815 double bottom = qMin(d->bottomRight.latitude(), rectangle.d_func()->bottomRight.latitude());
817 QGeoRectangle candidate(
818 {top, d->topLeft.longitude()},
819 {bottom, rectangle.d_func()->bottomRight.longitude()}
821 QGeoRectangle otherCandidate(
822 {top, rectangle.d_func()->topLeft.longitude()},
823 {bottom, d->bottomRight.longitude()}
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;
831 if (360 <= unwrappedWidth) {
832 candidate.d_func()->topLeft.setLongitude(-180.0);
833 candidate.d_func()->bottomRight.setLongitude(180.0);
836 candidate = (candidate.width() < width() ? *
this : candidate);
837 candidate = (candidate.width() < rectangle.width() ? rectangle : candidate);
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);
847 this->d_func()->topLeft.setLatitude(top);
848 this->d_func()->bottomRight.setLatitude(bottom);
858QString QGeoRectangle::toString()
const
860 if (type() != QGeoShape::RectangleType) {
861 qWarning(
"Not a rectangle a %d\n", type());
862 return QStringLiteral(
"QGeoRectangle(not a rectangle)");
865 return QStringLiteral(
"QGeoRectangle({%1, %2}, {%3, %4})")
866 .arg(topLeft().latitude())
867 .arg(topLeft().longitude())
868 .arg(bottomRight().latitude())
869 .arg(bottomRight().longitude());
886QGeoRectanglePrivate::QGeoRectanglePrivate(
const QGeoRectanglePrivate &other)
887: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(other.topLeft),
888 bottomRight(other.bottomRight)
899bool QGeoRectanglePrivate::operator==(
const QGeoShapePrivate &other)
const
901 if (!QGeoShapePrivate::operator==(other))
904 const QGeoRectanglePrivate &otherBox =
static_cast<
const QGeoRectanglePrivate &>(other);
906 return topLeft == otherBox.topLeft && bottomRight == otherBox.bottomRight;