Search code examples
c++qtgeolocationlocationcoordinates

how to get latitude/longitude from one geo address using Qt c++ on windows?


Its is possible get the coordinates(latitude and longitude), of a geo location using just the geo address (country, state, city, street, etc...), on Qt c++?

I know the libraries QGeoCoordinates, QGeoLocation and QGeoAddress, but i don´t know if is possible get coordinates from an address through them.

Every help is welcome.


Solution

  • I needed some time to master this but finally I got it working.

    At first I tried the classes mentioned by you: QGeoAddress, QGeoLocation, QGeoCoordinate:

    // standard C++ header:
    #include <iostream>
    
    // Qt header:
    #include <QGeoAddress>
    #include <QGeoCoordinate>
    #include <QGeoLocation>
    
    using namespace std;
    
    int main()
    {
      // build address
      QGeoAddress qGeoAddr;
      qGeoAddr.setCountry(QString::fromUtf8("Germany"));
      qGeoAddr.setPostalCode(QString::fromUtf8("88250"));
      qGeoAddr.setCity(QString::fromUtf8("Weingarten"));
      qGeoAddr.setStreet(QString::fromUtf8("Heinrich-Hertz-Str. 6"));
      QGeoLocation qGeoLoc.setAddress(qGeoAddr);
      QGeoCoordinate qGeoCoord = qGeoLoc.coordinate();
      cout
        << "Lat.:  " << qGeoCoord.latitude() << endl
        << "Long.: " << qGeoCoord.longitude() << endl
        << "Alt.:  " << qGeoCoord.altitude() << endl;
      return 0;
    }
    

    This compiles and run but the output is not very enjoying:

    $ ./testQGeoAddress
    Qt Version: 5.6.2
    Lat.:  nan
    Long.: nan
    Alt.:  nan
    

    So, what's wrong with the code? Leaning back and thinking a little bit about this I got a clue: There is some kind of service missing which could transform the address into the coordinates. What could this be? maps.google.com or something similar?

    I googled a while and finally found hits concerning the Qt location library. After experimenting and fiddling a while, I finally got this running example:

    File testQGeoAddress.pro:

    SOURCES = testQGeoAddress.cc
    
    QT += widgets
    QT += positioning
    QT += location
    

    File testQGeoAddress.cc:

    // standard C++ header:
    #include <iostream>
    #include <string>
    
    // Qt header:
    #include <QApplication>
    #include <QGeoAddress>
    #include <QGeoCodingManager>
    #include <QGeoCoordinate>
    #include <QGeoLocation>
    #include <QGeoServiceProvider>
    
    using namespace std;
    
    int main(int argc, char **argv)
    {
      cout << "Qt Version: " << QT_VERSION_STR << endl;
      // main application
    #undef qApp // undef macro qApp out of the way
      QCoreApplication qApp(argc, argv);
      // check for available services
      QStringList qGeoSrvList
        = QGeoServiceProvider::availableServiceProviders();
      for (QString entry : qGeoSrvList) {
        cout << "Try service: " << entry.toStdString() << endl;
        // choose provider
        QGeoServiceProvider qGeoService(entry);
        QGeoCodingManager *pQGeoCoder = qGeoService.geocodingManager();
        if (!pQGeoCoder) {
          cerr
            << "GeoCodingManager '" << entry.toStdString()
            << "' not available!" << endl;
          continue;
        }
        QLocale qLocaleC(QLocale::C, QLocale::AnyCountry);
        pQGeoCoder->setLocale(qLocaleC);
        // build address
        QGeoAddress qGeoAddr;
        qGeoAddr.setCountry(QString::fromUtf8("Germany"));
        qGeoAddr.setPostalCode(QString::fromUtf8("88250"));
        qGeoAddr.setCity(QString::fromUtf8("Weingarten"));
        qGeoAddr.setStreet(QString::fromUtf8("Heinrich-Hertz-Str. 6"));
        QGeoCodeReply *pQGeoCode = pQGeoCoder->geocode(qGeoAddr);
        if (!pQGeoCode) {
          cerr << "GeoCoding totally failed!" << endl;
          continue;
        }
        cout << "Searching..." << endl;
        QObject::connect(pQGeoCode, &QGeoCodeReply::finished,
          [&qApp, &qGeoAddr, pQGeoCode](){
            cout << "Reply: " << pQGeoCode->errorString().toStdString() << endl;
            switch (pQGeoCode->error()) {
    #define CASE(ERROR) \
    case QGeoCodeReply::ERROR: cerr << #ERROR << endl; break
              CASE(NoError);
              CASE(EngineNotSetError);
              CASE(CommunicationError);
              CASE(ParseError);
              CASE(UnsupportedOptionError);
              CASE(CombinationError);
              CASE(UnknownError);
    #undef CASE
              default: cerr << "Undocumented error!" << endl;
            }
            if (pQGeoCode->error() != QGeoCodeReply::NoError) return;
            // eval. result
            QList<QGeoLocation> qGeoLocs = pQGeoCode->locations();
            cout << qGeoLocs.size() << " location(s) returned." << endl;
            for (QGeoLocation &qGeoLoc : qGeoLocs) {
              qGeoLoc.setAddress(qGeoAddr);
              QGeoCoordinate qGeoCoord = qGeoLoc.coordinate();
              cout
                << "Lat.:  " << qGeoCoord.latitude() << endl
                << "Long.: " << qGeoCoord.longitude() << endl
                << "Alt.:  " << qGeoCoord.altitude() << endl;
            }
            qApp.exit(0);
          });
        return qApp.exec();
      }
      return 0;
    }
    

    Build with g++ in cygwin on Windows 10 (64 bit):

    $ qmake-qt5 
    
    $ make
    g++ -c -pipe -fno-keep-inline-dllexport -O2 -std=gnu++11 -Wall -W -D_REENTRANT -fexceptions -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_LOCATION_LIB -DQT_QUICK_LIB -DQT_GUI_LIB -DQT_POSITIONING_LIB -DQT_QML_LIB -DQT_NETWORK_LIB -DQT_CORE_LIB -I. -I/usr/include/qt5 -I/usr/include/qt5/QtWidgets -I/usr/include/qt5/QtLocation -I/usr/include/qt5/QtQuick -I/usr/include/qt5/QtGui -I/usr/include/qt5/QtPositioning -I/usr/include/qt5/QtQml -I/usr/include/qt5/QtNetwork -I/usr/include/qt5/QtCore -I. -I/usr/lib/qt5/mkspecs/cygwin-g++ -o testQGeoAddress.o testQGeoAddress.cc
    g++  -o testQGeoAddress.exe testQGeoAddress.o   -lQt5Widgets -lQt5Location -lQt5Quick -lQt5Gui -lQt5Positioning -lQt5Qml -lQt5Network -lQt5Core -lGL -lpthread 
    
    $ ./testQGeoAddress.exe
    Qt Version: 5.6.2
    Try service: mapbox
    GeoCodingManager 'mapbox' not available!
    Try service: osm
    Searching...
    Reply: 
    NoError
    1 location(s) returned.
    Lat.:  47.8198
    Long.: 9.63105
    Alt.:  nan
    
    $ 
    

    Not bad for the first try. About the QGeoCoordinate::altitude() value: this might be not available from Open Street Map (osm).

    To check whether the result is correct I resolved the output coordinate in maps.google.com:

    Search 47.8198, 9.63105 in maps.google.com

    The red balloon is the result of the search. I added the blue dot in GIMP to remark the correct position. Well, the search was close to the correct position. The difference might be caused by the limited precision of coordinates...