• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdeedu API Reference
  • KDE Home
  • Contact Us
 

marble

  • sources
  • kde-4.12
  • kdeedu
  • marble
  • src
  • lib
  • marble
  • geodata
  • data
GeoDataCoordinates.cpp
Go to the documentation of this file.
1 //
2 // This file is part of the Marble Virtual Globe.
3 //
4 // This program is free software licensed under the GNU LGPL. You can
5 // find a copy of this license in LICENSE.txt in the top directory of
6 // the source code.
7 //
8 // Copyright 2004-2007 Torsten Rahn <tackat@kde.org>
9 // Copyright 2007-2008 Inge Wallin <ingwa@kde.org>
10 // Copyright 2008 Patrick Spendrin <ps_ml@gmx.de>
11 // Copyright 2011 Friedrich W. H. Kossebau <kossebau@kde.org>
12 // Copyright 2011 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
13 //
14 
15 
16 #include "GeoDataCoordinates.h"
17 #include "GeoDataCoordinates_p.h"
18 
19 #include <qmath.h>
20 #include <QRegExp>
21 #include <QLocale>
22 #include <QString>
23 #include <QStringList>
24 #include <QCoreApplication>
25 #include <QAtomicInt>
26 
27 #include "MarbleGlobal.h"
28 #include "MarbleDebug.h"
29 
30 #include "Quaternion.h"
31 
32 namespace Marble
33 {
34 
35 // Helper class for GeoDataCoordinates::fromString(...)
36 class LonLatParser
37 {
38 private:
39  enum DirPosition { PrefixDir, PostfixDir };
40 
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);
55 
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 );
68 
69 public:
70  LonLatParser();
76  bool parse( const QString& input );
80  qreal lon() const { return m_lon; }
84  qreal lat() const { return m_lat; }
85 
86 private:
93  bool tryMatchFromDms( const QString& input, DirPosition dirPosition );
94  bool tryMatchFromDm( const QString& input, DirPosition dirPosition );
95  bool tryMatchFromD( const QString& input, DirPosition dirPosition );
96 
100  void initAll();
113  bool isCorrectDirections( const QString& dir1, const QString& dir2,
114  bool& isDir1LonDir,
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;
124 
125 private:
126  qreal m_lon;
127  qreal m_lat;
128 
129 private: // helper values
130  const QString m_north;
131  const QString m_east;
132  const QString m_south;
133  const QString m_west;
134 
135  const QString m_decimalPointExp;
136 
137 private: // helper value, lazily set, in initAll();
138  QStringList m_northLocale;
139  QStringList m_eastLocale;
140  QStringList m_southLocale;
141  QStringList m_westLocale;
142 
143  QStringList m_degreeLocale;
144  QStringList m_minutesLocale;
145  QStringList m_secondsLocale;
146 
147  QString m_dirCapExp;
148  QString m_degreeExp;
149  QString m_minutesExp;
150  QString m_secondsExp;
151 };
152 
153 LonLatParser::LonLatParser()
154  : m_lon( 0.0 )
155  , m_lat( 0.0 )
156  , m_north( QLatin1String("n") )
157  , m_east( QLatin1String("e") )
158  , m_south( QLatin1String("s") )
159  , m_west( QLatin1String("w") )
160  , m_decimalPointExp( createDecimalPointExp() )
161 {
162 }
163 
164 
165 void LonLatParser::initAll()
166 {
167  // already all initialized?
168  if (! m_dirCapExp.isEmpty() )
169  return;
170 
171  const QLatin1String placeholder = QLatin1String("*");
172  const QString separator = QLatin1String("|");
173 
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 );
182 
183  // use a set to remove duplicates
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();
190 
191  QString fullNamesExp;
192  QString simpleLetters;
193 
194  foreach( const QString& dir, dirs ) {
195  // collect simple letters
196  if ((dir.length() == 1) && (QLatin1Char('a')<=dir.at(0)) && (dir.at(0)<=QLatin1Char('z'))) {
197  simpleLetters += dir;
198  continue;
199  }
200 
201  // okay to add '|' also for last, separates from firstLetters
202  fullNamesExp += regExp(dir) + QLatin1Char('|');
203  }
204 
205  // Sets "(north|east|south|west|[nesw])" in en, as translated names match untranslated ones
206  m_dirCapExp =
207  QLatin1Char('(') + fullNamesExp + QLatin1Char('[') + simpleLetters + QLatin1String("])");
208 
209  // expressions for symbols of degree, minutes and seconds
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 );
216 
217  // Used unicode regexp expressions:
218  // x00B0: ° DEGREE SIGN
219  // x00BA: º MASCULINE ORDINAL INDICATOR (found used as degree sign)
220  // x2032: ′ PRIME (minutes)
221  // x00B4: ´ ACUTE ACCENT (found as minutes sign)
222  // x02CA: ˊ MODIFIER LETTER ACUTE ACCENT
223  // x2019: ’ RIGHT SINGLE QUOTATION MARK
224  // x2033: ″ DOUBLE PRIME (seconds)
225  // x201D: ” RIGHT DOUBLE QUOTATION MARK
226 
227  m_degreeExp = QLatin1String("\\x00B0|\\x00BA");
228  foreach(const QString& symbol, m_degreeLocale) {
229  m_degreeExp += QLatin1Char('|') + regExp(symbol);
230  }
231  m_minutesExp = QLatin1String("'|\\x2032|\\x00B4|\\x20C2|\\x2019");
232  foreach(const QString& symbol, m_minutesLocale) {
233  m_minutesExp += QLatin1Char('|') + regExp(symbol);
234  }
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);
238  }
239 }
240 
241 bool LonLatParser::parse( const QString& string )
242 {
243  QString input = string.toLower().trimmed();
244 
245  // #1: Just two numbers, no directions, e.g. 74.2245 -32.2434 (assumes lat lon)
246  {
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);
251 
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();
256 
257  return true;
258  }
259  }
260 
261  initAll();
262 
263  if ( tryMatchFromD( input, PostfixDir ) ) {
264  return true;
265  }
266 
267  if ( tryMatchFromD( input, PrefixDir ) ) {
268  return true;
269  }
270 
271  if ( tryMatchFromDms( input, PostfixDir ) ) {
272  return true;
273  }
274 
275  if ( tryMatchFromDms( input, PrefixDir ) ) {
276  return true;
277  }
278 
279  if ( tryMatchFromDm( input, PostfixDir ) ) {
280  return true;
281  }
282 
283  if ( tryMatchFromDm( input, PrefixDir ) ) {
284  return true;
285  }
286 
287  return false;
288 }
289 
290 // #3: Sexagesimal
291 bool LonLatParser::tryMatchFromDms( const QString& input, DirPosition dirPosition )
292 {
293  // direction as postfix
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";
299 
300  // direction as prefix
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)?";
306 
307  const char *expTemplate = ( dirPosition == PostfixDir ) ? postfixCapExp
308  : prefixCapExp;
309 
310  const QString numberCapExp =
311  QString::fromLatin1( expTemplate ).arg( m_decimalPointExp, m_dirCapExp,
312  m_degreeExp, m_minutesExp, m_secondsExp);
313 
314  const QRegExp regex = QRegExp( numberCapExp );
315  if( !regex.exactMatch( input ) ) {
316  return false;
317  }
318 
319  bool isDir1LonDir;
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 ) ) {
326  return false;
327  }
328 
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 );
335 
336  return true;
337 }
338 
339 // #4: Sexagesimal with minute precision
340 bool LonLatParser::tryMatchFromDm( const QString& input, DirPosition dirPosition )
341 {
342  // direction as postfix
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";
346 
347  // direction as prefix
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)?";
351 
352  const char *expTemplate = ( dirPosition == PostfixDir ) ? postfixCapExp
353  : prefixCapExp;
354 
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) ) {
360  return false;
361  }
362 
363  bool isDir1LonDir;
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 ) ) {
370  return false;
371  }
372 
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 );
379 
380  return true;
381 }
382 
383 // #2: Two numbers with directions
384 bool LonLatParser::tryMatchFromD( const QString& input, DirPosition dirPosition )
385 {
386  // direction as postfix, e.g. 74.2245 N 32.2434 W
387  const char *postfixCapExp =
388  "([-+]?\\d{1,3}%1?\\d*)(?:%3)?(?:\\s*)%2(?:,|;|\\s)\\s*"
389  "([-+]?\\d{1,3}%1?\\d*)(?:%3)?(?:\\s*)%2";
390 
391  // direction as prefix, e.g. N 74.2245 W 32.2434
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)?";
395 
396  const char *expTemplate = ( dirPosition == PostfixDir ) ? postfixCapExp
397  : prefixCapExp;
398 
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 ) ) {
403  return false;
404  }
405 
406  bool isDir1LonDir;
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 ) ) {
413  return false;
414  }
415 
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 );
422 
423  return true;
424 }
425 
426 QString LonLatParser::createDecimalPointExp()
427 {
428  const QChar decimalPoint = QLocale::system().decimalPoint();
429 
430  return (decimalPoint == QLatin1Char('.')) ? QString::fromLatin1("\\.") :
431  QLatin1String("[.") + decimalPoint + QLatin1Char(']');
432 }
433 
434 QString LonLatParser::regExp(const QString& string)
435 {
436  QString result;
437  for (int i = 0; i < string.length(); ++i) {
438  const QChar c = string.at(i);
439  if ((QLatin1Char('a') <= c) && (c <= QLatin1Char('z'))) {
440  result += c;
441  } else if (c.isSpace()) {
442  result += QLatin1String("\\s");
443  } else if (c == QLatin1Char('.')) {
444  result += QLatin1String("\\.");
445  } else {
446  result += QString::fromLatin1("\\x%1").arg(c.unicode(), 4, 16, QLatin1Char('0'));
447  }
448  }
449  return result;
450 }
451 
452 void LonLatParser::getLocaleList( QStringList& localeList, const QString& localeListString,
453  const QLatin1String& placeholder, const QString& separator )
454 {
455  const QString lowerLocaleListString = localeListString.toLower();
456  if (lowerLocaleListString != placeholder) {
457  localeList = lowerLocaleListString.split(separator, QString::SkipEmptyParts);
458  }
459 }
460 
461 bool LonLatParser::isDirection( const QString& input, const QStringList& directions )
462 {
463  return ( directions.contains(input) );
464 }
465 
466 bool LonLatParser::isDirection( const QString& input, const QString& direction )
467 {
468  return ( input == direction );
469 }
470 
471 bool LonLatParser::isOneOfDirections( const QString& input,
472  const QString& firstDirection,
473  const QString& secondDirection,
474  bool& isFirstDirection )
475 {
476  isFirstDirection = isDirection(input, firstDirection);
477  return isFirstDirection || isDirection(input, secondDirection);
478 }
479 
480 bool LonLatParser::isOneOfDirections( const QString& input,
481  const QStringList& firstDirections,
482  const QStringList& secondDirections,
483  bool& isFirstDirection )
484 {
485  isFirstDirection = isDirection(input, firstDirections);
486  return isFirstDirection || isDirection(input, secondDirections);
487 }
488 
489 
490 bool LonLatParser::isLocaleLonDirection( const QString& input,
491  bool& isDirPosHemisphere ) const
492 {
493  return isOneOfDirections(input, m_eastLocale, m_westLocale, isDirPosHemisphere);
494 }
495 
496 bool LonLatParser::isLocaleLatDirection( const QString& input,
497  bool& isDirPosHemisphere ) const
498 {
499  return isOneOfDirections(input, m_northLocale, m_southLocale, isDirPosHemisphere);
500 }
501 
502 bool LonLatParser::isLonDirection( const QString& input,
503  bool& isDirPosHemisphere ) const
504 {
505  return isOneOfDirections(input, m_east, m_west, isDirPosHemisphere);
506 }
507 
508 bool LonLatParser::isLatDirection( const QString& input,
509  bool& isDirPosHemisphere ) const
510 {
511  return isOneOfDirections(input, m_north, m_south, isDirPosHemisphere);
512 }
513 
514 
515 qreal LonLatParser::degreeValueFromDMS( const QRegExp& regex, int c, bool isPosHemisphere )
516 {
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();
521 
522  qreal result = degree + (minutes*MIN2HOUR) + (seconds*SEC2HOUR);
523 
524  if (isNegativeValue)
525  result *= -1;
526  if (! isPosHemisphere)
527  result *= -1;
528 
529  return result;
530 }
531 
532 qreal LonLatParser::degreeValueFromDM( const QRegExp& regex, int c, bool isPosHemisphere )
533 {
534  const bool isNegativeValue = (regex.cap( c++ ) == QLatin1String("-"));
535  const uint degree = regex.cap( c++ ).toUInt();
536  const qreal minutes = regex.cap( c ).toDouble();
537 
538  qreal result = degree + (minutes*MIN2HOUR);
539 
540  if (isNegativeValue)
541  result *= -1;
542  if (! isPosHemisphere)
543  result *= -1;
544 
545  return result;
546 }
547 
548 qreal LonLatParser::degreeValueFromD( const QRegExp& regex, int c, bool isPosHemisphere )
549 {
550  qreal result = regex.cap( c ).toDouble();
551 
552  if (! isPosHemisphere)
553  result *= -1;
554 
555  return result;
556 }
557 
558 bool LonLatParser::isCorrectDirections(const QString& dir1, const QString& dir2,
559  bool& isDir1LonDir,
560  bool& isLonDirPosHemisphere,
561  bool& isLatDirPosHemisphere) const
562 {
563  // first try localized names
564  isDir1LonDir = isLocaleLonDirection(dir1, isLonDirPosHemisphere);
565  const bool resultLocale = isDir1LonDir ?
566  isLocaleLatDirection(dir2, isLatDirPosHemisphere) :
567  (isLocaleLatDirection(dir1, isLatDirPosHemisphere) &&
568  isLocaleLonDirection(dir2, isLonDirPosHemisphere));
569 
570  if (resultLocale)
571  return resultLocale;
572 
573  // fallback to try english names as lingua franca
574  isDir1LonDir = isLonDirection(dir1, isLonDirPosHemisphere);
575  return isDir1LonDir ?
576  isLatDirection(dir2, isLatDirPosHemisphere) :
577  (isLatDirection(dir1, isLatDirPosHemisphere) &&
578  isLonDirection(dir2, isLonDirPosHemisphere));
579 }
580 
581 
582 
583 GeoDataCoordinates::Notation GeoDataCoordinates::s_notation = GeoDataCoordinates::DMS;
584 
585 const GeoDataCoordinates GeoDataCoordinates::null = GeoDataCoordinates( 0, 0, 0 ); // don't use default constructor!
586 
587 GeoDataCoordinates::GeoDataCoordinates( qreal _lon, qreal _lat, qreal _alt, GeoDataCoordinates::Unit unit, int _detail )
588  : d( new GeoDataCoordinatesPrivate( _lon, _lat, _alt, unit, _detail ) )
589 {
590  d->ref.ref();
591 }
592 
593 /* simply copy the d pointer
594 * it will be replaced in the detach function instead
595 */
596 GeoDataCoordinates::GeoDataCoordinates( const GeoDataCoordinates& other )
597  : d( other.d )
598 {
599  d->ref.ref();
600 }
601 
602 /* simply copy null's d pointer
603  * it will be replaced in the detach function
604  */
605 GeoDataCoordinates::GeoDataCoordinates()
606  : d( null.d )
607 {
608  d->ref.ref();
609 }
610 
611 /*
612  * only delete the private d pointer if the number of references is 0
613  * remember that all copies share the same d pointer!
614  */
615 GeoDataCoordinates::~GeoDataCoordinates()
616 {
617  if (!d->ref.deref())
618  delete d;
619 #ifdef DEBUG_GEODATA
620 // mDebug() << "delete coordinates";
621 #endif
622 }
623 
624 bool GeoDataCoordinates::isValid() const
625 {
626  return d != null.d;
627 }
628 
629 /*
630  * if only one copy exists, return
631  * else make a new private d pointer object and assign the values of the current
632  * one to it
633  * at the end, if the number of references thus reaches 0 delete it
634  * this state shouldn't happen, but if it does, we have to clean up behind us.
635  */
636 void GeoDataCoordinates::detach()
637 {
638 #if QT_VERSION < 0x050000
639  if(d->ref == 1)
640 #else
641  if(d->ref.load() == 1)
642 #endif
643  return;
644 
645  GeoDataCoordinatesPrivate *new_d = new GeoDataCoordinatesPrivate( *d );
646 
647  if (!d->ref.deref())
648  delete d;
649 
650  d = new_d;
651  d->ref.ref();
652 }
653 
654 /*
655  * call detach() at the start of all non-static, non-const functions
656  */
657 void GeoDataCoordinates::set( qreal _lon, qreal _lat, qreal _alt, GeoDataCoordinates::Unit unit )
658 {
659  detach();
660  d->m_altitude = _alt;
661  switch( unit ){
662  default:
663  case Radian:
664  d->m_q = Quaternion::fromSpherical( _lon, _lat );
665  d->m_lon = _lon;
666  d->m_lat = _lat;
667  break;
668  case Degree:
669  d->m_q = Quaternion::fromSpherical( _lon * DEG2RAD , _lat * DEG2RAD );
670  d->m_lon = _lon * DEG2RAD;
671  d->m_lat = _lat * DEG2RAD;
672  break;
673  }
674 }
675 
676 /*
677  * call detach() at the start of all non-static, non-const functions
678  */
679 void GeoDataCoordinates::setLongitude( qreal _lon, GeoDataCoordinates::Unit unit )
680 {
681  detach();
682  switch( unit ){
683  default:
684  case Radian:
685  d->m_q = Quaternion::fromSpherical( _lon, d->m_lat );
686  d->m_lon = _lon;
687  break;
688  case Degree:
689  d->m_q = Quaternion::fromSpherical( _lon * DEG2RAD , d->m_lat );
690  d->m_lon = _lon * DEG2RAD;
691  break;
692  }
693 }
694 
695 
696 /*
697  * call detach() at the start of all non-static, non-const functions
698  */
699 void GeoDataCoordinates::setLatitude( qreal _lat, GeoDataCoordinates::Unit unit )
700 {
701  detach();
702  switch( unit ){
703  case Radian:
704  d->m_q = Quaternion::fromSpherical( d->m_lon, _lat );
705  d->m_lat = _lat;
706  break;
707  case Degree:
708  d->m_q = Quaternion::fromSpherical( d->m_lon, _lat * DEG2RAD );
709  d->m_lat = _lat * DEG2RAD;
710  break;
711  }
712 }
713 
714 
715 void GeoDataCoordinates::geoCoordinates( qreal& lon, qreal& lat,
716  GeoDataCoordinates::Unit unit ) const
717 {
718  switch ( unit )
719  {
720  default:
721  case Radian:
722  lon = d->m_lon;
723  lat = d->m_lat;
724  break;
725  case Degree:
726  lon = d->m_lon * RAD2DEG;
727  lat = d->m_lat * RAD2DEG;
728  break;
729  }
730 }
731 
732 void GeoDataCoordinates::geoCoordinates( qreal& lon, qreal& lat, qreal& alt,
733  GeoDataCoordinates::Unit unit ) const
734 {
735  geoCoordinates( lon, lat, unit );
736  alt = d->m_altitude;
737 }
738 
739 qreal GeoDataCoordinates::longitude( GeoDataCoordinates::Unit unit ) const
740 {
741  switch ( unit )
742  {
743  default:
744  case Radian:
745  return d->m_lon;
746  case Degree:
747  return d->m_lon * RAD2DEG;
748  }
749 }
750 
751 qreal GeoDataCoordinates::latitude( GeoDataCoordinates::Unit unit ) const
752 {
753  switch ( unit )
754  {
755  default:
756  case Radian:
757  return d->m_lat;
758  case Degree:
759  return d->m_lat * RAD2DEG;
760  }
761 }
762 
763 //static
764 GeoDataCoordinates::Notation GeoDataCoordinates::defaultNotation()
765 {
766  return s_notation;
767 }
768 
769 //static
770 void GeoDataCoordinates::setDefaultNotation( GeoDataCoordinates::Notation notation )
771 {
772  s_notation = notation;
773 }
774 
775 //static
776 qreal GeoDataCoordinates::normalizeLon( qreal lon, GeoDataCoordinates::Unit unit )
777 {
778  qreal halfCircle;
779  if ( unit == GeoDataCoordinates::Radian ) {
780  halfCircle = M_PI;
781  }
782  else {
783  halfCircle = 180;
784  }
785 
786  if ( lon > halfCircle ) {
787  int cycles = (int)( ( lon + halfCircle ) / ( 2 * halfCircle ) );
788  return lon - ( cycles * 2 * halfCircle );
789  }
790  if ( lon < -halfCircle ) {
791  int cycles = (int)( ( lon - halfCircle ) / ( 2 * halfCircle ) );
792  return lon - ( cycles * 2 * halfCircle );
793  }
794 
795  return lon;
796 }
797 
798 //static
799 qreal GeoDataCoordinates::normalizeLat( qreal lat, GeoDataCoordinates::Unit unit )
800 {
801  qreal halfCircle;
802  if ( unit == GeoDataCoordinates::Radian ) {
803  halfCircle = M_PI;
804  }
805  else {
806  halfCircle = 180;
807  }
808 
809  if ( lat > ( halfCircle / 2.0 ) ) {
810  int cycles = (int)( ( lat + halfCircle ) / ( 2 * halfCircle ) );
811  qreal temp;
812  if( cycles == 0 ) { // pi/2 < lat < pi
813  temp = halfCircle - lat;
814  } else {
815  temp = lat - ( cycles * 2 * halfCircle );
816  }
817  if ( temp > ( halfCircle / 2.0 ) ) {
818  return ( halfCircle - temp );
819  }
820  if ( temp < ( -halfCircle / 2.0 ) ) {
821  return ( -halfCircle - temp );
822  }
823  return temp;
824  }
825  if ( lat < ( -halfCircle / 2.0 ) ) {
826  int cycles = (int)( ( lat - halfCircle ) / ( 2 * halfCircle ) );
827  qreal temp;
828  if( cycles == 0 ) {
829  temp = -halfCircle - lat;
830  } else {
831  temp = lat - ( cycles * 2 * halfCircle );
832  }
833  if ( temp > ( +halfCircle / 2.0 ) ) {
834  return ( +halfCircle - temp );
835  }
836  if ( temp < ( -halfCircle / 2.0 ) ) {
837  return ( -halfCircle - temp );
838  }
839  return temp;
840  }
841  return lat;
842 }
843 
844 //static
845 void GeoDataCoordinates::normalizeLonLat( qreal &lon, qreal &lat, GeoDataCoordinates::Unit unit )
846 {
847  qreal halfCircle;
848  if ( unit == GeoDataCoordinates::Radian ) {
849  halfCircle = M_PI;
850  }
851  else {
852  halfCircle = 180;
853  }
854 
855  if ( lon > +halfCircle ) {
856  int cycles = (int)( ( lon + halfCircle ) / ( 2 * halfCircle ) );
857  lon = lon - ( cycles * 2 * halfCircle );
858  }
859  if ( lon < -halfCircle ) {
860  int cycles = (int)( ( lon - halfCircle ) / ( 2 * halfCircle ) );
861  lon = lon - ( cycles * 2 * halfCircle );
862  }
863 
864  if ( lat > ( +halfCircle / 2.0 ) ) {
865  int cycles = (int)( ( lat + halfCircle ) / ( 2 * halfCircle ) );
866  qreal temp;
867  if( cycles == 0 ) { // pi/2 < lat < pi
868  temp = halfCircle - lat;
869  } else {
870  temp = lat - ( cycles * 2 * halfCircle );
871  }
872  if ( temp > ( +halfCircle / 2.0 ) ) {
873  lat = +halfCircle - temp;
874  }
875  if ( temp < ( -halfCircle / 2.0 ) ) {
876  lat = -halfCircle - temp;
877  }
878  lat = temp;
879  if( lon > 0 ) {
880  lon = -halfCircle + lon;
881  } else {
882  lon = halfCircle + lon;
883  }
884  }
885  if ( lat < ( -halfCircle / 2.0 ) ) {
886  int cycles = (int)( ( lat - halfCircle ) / ( 2 * halfCircle ) );
887  qreal temp;
888  if( cycles == 0 ) {
889  temp = -halfCircle - lat;
890  } else {
891  temp = lat - ( cycles * 2 * halfCircle );
892  }
893  if ( temp > ( +halfCircle / 2.0 ) ) {
894  lat = +halfCircle - temp;
895  }
896  if ( temp < ( -halfCircle / 2.0 ) ) {
897  lat = -halfCircle - temp;
898  }
899  lat = temp;
900  if( lon > 0 ) {
901  lon = -halfCircle + lon;
902  } else {
903  lon = halfCircle + lon;
904  }
905  }
906  return;
907 }
908 
909 GeoDataCoordinates GeoDataCoordinates::fromString( const QString& string, bool& successful )
910 {
911  LonLatParser parser;
912  successful = parser.parse(string);
913  if (successful) {
914  return GeoDataCoordinates( parser.lon(), parser.lat(), 0, GeoDataCoordinates::Degree );
915  } else {
916  return GeoDataCoordinates();
917  }
918 }
919 
920 
921 QString GeoDataCoordinates::toString() const
922 {
923  return GeoDataCoordinates::toString( s_notation );
924 }
925 
926 QString GeoDataCoordinates::toString( GeoDataCoordinates::Notation notation, int precision ) const
927 {
928  return lonToString( d->m_lon, notation, Radian, precision )
929  + QString(", ")
930  + latToString( d->m_lat, notation, Radian, precision );
931 }
932 
933 QString GeoDataCoordinates::lonToString( qreal lon, GeoDataCoordinates::Notation notation,
934  GeoDataCoordinates::Unit unit,
935  int precision,
936  char format )
937 {
938  if ( notation == UTM ) {
939  int zoneNumber = static_cast<int>( lon / 6.0 ) + 30;
940  return QString::number( zoneNumber );
941  }
942 
943  QString weString = ( lon < 0 ) ? tr("W") : tr("E");
944 
945  QString lonString;
946 
947  qreal lonDegF = ( unit == Degree ) ? fabs( lon ) : fabs( (qreal)(lon) * RAD2DEG );
948 
949  // Take care of -1 case
950  precision = ( precision < 0 ) ? 5 : precision;
951 
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;
958 
959  // Adjustment for fuzziness (like 49.999999999999999999999)
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 );
966  } else {
967  if ( notation == DMS ) {
968  lonSec = lonSecF = qRound( lonSecF * qPow( 10, precision - 4 ) ) / qPow( 10, precision - 4 );
969  }
970  else {
971  lonMin = lonMinF = qRound( lonMinF * qPow( 10, precision - 2 ) ) / qPow( 10, precision - 2 );
972  }
973  }
974 
975  if (lonSec > 59 && notation == DMS ) {
976  lonSec = lonSecF = 0;
977  lonMin = lonMinF = lonMinF + 1;
978  }
979  if (lonMin > 59) {
980  lonMin = lonMinF = 0;
981  lonDeg = lonDegF = lonDegF + 1;
982  }
983 
984  // Evaluate the string
985  lonString = QString::fromUtf8("%1\xc2\xb0").arg(lonDeg, 3, 10, QChar(' ') );
986 
987  if ( precision == 0 ) {
988  return lonString + weString;
989  }
990 
991  if ( notation == DMS || precision < 3 ) {
992  lonString += QString(" %2\'").arg(lonMin, 2, 10, QChar('0') );
993  }
994 
995  if ( precision < 3 ) {
996  return lonString + weString;
997  }
998 
999  if ( notation == DMS ) {
1000  // Includes -1 case!
1001  if ( precision < 5 ) {
1002  lonString += QString(" %3\"").arg(lonSec, 2, 'f', 0, QChar('0') );
1003  return lonString + weString;
1004  }
1005 
1006  lonString += QString(" %L3\"").arg(lonSecF, precision - 1, 'f', precision - 4, QChar('0') );
1007  }
1008  else {
1009  lonString += QString(" %L3'").arg(lonMinF, precision + 1, 'f', precision - 2, QChar('0') );
1010  }
1011  }
1012  else if ( notation == GeoDataCoordinates::Decimal )
1013  {
1014  lonString = QString::fromUtf8("%L1\xc2\xb0").arg(lonDegF, 4 + precision, format, precision, QChar(' ') );
1015  }
1016  else if ( notation == GeoDataCoordinates::Astro )
1017  {
1018  if (lon < 0) {
1019  lon += ( unit == Degree ) ? 360 : 2 * M_PI;
1020  }
1021 
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;
1028 
1029  // Adjustment for fuzziness (like 49.999999999999999999999)
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 );
1036  } else {
1037  lonSec = lonSecF = qRound( lonSecF * qPow( 10, precision - 4 ) ) / qPow( 10, precision - 4 );
1038  }
1039 
1040  if (lonSec > 59 ) {
1041  lonSec = lonSecF = 0;
1042  lonMin = lonMinF = lonMinF + 1;
1043  }
1044  if (lonMin > 59) {
1045  lonMin = lonMinF = 0;
1046  lonHour = lonHourF = lonHourF + 1;
1047  }
1048 
1049  // Evaluate the string
1050  lonString = QString::fromUtf8("%1h").arg(lonHour, 3, 10, QChar(' ') );
1051 
1052  if ( precision == 0 ) {
1053  return lonString;
1054  }
1055 
1056  lonString += QString(" %2\'").arg(lonMin, 2, 10, QChar('0') );
1057 
1058  if ( precision < 3 ) {
1059  return lonString;
1060  }
1061 
1062  // Includes -1 case!
1063  if ( precision < 5 ) {
1064  lonString += QString(" %3\"").arg(lonSec, 2, 'f', 0, QChar('0') );
1065  return lonString;
1066  }
1067 
1068  lonString += QString(" %L3\"").arg(lonSecF, precision - 1, 'f', precision - 4, QChar('0') );
1069  return lonString;
1070  }
1071 
1072  return lonString + weString;
1073 }
1074 
1075 QString GeoDataCoordinates::lonToString() const
1076 {
1077  return GeoDataCoordinates::lonToString( d->m_lon , s_notation );
1078 }
1079 
1080 QString GeoDataCoordinates::latToString( qreal lat, GeoDataCoordinates::Notation notation,
1081  GeoDataCoordinates::Unit unit,
1082  int precision,
1083  char format )
1084 {
1085  if ( notation == UTM ) {
1086  int bandLetterIndex = static_cast<int>( lat / 8.0 ) + 10;
1087  return QString( "CDEFGHJKLMNPQRSTUVWX???" ).at( bandLetterIndex );
1088  }
1089 
1090  QString pmString;
1091  QString nsString;
1092 
1093  if (notation == GeoDataCoordinates::Astro){
1094  pmString = ( lat > 0 ) ? "+" : "-";
1095  }
1096  else {
1097  nsString = ( lat > 0 ) ? tr("N") : tr("S");
1098  }
1099 
1100  QString latString;
1101 
1102  qreal latDegF = ( unit == Degree ) ? fabs( lat ) : fabs( (qreal)(lat) * RAD2DEG );
1103 
1104  // Take care of -1 case
1105  precision = ( precision < 0 ) ? 5 : precision;
1106 
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;
1113 
1114  // Adjustment for fuzziness (like 49.999999999999999999999)
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 );
1121  } else {
1122  if ( notation == DMS || notation == Astro ) {
1123  latSec = latSecF = qRound( latSecF * qPow( 10, precision - 4 ) ) / qPow( 10, precision - 4 );
1124  }
1125  else {
1126  latMin = latMinF = qRound( latMinF * qPow( 10, precision - 2 ) ) / qPow( 10, precision - 2 );
1127  }
1128  }
1129 
1130  if (latSec > 59 && ( notation == DMS || notation == Astro )) {
1131  latSecF = 0;
1132  latSec = latSecF;
1133  latMin = latMin + 1;
1134  }
1135  if (latMin > 59) {
1136  latMinF = 0;
1137  latMin = latMinF;
1138  latDeg = latDeg + 1;
1139  }
1140 
1141  // Evaluate the string
1142  latString = QString::fromUtf8("%1\xc2\xb0").arg(latDeg, 3, 10, QChar(' ') );
1143 
1144  if ( precision == 0 ) {
1145  return pmString + latString + nsString;
1146  }
1147 
1148  if ( notation == DMS || notation == Astro || precision < 3 ) {
1149  latString += QString(" %2\'").arg(latMin, 2, 10, QChar('0') );
1150  }
1151 
1152  if ( precision < 3 ) {
1153  return pmString + latString + nsString;
1154  }
1155 
1156  if ( notation == DMS || notation == Astro ) {
1157  // Includes -1 case!
1158  if ( precision < 5 ) {
1159  latString += QString(" %3\"").arg(latSec, 2, 'f', 0, QChar('0') );
1160  return latString + nsString;
1161  }
1162 
1163  latString += QString(" %L3\"").arg(latSecF, precision - 1, 'f', precision - 4, QChar('0') );
1164  }
1165  else {
1166  latString += QString(" %L3'").arg(latMinF, precision + 1, 'f', precision - 2, QChar('0') );
1167  }
1168  }
1169  else // notation = GeoDataCoordinates::Decimal
1170  {
1171  latString = QString::fromUtf8("%L1\xc2\xb0").arg(latDegF, 4 + precision, format, precision, QChar(' ') );
1172  }
1173  return pmString + latString + nsString;
1174 }
1175 
1176 QString GeoDataCoordinates::latToString() const
1177 {
1178  return GeoDataCoordinates::latToString( d->m_lat, s_notation );
1179 }
1180 
1181 bool GeoDataCoordinates::operator==( const GeoDataCoordinates &rhs ) const
1182 {
1183  return *d == *rhs.d;
1184 }
1185 
1186 bool GeoDataCoordinates::operator!=( const GeoDataCoordinates &rhs ) const
1187 {
1188  return *d != *rhs.d;
1189 }
1190 
1191 void GeoDataCoordinates::setAltitude( const qreal altitude )
1192 {
1193  detach();
1194  d->m_altitude = altitude;
1195 }
1196 
1197 qreal GeoDataCoordinates::altitude() const
1198 {
1199  return d->m_altitude;
1200 }
1201 
1202 int GeoDataCoordinates::detail() const
1203 {
1204  return d->m_detail;
1205 }
1206 
1207 void GeoDataCoordinates::setDetail( const int det )
1208 {
1209  detach();
1210  d->m_detail = det;
1211 }
1212 
1213 qreal GeoDataCoordinates::bearing( const GeoDataCoordinates &other, Unit unit, BearingType type ) const
1214 {
1215  if ( type == FinalBearing ) {
1216  double const offset = unit == Degree ? 180.0 : M_PI;
1217  return offset + other.bearing( *this, unit, InitialBearing );
1218  }
1219 
1220  qreal const delta = other.d->m_lon - d->m_lon;
1221  double const bearing = atan2( sin ( delta ) * cos ( other.d->m_lat ),
1222  cos( d->m_lat ) * sin( other.d->m_lat ) - sin( d->m_lat ) * cos( other.d->m_lat ) * cos ( delta ) );
1223  return unit == Radian ? bearing : bearing * RAD2DEG;
1224 }
1225 
1226 const Quaternion& GeoDataCoordinates::quaternion() const
1227 {
1228  return d->m_q;
1229 }
1230 
1231 bool GeoDataCoordinates::isPole( Pole pole ) const
1232 {
1233  // Evaluate the most likely case first:
1234  // The case where we haven't hit the pole and where our latitude is normalized
1235  // to the range of 90 deg S ... 90 deg N
1236  if ( fabs( (qreal) 2.0 * d->m_lat ) < M_PI ) {
1237  return false;
1238  }
1239  else {
1240  if ( fabs( (qreal) 2.0 * d->m_lat ) == M_PI ) {
1241  // Ok, we have hit a pole. Now let's check whether it's the one we've asked for:
1242  if ( pole == AnyPole ){
1243  return true;
1244  }
1245  else {
1246  if ( pole == NorthPole && 2.0 * d->m_lat == +M_PI ) {
1247  return true;
1248  }
1249  if ( pole == SouthPole && 2.0 * d->m_lat == -M_PI ) {
1250  return true;
1251  }
1252  return false;
1253  }
1254  }
1255  //
1256  else {
1257  // FIXME: Should we just normalize latitude and longitude and be done?
1258  // While this might work well for persistent data it would create some
1259  // possible overhead for temporary data, so this needs careful thinking.
1260  mDebug() << "GeoDataCoordinates not normalized!";
1261 
1262  // Only as a last resort we cover the unlikely case where
1263  // the latitude is not normalized to the range of
1264  // 90 deg S ... 90 deg N
1265  if ( fabs( (qreal) 2.0 * normalizeLat( d->m_lat ) ) < M_PI ) {
1266  return false;
1267  }
1268  else {
1269  // Ok, we have hit a pole. Now let's check whether it's the one we've asked for:
1270  if ( pole == AnyPole ){
1271  return true;
1272  }
1273  else {
1274  if ( pole == NorthPole && 2.0 * d->m_lat == +M_PI ) {
1275  return true;
1276  }
1277  if ( pole == SouthPole && 2.0 * d->m_lat == -M_PI ) {
1278  return true;
1279  }
1280  return false;
1281  }
1282  }
1283  }
1284  }
1285 }
1286 
1287 GeoDataCoordinates& GeoDataCoordinates::operator=( const GeoDataCoordinates &other )
1288 {
1289  qAtomicAssign(d, other.d);
1290  return *this;
1291 }
1292 
1293 void GeoDataCoordinates::pack( QDataStream& stream ) const
1294 {
1295  stream << d->m_lon;
1296  stream << d->m_lat;
1297  stream << d->m_altitude;
1298 }
1299 
1300 void GeoDataCoordinates::unpack( QDataStream& stream )
1301 {
1302  // call detach even though it shouldn't be needed - one never knows
1303  detach();
1304  stream >> d->m_lon;
1305  stream >> d->m_lat;
1306  stream >> d->m_altitude;
1307 
1308  d->m_q = Quaternion::fromSpherical( d->m_lon, d->m_lat );
1309 }
1310 
1311 }
Marble::GeoDataCoordinates::Unit
Unit
enum used constructor to specify the units used
Definition: GeoDataCoordinates.h:64
Marble::GeoDataCoordinatesPrivate::m_detail
int m_detail
Definition: GeoDataCoordinates_p.h:103
Marble::GeoDataCoordinates::operator==
virtual bool operator==(const GeoDataCoordinates &) const
Definition: GeoDataCoordinates.cpp:1181
GeoDataCoordinates.h
Quaternion.h
Marble::RAD2DEG
const qreal RAD2DEG
Definition: MarbleGlobal.h:201
Marble::GeoDataCoordinates::unpack
virtual void unpack(QDataStream &stream)
Unserialize the contents of the feature from stream.
Definition: GeoDataCoordinates.cpp:1300
Marble::AnyPole
Any pole.
Definition: MarbleGlobal.h:152
Marble::GeoDataCoordinates
A 3d point representation.
Definition: GeoDataCoordinates.h:52
Marble::SouthPole
Only South Pole.
Definition: MarbleGlobal.h:154
Marble::GeoDataCoordinates::UTM
Definition: GeoDataCoordinates.h:83
Marble::GeoDataCoordinates::Radian
Definition: GeoDataCoordinates.h:65
Marble::GeoDataCoordinates::detail
int detail() const
return the detail flag detail range: 0 for most important points, 5 for least important ...
Definition: GeoDataCoordinates.cpp:1202
Marble::GeoDataCoordinates::d
GeoDataCoordinatesPrivate * d
Definition: GeoDataCoordinates.h:356
Marble::GeoDataCoordinatesPrivate
Definition: GeoDataCoordinates_p.h:20
Marble::GeoDataCoordinates::setAltitude
void setAltitude(const qreal altitude)
set the altitude of the Point in meters
Definition: GeoDataCoordinates.cpp:1191
Marble::GeoDataCoordinates::normalizeLon
static qreal normalizeLon(qreal lon, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize the longitude to always be -M_PI <= lon <= +M_PI (Radian).
Definition: GeoDataCoordinates.cpp:776
Marble::GeoDataCoordinates::~GeoDataCoordinates
virtual ~GeoDataCoordinates()
Definition: GeoDataCoordinates.cpp:615
Marble::GeoDataCoordinates::GeoDataCoordinates
GeoDataCoordinates()
constructs an invalid instance
Definition: GeoDataCoordinates.cpp:605
Marble::GeoDataCoordinatesPrivate::m_lon
qreal m_lon
Definition: GeoDataCoordinates_p.h:100
Marble::GeoDataCoordinates::Decimal
"Decimal" notation (base-10)
Definition: GeoDataCoordinates.h:80
Marble::GeoDataCoordinates::latitude
qreal latitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
Definition: GeoDataCoordinates.cpp:751
Marble::GeoDataCoordinates::setDetail
void setDetail(const int det)
set the detail flag
Definition: GeoDataCoordinates.cpp:1207
MarbleDebug.h
Marble::GeoDataCoordinates::Degree
Definition: GeoDataCoordinates.h:66
Marble::GeoDataCoordinates::InitialBearing
Definition: GeoDataCoordinates.h:97
Marble::GeoDataCoordinates::BearingType
BearingType
The BearingType enum specifies where to measure the bearing along great circle arcs.
Definition: GeoDataCoordinates.h:96
Marble::GeoDataCoordinates::altitude
qreal altitude() const
return the altitude of the Point in meters
Definition: GeoDataCoordinates.cpp:1197
Marble::GeoDataCoordinates::geoCoordinates
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 ...
Definition: GeoDataCoordinates.cpp:715
Marble::GeoDataCoordinates::FinalBearing
Definition: GeoDataCoordinates.h:98
Marble::GeoDataCoordinates::bearing
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...
Definition: GeoDataCoordinates.cpp:1213
Marble::GeoDataCoordinatesPrivate::m_altitude
qreal m_altitude
Definition: GeoDataCoordinates_p.h:102
Marble::GeoDataCoordinatesPrivate::ref
QAtomicInt ref
Definition: GeoDataCoordinates_p.h:104
Marble::GeoDataCoordinates::normalizeLat
static qreal normalizeLat(qreal lat, GeoDataCoordinates::Unit=GeoDataCoordinates::Radian)
normalize latitude to always be in -M_PI / 2.
Definition: GeoDataCoordinates.cpp:799
Marble::GeoDataCoordinates::normalizeLonLat
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...
Definition: GeoDataCoordinates.cpp:845
MarbleGlobal.h
Marble::GeoDataCoordinates::set
void set(qreal lon, qreal lat, qreal alt=0, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
(re)set the coordinates in a GeoDataCoordinates object
Definition: GeoDataCoordinates.cpp:657
Marble::DEG2RAD
const qreal DEG2RAD
Definition: MarbleGlobal.h:200
Marble::GeoDataCoordinates::latToString
QString latToString() const
return a string representation of latitude of the coordinate convenience function that uses the defau...
Definition: GeoDataCoordinates.cpp:1176
Marble::GeoDataCoordinates::operator!=
virtual bool operator!=(const GeoDataCoordinates &) const
Definition: GeoDataCoordinates.cpp:1186
Marble::GeoDataCoordinates::lonToString
QString lonToString() const
return a string representation of longitude of the coordinate convenience function that uses the defa...
Definition: GeoDataCoordinates.cpp:1075
Marble::GeoDataCoordinates::longitude
qreal longitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
Definition: GeoDataCoordinates.cpp:739
Marble::GeoDataCoordinates::setLatitude
void setLatitude(qreal lat, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
set the longitude in a GeoDataCoordinates object
Definition: GeoDataCoordinates.cpp:699
Marble::GeoDataCoordinatesPrivate::m_q
Quaternion m_q
Definition: GeoDataCoordinates_p.h:99
Marble::GeoDataCoordinates::setLongitude
void setLongitude(qreal lon, GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian)
set the longitude in a GeoDataCoordinates object
Definition: GeoDataCoordinates.cpp:679
direction
qreal direction
Definition: tools/osm-addresses/OsmParser.cpp:39
Marble::GeoDataCoordinates::Notation
Notation
enum used to specify the notation / numerical system
Definition: GeoDataCoordinates.h:79
Marble::SEC2HOUR
const qreal SEC2HOUR
Definition: MarbleGlobal.h:217
Marble::GeoDataCoordinates::isPole
bool isPole(Pole=AnyPole) const
return whether our coordinates represent a pole This method can be used to check whether the coordina...
Definition: GeoDataCoordinates.cpp:1231
Marble::Quaternion
Definition: Quaternion.h:43
Marble::GeoDataCoordinates::toString
QString toString() const
return a string representation of the coordinate this is a convenience function which uses the defaul...
Definition: GeoDataCoordinates.cpp:921
M_PI
#define M_PI
Definition: GeoDataCoordinates.h:26
Marble::GeoDataCoordinates::setDefaultNotation
static void setDefaultNotation(GeoDataCoordinates::Notation notation)
set the Notation of the string representation
Definition: GeoDataCoordinates.cpp:770
GeoDataCoordinates_p.h
Marble::MIN2HOUR
const qreal MIN2HOUR
Definition: MarbleGlobal.h:209
Marble::GeoDataCoordinates::detach
virtual void detach()
Definition: GeoDataCoordinates.cpp:636
Marble::GeoDataCoordinates::fromString
static GeoDataCoordinates fromString(const QString &string, bool &successful)
try to parse the string into a coordinate pair
Definition: GeoDataCoordinates.cpp:909
Marble::GeoDataCoordinates::isValid
bool isValid() const
Returns.
Definition: GeoDataCoordinates.cpp:624
Marble::Pole
Pole
Definition: MarbleGlobal.h:151
Marble::GeoDataCoordinates::DMS
"Sexagesimal DMS" notation (base-60)
Definition: GeoDataCoordinates.h:81
Marble::GeoDataCoordinates::defaultNotation
static GeoDataCoordinates::Notation defaultNotation()
return Notation of string representation
Definition: GeoDataCoordinates.cpp:764
Marble::GeoDataCoordinates::DM
"Sexagesimal DM" notation (base-60)
Definition: GeoDataCoordinates.h:82
Marble::mDebug
QDebug mDebug()
a function to replace qDebug() in Marble library code
Definition: MarbleDebug.cpp:31
Marble::NorthPole
Only North Pole.
Definition: MarbleGlobal.h:153
Marble::GeoDataCoordinatesPrivate::m_lat
qreal m_lat
Definition: GeoDataCoordinates_p.h:101
Marble::GeoDataCoordinates::Astro
< "RA and DEC" notation (used for astronomical sky coordinates)
Definition: GeoDataCoordinates.h:84
Marble::Quaternion::fromSpherical
static Quaternion fromSpherical(qreal lon, qreal lat)
used to generate Quaternion from longitude and latitude
Definition: Quaternion.cpp:38
Marble::GeoDataCoordinates::quaternion
const Quaternion & quaternion() const
return a Quaternion with the used coordinates
Definition: GeoDataCoordinates.cpp:1226
Marble::GeoDataCoordinates::pack
virtual void pack(QDataStream &stream) const
Serialize the contents of the feature to stream.
Definition: GeoDataCoordinates.cpp:1293
Marble::GeoDataCoordinates::operator=
GeoDataCoordinates & operator=(const GeoDataCoordinates &other)
Definition: GeoDataCoordinates.cpp:1287
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 22:38:49 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

marble

Skip menu "marble"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Related Pages

kdeedu API Reference

Skip menu "kdeedu API Reference"
  • Analitza
  •     lib
  • kalgebra
  • kalzium
  •   libscience
  • kanagram
  • kig
  •   lib
  • klettres
  • kstars
  • libkdeedu
  •   keduvocdocument
  • marble
  • parley
  • rocs
  •   App
  •   RocsCore
  •   VisualEditor
  •   stepcore

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal