File indexing completed on 2024-04-28 03:49:28

0001 // SPDX-License-Identifier: LGPL-2.1-or-later
0002 //
0003 // SPDX-FileCopyrightText: 2011 Dennis Nienhüser <nienhueser@kde.org>
0004 //
0005 
0006 #include "Route.h"
0007 
0008 namespace Marble
0009 {
0010 
0011 Route::Route() :
0012     m_distance( 0.0 ),
0013     m_travelTime( 0 ),
0014     m_positionDirty( true ),
0015     m_closestSegmentIndex( -1 )
0016 {
0017     // nothing to do
0018 }
0019 
0020 void Route::addRouteSegment( const RouteSegment &segment )
0021 {
0022     if ( segment.isValid() ) {
0023         m_bounds = m_bounds.united( segment.bounds() );
0024         m_distance += segment.distance();
0025         m_path << segment.path();
0026         if ( segment.maneuver().position().isValid() ) {
0027             m_turnPoints << segment.maneuver().position();
0028         }
0029         if ( segment.maneuver().hasWaypoint() ) {
0030             m_waypoints << segment.maneuver().waypoint();
0031         }
0032         m_segments.push_back( segment );
0033         m_positionDirty = true;
0034 
0035         for ( int i=1; i<m_segments.size(); ++i ) {
0036             m_segments[i-1].setNextRouteSegment(&m_segments[i]);
0037         }
0038     }
0039 }
0040 
0041 GeoDataLatLonBox Route::bounds() const
0042 {
0043     return m_bounds;
0044 }
0045 
0046 qreal Route::distance() const
0047 {
0048     return m_distance;
0049 }
0050 
0051 int Route::size() const
0052 {
0053     return m_segments.size();
0054 }
0055 
0056 const RouteSegment & Route::at( int index ) const
0057 {
0058     return m_segments[index];
0059 }
0060 
0061 int Route::indexOf(const RouteSegment &segment) const
0062 {
0063     return m_segments.indexOf(segment);
0064 }
0065 
0066 const GeoDataLineString & Route::path() const
0067 {
0068     return m_path;
0069 }
0070 
0071 int Route::travelTime() const
0072 {
0073     return m_travelTime;
0074 }
0075 
0076 const GeoDataLineString & Route::turnPoints() const
0077 {
0078     return m_turnPoints;
0079 }
0080 
0081 const GeoDataLineString & Route::waypoints() const
0082 {
0083     return m_waypoints;
0084 }
0085 
0086 void Route::setPosition( const GeoDataCoordinates &position )
0087 {
0088     m_position = position;
0089     m_positionDirty = true;
0090 }
0091 
0092 GeoDataCoordinates Route::position() const
0093 {
0094     return m_position;
0095 }
0096 
0097 void Route::updatePosition() const
0098 {
0099     if ( !m_segments.isEmpty() ) {
0100         if ( m_closestSegmentIndex < 0 || m_closestSegmentIndex >= m_segments.size() ) {
0101             m_closestSegmentIndex = 0;
0102         }
0103 
0104         qreal distance = m_segments[m_closestSegmentIndex].distanceTo( m_position, m_currentWaypoint, m_positionOnRoute );
0105         QList<int> candidates;
0106 
0107         for ( int i=0; i<m_segments.size(); ++i ) {
0108             if ( i != m_closestSegmentIndex && m_segments[i].minimalDistanceTo( m_position ) <= distance ) {
0109                 candidates << i;
0110             }
0111         }
0112 
0113         GeoDataCoordinates closest, interpolated;
0114         for( int i: candidates ) {
0115             qreal const dist = m_segments[i].distanceTo( m_position, closest, interpolated );
0116             if ( distance < 0.0 || dist < distance ) {
0117                 distance = dist;
0118                 m_closestSegmentIndex = i;
0119                 m_positionOnRoute = interpolated;
0120                 m_currentWaypoint = closest;
0121             }
0122         }
0123     }
0124 
0125     m_positionDirty = false;
0126 }
0127 
0128 const RouteSegment & Route::currentSegment() const
0129 {
0130     if ( m_positionDirty ) {
0131         updatePosition();
0132     }
0133 
0134     if ( m_closestSegmentIndex < 0 || m_closestSegmentIndex >= m_segments.size() ) {
0135         static RouteSegment invalid;
0136         return invalid;
0137     }
0138 
0139     return m_segments[m_closestSegmentIndex];
0140 }
0141 
0142 GeoDataCoordinates Route::positionOnRoute() const
0143 {
0144     if ( m_positionDirty ) {
0145         updatePosition();
0146     }
0147 
0148     return m_positionOnRoute;
0149 }
0150 
0151 GeoDataCoordinates Route::currentWaypoint() const
0152 {
0153     if ( m_positionDirty ) {
0154         updatePosition();
0155     }
0156 
0157     return m_currentWaypoint;
0158 }
0159 
0160 }