194QGeoRectangle::QGeoRectangle(
const QList<QGeoCoordinate> &coordinates)
196 if (coordinates.isEmpty()) {
197 d_ptr =
new QGeoRectanglePrivate;
199 const QGeoCoordinate &startCoordinate = coordinates.first();
200 d_ptr =
new QGeoRectanglePrivate(startCoordinate, startCoordinate);
202 for (
const QGeoCoordinate &coordinate : coordinates)
203 d_func()->extendRectangle(coordinate);
362void QGeoRectangle::setCenter(
const QGeoCoordinate ¢er)
368 d->bottomRight = center;
371 double width =
this->width();
372 double height =
this->height();
374 double tlLat = center.latitude() + height / 2.0;
375 double tlLon = center.longitude() - width / 2.0;
376 double brLat = center.latitude() - height / 2.0;
377 double brLon = center.longitude() + width / 2.0;
378 tlLon = QLocationUtils::wrapLong(tlLon);
379 brLon = QLocationUtils::wrapLong(brLon);
382 brLat = 2 * center.latitude() - 90.0;
397 tlLat = 2 * center.latitude() + 90.0;
401 if (width == 360.0) {
406 d->topLeft = QGeoCoordinate(tlLat, tlLon);
407 d->bottomRight = QGeoCoordinate(brLat, brLon);
423void QGeoRectangle::setWidth(
double degreesWidth)
428 if (degreesWidth < 0.0)
433 if (degreesWidth >= 360.0) {
434 d->topLeft.setLongitude(-180.0);
435 d->bottomRight.setLongitude(180.0);
439 double tlLat = d->topLeft.latitude();
440 double brLat = d->bottomRight.latitude();
442 QGeoCoordinate c = center();
444 double tlLon = c.longitude() - degreesWidth / 2.0;
445 tlLon = QLocationUtils::wrapLong(tlLon);
447 double brLon = c.longitude() + degreesWidth / 2.0;
448 brLon = QLocationUtils::wrapLong(brLon);
450 d->topLeft = QGeoCoordinate(tlLat, tlLon);
451 d->bottomRight = QGeoCoordinate(brLat, brLon);
478void QGeoRectangle::setHeight(
double degreesHeight)
483 if (degreesHeight < 0.0)
486 if (degreesHeight >= 180.0) {
487 degreesHeight = 180.0;
492 double tlLon = d->topLeft.longitude();
493 double brLon = d->bottomRight.longitude();
495 QGeoCoordinate c = center();
497 double tlLat = c.latitude() + degreesHeight / 2.0;
498 double brLat = c.latitude() - degreesHeight / 2.0;
501 brLat = 2* c.latitude() - 90.0;
516 tlLat = 2 * c.latitude() + 90.0;
520 d->topLeft = QGeoCoordinate(tlLat, tlLon);
521 d->bottomRight = QGeoCoordinate(brLat, brLon);
539bool QGeoRectanglePrivate::contains(
const QGeoCoordinate &coordinate)
const
541 if (!isValid() || !coordinate.isValid())
544 double left = topLeft.longitude();
545 double right = bottomRight.longitude();
546 double top = topLeft.latitude();
547 double bottom = bottomRight.latitude();
549 double lon = coordinate.longitude();
550 double lat = coordinate.latitude();
557 if ((lat == 90.0) && (top == 90.0))
560 if ((lat == -90.0) && (bottom == -90.0))
564 if ((lon < left) || (lon > right))
567 if ((lon < left) && (lon > right))
574QGeoCoordinate QGeoRectanglePrivate::center()
const
577 return QGeoCoordinate();
579 double cLat = (topLeft.latitude() + bottomRight.latitude()) / 2.0;
580 double cLon = (bottomRight.longitude() + topLeft.longitude()) / 2.0;
582 if (topLeft.longitude() > bottomRight.longitude())
585 cLon = QLocationUtils::wrapLong(cLon);
586 return QGeoCoordinate(cLat, cLon);
598bool QGeoRectangle::contains(
const QGeoRectangle &rectangle)
const
600 Q_D(
const QGeoRectangle);
602 return (d->contains(rectangle.topLeft())
603 && d->contains(rectangle.topRight())
604 && d->contains(rectangle.bottomLeft())
605 && d->contains(rectangle.bottomRight()));
615bool QGeoRectangle::intersects(
const QGeoRectangle &rectangle)
const
617 Q_D(
const QGeoRectangle);
619 double left1 = d->topLeft.longitude();
620 double right1 = d->bottomRight.longitude();
621 double top1 = d->topLeft.latitude();
622 double bottom1 = d->bottomRight.latitude();
624 double left2 = rectangle.d_func()->topLeft.longitude();
625 double right2 = rectangle.d_func()->bottomRight.longitude();
626 double top2 = rectangle.d_func()->topLeft.latitude();
627 double bottom2 = rectangle.d_func()->bottomRight.latitude();
635 if ((top1 == 90.0) && (top1 == top2))
638 if ((bottom1 == -90.0) && (bottom1 == bottom2))
641 if (left1 < right1) {
642 if (left2 < right2) {
643 if ((left1 > right2) || (right1 < left2))
646 if ((left1 > right2) && (right1 < left2))
650 if (left2 < right2) {
651 if ((left2 > right1) && (right2 < left1))
672void QGeoRectangle::translate(
double degreesLatitude,
double degreesLongitude)
678 double tlLat = d->topLeft.latitude();
679 double tlLon = d->topLeft.longitude();
680 double brLat = d->bottomRight.latitude();
681 double brLon = d->bottomRight.longitude();
683 if (degreesLatitude >= 0.0)
684 degreesLatitude = qMin(degreesLatitude, 90.0 - tlLat);
686 degreesLatitude = qMax(degreesLatitude, -90.0 - brLat);
688 if ( (tlLon != -180.0) || (brLon != 180.0) ) {
689 tlLon = QLocationUtils::wrapLong(tlLon + degreesLongitude);
690 brLon = QLocationUtils::wrapLong(brLon + degreesLongitude);
693 tlLat += degreesLatitude;
694 brLat += degreesLatitude;
696 d->topLeft = QGeoCoordinate(tlLat, tlLon);
697 d->bottomRight = QGeoCoordinate(brLat, brLon);
752void QGeoRectanglePrivate::extendRectangle(
const QGeoCoordinate &coordinate)
754 if (!isValid() || !coordinate.isValid() || contains(coordinate))
757 double left = topLeft.longitude();
758 double right = bottomRight.longitude();
759 double top = topLeft.latitude();
760 double bottom = bottomRight.latitude();
762 double inputLat = coordinate.latitude();
763 double inputLon = coordinate.longitude();
765 top = qMax(top, inputLat);
766 bottom = qMin(bottom, inputLat);
768 bool wrap = left > right;
770 if (wrap && inputLon > right && inputLon < left) {
771 if (qAbs(left - inputLon) < qAbs(right - inputLon))
776 if (inputLon < left) {
777 if (360 - (right - inputLon) < left - inputLon)
781 }
else if (inputLon > right) {
782 if (360 - (inputLon - left) < inputLon - right)
788 topLeft = QGeoCoordinate(top, left);
789 bottomRight = QGeoCoordinate(bottom, right);
813QGeoRectangle &QGeoRectangle::operator|=(
const QGeoRectangle &rectangle)
819 double top = qMax(d->topLeft.latitude(), rectangle.d_func()->topLeft.latitude());
820 double bottom = qMin(d->bottomRight.latitude(), rectangle.d_func()->bottomRight.latitude());
822 QGeoRectangle candidate(
823 {top, d->topLeft.longitude()},
824 {bottom, rectangle.d_func()->bottomRight.longitude()}
826 QGeoRectangle otherCandidate(
827 {top, rectangle.d_func()->topLeft.longitude()},
828 {bottom, d->bottomRight.longitude()}
830 double unwrappedWidth = (candidate.width() < rectangle.width() ? 360 : 0) + candidate.width();
831 double otherUnwrappedWidth = (otherCandidate.width() < width() ? 360 : 0) + otherCandidate.width();
832 if (otherUnwrappedWidth < unwrappedWidth) {
833 candidate = otherCandidate;
834 unwrappedWidth = otherUnwrappedWidth;
836 if (360 <= unwrappedWidth) {
837 candidate.d_func()->topLeft.setLongitude(-180.0);
838 candidate.d_func()->bottomRight.setLongitude(180.0);
841 candidate = (candidate.width() < width() ? *
this : candidate);
842 candidate = (candidate.width() < rectangle.width() ? rectangle : candidate);
844 double middle1 = center().longitude();
845 double middle2 = rectangle.center().longitude();
846 if ((middle1 <= middle2 ? 0 : 360) + middle2 - middle1 == 180) {
847 candidate.d_func()->topLeft.setLongitude(-180.0);
848 candidate.d_func()->bottomRight.setLongitude(180.0);
852 this->d_func()->topLeft.setLatitude(top);
853 this->d_func()->bottomRight.setLatitude(bottom);
863QString QGeoRectangle::toString()
const
865 if (type() != QGeoShape::RectangleType) {
866 qWarning(
"Not a rectangle a %d\n", type());
867 return QStringLiteral(
"QGeoRectangle(not a rectangle)");
870 return QStringLiteral(
"QGeoRectangle({%1, %2}, {%3, %4})")
871 .arg(topLeft().latitude())
872 .arg(topLeft().longitude())
873 .arg(bottomRight().latitude())
874 .arg(bottomRight().longitude());
891QGeoRectanglePrivate::QGeoRectanglePrivate(
const QGeoRectanglePrivate &other)
892: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(other.topLeft),
893 bottomRight(other.bottomRight)
904bool QGeoRectanglePrivate::operator==(
const QGeoShapePrivate &other)
const
906 if (!QGeoShapePrivate::operator==(other))
909 const QGeoRectanglePrivate &otherBox =
static_cast<
const QGeoRectanglePrivate &>(other);
911 return topLeft == otherBox.topLeft && bottomRight == otherBox.bottomRight;