6 #include "RouteSegment.h"
8 #include "GeoDataLatLonAltBox.h"
13 RouteSegment::RouteSegment() :
17 m_nextRouteSegment( nullptr )
22 qreal RouteSegment::distance()
const
27 const Maneuver & RouteSegment::maneuver()
const
32 void RouteSegment::setManeuver(
const Maneuver &maneuver )
34 m_maneuver = maneuver;
38 const GeoDataLineString & RouteSegment::path()
const
43 void RouteSegment::setPath(
const GeoDataLineString &path )
46 m_distance = m_path.
length( EARTH_RADIUS );
47 m_bounds = m_path.latLonAltBox();
51 int RouteSegment::travelTime()
const
56 void RouteSegment::setTravelTime(
int seconds )
58 m_travelTime = seconds;
62 GeoDataLatLonBox RouteSegment::bounds()
const
67 const RouteSegment & RouteSegment::nextRouteSegment()
const
69 if ( m_nextRouteSegment ) {
70 return *m_nextRouteSegment;
73 static RouteSegment invalid;
77 void RouteSegment::setNextRouteSegment(
const RouteSegment* segment )
79 m_nextRouteSegment = segment;
85 bool RouteSegment::isValid()
const
90 qreal RouteSegment::distancePointToLine(
const GeoDataCoordinates &p,
const GeoDataCoordinates &a,
const GeoDataCoordinates &b)
92 return EARTH_RADIUS * p.sphericalDistanceTo(projected(p, a, b));
95 GeoDataCoordinates RouteSegment::projected(
const GeoDataCoordinates &p,
const GeoDataCoordinates &a,
const GeoDataCoordinates &b)
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;
111 }
else if ( t > 1.0 ) {
115 qreal
const lon = x1 + t * ( x2 - x1 );
116 qreal
const lat = y1 + t * ( y2 - y1 );
117 return GeoDataCoordinates( lon, lat );
122 qreal RouteSegment::distanceTo(
const GeoDataCoordinates &point, GeoDataCoordinates &closest, GeoDataCoordinates &interpolated )
const
124 Q_ASSERT( !m_path.isEmpty() );
126 if ( m_path.size() == 1 ) {
127 closest = m_path.first();
128 return EARTH_RADIUS * m_path.first().sphericalDistanceTo(point);
131 qreal minDistance = -1.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 ) {
141 closest = m_path[minIndex];
142 if ( minIndex == 0 ) {
143 interpolated = closest;
145 interpolated = projected( point, m_path[minIndex-1], m_path[minIndex] );
151 qreal RouteSegment::minimalDistanceTo(
const GeoDataCoordinates &point )
const
153 if ( bounds().contains( point) ) {
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 );
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 ) );
171 qreal RouteSegment::projectedDirection(
const GeoDataCoordinates &point)
const
173 if (m_path.size() < 2){
177 qreal minDistance = -1.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 ) {
187 if ( minIndex == 0 ) {
188 return m_path[0].bearing( m_path[1], GeoDataCoordinates::Degree, GeoDataCoordinates::FinalBearing );
190 return m_path[minIndex-1].bearing( m_path[minIndex], GeoDataCoordinates::Degree, GeoDataCoordinates::FinalBearing );
194 bool RouteSegment::operator ==(
const RouteSegment &other)
const
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;
204 bool RouteSegment::operator !=(
const RouteSegment &other)
const
206 return !(other == *
this);