6#include "RoutingInstruction.h"
8#include <QCoreApplication>
18 m_roadName( item.roadName() ), m_roadType( item.roadType() ),
19 m_secondsLeft( item.secondsRemaining() ),
20 m_angleToPredecessor( 0.0 ), m_roundaboutExit( 0 ),
21 m_predecessor( nullptr ), m_successor( nullptr )
23 m_points.append( item );
28 if (m_points.size() &&
32 m_points.push_back( item );
36 if (m_points.size() &&
40 m_points.push_back( item );
44 m_points.push_back( item );
46 if ( item.
junctionType() == RoutingWaypoint::Roundabout ) {
57 return angle >= 150 && angle <= 210;
78void 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 );
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 );
116 qreal after = one.bearing( two );
117 m_angleToPredecessor = after - before;
120void RoutingInstruction::calculateTurnType()
126 m_turnType = RoundaboutFirstExit;
129 m_turnType = RoundaboutSecondExit;
132 m_turnType = RoundaboutThirdExit;
135 m_turnType = RoundaboutExit;
143 Q_ASSERT( angle >= 0 && angle <= 360 );
145 const int sharp = 30;
146 if ( angle >= 360 - sharp || angle < sharp ) {
147 m_turnType = TurnAround;
148 }
else if ( angle >= sharp && angle < 90 - sharp ) {
149 m_turnType = SharpLeft;
150 }
else if ( angle >= 90 - sharp && angle < 90 + sharp ) {
152 }
else if ( angle >= 90 + sharp && angle < 180 - sharp ) {
153 m_turnType = SlightLeft;
154 }
else if ( angle >= 180 - sharp && angle < 180 + sharp ) {
155 m_turnType = Straight;
156 }
else if ( angle >= 180 + sharp && angle < 270 - sharp ) {
157 m_turnType = SlightRight;
158 }
else if ( angle >= 270 - sharp && angle < 270 + sharp ) {
160 }
else if ( angle >= 270 + sharp && angle < 360 - sharp ) {
161 m_turnType = SharpRight;
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() );
269 TurnType turnType = m_turnType;
273 turnType = RoundaboutFirstExit;
276 turnType = RoundaboutSecondExit;
279 turnType = RoundaboutThirdExit;
284 return generateRoadInstruction( turnType,
roadName() );
299 if ( length < 0.1 ) {
300 length = 10 * qRound( length * 528 );
305 if ( length >= 1000 ) {
309 }
else if ( length >= 200 ) {
310 length = 50 * qRound( length / 50 );
311 }
else if ( length >= 100 ) {
312 length = 25 * qRound( length / 25 );
314 length = 10 * qRound( length / 10 );
322 return text.
arg( length, 0,
'f', precision ).
arg( distanceUnit );
331 if ( duration >= 60.0 ) {
333 durationUnit =
"min";
336 if ( duration >= 60.0 ) {
338 durationUnit = QStringLiteral(
"h");
342 QString text =
"Arrival in %1 %2.";
343 return text.
arg( duration, 0,
'f', precision ).
arg( durationUnit );
356QString RoutingInstruction::generateRoadInstruction( RoutingInstruction::TurnType turnType,
const QString &roadName )
358 int roundaboutExit = 0;
359 switch ( turnType ) {
360 case RoundaboutFirstExit:
363 case RoundaboutSecondExit:
366 case RoundaboutThirdExit:
373 if ( roundaboutExit > 0 ) {
375 return QObject::tr(
"Take the %1. exit in the roundabout." ).
arg( roundaboutExit );
407 case RoundaboutFirstExit:
408 case RoundaboutSecondExit:
409 case RoundaboutThirdExit:
410 Q_ASSERT(
false &&
"Internal error: Unknown/Roundabout should have been handled earlier." );
413 return QObject::tr(
"Take the exit to the left." );
415 return QObject::tr(
"Take the exit to the right." );
442 case RoundaboutFirstExit:
443 case RoundaboutSecondExit:
444 case RoundaboutThirdExit:
445 Q_ASSERT(
false &&
"Internal error: Unknown/Roundabout should have been handled earlier." );
454 Q_ASSERT(
false &&
"Internal error: Switch did not handle all cases.");
461 if ( i.points().isEmpty() ) {
467 int maxElement = points.
size() - ( i.successor() ? 1 : 0 );
468 for (
int j = 0; j < maxElement; ++j ) {
469 stream << points[j].point().lat() <<
',';
470 stream << points[j].point().lon() <<
',';
471 stream << points[j].junctionTypeRaw() <<
',';
472 stream << points[j].roadType() <<
',';
473 stream << points[j].secondsRemaining() <<
',';
475 stream << i.instructionText();
477 if ( j < maxElement - 1 ) {
486 stream << i.points().first().point().lat() <<
',';
487 stream << i.points().first().point().lon() <<
',';
491 qreal length = i.distanceFromStart();
492 if ( length >= 1000 ) {
498 QString totalDistance =
"[%1 %2] ";
499 stream << totalDistance.
arg( length, 3,
'f', precision ).
arg( distanceUnit );
502 stream << i.instructionText();
506 for (
const RoutingPoint &point: i.intersectionPoints() ) {
507 stream <<
',' << point.lat() <<
',' << point.lon();
514int RoutingInstruction::roundaboutExitNumber()
const
516 return m_roundaboutExit;
519RoutingInstruction::TurnType RoutingInstruction::turnType()
const
Stores data related to one instruction: Road name, angle to predecessor, associated waypoints etc.
bool append(const RoutingWaypoint &item, int angle)
Append data of the given item, returns true if item's street name matches instructions street name.
QString roadName() const
Name of the road to turn into.
QString totalDurationRemaining() const
Formats the instruction (duration to destination) for a human reader.
RoutingInstruction(const RoutingWaypoint &item=RoutingWaypoint())
Constructor.
void setPredecessor(RoutingInstruction *predecessor)
Change the predecessor.
QString instructionText() const
Formats the instruction for a human reader.
QString nextDistanceInstruction() const
Formats the instruction (distance to next instruction) for a human reader.
qreal angleToPredecssor() const
The angle between the two turn roads, in radians.
QString nextRoadInstruction() const
Formats the instruction (road name) for a human reader.
qreal distanceToEnd() const
The distance to the route end.
QVector< RoutingPoint > intersectionPoints() const
Contains the intersection point and points near it on the previous and current road.
QString roadType() const
OSM type of the road to turn into.
RoutingInstruction * predecessor()
Previous turn road.
qreal distanceFromStart() const
The distance from the route start.
int secondsLeft() const
Estimated number of seconds to the route destination.
RoutingInstruction * successor()
Next turn road.
QVector< RoutingWaypoint > points() const
Waypoints from the last instruction to this instruction.
void setSuccessor(RoutingInstruction *successor)
Change the successor.
qreal distance() const
The accumulated distance of all waypoints belonging to this instruction.
Stores one line of gosmore/routino output.
QString roadType() const
OSM type of the road.
QString roadName() const
OSM name of the road.
JunctionType junctionType() const
Parsed junction type.
Binds a QML item to a specific geodetic location in screen coordinates.
QDebug operator<<(QDebug dbg, const PerceptualColor::LchaDouble &value)
QCoreApplication * instance()
qsizetype size() const const
MeasurementSystem measurementSystem() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(Args &&... args) const const
bool isEmpty() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
void setRealNumberPrecision(int precision)