13 #include <QCoreApplication>
14 #include <QStringList>
22 m_roadName( item.roadName() ), m_roadType( item.roadType() ),
23 m_secondsLeft( item.secondsRemaining() ),
24 m_angleToPredecessor( 0.0 ), m_roundaboutExit( 0 ),
25 m_predecessor( 0 ), m_successor( 0 )
27 m_points.append( item );
32 if ( m_points.size() && m_points.last().roadType() !=
"roundabout" && item.
roadType() ==
"roundabout" ) {
34 m_points.push_back( item );
38 if ( m_points.size() && m_points.last().roadType() ==
"roundabout" && item.
roadType() !=
"roundabout" ) {
40 m_points.push_back( item );
44 m_points.push_back( item );
57 return angle >= 150 && angle <= 210;
78 void RoutingInstruction::calculateAngle()
80 if ( !m_predecessor ) {
84 int hisSize = m_predecessor->
points().size();
85 int mySize = m_points.size();
86 Q_ASSERT( mySize > 0 && hisSize > 0 );
87 RoutingPoint one =
points().first().point();
88 RoutingPoint two = m_predecessor->
points().at( hisSize - 1 ).point();
90 for (
int i = 2; i <= qMin<int>( hisSize, 20 ) && distance < 50.0; ++i ) {
91 two = m_predecessor->
points().at( hisSize - i ).point();
92 m_intersectionPoints.push_front( two );
93 distance = one.distance( two );
95 qreal before = two.bearing( one );
96 m_intersectionPoints.push_back( one );
98 one =
points().first().point();
99 if ( mySize == 1 && !m_successor ) {
101 }
else if ( mySize == 1 ) {
102 Q_ASSERT( !m_successor->
points().isEmpty() );
103 two = m_successor->
points().first().point();
105 two =
points().at( 1 ).point();
109 m_intersectionPoints.push_back( one );
110 for (
int i = 2; i < qMin<int>( mySize, 20 ) && distance < 50.0; ++i ) {
111 two =
points().at( i ).point();
112 m_intersectionPoints.push_back( two );
113 distance = one.distance( two );
116 qreal after = one.bearing( two );
117 m_angleToPredecessor = after - before;
120 void RoutingInstruction::calculateTurnType()
143 Q_ASSERT( angle >= 0 && angle <= 360 );
145 const int sharp = 30;
146 if ( angle >= 360 - sharp || angle < sharp ) {
148 }
else if ( angle >= sharp && angle < 90 - sharp ) {
150 }
else if ( angle >= 90 - sharp && angle < 90 + sharp ) {
152 }
else if ( angle >= 90 + sharp && angle < 180 - sharp ) {
154 }
else if ( angle >= 180 - sharp && angle < 180 + sharp ) {
156 }
else if ( angle >= 180 + sharp && angle < 270 - sharp ) {
158 }
else if ( angle >= 270 - sharp && angle < 270 + sharp ) {
160 }
else if ( angle >= 270 + sharp && angle < 360 - sharp ) {
163 Q_ASSERT(
false &&
"Internal error: not all angles are properly handled" );
174 return m_intersectionPoints;
179 return m_angleToPredecessor;
184 return m_predecessor;
189 return m_predecessor;
217 for (
int i = 1; i < m_points.size(); ++i ) {
218 result += m_points[i-1].point().distance( m_points[i].point() );
249 return QObject::tr(
"Enter the roundabout." );
252 if (
roadType() ==
"motorway_link" ) {
253 QStringList motorways = QStringList() <<
"motorway" <<
"motorway_link";
257 return QObject::tr(
"Take the exit." );
259 return QObject::tr(
"Take the exit towards %1." ).arg(
roadName() );
263 return QObject::tr(
"Take the ramp." );
265 return QObject::tr(
"Take the ramp towards %1." ).arg(
roadName() );
289 QLocale::MeasurementSystem
const measurement = QLocale::system().measurementSystem();
292 QString distanceUnit = QLatin1String(
"m" );
294 if ( measurement == QLocale::ImperialSystem ) {
300 if ( length >= 1000 ) {
304 }
else if ( length >= 200 ) {
305 length = 50 * qRound( length / 50 );
306 }
else if ( length >= 100 ) {
307 length = 25 * qRound( length / 25 );
309 length = 10 * qRound( length / 10 );
316 QString text = QObject::tr(
"Follow the road for %1 %2." );
317 return text.arg( length, 0,
'f', precision ).arg( distanceUnit );
324 QString durationUnit =
"sec";
326 if ( duration >= 60.0 ) {
328 durationUnit =
"min";
331 if ( duration >= 60.0 ) {
337 QString text =
"Arrival in %1 %2.";
338 return text.arg( duration, 0,
'f', precision ).arg( durationUnit );
345 if ( QCoreApplication::instance()->arguments().contains(
"--remaining-duration" ) ) {
353 int roundaboutExit = 0;
354 switch ( turnType ) {
368 if ( roundaboutExit > 0 ) {
369 if ( roadName.isEmpty() ) {
370 return QObject::tr(
"Take the %1. exit in the roundabout." ).arg( roundaboutExit );
372 QString text = QObject::tr(
"Take the %1. exit in the roundabout into %2." );
373 return text.arg( roundaboutExit ).arg( roadName );
377 if ( roadName.isEmpty() ) {
380 return QObject::tr(
"Continue." );
382 return QObject::tr(
"Merge." );
384 return QObject::tr(
"Turn around." );
386 return QObject::tr(
"Turn sharp left." );
388 return QObject::tr(
"Turn left." );
390 return QObject::tr(
"Keep slightly left." );
392 return QObject::tr(
"Go straight ahead." );
394 return QObject::tr(
"Keep slightly right." );
396 return QObject::tr(
"Turn right." );
398 return QObject::tr(
"Turn sharp right." );
400 return QObject::tr(
"Exit the roundabout." );
405 Q_ASSERT(
false &&
"Internal error: Unknown/Roundabout should have been handled earlier." );
409 return QObject::tr(
"Take the exit to the left." );
411 return QObject::tr(
"Take the exit to the right." );
416 return QObject::tr(
"Continue onto %1." ).arg( roadName );
418 return QObject::tr(
"Merge onto %1." ).arg( roadName );
420 return QObject::tr(
"Turn around onto %1." ).arg( roadName );
422 return QObject::tr(
"Turn sharp left on %1." ).arg( roadName );
424 return QObject::tr(
"Turn left into %1." ).arg( roadName );
426 return QObject::tr(
"Keep slightly left on %1." ).arg( roadName );
428 return QObject::tr(
"Continue on %1." ).arg( roadName );
430 return QObject::tr(
"Keep slightly right on %1." ).arg( roadName );
432 return QObject::tr(
"Turn right into %1." ).arg( roadName );
434 return QObject::tr(
"Turn sharp right into %1." ).arg( roadName );
436 return QObject::tr(
"Exit the roundabout into %2." ).arg( roadName );
441 Q_ASSERT(
false &&
"Internal error: Unknown/Roundabout should have been handled earlier." );
445 return QObject::tr(
"Take the exit to the left onto %1." ).arg( roadName );
447 return QObject::tr(
"Take the exit to the right onto %1." ).arg( roadName );
451 Q_ASSERT(
false &&
"Internal error: Switch did not handle all cases.");
457 stream.setRealNumberPrecision( 8 );
458 if ( i.
points().isEmpty() ) {
462 if ( QCoreApplication::instance()->arguments().contains(
"--dense" ) ) {
463 QVector<RoutingWaypoint> points = i.
points();
464 int maxElement = points.size() - ( i.
successor() ? 1 : 0 );
465 for (
int j = 0; j < maxElement; ++j ) {
466 stream << points[j].point().lat() <<
',';
467 stream << points[j].point().lon() <<
',';
468 stream << points[j].junctionTypeRaw() <<
',';
469 stream << points[j].roadType() <<
',';
470 stream << points[j].secondsRemaining() <<
',';
474 if ( j < maxElement - 1 ) {
482 if ( QCoreApplication::instance()->arguments().contains(
"--csv" ) ) {
483 stream << i.
points().first().point().lat() <<
',';
484 stream << i.
points().first().point().lon() <<
',';
486 QString distanceUnit =
"m ";
489 if ( length >= 1000 ) {
495 QString totalDistance =
"[%1 %2] ";
496 stream << totalDistance.arg( length, 3,
'f', precision ).arg( distanceUnit );
501 if ( QCoreApplication::instance()->arguments().contains(
"--csv" ) && QCoreApplication::instance()->arguments().contains(
"--intersection-points" ) ) {
503 stream <<
',' << point.
lat() <<
',' << point.
lon();
512 return m_roundaboutExit;
Stores data related to one instruction: Road name, angle to predecessor, associated waypoints etc...
qreal lat() const
Latitude of the point.
QString roadName() const
OSM name of the road.
qreal distanceFromStart() const
The distance from the route start.
RoutingInstruction(const RoutingWaypoint &item=RoutingWaypoint())
Constructor.
double angle(double vec1[3], double vec2[3])
bool append(const RoutingWaypoint &item, int angle)
Append data of the given item, returns true if item's street name matches instructions street name...
qreal lon() const
Longitude of the point.
void setPredecessor(RoutingInstruction *predecessor)
Change the predecessor.
TurnType turnType() const
qreal angleToPredecssor() const
The angle between the two turn roads, in radians.
static QString generateRoadInstruction(TurnType turnType, const QString &roadName)
QString roadType() const
OSM type of the road to turn into.
JunctionType junctionType() const
Parsed junction type.
qreal distanceToEnd() const
The distance to the route end.
void setSuccessor(RoutingInstruction *successor)
Change the successor.
QString totalDurationRemaining() const
Formats the instruction (duration to destination) for a human reader.
int roundaboutExitNumber() const
QVector< RoutingPoint > intersectionPoints() const
Contains the intersection point and points near it on the previous and current road.
QString roadName() const
Name of the road to turn into.
QVector< RoutingWaypoint > points() const
Waypoints from the last instruction to this instruction.
QString nextDistanceInstruction() const
Formats the instruction (distance to next instruction) for a human reader.
RoutingInstruction * predecessor()
Previous turn road.
QString nextRoadInstruction() const
Formats the instruction (road name) for a human reader.
int secondsLeft() const
Estimated number of seconds to the route destination.
RoutingInstruction * successor()
Next turn road.
QString roadType() const
OSM type of the road.
There are many Point classes, but this is mine.
QString instructionText() const
Formats the instruction for a human reader.
qreal distance() const
The accumulated distance of all waypoints belonging to this instruction.
QTextStream & operator<<(QTextStream &stream, const RoutingInstruction &i)
Stores one line of gosmore/routino output.