File indexing completed on 2024-04-21 03:50:27

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2010 Dennis Nienhüser <nienhueser@kde.org>
0004 // SPDX-FileCopyrightText: 2012 Bernhard Beschow <bbeschow@cs.tu-berlin.de>
0005 //
0006 
0007 #include "GosmoreReverseGeocodingRunner.h"
0008 
0009 #include "MarbleDebug.h"
0010 #include "MarbleDirs.h"
0011 #include "routing/RouteRequest.h"
0012 #include "routing/instructions/WaypointParser.h"
0013 #include "routing/instructions/InstructionTransformation.h"
0014 #include "GeoDataExtendedData.h"
0015 #include "GeoDataData.h"
0016 #include "GeoDataPlacemark.h"
0017 
0018 #include <QProcess>
0019 
0020 namespace Marble
0021 {
0022 
0023 class GosmoreRunnerPrivate
0024 {
0025 public:
0026     QFileInfo m_gosmoreMapFile;
0027 
0028     WaypointParser m_parser;
0029 
0030     QByteArray retrieveWaypoints( const QString &query ) const;
0031 
0032     GosmoreRunnerPrivate();
0033 };
0034 
0035 GosmoreRunnerPrivate::GosmoreRunnerPrivate()
0036 {
0037     m_parser.setLineSeparator("\r");
0038     m_parser.setFieldSeparator(QLatin1Char(','));
0039     m_parser.setFieldIndex( WaypointParser::RoadName, 4 );
0040     m_parser.addJunctionTypeMapping( "Jr", RoutingWaypoint::Roundabout );
0041 }
0042 
0043 QByteArray GosmoreRunnerPrivate::retrieveWaypoints( const QString &query ) const
0044 {
0045     QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
0046     env.insert("QUERY_STRING", query);
0047     env.insert("LC_ALL", "C");
0048     QProcess gosmore;
0049     gosmore.setProcessEnvironment(env);
0050 
0051     gosmore.start("gosmore", QStringList() << m_gosmoreMapFile.absoluteFilePath() );
0052     if (!gosmore.waitForStarted(5000)) {
0053         mDebug() << "Couldn't start gosmore from the current PATH. Install it to retrieve routing results from gosmore.";
0054         return QByteArray();
0055     }
0056 
0057     if ( gosmore.waitForFinished(15000) ) {
0058         return gosmore.readAllStandardOutput();
0059     }
0060     else {
0061         mDebug() << "Couldn't stop gosmore";
0062     }
0063 
0064     return QByteArray();
0065 }
0066 
0067 GosmoreRunner::GosmoreRunner( QObject *parent ) :
0068         ReverseGeocodingRunner( parent ),
0069         d( new GosmoreRunnerPrivate )
0070 {
0071     // Check installation
0072     QDir mapDir(MarbleDirs::localPath() + QLatin1String("/maps/earth/gosmore/"));
0073     d->m_gosmoreMapFile = QFileInfo ( mapDir, "gosmore.pak" );
0074 }
0075 
0076 GosmoreRunner::~GosmoreRunner()
0077 {
0078     delete d;
0079 }
0080 
0081 void GosmoreRunner::reverseGeocoding( const GeoDataCoordinates &coordinates )
0082 {
0083     if ( !d->m_gosmoreMapFile.exists() )
0084     {
0085         emit reverseGeocodingFinished( coordinates, GeoDataPlacemark() );
0086         return;
0087     }
0088 
0089     QString queryString = "flat=%1&flon=%2&tlat=%1&tlon=%2&fastest=1&v=motorcar";
0090     double lon = coordinates.longitude( GeoDataCoordinates::Degree );
0091     double lat = coordinates.latitude( GeoDataCoordinates::Degree );
0092     queryString = queryString.arg( lat, 0, 'f', 8).arg(lon, 0, 'f', 8 );
0093     QByteArray output = d->retrieveWaypoints( queryString );
0094 
0095     GeoDataPlacemark placemark;
0096     placemark.setCoordinate( coordinates );
0097 
0098     QStringList lines = QString::fromUtf8(output).split(QLatin1Char('\r'));
0099     if ( lines.size() > 2 ) {
0100         QStringList fields = lines.at( lines.size()-2 ).split(QLatin1Char(','));
0101         if ( fields.size() >= 5 ) {
0102             QString road = fields.last().trimmed();
0103             placemark.setAddress( road );
0104             GeoDataExtendedData extendedData;
0105             extendedData.addValue(GeoDataData(QStringLiteral("road"), road));
0106             placemark.setExtendedData( extendedData );
0107         }
0108     }
0109 
0110     emit reverseGeocodingFinished( coordinates, placemark );
0111 }
0112 
0113 } // namespace Marble