~ubuntu-branches/ubuntu/quantal/marble/quantal

« back to all changes in this revision

Viewing changes to src/plugins/runner/routino/RoutinoRunner.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Philip Muškovac
  • Date: 2011-07-11 15:43:02 UTC
  • Revision ID: james.westby@ubuntu.com-20110711154302-lq69ftcx125g1jx5
Tags: upstream-4.6.90+repack
Import upstream version 4.6.90+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 2010      Dennis Nienhüser <earthwings@gentoo.org>
 
9
// Copyright 2010      Niko Sams <niko.sams@gmail.com>
 
10
//
 
11
 
 
12
#include "RoutinoRunner.h"
 
13
 
 
14
#include "MarbleDebug.h"
 
15
#include "MarbleDirs.h"
 
16
#include "routing/RouteRequest.h"
 
17
#include "routing/instructions/WaypointParser.h"
 
18
#include "routing/instructions/InstructionTransformation.h"
 
19
#include "GeoDataDocument.h"
 
20
#include "GeoDataExtendedData.h"
 
21
 
 
22
#include <QtCore/QProcess>
 
23
#include <QtCore/QMap>
 
24
#include <QtCore/QTemporaryFile>
 
25
#include <MarbleMap.h>
 
26
#include <MarbleModel.h>
 
27
#include <routing/RoutingManager.h>
 
28
#include <routing/RoutingModel.h>
 
29
#include <routing/RoutingProfilesModel.h>
 
30
 
 
31
namespace Marble
 
