21 #include <QTemporaryFile>
26 class TravelingSalesmanRunnerPrivate
29 QFileInfo m_travelingsalesmanJar;
31 GeoDataLineString retrieveWaypoints(
const QPair<QString, QString> &query )
const;
33 GeoDataDocument* createDocument( GeoDataLineString* routeWaypoints )
const;
35 GeoDataLineString parseTravelingSalesmanOutput( QFile &file )
const;
37 void merge( GeoDataLineString* one,
const GeoDataLineString& two )
const;
40 static QMap<QString, GeoDataLineString> m_partialRoutes;
43 QMap<QString, GeoDataLineString> TravelingSalesmanRunnerPrivate::m_partialRoutes;
45 void TravelingSalesmanRunnerPrivate::merge( GeoDataLineString* one,
const GeoDataLineString& two )
const
49 QVector<GeoDataCoordinates>::const_iterator iter = two.constBegin();
50 for ( ; iter != two.constEnd(); ++iter ) {
56 GeoDataLineString TravelingSalesmanRunnerPrivate::retrieveWaypoints(
const QPair<QString, QString> &query )
const
58 QString cacheItem = query.first + query.second;
59 if ( m_partialRoutes.contains( cacheItem ) ) {
60 return m_partialRoutes[cacheItem];
63 QTemporaryFile gpxFile;
64 if ( !gpxFile.open() ) {
65 mDebug() <<
"Unable to create a temporary work file";
66 return GeoDataLineString();
69 QProcess travelingsalesman;
70 QStringList arguments = QStringList() <<
"-jar" << m_travelingsalesmanJar.absoluteFilePath();
71 arguments <<
"route" <<
"-gpx" << gpxFile.fileName();
72 arguments << query.first << query.second;
73 travelingsalesman.start(
"java", arguments );
74 if ( !travelingsalesman.waitForStarted( 5000 ) ) {
75 mDebug() <<
"Couldn't start travelingsalesman from the current PATH. Is java setup correctly?";
76 return GeoDataLineString();
79 if ( travelingsalesman.waitForFinished( 60 * 1000 ) ) {
80 m_partialRoutes[cacheItem] = parseTravelingSalesmanOutput( gpxFile );
81 return m_partialRoutes[cacheItem];
83 mDebug() <<
"Couldn't stop travelingsalesman";
86 return GeoDataLineString();
89 GeoDataLineString TravelingSalesmanRunnerPrivate::parseTravelingSalesmanOutput( QFile &file )
const
91 GeoDataParser parser( GeoData_GPX );
92 if ( !parser.read( &file ) ) {
93 mDebug() <<
"Could not parse gpx file " << file.fileName();
94 return GeoDataLineString();
97 GeoDataLineString result;
98 GeoDocument* document = parser.releaseDocument();
99 GeoDataDocument* route =
dynamic_cast<GeoDataDocument*
>( document );
102 if ( route->placemarkList().size() == 1 ) {
103 GeoDataPlacemark* placemark = route->placemarkList().first();
104 GeoDataMultiGeometry* multi =
dynamic_cast<GeoDataMultiGeometry*
>( placemark->geometry() );
105 if ( multi && multi->size() == 1 ) {
106 GeoDataLineString* lineString =
dynamic_cast<GeoDataLineString*
>( &multi->first() );
117 GeoDataDocument* TravelingSalesmanRunnerPrivate::createDocument( GeoDataLineString* routeWaypoints )
const
119 if ( !routeWaypoints || routeWaypoints->isEmpty() ) {
123 GeoDataDocument* result =
new GeoDataDocument();
124 GeoDataPlacemark* routePlacemark =
new GeoDataPlacemark;
125 routePlacemark->setName(
"Route" );
126 routePlacemark->setGeometry( routeWaypoints );
127 result->append( routePlacemark );
129 QString name =
"%1 %2 (Traveling Salesman)";
132 if ( length >= 1000 ) {
136 result->setName( name.arg( length, 0,
'f', 1 ).arg( unit ) );
142 d( new TravelingSalesmanRunnerPrivate )
146 d->m_travelingsalesmanJar = QFileInfo ( mapDir,
"traveling-salesman.jar" );
161 if ( !d->m_travelingsalesmanJar.exists() ) {
162 emit routeCalculated( 0 );
168 for (
int i = 0; i < route->
size() - 1; ++i ) {
169 QPair<QString, QString> queryString;
173 queryString.first = QString(
"[%1,%2]" ).arg( fLat, 0,
'f', 8 ).arg( fLon, 0,
'f', 8 );
177 queryString.second = QString(
"[%1,%2]" ).arg( tLat, 0,
'f', 8 ).arg( tLon, 0,
'f', 8 );
179 d->merge( wayPoints, d->retrieveWaypoints( queryString ) );
183 emit routeCalculated( result );
int size() const
Number of points in the route.
A 3d point representation.
A container for Features, Styles and in the future Schemas.
TravelingSalesmanRunner(QObject *parent=0)
static QString localPath()
qreal latitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the latitude of the GeoDataCoordinates object use the unit parameter to switch between Radi...
Points to be included in a route.
A LineString that allows to store a contiguous set of line segments.
qreal longitude(GeoDataCoordinates::Unit unit=GeoDataCoordinates::Radian) const
retrieves the longitude of the GeoDataCoordinates object use the unit parameter to switch between Rad...
GeoDataFeature::GeoDataVisualCategory category() const
virtual void retrieveRoute(RouteRequest *request)
GeoDataVisualCategory
A categorization of a placemark as defined by ...FIXME.
~TravelingSalesmanRunner()
QDebug mDebug()
a function to replace qDebug() in Marble library code
GeoDataCoordinates at(int index) const
Accessor for the n-th position.