Marble

RouteSegment.cpp
1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 //
3 // SPDX-FileCopyrightText: 2011 Dennis Nienhüser <[email protected]>
4 //
5 
6 #include "RouteSegment.h"
7 
8 #include "GeoDataLatLonAltBox.h"
9 
10 namespace Marble
11 {
12 
13 RouteSegment::RouteSegment() :
14  m_valid( false ),
15  m_distance( 0.0 ),
16  m_travelTime( 0 ),
17  m_nextRouteSegment( nullptr )
18 {
19  // nothing to do
20 }
21 
22 qreal RouteSegment::distance() const
23 {
24  return m_distance;
25 }
26 
27 const Maneuver & RouteSegment::maneuver() const
28 {
29  return m_maneuver;
30 }
31 
32 void RouteSegment::setManeuver( const Maneuver &maneuver )
33 {
34  m_maneuver = maneuver;
35  m_valid = true;
36 }
37 
38 const GeoDataLineString & RouteSegment::path() const
39 {
40  return m_path;
41 }
42 
43 void RouteSegment::setPath( const GeoDataLineString &path )
44 {
45  m_path = path;
46  m_distance = m_path.length( EARTH_RADIUS );
47  m_bounds = m_path.latLonAltBox();
48  m_valid = true;
49 }
50 
51 int RouteSegment::travelTime() const
52 {
53  return m_travelTime;
54 }
55 
56 void RouteSegment::setTravelTime( int seconds )
57 {
58  m_travelTime = seconds;
59  m_valid = true;
60 }
61 
62 GeoDataLatLonBox RouteSegment::bounds() const
63 {
64  return m_bounds;
65 }
66 
67 const RouteSegment & RouteSegment::nextRouteSegment() const
68 {
69  if ( m_nextRouteSegment ) {
70  return *m_nextRouteSegment;
71  }
72 
73  static RouteSegment invalid;
74  return invalid;
75 }
76 
77 void RouteSegment::setNextRouteSegment( const RouteSegment* segment )
78 {
79  m_nextRouteSegment = segment;
80  if ( segment ) {
81  m_valid = true;
82  }
83 }
84 
85 bool RouteSegment::isValid() const
86 {
87  return m_valid;
88 }
89 
90 qreal RouteSegment::distancePointToLine(const GeoDataCoordinates &p, const GeoDataCoordinates &a, const GeoDataCoordinates &b)
91 {
92  return EARTH_RADIUS * p.sphericalDistanceTo(projected(p, a, b));
93 }
94 
95 GeoDataCoordinates RouteSegment::projected(const GeoDataCoordinates &p, const GeoDataCoordinates &a, const GeoDataCoordinates &b)
96 {
97  qreal const y0 = p.latitude();
98  qreal const x0 = p.longitude();
99  qreal const y1 = a.latitude();
100  qreal const x1 = a.longitude();
101  qreal const y2 = b.latitude();
102  qreal const x2 = b.longitude();
103  qreal const y01 = x0 - x1;
104  qreal const x01 = y0 - y1;
105  qreal const y21 = x2 - x1;
106  qreal const x21 = y2 - y1;
107  qreal const len = x21*x21 + y21*y21;
108  qreal const t = (x01*x21 + y01*y21) / len;
109  if ( t<0.0 ) {
110  return a;
111  } else if ( t > 1.0 ) {
112  return b;
113  } else {
114  // a + t (b - a);
115  qreal const lon = x1 + t * ( x2 - x1 );
116  qreal const lat = y1 + t * ( y2 - y1 );
117  return GeoDataCoordinates( lon, lat );
118  }
119 
120 }
121 
122 qreal RouteSegment::distanceTo( const GeoDataCoordinates &point, GeoDataCoordinates &closest, GeoDataCoordinates &interpolated ) const
123 {
124  Q_ASSERT( !m_path.isEmpty() );
125 
126  if ( m_path.size() == 1 ) {
127  closest = m_path.first();
128  return EARTH_RADIUS * m_path.first().sphericalDistanceTo(point);
129  }
130 
131  qreal minDistance = -1.0;
132  int minIndex = 0;
133  for ( int i=1; i<m_path.size(); ++i ) {
134  qreal const distance = distancePointToLine( point, m_path[i-1], m_path[i] );
135  if ( minDistance < 0.0 || distance < minDistance ) {
136  minDistance = distance;
137  minIndex = i;
138  }
139  }
140 
141  closest = m_path[minIndex];
142  if ( minIndex == 0 ) {
143  interpolated = closest;
144  } else {
145  interpolated = projected( point, m_path[minIndex-1], m_path[minIndex] );
146  }
147 
148  return minDistance;
149 }
150 
151 qreal RouteSegment::minimalDistanceTo( const GeoDataCoordinates &point ) const
152 {
153  if ( bounds().contains( point) ) {
154  return 0.0;
155  }
156 
157  qreal north(0.0), east(0.0), south(0.0), west(0.0);
158  bounds().boundaries( north, south, east, west );
159  GeoDataCoordinates const northWest( west, north );
160  GeoDataCoordinates const northEast( east, north );
161  GeoDataCoordinates const southhWest( west, south );
162  GeoDataCoordinates const southEast( east, south );
163 
164  qreal distNorth = distancePointToLine( point, northWest, northEast );
165  qreal distEast = distancePointToLine( point, northEast, southEast );
166  qreal distSouth = distancePointToLine( point, southhWest, southEast );
167  qreal distWest = distancePointToLine( point, northWest, southhWest );
168  return qMin( qMin( distNorth, distEast ), qMin( distWest, distSouth ) );
169 }
170 
171 qreal RouteSegment::projectedDirection(const GeoDataCoordinates &point) const
172 {
173  if (m_path.size() < 2){
174  return 0;
175  }
176 
177  qreal minDistance = -1.0;
178  int minIndex = 0;
179  for ( int i=1; i<m_path.size(); ++i ) {
180  qreal const distance = distancePointToLine( point, m_path[i-1], m_path[i] );
181  if ( minDistance < 0.0 || distance < minDistance ) {
182  minDistance = distance;
183  minIndex = i;
184  }
185  }
186 
187  if ( minIndex == 0 ) {
188  return m_path[0].bearing( m_path[1], GeoDataCoordinates::Degree, GeoDataCoordinates::FinalBearing );
189  } else {
190  return m_path[minIndex-1].bearing( m_path[minIndex], GeoDataCoordinates::Degree, GeoDataCoordinates::FinalBearing );
191  }
192 }
193 
194 bool RouteSegment::operator ==(const RouteSegment &other) const
195 {
196  return m_valid == other.m_valid &&
197  m_distance == other.m_distance &&
198  m_maneuver == other.m_maneuver &&
199  m_travelTime == other.m_travelTime &&
200  m_bounds == other.m_bounds &&
201  m_nextRouteSegment == other.m_nextRouteSegment;
202 }
203 
204 bool RouteSegment::operator !=(const RouteSegment &other) const
205 {
206  return !(other == *this);
207 }
208 
209 }
KOSM_EXPORT double distance(const std::vector< const OSM::Node * > &path, Coordinate coord)
int length() const const
Binds a QML item to a specific geodetic location in screen coordinates.
QString path(const QString &relativePath)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Oct 4 2023 04:09:43 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.