File indexing completed on 2024-05-12 03:50:13

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2007 Andrew Manson <g.real.ate@gmail.com>
0004 // SPDX-FileCopyrightText: 2008-2009 Torsten Rahn <rahn@kde.org>
0005 //
0006 
0007 
0008 #ifndef MARBLE_GEODATALATLONBOX_H
0009 #define MARBLE_GEODATALATLONBOX_H
0010 
0011 
0012 #include "MarbleGlobal.h"
0013 
0014 #include "GeoDataObject.h"
0015 #include "GeoDataCoordinates.h"
0016 
0017 #include "geodata_export.h"
0018 
0019 namespace Marble
0020 {
0021 
0022 class GeoDataLatLonBoxPrivate;
0023 
0024 class GeoDataLineString;
0025 
0026 /**
0027  * @short A class that defines a 2D bounding box for geographic data.
0028  *
0029  * GeoDataLatLonBox is a 2D bounding box that describes a geographic area
0030  * in terms of latitude and longitude.
0031  *
0032  * The bounding box gets described by assigning the northern, southern, 
0033  * eastern and western boundary.
0034  * So usually the value of the eastern boundary is bigger than the
0035  * value of the western boundary.
0036  *
0037  * This is also true if the GeoDataLatLonBox covers the whole longitude
0038  * range from 180 deg West to 180 deg East. Notably in this case
0039  * the bounding box crosses the date line.
0040  *
0041  * If the GeoDataLatLonBox does not cover the whole longitude range but still
0042  * crosses the date line then the eastern boundary has got a smaller value than
0043  * the western one.
0044  */
0045 
0046 class GEODATA_EXPORT GeoDataLatLonBox : public GeoDataObject
0047 {
0048     friend bool GEODATA_EXPORT operator==( GeoDataLatLonBox const& lhs, GeoDataLatLonBox const& rhs );
0049     friend bool GEODATA_EXPORT operator!=( GeoDataLatLonBox const& lhs, GeoDataLatLonBox const& rhs );
0050 
0051  public:
0052     GeoDataLatLonBox();
0053     GeoDataLatLonBox( qreal north, qreal south, qreal east, qreal west, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0054     GeoDataLatLonBox( const GeoDataLatLonBox & );
0055     ~GeoDataLatLonBox() override;
0056 
0057     GeoDataLatLonBox& operator=( const GeoDataLatLonBox& other );
0058 
0059     /// Provides type information for downcasting a GeoData
0060     const char* nodeType() const override;
0061 
0062     /**
0063      * @brief Get the northern boundary of the bounding box.
0064      * @return the latitude of the northern boundary.
0065      */
0066     qreal north( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
0067     void setNorth( const qreal north, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0068 
0069     /**
0070      * @brief Get the southern boundary of the bounding box.
0071      * @return the latitude of the southern boundary.
0072      */
0073     qreal south( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
0074     void setSouth( const qreal south, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0075 
0076     /**
0077      * @brief Get the eastern boundary of the bounding box.
0078      * @return the longitude of the eastern boundary.
0079      */
0080     qreal east( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
0081     void setEast( const qreal east, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0082 
0083     /**
0084      * @brief Get the western boundary of the bounding box.
0085      * @return the longitude of the western boundary.
0086      */
0087     qreal west( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
0088     void setWest( const qreal west, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0089 
0090     /**
0091      * @brief Get the rotation of the bounding box.
0092      * @return the rotation of the bounding box.
0093      */
0094     qreal rotation( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
0095     void setRotation( const qreal rotation, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0096 
0097     void boundaries( qreal &north, qreal &south, qreal &east, qreal &west, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
0098     void setBoundaries( qreal north, qreal south, qreal east, qreal west, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0099 
0100     /**
0101      * @brief Changes the differences between the boundaries and the center by the given factor, keeping the center unchanged
0102      * @param verticalFactor Vertical scale factor (affects north and south boundaries)
0103      * @param horizontalFactor Horizontal scale factor (affects west and east boundaries)
0104      */
0105     void scale(qreal verticalFactor, qreal horizontalFactor) const;
0106     GeoDataLatLonBox scaled(qreal verticalFactor, qreal horizontalFactor) const;
0107 
0108     /**
0109      * @brief Get the width of the longitude interval
0110      * @return the angle covered by the longitude range.
0111      */
0112     qreal width( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
0113 
0114     /**
0115      * @brief Get the width of the longitude interval. East and west parameters are in radians.
0116      * @return the angle covered by the longitude range in given unit.
0117      */
0118     static qreal width( qreal east, qreal west, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0119 
0120     /**
0121      * @brief Get the height of the latitude interval
0122      * @return the angle covered by the latitude range.
0123      */
0124     qreal height( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
0125 
0126     /**
0127      * @brief Get the height of the latitude interval. North and south parameters are in radians.
0128      * @return the angle covered by the latitude range in given unit.
0129      */
0130     static qreal height( qreal north, qreal south, GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
0131 
0132     /**
0133      * @brief Detect whether the bounding box crosses the IDL.
0134      * @return @c true  the bounding box crosses the +/-180 deg longitude.
0135      *         @c false the bounding box doesn't cross the +/-180 deg longitude.
0136      */
0137     bool     crossesDateLine() const;
0138 
0139     /**
0140      * @brief Detect whether the bounding box crosses the IDL.
0141      * @param east radians east.
0142      * @param west radians west.
0143      * @return @c true  the bounding box crosses the +/-180 deg longitude.
0144      *         @c false the bounding box doesn't cross the +/-180 deg longitude.
0145      */
0146     static bool crossesDateLine(qreal east, qreal west);
0147 
0148     /**
0149      * @brief returns the center of this box
0150      * @return a coordinate, face-center of the box
0151      */
0152     virtual GeoDataCoordinates center() const;
0153 
0154     /**
0155      * @brief Detect whether the bounding box contains one of the poles.
0156      * @return @c true  the bounding box contains one of the poles.
0157      *         @c false the bounding box doesn't contain one of the poles.
0158      */
0159     bool containsPole( Pole pole = AnyPole ) const;
0160 
0161     virtual bool contains( const GeoDataCoordinates & ) const;
0162     bool     contains( const GeoDataLatLonBox & ) const;
0163 
0164     /**
0165      * @brief Detect whether the bounding box contains a point of given lon and lat.
0166      * @param lon longitude in radians.
0167      * @param lat latitude in radians.
0168      * @return true if the box contains given point, false otherwise
0169      */
0170     bool contains(qreal lon, qreal lat) const; //Optimized version for overlay painting
0171 
0172     virtual bool intersects( const GeoDataLatLonBox & ) const;
0173 
0174     /**
0175      * @brief Returns the bounding LatLonBox of this box with the given one.
0176      */
0177     GeoDataLatLonBox united( const GeoDataLatLonBox& other) const;
0178 
0179     /**
0180      * @return Returns the smallest bounding box that contains this LatLonBox rotated with its given angle.
0181      */
0182     GeoDataLatLonBox toCircumscribedRectangle() const;
0183 
0184     /**
0185      * @brief Create the smallest bounding box from a line string.
0186      * @return the smallest bounding box that contains the linestring.
0187      */
0188     static GeoDataLatLonBox fromLineString( const GeoDataLineString& lineString );
0189 
0190     /**
0191      * @brief Indicates whether the bounding box only contains a single 2D point ("singularity").
0192      * @return Return value is true if the height and the width of the bounding box equal zero.
0193      */
0194     virtual bool isNull() const;
0195 
0196     /**
0197      * @brief Indicates whether the bounding box is not initialised (and contains nothing).
0198      * @return Return value is true if bounding box is not initialised.
0199      */
0200     virtual bool isEmpty() const;
0201 
0202     /**
0203      * @brief Indicates whether two bounding boxes are roughly equal.
0204      *        The factor specifies the margin threshold relative to the left handside
0205      *        bounding box within which both bounding boxes are considered equal.
0206      * @return Return value is true if both bounding box are approximately equal.
0207      */
0208     static bool fuzzyCompare(const GeoDataLatLonBox& lhs,
0209                              const GeoDataLatLonBox& rhs,
0210                              const qreal factor = 0.01);
0211 
0212     /**
0213      * @brief Resets the bounding box to its uninitialised state (and thus contains nothing).
0214      */
0215     virtual void clear();
0216 
0217     GeoDataLatLonBox operator|( const GeoDataLatLonBox& other ) const;
0218 
0219     /**
0220      * @brief Unites this bounding box with the given one.
0221      * @return Returns a reference to self.
0222      */
0223     GeoDataLatLonBox& operator |=( const GeoDataLatLonBox& other) ;
0224 
0225     /// Serialize the contents of the feature to @p stream.
0226     void pack( QDataStream& stream ) const override;
0227     /// Unserialize the contents of the feature from @p stream.
0228     void unpack( QDataStream& stream ) override;
0229 
0230  private:
0231     GeoDataLatLonBoxPrivate  * const d;
0232     static const GeoDataLatLonBox empty;
0233 };
0234 
0235 }
0236 
0237 Q_DECLARE_METATYPE( Marble::GeoDataLatLonBox )
0238 
0239 #endif