23 #include <QStringList>
24 #include <QCoreApplication>
39 enum DirPosition { PrefixDir, PostfixDir };
41 static QString createDecimalPointExp();
42 static QString regExp(
const QString&
string );
43 static void getLocaleList( QStringList& localeList,
const QString& localeListString,
44 const QLatin1String& placeholder,
const QString& separator );
45 static bool isDirection(
const QString& input,
const QString&
direction);
46 static bool isDirection(
const QString& input,
const QStringList& directions);
47 static bool isOneOfDirections(
const QString& input,
48 const QString& firstDirection,
49 const QString& secondDirection,
50 bool& isFirstDirection);
51 static bool isOneOfDirections(
const QString& input,
52 const QStringList& firstDirections,
53 const QStringList& secondDirections,
54 bool& isFirstDirection);
65 static qreal degreeValueFromDMS(
const QRegExp& regex,
int c,
bool isPosHemisphere );
66 static qreal degreeValueFromDM(
const QRegExp& regex,
int c,
bool isPosHemisphere );
67 static qreal degreeValueFromD(
const QRegExp& regex,
int c,
bool isPosHemisphere );
76 bool parse(
const QString& input );
80 qreal lon()
const {
return m_lon; }
84 qreal lat()
const {
return m_lat; }
93 bool tryMatchFromDms(
const QString& input, DirPosition dirPosition );
94 bool tryMatchFromDm(
const QString& input, DirPosition dirPosition );
95 bool tryMatchFromD(
const QString& input, DirPosition dirPosition );
113 bool isCorrectDirections(
const QString& dir1,
const QString& dir2,
115 bool& isLonDirPosHemisphere,
bool& isLatDirPosHemisphere )
const;
116 bool isLocaleLonDirection(
const QString& input,
117 bool& isDirPosHemisphere )
const;
118 bool isLocaleLatDirection(
const QString& input,
119 bool& isDirPosHemisphere )
const;
120 bool isLonDirection(
const QString& input,
121 bool& isDirPosHemisphere )
const;
122 bool isLatDirection(
const QString& input,
123 bool& isDirPosHemisphere )
const;
130 const QString m_north;
131 const QString m_east;
132 const QString m_south;
133 const QString m_west;
135 const QString m_decimalPointExp;
138 QStringList m_northLocale;
139 QStringList m_eastLocale;
140 QStringList m_southLocale;
141 QStringList m_westLocale;
143 QStringList m_degreeLocale;
144 QStringList m_minutesLocale;
145 QStringList m_secondsLocale;
149 QString m_minutesExp;
150 QString m_secondsExp;
153 LonLatParser::LonLatParser()
156 , m_north( QLatin1String(
"n") )
157 , m_east( QLatin1String(
"e") )
158 , m_south( QLatin1String(
"s") )
159 , m_west( QLatin1String(
"w") )
160 , m_decimalPointExp( createDecimalPointExp() )
165 void LonLatParser::initAll()
168 if (! m_dirCapExp.isEmpty() )
171 const QLatin1String placeholder = QLatin1String(
"*");
172 const QString separator = QLatin1String(
"|");
174 getLocaleList( m_northLocale, GeoDataCoordinates::tr(
"*",
"North direction terms, see http://techbase.kde.org/Projects/Marble/GeoDataCoordinatesTranslation" ),
175 placeholder, separator );
176 getLocaleList( m_eastLocale, GeoDataCoordinates::tr(
"*",
"East direction terms, see http://techbase.kde.org/Projects/Marble/GeoDataCoordinatesTranslation" ),
177 placeholder, separator );
178 getLocaleList( m_southLocale, GeoDataCoordinates::tr(
"*",
"South direction terms, see http://techbase.kde.org/Projects/Marble/GeoDataCoordinatesTranslation" ),
179 placeholder, separator );
180 getLocaleList( m_westLocale, GeoDataCoordinates::tr(
"*",
"West direction terms, see http://techbase.kde.org/Projects/Marble/GeoDataCoordinatesTranslation" ),
181 placeholder, separator );
184 QSet<QString> dirs = QSet<QString>()
185 << m_north << m_east << m_south << m_west;
186 dirs += m_northLocale.toSet();
187 dirs += m_eastLocale.toSet();
188 dirs += m_southLocale.toSet();
189 dirs += m_westLocale.toSet();
191 QString fullNamesExp;
192 QString simpleLetters;
194 foreach(
const QString& dir, dirs ) {
196 if ((dir.length() == 1) && (QLatin1Char(
'a')<=dir.at(0)) && (dir.at(0)<=QLatin1Char(
'z'))) {
197 simpleLetters += dir;
202 fullNamesExp += regExp(dir) + QLatin1Char(
'|');
207 QLatin1Char(
'(') + fullNamesExp + QLatin1Char(
'[') + simpleLetters + QLatin1String(
"])");
210 getLocaleList( m_degreeLocale, GeoDataCoordinates::tr(
"*",
"Degree symbol terms, see http://techbase.kde.org/Projects/Marble/GeoDataCoordinatesTranslation" ),
211 placeholder, separator );
212 getLocaleList( m_minutesLocale, GeoDataCoordinates::tr(
"*",
"Minutes symbol terms, see http://techbase.kde.org/Projects/Marble/GeoDataCoordinatesTranslation" ),
213 placeholder, separator );
214 getLocaleList( m_secondsLocale, GeoDataCoordinates::tr(
"*",
"Seconds symbol terms, see http://techbase.kde.org/Projects/Marble/GeoDataCoordinatesTranslation" ),
215 placeholder, separator );
227 m_degreeExp = QLatin1String(
"\\x00B0|\\x00BA");
228 foreach(
const QString& symbol, m_degreeLocale) {
229 m_degreeExp += QLatin1Char(
'|') + regExp(symbol);
231 m_minutesExp = QLatin1String(
"'|\\x2032|\\x00B4|\\x20C2|\\x2019");
232 foreach(
const QString& symbol, m_minutesLocale) {
233 m_minutesExp += QLatin1Char(
'|') + regExp(symbol);
235 m_secondsExp = QLatin1String(
"\"|\\x2033|\\x201D|''|\\x2032\\x2032|\\x00B4\\x00B4|\\x20C2\\x20C2|\\x2019\\x2019");
236 foreach(
const QString& symbol, m_secondsLocale) {
237 m_secondsExp += QLatin1Char(
'|') + regExp(symbol);
241 bool LonLatParser::parse(
const QString&
string )
243 QString input =
string.toLower().trimmed();
247 const QString numberCapExp = QString::fromLatin1(
248 "([-+]?\\d{1,3}%1?\\d*(?:[eE][+-]?\\d+)?)(?:,|;|\\s)\\s*"
249 "([-+]?\\d{1,3}%1?\\d*(?:[eE][+-]?\\d+)?)"
250 ).arg(m_decimalPointExp);
252 const QRegExp regex = QRegExp( numberCapExp );
253 if( regex.exactMatch(input) ) {
254 m_lon = regex.cap(2).toDouble();
255 m_lat = regex.cap(1).toDouble();
263 if ( tryMatchFromD( input, PostfixDir ) ) {
267 if ( tryMatchFromD( input, PrefixDir ) ) {
271 if ( tryMatchFromDms( input, PostfixDir ) ) {
275 if ( tryMatchFromDms( input, PrefixDir ) ) {
279 if ( tryMatchFromDm( input, PostfixDir ) ) {
283 if ( tryMatchFromDm( input, PrefixDir ) ) {
291 bool LonLatParser::tryMatchFromDms(
const QString& input, DirPosition dirPosition )
294 const char *postfixCapExp =
295 "([-+]?)(\\d{1,3})(?:%3|\\s)\\s*(\\d{1,2})(?:%4|\\s)\\s*"
296 "(\\d{1,2}%1?\\d*)(?:%5)?\\s*%2[,;]?\\s*"
297 "([-+]?)(\\d{1,3})(?:%3|\\s)\\s*(\\d{1,2})(?:%4|\\s)\\s*"
298 "(\\d{1,2}%1?\\d*)(?:%5)?\\s*%2";
301 const char *prefixCapExp =
302 "%2\\s*([-+]?)(\\d{1,3})(?:%3|\\s)\\s*(\\d{1,2})(?:%4|\\s)\\s*"
303 "(\\d{1,2}%1?\\d*)(?:%5)?\\s*(?:,|;|\\s)\\s*"
304 "%2\\s*([-+]?)(\\d{1,3})(?:%3|\\s)\\s*(\\d{1,2})(?:%4|\\s)\\s*"
305 "(\\d{1,2}%1?\\d*)(?:%5)?";
307 const char *expTemplate = ( dirPosition == PostfixDir ) ? postfixCapExp
310 const QString numberCapExp =
311 QString::fromLatin1( expTemplate ).arg( m_decimalPointExp, m_dirCapExp,
312 m_degreeExp, m_minutesExp, m_secondsExp);
314 const QRegExp regex = QRegExp( numberCapExp );
315 if( !regex.exactMatch( input ) ) {
320 bool isLonDirPosHemisphere;
321 bool isLatDirPosHemisphere;
322 const QString dir1 = regex.cap( dirPosition == PostfixDir ? 5 : 1 );
323 const QString dir2 = regex.cap( dirPosition == PostfixDir ? 10 : 6 );
324 if ( !isCorrectDirections( dir1, dir2, isDir1LonDir,
325 isLonDirPosHemisphere, isLatDirPosHemisphere ) ) {
329 const int valueStartIndex1 = (dirPosition == PostfixDir ? 1 : 2);
330 const int valueStartIndex2 = (dirPosition == PostfixDir ? 6 : 7);
331 m_lon = degreeValueFromDMS( regex, isDir1LonDir ? valueStartIndex1 : valueStartIndex2,
332 isLonDirPosHemisphere );
333 m_lat = degreeValueFromDMS( regex, isDir1LonDir ? valueStartIndex2 : valueStartIndex1,
334 isLatDirPosHemisphere );
340 bool LonLatParser::tryMatchFromDm(
const QString& input, DirPosition dirPosition )
343 const char *postfixCapExp =
344 "([-+]?)(\\d{1,3})(?:%3|\\s)\\s*(\\d{1,2}%1?\\d*)(?:%4)?\\s*%2[,;]?\\s*"
345 "([-+]?)(\\d{1,3})(?:%3|\\s)\\s*(\\d{1,2}%1?\\d*)(?:%4)?\\s*%2";
348 const char *prefixCapExp =
349 "%2\\s*([-+]?)(\\d{1,3})(?:%3|\\s)\\s*(\\d{1,2}%1?\\d*)(?:%4)?\\s*(?:,|;|\\s)\\s*"
350 "%2\\s*([-+]?)(\\d{1,3})(?:%3|\\s)\\s*(\\d{1,2}%1?\\d*)(?:%4)?";
352 const char *expTemplate = ( dirPosition == PostfixDir ) ? postfixCapExp
355 const QString numberCapExp =
356 QString::fromLatin1( expTemplate ).arg( m_decimalPointExp, m_dirCapExp,
357 m_degreeExp, m_minutesExp );
358 const QRegExp regex = QRegExp( numberCapExp );
359 if( !regex.exactMatch(input) ) {
364 bool isLonDirPosHemisphere;
365 bool isLatDirPosHemisphere;
366 const QString dir1 = regex.cap( dirPosition == PostfixDir ? 4 : 1 );
367 const QString dir2 = regex.cap( dirPosition == PostfixDir ? 8 : 5 );
368 if ( !isCorrectDirections( dir1, dir2, isDir1LonDir,
369 isLonDirPosHemisphere, isLatDirPosHemisphere ) ) {
373 const int valueStartIndex1 = ( dirPosition == PostfixDir ? 1 : 2 );
374 const int valueStartIndex2 = ( dirPosition == PostfixDir ? 5 : 6 );
375 m_lon = degreeValueFromDM( regex, isDir1LonDir ? valueStartIndex1 : valueStartIndex2,
376 isLonDirPosHemisphere );
377 m_lat = degreeValueFromDM( regex, isDir1LonDir ? valueStartIndex2 : valueStartIndex1,
378 isLatDirPosHemisphere );
384 bool LonLatParser::tryMatchFromD(
const QString& input, DirPosition dirPosition )
387 const char *postfixCapExp =
388 "([-+]?\\d{1,3}%1?\\d*)(?:%3)?(?:\\s*)%2(?:,|;|\\s)\\s*"
389 "([-+]?\\d{1,3}%1?\\d*)(?:%3)?(?:\\s*)%2";
392 const char *prefixCapExp =
393 "%2\\s*([-+]?\\d{1,3}%1?\\d*)(?:%3)?\\s*(?:,|;|\\s)\\s*"
394 "%2\\s*([-+]?\\d{1,3}%1?\\d*)(?:%3)?";
396 const char *expTemplate = ( dirPosition == PostfixDir ) ? postfixCapExp
399 const QString numberCapExp =
400 QString::fromLatin1( expTemplate ).arg( m_decimalPointExp, m_dirCapExp, m_degreeExp );
401 const QRegExp regex = QRegExp( numberCapExp );
402 if( !regex.exactMatch( input ) ) {
407 bool isLonDirPosHemisphere;
408 bool isLatDirPosHemisphere;
409 const QString dir1 = regex.cap( dirPosition == PostfixDir ? 2 : 1 );
410 const QString dir2 = regex.cap( dirPosition == PostfixDir ? 4 : 3 );
411 if ( !isCorrectDirections( dir1, dir2, isDir1LonDir,
412 isLonDirPosHemisphere, isLatDirPosHemisphere ) ) {
416 const int valueStartIndex1 = ( dirPosition == PostfixDir ? 1 : 2 );
417 const int valueStartIndex2 = ( dirPosition == PostfixDir ? 3 : 4 );
418 m_lon = degreeValueFromD( regex, isDir1LonDir ? valueStartIndex1 : valueStartIndex2,
419 isLonDirPosHemisphere );
420 m_lat = degreeValueFromD( regex, isDir1LonDir ? valueStartIndex2 : valueStartIndex1,
421 isLatDirPosHemisphere );
426 QString LonLatParser::createDecimalPointExp()
428 const QChar decimalPoint = QLocale::system().decimalPoint();
430 return (decimalPoint == QLatin1Char(
'.')) ? QString::fromLatin1(
"\\.") :
431 QLatin1String(
"[.") + decimalPoint + QLatin1Char(
']');
434 QString LonLatParser::regExp(
const QString&
string)
437 for (
int i = 0; i <
string.length(); ++i) {
438 const QChar c =
string.at(i);
439 if ((QLatin1Char(
'a') <= c) && (c <= QLatin1Char(
'z'))) {
441 }
else if (c.isSpace()) {
442 result += QLatin1String(
"\\s");
443 }
else if (c == QLatin1Char(
'.')) {
444 result += QLatin1String(
"\\.");
446 result += QString::fromLatin1(
"\\x%1").arg(c.unicode(), 4, 16, QLatin1Char(
'0'));
452 void LonLatParser::getLocaleList( QStringList& localeList,
const QString& localeListString,
453 const QLatin1String& placeholder,
const QString& separator )
455 const QString lowerLocaleListString = localeListString.toLower();
456 if (lowerLocaleListString != placeholder) {
457 localeList = lowerLocaleListString.split(separator, QString::SkipEmptyParts);
461 bool LonLatParser::isDirection(
const QString& input,
const QStringList& directions )
463 return ( directions.contains(input) );
466 bool LonLatParser::isDirection(
const QString& input,
const QString&
direction )
468 return ( input == direction );
471 bool LonLatParser::isOneOfDirections(
const QString& input,
472 const QString& firstDirection,
473 const QString& secondDirection,
474 bool& isFirstDirection )
476 isFirstDirection = isDirection(input, firstDirection);
477 return isFirstDirection || isDirection(input, secondDirection);
480 bool LonLatParser::isOneOfDirections(
const QString& input,
481 const QStringList& firstDirections,
482 const QStringList& secondDirections,
483 bool& isFirstDirection )
485 isFirstDirection = isDirection(input, firstDirections);
486 return isFirstDirection || isDirection(input, secondDirections);
490 bool LonLatParser::isLocaleLonDirection(
const QString& input,
491 bool& isDirPosHemisphere )
const
493 return isOneOfDirections(input, m_eastLocale, m_westLocale, isDirPosHemisphere);
496 bool LonLatParser::isLocaleLatDirection(
const QString& input,
497 bool& isDirPosHemisphere )
const
499 return isOneOfDirections(input, m_northLocale, m_southLocale, isDirPosHemisphere);
502 bool LonLatParser::isLonDirection(
const QString& input,
503 bool& isDirPosHemisphere )
const
505 return isOneOfDirections(input, m_east, m_west, isDirPosHemisphere);
508 bool LonLatParser::isLatDirection(
const QString& input,
509 bool& isDirPosHemisphere )
const
511 return isOneOfDirections(input, m_north, m_south, isDirPosHemisphere);
515 qreal LonLatParser::degreeValueFromDMS(
const QRegExp& regex,
int c,
bool isPosHemisphere )
517 const bool isNegativeValue = (regex.cap( c++ ) == QLatin1String(
"-"));
518 const uint degree = regex.cap( c++ ).toUInt();
519 const uint minutes = regex.cap( c++ ).toUInt();
520 const qreal seconds = regex.cap( c ).toDouble();
526 if (! isPosHemisphere)
532 qreal LonLatParser::degreeValueFromDM(
const QRegExp& regex,
int c,
bool isPosHemisphere )
534 const bool isNegativeValue = (regex.cap( c++ ) == QLatin1String(
"-"));
535 const uint degree = regex.cap( c++ ).toUInt();
536 const qreal minutes = regex.cap( c ).toDouble();
538 qreal result = degree + (minutes*
MIN2HOUR);
542 if (! isPosHemisphere)
548 qreal LonLatParser::degreeValueFromD(
const QRegExp& regex,
int c,
bool isPosHemisphere )
550 qreal result = regex.cap( c ).toDouble();
552 if (! isPosHemisphere)
558 bool LonLatParser::isCorrectDirections(
const QString& dir1,
const QString& dir2,
560 bool& isLonDirPosHemisphere,
561 bool& isLatDirPosHemisphere)
const
564 isDir1LonDir = isLocaleLonDirection(dir1, isLonDirPosHemisphere);
565 const bool resultLocale = isDir1LonDir ?
566 isLocaleLatDirection(dir2, isLatDirPosHemisphere) :
567 (isLocaleLatDirection(dir1, isLatDirPosHemisphere) &&
568 isLocaleLonDirection(dir2, isLonDirPosHemisphere));
574 isDir1LonDir = isLonDirection(dir1, isLonDirPosHemisphere);
575 return isDir1LonDir ?
576 isLatDirection(dir2, isLatDirPosHemisphere) :
577 (isLatDirection(dir1, isLatDirPosHemisphere) &&
578 isLonDirection(dir2, isLonDirPosHemisphere));
585 const GeoDataCoordinates GeoDataCoordinates::null = GeoDataCoordinates( 0, 0, 0 );
638 #if QT_VERSION < 0x050000
641 if(
d->
ref.load() == 1)
772 s_notation = notation;
786 if ( lon > halfCircle ) {
787 int cycles = (int)( ( lon + halfCircle ) / ( 2 * halfCircle ) );
788 return lon - ( cycles * 2 * halfCircle );
790 if ( lon < -halfCircle ) {
791 int cycles = (int)( ( lon - halfCircle ) / ( 2 * halfCircle ) );
792 return lon - ( cycles * 2 * halfCircle );
809 if ( lat > ( halfCircle / 2.0 ) ) {
810 int cycles = (int)( ( lat + halfCircle ) / ( 2 * halfCircle ) );
813 temp = halfCircle - lat;
815 temp = lat - ( cycles * 2 * halfCircle );
817 if ( temp > ( halfCircle / 2.0 ) ) {
818 return ( halfCircle - temp );
820 if ( temp < ( -halfCircle / 2.0 ) ) {
821 return ( -halfCircle - temp );
825 if ( lat < ( -halfCircle / 2.0 ) ) {
826 int cycles = (int)( ( lat - halfCircle ) / ( 2 * halfCircle ) );
829 temp = -halfCircle - lat;
831 temp = lat - ( cycles * 2 * halfCircle );
833 if ( temp > ( +halfCircle / 2.0 ) ) {
834 return ( +halfCircle - temp );
836 if ( temp < ( -halfCircle / 2.0 ) ) {
837 return ( -halfCircle - temp );
855 if ( lon > +halfCircle ) {
856 int cycles = (int)( ( lon + halfCircle ) / ( 2 * halfCircle ) );
857 lon = lon - ( cycles * 2 * halfCircle );
859 if ( lon < -halfCircle ) {
860 int cycles = (int)( ( lon - halfCircle ) / ( 2 * halfCircle ) );
861 lon = lon - ( cycles * 2 * halfCircle );
864 if ( lat > ( +halfCircle / 2.0 ) ) {
865 int cycles = (int)( ( lat + halfCircle ) / ( 2 * halfCircle ) );
868 temp = halfCircle - lat;
870 temp = lat - ( cycles * 2 * halfCircle );
872 if ( temp > ( +halfCircle / 2.0 ) ) {
873 lat = +halfCircle - temp;
875 if ( temp < ( -halfCircle / 2.0 ) ) {
876 lat = -halfCircle - temp;
880 lon = -halfCircle + lon;
882 lon = halfCircle + lon;
885 if ( lat < ( -halfCircle / 2.0 ) ) {
886 int cycles = (int)( ( lat - halfCircle ) / ( 2 * halfCircle ) );
889 temp = -halfCircle - lat;
891 temp = lat - ( cycles * 2 * halfCircle );
893 if ( temp > ( +halfCircle / 2.0 ) ) {
894 lat = +halfCircle - temp;
896 if ( temp < ( -halfCircle / 2.0 ) ) {
897 lat = -halfCircle - temp;
901 lon = -halfCircle + lon;
903 lon = halfCircle + lon;
912 successful = parser.parse(
string);
938 if ( notation ==
UTM ) {
939 int zoneNumber =
static_cast<int>( lon / 6.0 ) + 30;
940 return QString::number( zoneNumber );
943 QString weString = ( lon < 0 ) ? tr(
"W") : tr(
"E");
947 qreal lonDegF = ( unit ==
Degree ) ? fabs( lon ) : fabs( (qreal)(lon) *
RAD2DEG );
950 precision = ( precision < 0 ) ? 5 : precision;
952 if ( notation ==
DMS || notation ==
DM ) {
953 int lonDeg = (int) lonDegF;
954 qreal lonMinF = 60 * (lonDegF - lonDeg);
955 int lonMin = (int) lonMinF;
956 qreal lonSecF = 60 * (lonMinF - lonMin);
957 int lonSec = (int) lonSecF;
960 if ( precision == 0 ) {
961 lonDeg = qRound( lonDegF );
962 }
else if ( precision <= 2 ) {
963 lonMin = qRound( lonMinF );
964 }
else if ( precision <= 4 && notation ==
DMS ) {
965 lonSec = qRound( lonSecF );
967 if ( notation ==
DMS ) {
968 lonSec = lonSecF = qRound( lonSecF * qPow( 10, precision - 4 ) ) / qPow( 10, precision - 4 );
971 lonMin = lonMinF = qRound( lonMinF * qPow( 10, precision - 2 ) ) / qPow( 10, precision - 2 );
975 if (lonSec > 59 && notation ==
DMS ) {
976 lonSec = lonSecF = 0;
977 lonMin = lonMinF = lonMinF + 1;
980 lonMin = lonMinF = 0;
981 lonDeg = lonDegF = lonDegF + 1;
985 lonString = QString::fromUtf8(
"%1\xc2\xb0").arg(lonDeg, 3, 10, QChar(
' ') );
987 if ( precision == 0 ) {
988 return lonString + weString;
991 if ( notation ==
DMS || precision < 3 ) {
992 lonString += QString(
" %2\'").arg(lonMin, 2, 10, QChar(
'0') );
995 if ( precision < 3 ) {
996 return lonString + weString;
999 if ( notation ==
DMS ) {
1001 if ( precision < 5 ) {
1002 lonString += QString(
" %3\"").arg(lonSec, 2,
'f', 0, QChar(
'0') );
1003 return lonString + weString;
1006 lonString += QString(
" %L3\"").arg(lonSecF, precision - 1,
'f', precision - 4, QChar(
'0') );
1009 lonString += QString(
" %L3'").arg(lonMinF, precision + 1,
'f', precision - 2, QChar(
'0') );
1014 lonString = QString::fromUtf8(
"%L1\xc2\xb0").arg(lonDegF, 4 + precision, format, precision, QChar(
' ') );
1022 qreal lonHourF = ( unit ==
Degree ) ? fabs( lon/15.0 ) : fabs( (qreal)(lon/15.0) * RAD2DEG );
1023 int lonHour = (int) lonHourF;
1024 qreal lonMinF = 60 * (lonHourF - lonHour);
1025 int lonMin = (int) lonMinF;
1026 qreal lonSecF = 60 * (lonMinF - lonMin);
1027 int lonSec = (int) lonSecF;
1030 if ( precision == 0 ) {
1031 lonHour = qRound( lonHourF );
1032 }
else if ( precision <= 2 ) {
1033 lonMin = qRound( lonMinF );
1034 }
else if ( precision <= 4 ) {
1035 lonSec = qRound( lonSecF );
1037 lonSec = lonSecF = qRound( lonSecF * qPow( 10, precision - 4 ) ) / qPow( 10, precision - 4 );
1041 lonSec = lonSecF = 0;
1042 lonMin = lonMinF = lonMinF + 1;
1045 lonMin = lonMinF = 0;
1046 lonHour = lonHourF = lonHourF + 1;
1050 lonString = QString::fromUtf8(
"%1h").arg(lonHour, 3, 10, QChar(
' ') );
1052 if ( precision == 0 ) {
1056 lonString += QString(
" %2\'").arg(lonMin, 2, 10, QChar(
'0') );
1058 if ( precision < 3 ) {
1063 if ( precision < 5 ) {
1064 lonString += QString(
" %3\"").arg(lonSec, 2,
'f', 0, QChar(
'0') );
1068 lonString += QString(
" %L3\"").arg(lonSecF, precision - 1,
'f', precision - 4, QChar(
'0') );
1072 return lonString + weString;
1085 if ( notation ==
UTM ) {
1086 int bandLetterIndex =
static_cast<int>( lat / 8.0 ) + 10;
1087 return QString(
"CDEFGHJKLMNPQRSTUVWX???" ).at( bandLetterIndex );
1094 pmString = ( lat > 0 ) ?
"+" :
"-";
1097 nsString = ( lat > 0 ) ? tr(
"N") : tr(
"S");
1102 qreal latDegF = ( unit ==
Degree ) ? fabs( lat ) : fabs( (qreal)(lat) *
RAD2DEG );
1105 precision = ( precision < 0 ) ? 5 : precision;
1107 if ( notation ==
DMS || notation ==
DM || notation ==
Astro) {
1108 int latDeg = (int) latDegF;
1109 qreal latMinF = 60 * (latDegF - latDeg);
1110 int latMin = (int) latMinF;
1111 qreal latSecF = 60 * (latMinF - latMin);
1112 int latSec = (int) latSecF;
1115 if ( precision == 0 ) {
1116 latDeg = qRound( latDegF );
1117 }
else if ( precision <= 2 ) {
1118 latMin = qRound( latMinF );
1119 }
else if ( precision <= 4 && notation ==
DMS ) {
1120 latSec = qRound( latSecF );
1122 if ( notation ==
DMS || notation ==
Astro ) {
1123 latSec = latSecF = qRound( latSecF * qPow( 10, precision - 4 ) ) / qPow( 10, precision - 4 );
1126 latMin = latMinF = qRound( latMinF * qPow( 10, precision - 2 ) ) / qPow( 10, precision - 2 );
1130 if (latSec > 59 && ( notation ==
DMS || notation ==
Astro )) {
1133 latMin = latMin + 1;
1138 latDeg = latDeg + 1;
1142 latString = QString::fromUtf8(
"%1\xc2\xb0").arg(latDeg, 3, 10, QChar(
' ') );
1144 if ( precision == 0 ) {
1145 return pmString + latString + nsString;
1148 if ( notation ==
DMS || notation ==
Astro || precision < 3 ) {
1149 latString += QString(
" %2\'").arg(latMin, 2, 10, QChar(
'0') );
1152 if ( precision < 3 ) {
1153 return pmString + latString + nsString;
1156 if ( notation ==
DMS || notation ==
Astro ) {
1158 if ( precision < 5 ) {
1159 latString += QString(
" %3\"").arg(latSec, 2,
'f', 0, QChar(
'0') );
1160 return latString + nsString;
1163 latString += QString(
" %L3\"").arg(latSecF, precision - 1,
'f', precision - 4, QChar(
'0') );
1166 latString += QString(
" %L3'").arg(latMinF, precision + 1,
'f', precision - 2, QChar(
'0') );
1171 latString = QString::fromUtf8(
"%L1\xc2\xb0").arg(latDegF, 4 + precision, format, precision, QChar(
' ') );
1173 return pmString + latString + nsString;
1183 return *
d == *rhs.
d;
1188 return *
d != *rhs.
d;
1216 double const offset = unit ==
Degree ? 180.0 :
M_PI;
1221 double const bearing = atan2( sin ( delta ) * cos ( other.
d->
m_lat ),
1236 if ( fabs( (qreal) 2.0 *
d->
m_lat ) <
M_PI ) {
1240 if ( fabs( (qreal) 2.0 *
d->
m_lat ) ==
M_PI ) {
1260 mDebug() <<
"GeoDataCoordinates not normalized!";
1289 qAtomicAssign(
d, other.
d);
Unit
enum used constructor to specify the units used
virtual bool operator==(const GeoDataCoordinates &) const
virtual void unpack(QDataStream &stream)
Unserialize the contents of the feature from stream.
A 3d point representation.
int detail() const
return the detail flag detail range: 0 for most important points, 5 for least important ...
GeoDataCoordinatesPrivate * d
void setAltitude(const qreal altitude)
set the altitude of the Point in meters
static qreal normalizeLon(qreal lon, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize the longitude to always be -M_PI <= lon <= +M_PI (Radian).
virtual ~GeoDataCoordinates()
GeoDataCoordinates()
constructs an invalid instance
"Decimal" notation (base-10)
qreal latitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
void setDetail(const int det)
set the detail flag
BearingType
The BearingType enum specifies where to measure the bearing along great circle arcs.
qreal altitude() const
return the altitude of the Point in meters
void geoCoordinates(qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
use this function to get the longitude and latitude with one call - use the unit parameter to switch ...
qreal bearing(const GeoDataCoordinates &other, Unit unit=Radian, BearingType type=InitialBearing) const
Returns the bearing (true bearing, the angle between the line defined by this point and the other and...
static qreal normalizeLat(qreal lat, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize latitude to always be in -M_PI / 2.
static void normalizeLonLat(qreal &lon, qreal &lat, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize both longitude and latitude at the same time This method normalizes both latitude and longi...
void set(qreal lon, qreal lat, qreal alt=0, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
(re)set the coordinates in a GeoDataCoordinates object
QString latToString() const
return a string representation of latitude of the coordinate convenience function that uses the defau...
virtual bool operator!=(const GeoDataCoordinates &) const
QString lonToString() const
return a string representation of longitude of the coordinate convenience function that uses the defa...
qreal longitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
void setLatitude(qreal lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
set the longitude in a GeoDataCoordinates object
void setLongitude(qreal lon, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
set the longitude in a GeoDataCoordinates object
Notation
enum used to specify the notation / numerical system
bool isPole(Pole=AnyPole) const
return whether our coordinates represent a pole This method can be used to check whether the coordina...
QString toString() const
return a string representation of the coordinate this is a convenience function which uses the defaul...
static void setDefaultNotation(GeoDataCoordinates::Notation notation)
set the Notation of the string representation
static GeoDataCoordinates fromString(const QString &string, bool &successful)
try to parse the string into a coordinate pair
bool isValid() const
Returns.
"Sexagesimal DMS" notation (base-60)
static GeoDataCoordinates::Notation defaultNotation()
return Notation of string representation
"Sexagesimal DM" notation (base-60)
QDebug mDebug()
a function to replace qDebug() in Marble library code
< "RA and DEC" notation (used for astronomical sky coordinates)
static Quaternion fromSpherical(qreal lon, qreal lat)
used to generate Quaternion from longitude and latitude
const Quaternion & quaternion() const
return a Quaternion with the used coordinates
virtual void pack(QDataStream &stream) const
Serialize the contents of the feature to stream.
GeoDataCoordinates & operator=(const GeoDataCoordinates &other)