File indexing completed on 2024-05-12 03:50:10
0001 // SPDX-License-Identifier: LGPL-2.1-or-later 0002 // 0003 // SPDX-FileCopyrightText: 2008 Patrick Spendrin <ps_ml@gmx.de> 0004 // 0005 0006 #ifndef MARBLE_GEODATACOORDINATES_P_H 0007 #define MARBLE_GEODATACOORDINATES_P_H 0008 0009 #include "Quaternion.h" 0010 #include <QAtomicInt> 0011 0012 namespace Marble 0013 { 0014 0015 class GeoDataCoordinatesPrivate 0016 { 0017 public: 0018 /* 0019 * if this ctor is called there exists exactly one GeoDataCoordinates object 0020 * with this data. 0021 * changes will be made in the GeoDataCoordinates class 0022 * ref must be called ref as qAtomicAssign used in GeoDataCoordinates::operator= 0023 * needs this name. Maybe we can rename it to our scheme later on. 0024 */ 0025 GeoDataCoordinatesPrivate() 0026 : m_q( nullptr ), 0027 m_lon( 0 ), 0028 m_lat( 0 ), 0029 m_altitude( 0 ), 0030 m_detail( 0 ), 0031 ref( 0 ) 0032 { 0033 } 0034 0035 /* 0036 * if this ctor is called there exists exactly one GeoDataCoordinates object 0037 * with this data. 0038 * changes will be made in the GeoDataCoordinates class 0039 * ref must be called ref as qAtomicAssign used in GeoDataCoordinates::operator= 0040 * needs this name. Maybe we can rename it to our scheme later on. 0041 */ 0042 GeoDataCoordinatesPrivate( qreal _lon, qreal _lat, qreal _alt, 0043 GeoDataCoordinates::Unit unit, 0044 int _detail ) 0045 : m_q( nullptr ), 0046 m_altitude( _alt ), 0047 m_detail( _detail ), 0048 ref( 0 ) 0049 { 0050 switch( unit ){ 0051 default: 0052 case GeoDataCoordinates::Radian: 0053 m_lon = _lon; 0054 m_lat = _lat; 0055 break; 0056 case GeoDataCoordinates::Degree: 0057 m_lon = _lon * DEG2RAD; 0058 m_lat = _lat * DEG2RAD; 0059 break; 0060 } 0061 } 0062 0063 /* 0064 * this constructor is needed as Quaternion doesn't define a copy ctor 0065 * initialize the reference with the value of the other 0066 */ 0067 GeoDataCoordinatesPrivate( const GeoDataCoordinatesPrivate &other ) 0068 : m_q( nullptr ), 0069 m_lon( other.m_lon ), 0070 m_lat( other.m_lat ), 0071 m_altitude( other.m_altitude ), 0072 m_detail( other.m_detail ), 0073 ref( 0 ) 0074 { 0075 } 0076 0077 /* 0078 * return this instead of &other 0079 */ 0080 GeoDataCoordinatesPrivate& operator=( const GeoDataCoordinatesPrivate &other ) 0081 { 0082 m_lon = other.m_lon; 0083 m_lat = other.m_lat; 0084 m_altitude = other.m_altitude; 0085 m_detail = other.m_detail; 0086 ref = 0; 0087 delete m_q; 0088 m_q = nullptr; 0089 return *this; 0090 } 0091 0092 bool operator==( const GeoDataCoordinatesPrivate &rhs ) const; 0093 bool operator!=( const GeoDataCoordinatesPrivate &rhs ) const; 0094 0095 static Quaternion basePoint( const Quaternion &q1, const Quaternion &q2, const Quaternion &q3 ); 0096 0097 // Helper functions for UTM-related development. 0098 // Based on Chuck Taylor work: 0099 // http://home.hiwaay.net/~taylorc/toolbox/geography/geoutm.html 0100 0101 /** 0102 * Computes the ellipsoidal distance from the equator to a point at a 0103 * given latitude. 0104 * 0105 * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J., 0106 * GPS: Theory and Practice, 3rd ed. New York: Springer-Verlag Wien, 1994. 0107 * 0108 * @param phi Latitude of the point, in radians. 0109 * @return The ellipsoidal distance of the point from the equator, in meters. 0110 */ 0111 static qreal arcLengthOfMeridian( qreal phi ); 0112 0113 /** 0114 * Determines the central meridian for the given UTM zone. 0115 * 0116 * @param zone An integer value designating the UTM zone, range [1,60]. 0117 * @return The central meridian for the given UTM zone, in radians, or zero 0118 * if the UTM zone parameter is outside the range [1,60]. 0119 * Range of the central meridian is the radian equivalent of [-177,+177]. 0120 */ 0121 static qreal centralMeridianUTM( qreal zone ); 0122 0123 0124 /** 0125 * Computes the footpoint latitude for use in converting transverse 0126 * Mercator coordinates to ellipsoidal coordinates. 0127 * 0128 * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J., 0129 * GPS: Theory and Practice, 3rd ed. New York: Springer-Verlag Wien, 1994. 0130 * 0131 * @param northing The UTM northing coordinate, in meters. 0132 * @return The footpoint latitude, in radians. 0133 */ 0134 static qreal footpointLatitude( qreal northing ); 0135 0136 /** 0137 * Converts a latitude/longitude pair to x and y coordinates in the 0138 * Transverse Mercator projection. Note that Transverse Mercator is not 0139 * the same as UTM; a scale factor is required to convert between them. 0140 * 0141 * Reference: Hoffmann-Wellenhof, B., Lichtenegger, H., and Collins, J., 0142 * GPS: Theory and Practice, 3rd ed. New York: Springer-Verlag Wien, 1994. 0143 * 0144 * @param lambda Longitude of the point, in radians. 0145 * @param phi Latitude of the point, in radians. 0146 * @param lambda0 Longitude of the central meridian to be used, in radians. 0147 * @return The computed point with its x and y coordinates 0148 */ 0149 static QPointF mapLonLatToXY( qreal lambda, qreal phi, qreal lambda0 ); 0150 0151 /** 0152 * Converts a latitude/longitude pair to x and y coordinates in the 0153 * Universal Transverse Mercator projection. 0154 * 0155 * @param lon Longitude of the point, in radians. 0156 * @param lat Latitude of the point, in radians. 0157 * @param zone UTM zone between 1 and 60 to be used for calculating 0158 * values for x and y. 0159 * @return A point with its x and y coordinates representing 0160 * easting and northing of the UTM coordinates computed. 0161 */ 0162 static QPointF lonLatToUTMXY( qreal lon, qreal lat, qreal zone ); 0163 0164 /** 0165 * @brief retrieves the UTM latitude band of a longitude/latitude 0166 * pair 0167 * @param lon longitude, in radians 0168 * @param lat latitude, in radians 0169 * @return latitude band 0170 */ 0171 static QString lonLatToLatitudeBand( qreal lon, qreal lat ); 0172 0173 /** 0174 * @brief retrieves the northing value of a longitude/latitude 0175 * pair 0176 * @param lon longitude, in radians 0177 * @param lat latitude, in radians 0178 * @return UTM northing value 0179 */ 0180 static qreal lonLatToNorthing( qreal lon, qreal lat ); 0181 0182 /** 0183 * @brief retrieves the UTM zone number of a longitude/latitude 0184 * pair 0185 * @param lon longitude, in radians 0186 * @param lat latitude, in radians 0187 * @return UTM zone number 0188 */ 0189 static int lonLatToZone( qreal lon, qreal lat ); 0190 0191 /** 0192 * @brief retrieves the easting value of a longitude/latitude 0193 * pair 0194 * @param lon longitude, in radians 0195 * @param lat latitude, in radians 0196 * @return UTM easting value 0197 */ 0198 static qreal lonLatToEasting( qreal lon, qreal lat ); 0199 0200 Quaternion * m_q; 0201 qreal m_lon; 0202 qreal m_lat; 0203 qreal m_altitude; // in meters above sea level 0204 quint8 m_detail; 0205 QAtomicInt ref; 0206 0207 /* UTM Ellipsoid model constants (actual values here are for WGS84) */ 0208 static const qreal sm_semiMajorAxis; 0209 static const qreal sm_semiMinorAxis; 0210 static const qreal sm_eccentricitySquared; 0211 static const qreal sm_utmScaleFactor; 0212 0213 }; 0214 0215 inline bool GeoDataCoordinatesPrivate::operator==( const GeoDataCoordinatesPrivate &rhs ) const 0216 { 0217 // do not compare the m_detail member as it does not really belong to 0218 // GeoDataCoordinates and should be removed 0219 return m_lon == rhs.m_lon && m_lat == rhs.m_lat && m_altitude == rhs.m_altitude; 0220 } 0221 0222 inline bool GeoDataCoordinatesPrivate::operator!=( const GeoDataCoordinatesPrivate &rhs ) const 0223 { 0224 // do not compare the m_detail member as it does not really belong to 0225 // GeoDataCoordinates and should be removed 0226 return ! (*this == rhs); 0227 } 0228 0229 } 0230 0231 #endif