diff options
Diffstat (limited to 'src/positioning/qgeorectangle.cpp')
-rw-r--r-- | src/positioning/qgeorectangle.cpp | 1031 |
1 files changed, 0 insertions, 1031 deletions
diff --git a/src/positioning/qgeorectangle.cpp b/src/positioning/qgeorectangle.cpp deleted file mode 100644 index b92ca17c..00000000 --- a/src/positioning/qgeorectangle.cpp +++ /dev/null @@ -1,1031 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtPositioning module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qgeorectangle.h" -#include "qgeorectangle_p.h" - -#include "qwebmercator_p.h" -#include "qdoublevector2d_p.h" -#include "qgeocoordinate.h" -#include "qnumeric.h" -#include "qlocationutils_p.h" -#include <QList> -QT_BEGIN_NAMESPACE - -/*! - \class QGeoRectangle - \inmodule QtPositioning - \ingroup QtPositioning-positioning - \since 5.2 - - \brief The QGeoRectangle class defines a rectangular geographic area. - - The rectangle is defined in terms of a QGeoCoordinate which specifies the - top left coordinate of the rectangle and a QGeoCoordinate which specifies - the bottom right coordinate of the rectangle. - - A geo rectangle is considered invalid if the top left or bottom right - coordinates are invalid or if the top left coordinate is south of the - bottom right coordinate. - - Geo rectangles can never cross the poles. - - Several methods behave as though the geo rectangle is defined in terms of a - center coordinate, the width of the geo rectangle in degrees and the height - of the geo rectangle in degrees. - - If the height or center of a geo rectangle is adjusted such that it would - cross one of the poles the height is modified such that the geo rectangle - touches but does not cross the pole and that the center coordinate is still - in the center of the geo rectangle. - - This class is a \l Q_GADGET since Qt 5.5. It can be - \l{Cpp_value_integration_positioning}{directly used from C++ and QML}. -*/ - -/*! - \property QGeoRectangle::bottomLeft - \brief This property holds the bottom left coorindate of this geo rectangle. - - While this property is introduced in Qt 5.5, the related accessor functions - exist since the first version of this class. - - \since 5.5 -*/ - -/*! - \property QGeoRectangle::bottomRight - \brief This property holds the bottom right coordinate of this geo rectangle. - - While this property is introduced in Qt 5.5, the related accessor functions - exist since the first version of this class. - - \since 5.5 -*/ - -/*! - \property QGeoRectangle::topLeft - \brief This property holds the top left coordinate of this geo rectangle. - - While this property is introduced in Qt 5.5, the related accessor functions - exist since the first version of this class. - - \since 5.5 -*/ - -/*! - \property QGeoRectangle::topRight - \brief This property holds the top right coordinate of this geo rectangle. - - While this property is introduced in Qt 5.5, the related accessor functions - exist since the first version of this class. - - \since 5.5 -*/ - -/*! - \property QGeoRectangle::center - \brief This property holds the center of this geo rectangle. - - While this property is introduced in Qt 5.5, the related accessor functions - exist since the first version of this class. - - \sa QGeoShape::center - - \since 5.5 -*/ - -/*! - \property QGeoRectangle::width - \brief This property holds the width of this geo rectangle in degrees. - - The property value is undefined if this geo rectangle is invalid. - - If the new width is less than 0.0 or if this geo rectangle is invalid, this - function does nothing. To set up the values of an invalid - geo rectangle based on the center, width, and height, you should use - \l setCenter() first to make the geo rectangle valid. - - 360.0 is the width used only if the new width is equal or greater than 360. - In such cases the leftmost longitude of the geo rectangle is set to -180.0 - degrees and the rightmost longitude of the geo rectangle is set to 180.0 - degrees. - - While this property is introduced in Qt 5.5, the related accessor functions - exist since the first version of this class. - - \since 5.5 -*/ - -/*! - \property QGeoRectangle::height - \brief This property holds the height of this geo rectangle in degrees. - - The property value is undefined if this geo rectangle is invalid. - - If the new height is less than 0.0 or if this geo rectangle is invalid, - the property is not changed. To set up the values of an invalid - geo rectangle based on the center, width, and height, you should use - \l setCenter() first to make the geo rectangle valid. - - If the change in height would cause the geo rectangle to cross a pole, - the height is adjusted such that the geo rectangle only touches the pole. - - This change is done such that the center coordinate is still at the - center of the geo rectangle, which may result in a geo rectangle with - a smaller height than expected. - - 180.0 is the height used only if the new height is greater or equal than 180. - - While this property is introduced in Qt 5.5, the related accessor functions - exist since the first version of this class. - - \since 5.5 -*/ - -inline QGeoRectanglePrivate *QGeoRectangle::d_func() -{ - return static_cast<QGeoRectanglePrivate *>(d_ptr.data()); -} - -inline const QGeoRectanglePrivate *QGeoRectangle::d_func() const -{ - return static_cast<const QGeoRectanglePrivate *>(d_ptr.constData()); -} - -struct RectangleVariantConversions -{ - RectangleVariantConversions() - { - QMetaType::registerConverter<QGeoRectangle, QGeoShape>(); - QMetaType::registerConverter<QGeoShape, QGeoRectangle>(); - } -}; - - -Q_GLOBAL_STATIC(RectangleVariantConversions, initRectangleConversions) - -/*! - Constructs a new, invalid geo rectangle. -*/ -QGeoRectangle::QGeoRectangle() -: QGeoShape(new QGeoRectanglePrivate) -{ - initRectangleConversions(); -} - -/*! - Constructs a new geo rectangle centered at \a center with a - width in degrees of \a degreesWidth and a height in degrees of \a degreesHeight. - - If \a degreesHeight would take the geo rectangle beyond one of the poles, - the height of the geo rectangle will be truncated such that the geo rectangle - only extends up to the pole. The center of the geo rectangle will be - unchanged, and the height will be adjusted such that the center point is at - the center of the truncated geo rectangle. -*/ -QGeoRectangle::QGeoRectangle(const QGeoCoordinate ¢er, double degreesWidth, double degreesHeight) -{ - initRectangleConversions(); - d_ptr = new QGeoRectanglePrivate(center, center); - setWidth(degreesWidth); - setHeight(degreesHeight); -} - -/*! - Constructs a new geo rectangle with a top left coordinate \a topLeft and a bottom right - coordinate \a bottomRight. -*/ -QGeoRectangle::QGeoRectangle(const QGeoCoordinate &topLeft, const QGeoCoordinate &bottomRight) -{ - initRectangleConversions(); - d_ptr = new QGeoRectanglePrivate(topLeft, bottomRight); -} - -/*! - Constructs a new geo rectangle, of minimum size, containing all of the \a coordinates. -*/ -QGeoRectangle::QGeoRectangle(const QList<QGeoCoordinate> &coordinates) -{ - initRectangleConversions(); - if (coordinates.isEmpty()) { - d_ptr = new QGeoRectanglePrivate; - } else { - const QGeoCoordinate &startCoordinate = coordinates.first(); - d_ptr = new QGeoRectanglePrivate(startCoordinate, startCoordinate); - - foreach (const QGeoCoordinate &coordinate, coordinates) { - d_func()->extendRectangle(coordinate); - } - } -} - -/*! - Constructs a geo rectangle from the contents of \a other. -*/ -QGeoRectangle::QGeoRectangle(const QGeoRectangle &other) -: QGeoShape(other) -{ - initRectangleConversions(); -} - -/*! - Constructs a geo rectangle from the contents of \a other. -*/ -QGeoRectangle::QGeoRectangle(const QGeoShape &other) -: QGeoShape(other) -{ - initRectangleConversions(); - if (type() != QGeoShape::RectangleType) - d_ptr = new QGeoRectanglePrivate; -} - -/*! - Destroys this geo rectangle. -*/ -QGeoRectangle::~QGeoRectangle() -{ -} - -/*! - Assigns \a other to this geo rectangle and returns a reference to this geo rectangle. -*/ -QGeoRectangle &QGeoRectangle::operator=(const QGeoRectangle &other) -{ - QGeoShape::operator=(other); - return *this; -} - -bool QGeoRectanglePrivate::isValid() const -{ - return topLeft.isValid() && bottomRight.isValid() && - topLeft.latitude() >= bottomRight.latitude(); -} - -bool QGeoRectanglePrivate::isEmpty() const -{ - if (!isValid()) - return true; - - return topLeft.latitude() == bottomRight.latitude() || - topLeft.longitude() == bottomRight.longitude(); -} - -/*! - Sets the top left coordinate of this geo rectangle to \a topLeft. -*/ -void QGeoRectangle::setTopLeft(const QGeoCoordinate &topLeft) -{ - Q_D(QGeoRectangle); - - d->topLeft = topLeft; -} - -/*! - Returns the top left coordinate of this geo rectangle. -*/ -QGeoCoordinate QGeoRectangle::topLeft() const -{ - Q_D(const QGeoRectangle); - - return d->topLeft; -} - -/*! - Sets the top right coordinate of this geo rectangle to \a topRight. -*/ -void QGeoRectangle::setTopRight(const QGeoCoordinate &topRight) -{ - Q_D(QGeoRectangle); - - d->topLeft.setLatitude(topRight.latitude()); - d->bottomRight.setLongitude(topRight.longitude()); -} - -/*! - Returns the top right coordinate of this geo rectangle. -*/ -QGeoCoordinate QGeoRectangle::topRight() const -{ - // TODO remove? - if (!isValid()) - return QGeoCoordinate(); - - Q_D(const QGeoRectangle); - - return QGeoCoordinate(d->topLeft.latitude(), d->bottomRight.longitude()); -} - -/*! - Sets the bottom left coordinate of this geo rectangle to \a bottomLeft. -*/ -void QGeoRectangle::setBottomLeft(const QGeoCoordinate &bottomLeft) -{ - Q_D(QGeoRectangle); - - d->bottomRight.setLatitude(bottomLeft.latitude()); - d->topLeft.setLongitude(bottomLeft.longitude()); -} - -/*! - Returns the bottom left coordinate of this geo rectangle. -*/ -QGeoCoordinate QGeoRectangle::bottomLeft() const -{ - // TODO remove? - if (!isValid()) - return QGeoCoordinate(); - - Q_D(const QGeoRectangle); - - return QGeoCoordinate(d->bottomRight.latitude(), d->topLeft.longitude()); -} - -/*! - Sets the bottom right coordinate of this geo rectangle to \a bottomRight. -*/ -void QGeoRectangle::setBottomRight(const QGeoCoordinate &bottomRight) -{ - Q_D(QGeoRectangle); - - d->bottomRight = bottomRight; -} - -/*! - Returns the bottom right coordinate of this geo rectangle. -*/ -QGeoCoordinate QGeoRectangle::bottomRight() const -{ - Q_D(const QGeoRectangle); - - return d->bottomRight; -} - -/*! - Sets the center of this geo rectangle to \a center. - - If this causes the geo rectangle to cross on of the poles the height of the - geo rectangle will be truncated such that the geo rectangle only extends up - to the pole. The center of the geo rectangle will be unchanged, and the - height will be adjusted such that the center point is at the center of the - truncated geo rectangle. - -*/ -void QGeoRectangle::setCenter(const QGeoCoordinate ¢er) -{ - Q_D(QGeoRectangle); - - if (!isValid()) { - d->topLeft = center; - d->bottomRight = center; - return; - } - double width = this->width(); - double height = this->height(); - - double tlLat = center.latitude() + height / 2.0; - double tlLon = center.longitude() - width / 2.0; - double brLat = center.latitude() - height / 2.0; - double brLon = center.longitude() + width / 2.0; - tlLon = QLocationUtils::wrapLong(tlLon); - brLon = QLocationUtils::wrapLong(brLon); - - if (tlLat > 90.0) { - brLat = 2 * center.latitude() - 90.0; - tlLat = 90.0; - } - - if (tlLat < -90.0) { - brLat = -90.0; - tlLat = -90.0; - } - - if (brLat > 90.0) { - tlLat = 90.0; - brLat = 90.0; - } - - if (brLat < -90.0) { - tlLat = 2 * center.latitude() + 90.0; - brLat = -90.0; - } - - if (width == 360.0) { - tlLon = -180.0; - brLon = 180.0; - } - - d->topLeft = QGeoCoordinate(tlLat, tlLon); - d->bottomRight = QGeoCoordinate(brLat, brLon); -} - -/*! - Returns the center of this geo rectangle. Equivalent to QGeoShape::center(). -*/ -QGeoCoordinate QGeoRectangle::center() const -{ - Q_D(const QGeoRectangle); - - return d->center(); -} - -/*! - Sets the width of this geo rectangle in degrees to \a degreesWidth. -*/ -void QGeoRectangle::setWidth(double degreesWidth) -{ - if (!isValid()) - return; - - if (degreesWidth < 0.0) - return; - - Q_D(QGeoRectangle); - - if (degreesWidth >= 360.0) { - d->topLeft.setLongitude(-180.0); - d->bottomRight.setLongitude(180.0); - return; - } - - double tlLat = d->topLeft.latitude(); - double brLat = d->bottomRight.latitude(); - - QGeoCoordinate c = center(); - - double tlLon = c.longitude() - degreesWidth / 2.0; - tlLon = QLocationUtils::wrapLong(tlLon); - - double brLon = c.longitude() + degreesWidth / 2.0; - brLon = QLocationUtils::wrapLong(brLon); - - d->topLeft = QGeoCoordinate(tlLat, tlLon); - d->bottomRight = QGeoCoordinate(brLat, brLon); -} - -/*! - Returns the width of this geo rectangle in degrees. - - The return value is undefined if this geo rectangle is invalid. -*/ -double QGeoRectangle::width() const -{ - if (!isValid()) - return qQNaN(); - - Q_D(const QGeoRectangle); - - double result = d->bottomRight.longitude() - d->topLeft.longitude(); - if (result < 0.0) - result += 360.0; - if (result > 360.0) - result -= 360.0; - - return result; -} - -/*! - Sets the height of this geo rectangle in degrees to \a degreesHeight. -*/ -void QGeoRectangle::setHeight(double degreesHeight) -{ - if (!isValid()) - return; - - if (degreesHeight < 0.0) - return; - - if (degreesHeight >= 180.0) { - degreesHeight = 180.0; - } - - Q_D(QGeoRectangle); - - double tlLon = d->topLeft.longitude(); - double brLon = d->bottomRight.longitude(); - - QGeoCoordinate c = center(); - - double tlLat = c.latitude() + degreesHeight / 2.0; - double brLat = c.latitude() - degreesHeight / 2.0; - - if (tlLat > 90.0) { - brLat = 2* c.latitude() - 90.0; - tlLat = 90.0; - } - - if (tlLat < -90.0) { - brLat = -90.0; - tlLat = -90.0; - } - - if (brLat > 90.0) { - tlLat = 90.0; - brLat = 90.0; - } - - if (brLat < -90.0) { - tlLat = 2 * c.latitude() + 90.0; - brLat = -90.0; - } - - d->topLeft = QGeoCoordinate(tlLat, tlLon); - d->bottomRight = QGeoCoordinate(brLat, brLon); -} - -/*! - Returns the height of this geo rectangle in degrees. - - The return value is undefined if this geo rectangle is invalid. -*/ -double QGeoRectangle::height() const -{ - if (!isValid()) - return qQNaN(); - - Q_D(const QGeoRectangle); - - return d->topLeft.latitude() - d->bottomRight.latitude(); -} - -bool QGeoRectanglePrivate::contains(const QGeoCoordinate &coordinate) const -{ - if (!isValid() || !coordinate.isValid()) - return false; - - double left = topLeft.longitude(); - double right = bottomRight.longitude(); - double top = topLeft.latitude(); - double bottom = bottomRight.latitude(); - - double lon = coordinate.longitude(); - double lat = coordinate.latitude(); - - if (lat > top) - return false; - if (lat < bottom) - return false; - - if ((lat == 90.0) && (top == 90.0)) - return true; - - if ((lat == -90.0) && (bottom == -90.0)) - return true; - - if (left <= right) { - if ((lon < left) || (lon > right)) - return false; - } else { - if ((lon < left) && (lon > right)) - return false; - } - - return true; -} - -QGeoCoordinate QGeoRectanglePrivate::center() const -{ - if (!isValid()) - return QGeoCoordinate(); - - double cLat = (topLeft.latitude() + bottomRight.latitude()) / 2.0; - double cLon = (bottomRight.longitude() + topLeft.longitude()) / 2.0; - - if (topLeft.longitude() > bottomRight.longitude()) - cLon = cLon - 180.0; - - cLon = QLocationUtils::wrapLong(cLon); - return QGeoCoordinate(cLat, cLon); -} - -QGeoRectangle QGeoRectanglePrivate::boundingGeoRectangle() const -{ - return QGeoRectangle(topLeft, bottomRight); -} - -/*! - Returns whether the geo rectangle \a rectangle is contained within this - geo rectangle. -*/ -bool QGeoRectangle::contains(const QGeoRectangle &rectangle) const -{ - Q_D(const QGeoRectangle); - - return (d->contains(rectangle.topLeft()) - && d->contains(rectangle.topRight()) - && d->contains(rectangle.bottomLeft()) - && d->contains(rectangle.bottomRight())); -} - -/*! - Returns whether the geo rectangle \a rectangle intersects this geo rectangle. - - If the top or bottom edges of both geo rectangles are at one of the poles - the geo rectangles are considered to be intersecting, since the longitude - is irrelevant when the edges are at the pole. -*/ -bool QGeoRectangle::intersects(const QGeoRectangle &rectangle) const -{ - Q_D(const QGeoRectangle); - - double left1 = d->topLeft.longitude(); - double right1 = d->bottomRight.longitude(); - double top1 = d->topLeft.latitude(); - double bottom1 = d->bottomRight.latitude(); - - double left2 = rectangle.d_func()->topLeft.longitude(); - double right2 = rectangle.d_func()->bottomRight.longitude(); - double top2 = rectangle.d_func()->topLeft.latitude(); - double bottom2 = rectangle.d_func()->bottomRight.latitude(); - - if (top1 < bottom2) - return false; - - if (bottom1 > top2) - return false; - - if ((top1 == 90.0) && (top1 == top2)) - return true; - - if ((bottom1 == -90.0) && (bottom1 == bottom2)) - return true; - - if (left1 < right1) { - if (left2 < right2) { - if ((left1 > right2) || (right1 < left2)) - return false; - } else { - if ((left1 > right2) && (right1 < left2)) - return false; - } - } else { - if (left2 < right2) { - if ((left2 > right1) && (right2 < left1)) - return false; - } else { - // if both wrap then they have to intersect - } - } - - return true; -} - -/*! - Translates this geo rectangle by \a degreesLatitude northwards and \a - degreesLongitude eastwards. - - Negative values of \a degreesLatitude and \a degreesLongitude correspond to - southward and westward translation respectively. - - If the translation would have caused the geo rectangle to cross a pole the - geo rectangle will be translated until the top or bottom edge of the geo rectangle - touches the pole but not further. -*/ -void QGeoRectangle::translate(double degreesLatitude, double degreesLongitude) -{ - // TODO handle dlat, dlon larger than 360 degrees - - Q_D(QGeoRectangle); - - double tlLat = d->topLeft.latitude(); - double tlLon = d->topLeft.longitude(); - double brLat = d->bottomRight.latitude(); - double brLon = d->bottomRight.longitude(); - - if (degreesLatitude >= 0.0) - degreesLatitude = qMin(degreesLatitude, 90.0 - tlLat); - else - degreesLatitude = qMax(degreesLatitude, -90.0 - brLat); - - if ( (tlLon != -180.0) || (brLon != 180.0) ) { - tlLon = QLocationUtils::wrapLong(tlLon + degreesLongitude); - brLon = QLocationUtils::wrapLong(brLon + degreesLongitude); - } - - tlLat += degreesLatitude; - brLat += degreesLatitude; - - d->topLeft = QGeoCoordinate(tlLat, tlLon); - d->bottomRight = QGeoCoordinate(brLat, brLon); -} - -/*! - Returns a copy of this geo rectangle translated by \a degreesLatitude northwards and \a - degreesLongitude eastwards. - - Negative values of \a degreesLatitude and \a degreesLongitude correspond to - southward and westward translation respectively. - - \sa translate() -*/ -QGeoRectangle QGeoRectangle::translated(double degreesLatitude, double degreesLongitude) const -{ - QGeoRectangle result(*this); - result.translate(degreesLatitude, degreesLongitude); - return result; -} - -/*! - Extends the geo rectangle to also cover the coordinate \a coordinate - - \since 5.9 -*/ -void QGeoRectangle::extendRectangle(const QGeoCoordinate &coordinate) -{ - Q_D(QGeoRectangle); - d->extendRectangle(coordinate); -} - -/*! - Returns the smallest geo rectangle which contains both this geo rectangle and \a rectangle. - - If the centers of the two geo rectangles are separated by exactly 180.0 degrees then the - width is set to 360.0 degrees with the leftmost longitude set to -180.0 degrees and the - rightmost longitude set to 180.0 degrees. This is done to ensure that the result is - independent of the order of the operands. - -*/ -QGeoRectangle QGeoRectangle::united(const QGeoRectangle &rectangle) const -{ - QGeoRectangle result(*this); - if (rectangle.isValid()) - result |= rectangle; - return result; -} - -/*! - Extends the rectangle in the smallest possible way to include \a coordinate in - the shape. - - Both the rectangle and coordinate needs to be valid. If the rectangle already covers - the coordinate noting happens. - -*/ -void QGeoRectanglePrivate::extendRectangle(const QGeoCoordinate &coordinate) -{ - if (!isValid() || !coordinate.isValid() || contains(coordinate)) - return; - - double left = topLeft.longitude(); - double right = bottomRight.longitude(); - double top = topLeft.latitude(); - double bottom = bottomRight.latitude(); - - double inputLat = coordinate.latitude(); - double inputLon = coordinate.longitude(); - - top = qMax(top, inputLat); - bottom = qMin(bottom, inputLat); - - bool wrap = left > right; - - if (wrap && inputLon > right && inputLon < left) { - if (qAbs(left - inputLon) < qAbs(right - inputLon)) - left = inputLon; - else - right = inputLon; - } else if (!wrap) { - if (inputLon < left) { - if (360 - (right - inputLon) < left - inputLon) - right = inputLon; - else - left = inputLon; - } else if (inputLon > right) { - if (360 - (inputLon - left) < inputLon - right) - left = inputLon; - else - right = inputLon; - } - } - topLeft = QGeoCoordinate(top, left); - bottomRight = QGeoCoordinate(bottom, right); -} - -/*! - \fn QGeoRectangle QGeoRectangle::operator|(const QGeoRectangle &rectangle) const - - Returns the smallest geo rectangle which contains both this geo rectangle and \a rectangle. - - If the centers of the two geo rectangles are separated by exactly 180.0 degrees then the - width is set to 360.0 degrees with the leftmost longitude set to -180.0 degrees and the - rightmost longitude set to 180.0 degrees. This is done to ensure that the result is - independent of the order of the operands. - -*/ - -/*! - Returns the smallest geo rectangle which contains both this geo rectangle and \a rectangle. - - If the centers of the two geo rectangles are separated by exactly 180.0 degrees then the - width is set to 360.0 degrees with the leftmost longitude set to -180.0 degrees and the - rightmost longitude set to 180.0 degrees. This is done to ensure that the result is - independent of the order of the operands. - -*/ -QGeoRectangle &QGeoRectangle::operator|=(const QGeoRectangle &rectangle) -{ - // If non-intersecting goes for most narrow box - - Q_D(QGeoRectangle); - - double left1 = d->topLeft.longitude(); - double right1 = d->bottomRight.longitude(); - double top1 = d->topLeft.latitude(); - double bottom1 = d->bottomRight.latitude(); - - double left2 = rectangle.d_func()->topLeft.longitude(); - double right2 = rectangle.d_func()->bottomRight.longitude(); - double top2 = rectangle.d_func()->topLeft.latitude(); - double bottom2 = rectangle.d_func()->bottomRight.latitude(); - - double top = qMax(top1, top2); - double bottom = qMin(bottom1, bottom2); - - double left = 0.0; - double right = 0.0; - - bool wrap1 = (left1 > right1); - bool wrap2 = (left2 > right2); - - if ((wrap1 && wrap2) || (!wrap1 && !wrap2)) { - - double w = qAbs((left1 + right1 - left2 - right2) / 2.0); - - if (w < 180.0) { - left = qMin(left1, left2); - right = qMax(right1, right2); - } else if (w > 180.0) { - left = qMax(left1, left2); - right = qMin(right1, right2); - } else { - left = -180.0; - right = 180.0; - } - - } else { - double wrapLeft = 0.0; - double wrapRight = 0.0; - double nonWrapLeft = 0.0; - double nonWrapRight = 0.0; - - if (wrap1) { - wrapLeft = left1; - wrapRight = right1; - nonWrapLeft = left2; - nonWrapRight = right2; - } else { - wrapLeft = left2; - wrapRight = right2; - nonWrapLeft = left1; - nonWrapRight = right1; - } - - bool joinWrapLeft = (nonWrapRight >= wrapLeft); - bool joinWrapRight = (nonWrapLeft <= wrapRight); - - if (wrapLeft <= nonWrapLeft) { // The wrapping rectangle contains the non-wrapping one entirely - left = wrapLeft; - right = wrapRight; - } else { - if (joinWrapLeft) { - if (joinWrapRight) { - left = -180.0; - right = 180.0; - } else { - left = nonWrapLeft; - right = wrapRight; - } - } else { - if (joinWrapRight) { - left = wrapLeft; - right = nonWrapRight; - } else { - double wrapRightDistance = nonWrapLeft - wrapRight; - double wrapLeftDistance = wrapLeft - nonWrapRight; - - if (wrapLeftDistance == wrapRightDistance) { - left = -180.0; - right = 180.0; - } else if (wrapLeftDistance < wrapRightDistance) { - left = nonWrapLeft; - right = wrapRight; - } else { - left = wrapLeft; - right = nonWrapRight; - } - } - } - } - } - - if (((left1 == -180) && (right1 == 180.0)) - || ((left2 == -180) && (right2 == 180.0))) { - left = -180; - right = 180; - } - - d->topLeft = QGeoCoordinate(top, left); - d->bottomRight = QGeoCoordinate(bottom, right); - - return *this; -} - -/*! - Returns the geo rectangle properties as a string. - - \since 5.5 -*/ -QString QGeoRectangle::toString() const -{ - if (type() != QGeoShape::RectangleType) { - qWarning("Not a rectangle a %d\n", type()); - return QStringLiteral("QGeoRectangle(not a rectangle)"); - } - - return QStringLiteral("QGeoRectangle({%1, %2}, {%3, %4})") - .arg(topLeft().latitude()) - .arg(topLeft().longitude()) - .arg(bottomRight().latitude()) - .arg(bottomRight().longitude()); -} - -/******************************************************************************* -*******************************************************************************/ - -QGeoRectanglePrivate::QGeoRectanglePrivate() -: QGeoShapePrivate(QGeoShape::RectangleType) -{ -} - -QGeoRectanglePrivate::QGeoRectanglePrivate(const QGeoCoordinate &topLeft, - const QGeoCoordinate &bottomRight) -: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(topLeft), bottomRight(bottomRight) -{ -} - -QGeoRectanglePrivate::QGeoRectanglePrivate(const QGeoRectanglePrivate &other) -: QGeoShapePrivate(QGeoShape::RectangleType), topLeft(other.topLeft), - bottomRight(other.bottomRight) -{ -} - -QGeoRectanglePrivate::~QGeoRectanglePrivate() {} - -QGeoShapePrivate *QGeoRectanglePrivate::clone() const -{ - return new QGeoRectanglePrivate(*this); -} - -bool QGeoRectanglePrivate::operator==(const QGeoShapePrivate &other) const -{ - if (!QGeoShapePrivate::operator==(other)) - return false; - - const QGeoRectanglePrivate &otherBox = static_cast<const QGeoRectanglePrivate &>(other); - - return topLeft == otherBox.topLeft && bottomRight == otherBox.bottomRight; -} - -size_t QGeoRectanglePrivate::hash(size_t seed) const -{ - return qHashMulti(seed, topLeft, bottomRight); -} - -QT_END_NAMESPACE - |