32
{
 
33
 
 
34
class RoutinoRunnerPrivate
 
35
{
 
36
public:
 
37
    QDir m_mapDir;
 
38
 
 
39
    WaypointParser m_parser;
 
40
 
 
41
    QByteArray retrieveWaypoints( const QStringList &params ) const;
 
42
 
 
43
    GeoDataDocument* createDocument( GeoDataLineString* routeWaypoints, const QVector<GeoDataPlacemark*> instructions ) const;
 
44
 
 
45
    GeoDataLineString* parseRoutinoOutput( const QByteArray &content ) const;
 
46
 
 
47
    QVector<GeoDataPlacemark*> parseRoutinoInstructions( const QByteArray &content ) const;
 
48
 
 
49
    RoutinoRunnerPrivate();
 
50
};
 
51
 
 
52
RoutinoRunnerPrivate::RoutinoRunnerPrivate()
 
53
{
 
54
    m_parser.setLineSeparator("\n");
 
55
    m_parser.setFieldSeparator('\t');
 
56
    m_parser.setFieldIndex( WaypointParser::RoadName, 10 );
 
57
}
 
58
 
 
59
class TemporaryDir
 
60
{
 
61
public:
 
62
    TemporaryDir() {
 
63
        QTemporaryFile f;
 
64
        f.setAutoRemove( false );
 
65
        f.open();
 
66
        m_dirName = f.fileName();
 
67
        f.close();
 
68
        f.remove();
 
69
        QFileInfo( m_dirName ).dir().mkdir( m_dirName );
 
70
    }
 
71
 
 
72
    ~TemporaryDir() {
 
73
        QDir dir( m_dirName );
 
74
        QFileInfoList entries = dir.entryInfoList( QDir::Files );
 
75
        foreach ( const QFileInfo &file, entries ) {
 
76
            QFile( file.absoluteFilePath() ).remove();
 
77
        }
 
78
        dir.rmdir( dir.absolutePath() );
 
79
    }
 
80
 
 
81
    QString dirName() const
 
82
    {
 
83
        return m_dirName;
 
84
    }
 
85
private:
 
86
    QString m_dirName;
 
87
};
 
88
 
 
89
QByteArray RoutinoRunnerPrivate::retrieveWaypoints( const QStringList &params ) const
 
90
{
 
91
    TemporaryDir dir;
 
92
    QProcess routinoProcess;
 
93
    routinoProcess.setWorkingDirectory( dir.dirName() );
 
94
 
 
95
    QStringList routinoParams;
 
96
    routinoParams << params;
 
97
    routinoParams << "--dir=" + m_mapDir.absolutePath();
 
98
    routinoParams << "--output-text-all";
 
99
    mDebug() << routinoParams;
 
100
    routinoProcess.start( "routino-router", routinoParams );
 
101
    if ( !routinoProcess.waitForStarted( 5000 ) ) {
 
102
        mDebug() << "Couldn't start routino-router from the current PATH. Install it to retrieve routing results from routino.";
 
103
        return 0;
 
104
    }
 
105
 
 
106
    if ( routinoProcess.waitForFinished(60 * 1000) ) {
 
107
        mDebug() << routinoProcess.readAll();
 
108
        mDebug() << "routino finished";
 
109
        QFile file( routinoProcess.workingDirectory() + "/shortest-all.txt" );
 
110
        if ( !file.exists() ) {
 
111
            file.setFileName( routinoProcess.workingDirectory() + "/quickest-all.txt" );
 
112
        }
 
113
        if ( !file.exists() ) {
 
114
            mDebug() << "Can't get results";
 
115
        } else {
 
116
            file.open( QIODevice::ReadOnly );
 
117
            return file.readAll();
 
118
        }
 
119
    }
 
120
    else {
 
121
        mDebug() << "Couldn't stop routino";
 
122
    }
 
123
    return 0;
 
124
}
 
125
 
 
126
GeoDataLineString* RoutinoRunnerPrivate::parseRoutinoOutput( const QByteArray &content ) const
 
127
{
 
128
    GeoDataLineString* routeWaypoints = new GeoDataLineString;
 
129
 
 
130
    QStringList lines = QString::fromUtf8( content ).split( '\n' );
 
131
    mDebug() << lines.count() << "lines";
 
132
    foreach( const QString &line, lines ) {
 
133
        if ( line.left(1) == QString('#') ) {
 
134
             //skip comment
 
135
            continue;
 
136
        }
 
137
        QStringList fields = line.split('\t');
 
138
        if ( fields.size() >= 10 ) {
 
139
            qreal lon = fields.at(1).trimmed().toDouble();
 
140
            qreal lat = fields.at(0).trimmed().toDouble();
 
141
            GeoDataCoordinates coordinates( lon, lat, 0.0, GeoDataCoordinates::Degree );
 
142
            routeWaypoints->append( coordinates );
 
143
        }
 
144
    }
 
145
 
 
146
    return routeWaypoints;
 
147
}
 
148
 
 
149
QVector<GeoDataPlacemark*> RoutinoRunnerPrivate::parseRoutinoInstructions( const QByteArray &content ) const
 
150
{
 
151
    QVector<GeoDataPlacemark*> result;
 
152
    QTextStream stream( content );
 
153
    stream.setCodec("UTF8");
 
154
    stream.setAutoDetectUnicode( true );
 
155
 
 
156
    RoutingInstructions directions = InstructionTransformation::process( m_parser.parse( stream ) );
 
157
    for( int i=0; i<directions.size(); ++i ) {
 
158
        GeoDataPlacemark* placemark = new GeoDataPlacemark( directions[i].instructionText() );
 
159
        GeoDataExtendedData extendedData;
 
160
        GeoDataData turnType;
 
161
        turnType.setName( "turnType" );
 
162
        turnType.setValue( qVariantFromValue<int>( int( directions[i].turnType() ) ) );
 
163
        extendedData.addValue( turnType );
 
164
        placemark->setExtendedData( extendedData );
 
165
        Q_ASSERT( !directions[i].points().isEmpty() );
 
166
        GeoDataLineString* geometry = new GeoDataLineString;
 
167
        QVector<RoutingWaypoint> items = directions[i].points();
 
168
        for (int j=0; j<items.size(); ++j ) {
 
169
            RoutingPoint point = items[j].point();
 
170
            GeoDataCoordinates coordinates( point.lon(), point.lat(), 0.0, GeoDataCoordinates::Degree );
 
171
            geometry->append( coordinates );
 
172
        }
 
173
        placemark->setGeometry( geometry );
 
174
        result.push_back( placemark );
 
175
    }
 
176
 
 
177
    return result;
 
178
}
 
179
 
 
180
GeoDataDocument* RoutinoRunnerPrivate::createDocument( GeoDataLineString* routeWaypoints, const QVector<GeoDataPlacemark*> instructions ) const
 
181
{
 
182
    if ( !routeWaypoints || routeWaypoints->isEmpty() ) {
 
183
        return 0;
 
184
    }
 
185
 
 
186
    GeoDataDocument* result = new GeoDataDocument();
 
187
    GeoDataPlacemark* routePlacemark = new GeoDataPlacemark;
 
188
    routePlacemark->setName( "Route" );
 
189
    routePlacemark->setGeometry( routeWaypoints );
 
190
    result->append( routePlacemark );
 
191
 
 
192
    QString name = "%1 %2 (Routino)";
 
193
    QString unit = "m";
 
194
    qreal length = routeWaypoints->length( EARTH_RADIUS );
 
195
    if (length >= 1000) {
 
196
        length /= 1000.0;
 
197
        unit = "km";
 
198
    }
 
199
    result->setName( name.arg( length, 0, 'f', 1 ).arg( unit ) );
 
200
 
 
201
    foreach( GeoDataPlacemark* placemark, instructions )
 
202
    {
 
203
        result->append( placemark );
 
204
    }
 
205
 
 
206
    return result;
 
207
}
 
208
 
 
209
RoutinoRunner::RoutinoRunner( QObject *parent ) :
 
210
        MarbleAbstractRunner( parent ),
 
211
        d( new RoutinoRunnerPrivate )
 
212
{
 
213
    // Check installation
 
214
    d->m_mapDir = QDir( MarbleDirs::localPath() + "/maps/earth/routino/" );
 
215
}
 
216
 
 
217
RoutinoRunner::~RoutinoRunner()
 
218
{
 
219
    delete d;
 
220
}
 
221
 
 
222
GeoDataFeature::GeoDataVisualCategory RoutinoRunner::category() const
 
223
{
 
224
    return GeoDataFeature::OsmSite;
 
225
}
 
226
 
 
227
void RoutinoRunner::retrieveRoute( RouteRequest *route )
 
228
{
 
229
    mDebug();
 
230
 
 
231
    if ( ! QFileInfo( d->m_mapDir, "nodes.mem" ).exists() )
 
232
    {
 
233
        emit routeCalculated( 0 );
 
234
        return;
 
235
    }
 
236
 
 
237
    QStringList params;
 
238
    for( int i=0; i<route->size(); ++i )
 
239
    {
 
240
        double fLon = route->at(i).longitude( GeoDataCoordinates::Degree );
 
241
        double fLat = route->at(i).latitude( GeoDataCoordinates::Degree );
 
242
        params << QString("--lat%1=%2").arg(i+1).arg(fLat, 0, 'f', 8);
 
243
        params << QString("--lon%1=%2").arg(i+1).arg(fLon, 0, 'f', 8);
 
244
    }
 
245
 
 
246
    QHash<QString, QVariant> settings = route->routingProfile().pluginSettings()["routino"];
 
247
    QString transport = settings["transport"].toString();
 
248
    params << QString( "--transport=%0" ).arg( transport );
 
249
 
 
250
    if ( settings["method"] == "shortest" ) {
 
251
        params << "--shortest";
 
252
    } else {
 
253
        params << "--quickest";
 
254
    }
 
255
    /*
 
256
    if ( route->avoidFeatures() & RouteRequest::AvoidHighway ) {
 
257
        params << "--highway-motorway=0";
 
258
    }
 
259
    */
 
260
 
 
261
    QByteArray output = d->retrieveWaypoints( params );
 
262
    GeoDataLineString* wayPoints = d->parseRoutinoOutput( output );
 
263
    QVector<GeoDataPlacemark*> instructions = d->parseRoutinoInstructions( output );
 
264
 
 
265
    GeoDataDocument* result = d->createDocument( wayPoints, instructions );
 
266
    mDebug() << this << "routeCalculated";
 
267
    emit routeCalculated( result );
 
268
}
 
269
 
 
270
} // namespace Marble
 
271
 
 
272
#include "RoutinoRunner.moc"