X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FNavaids%2FroutePath.cxx;h=afbd628542644387cefbe0fc46ac57a68f2a1bb7;hb=ac8869cd62734bfa95803671d0fe0f5e5946ef5a;hp=6353fb5b678711d5815de93ca7778dd4deb92b6c;hpb=458edb933903836ac10b2acd9ef68e06e2a04470;p=flightgear.git diff --git a/src/Navaids/routePath.cxx b/src/Navaids/routePath.cxx index 6353fb5b6..afbd62854 100644 --- a/src/Navaids/routePath.cxx +++ b/src/Navaids/routePath.cxx @@ -52,6 +52,25 @@ double pointsKnownDistanceFromGC(const SGGeoc& a, const SGGeoc&b, const SGGeoc& return SGMiscd::min(dp1Nm, dp2Nm); } +// http://williams.best.vwh.net/avform.htm#Int +double latitudeForGCLongitude(const SGGeoc& a, const SGGeoc& b, double lon) +{ +#if 0 +Intermediate points {lat,lon} lie on the great circle connecting points 1 and 2 when: + +lat=atan((sin(lat1)*cos(lat2)*sin(lon-lon2) + -sin(lat2)*cos(lat1)*sin(lon-lon1))/(cos(lat1)*cos(lat2)*sin(lon1-lon2))) +#endif + double lonDiff = a.getLongitudeRad() - b.getLongitudeRad(); + double cosLat1 = cos(a.getLatitudeRad()), + cosLat2 = cos(b.getLatitudeRad()); + double x = sin(a.getLatitudeRad()) * cosLat2 * sin(lon - b.getLongitudeRad()); + double y = sin(b.getLatitudeRad()) * cosLat1 * sin(lon - a.getLongitudeRad()); + double denom = cosLat1 * cosLat2 * sin(lonDiff); + double lat = atan((x - y) / denom); + return lat; +} + RoutePath::RoutePath(const flightgear::WayptVec& wpts) : _waypts(wpts) { @@ -89,17 +108,24 @@ SGGeodVec RoutePath::pathForIndex(int index) const } SGGeodVec r; - SGGeod pos; - if (!computedPositionForIndex(index-1, pos)) { + SGGeod from, to; + if (!computedPositionForIndex(index-1, from)) { return SGGeodVec(); } - r.push_back(pos); - if (!computedPositionForIndex(index, pos)) { + r.push_back(from); + if (!computedPositionForIndex(index, to)) { return SGGeodVec(); } - r.push_back(pos); + // compute rounding offset, we want to round towards the direction of travel + // which depends on the east/west sign of the longitude change + double lonDelta = to.getLongitudeDeg() - from.getLongitudeDeg(); + if (fabs(lonDelta) > 0.5) { + interpolateGreatCircle(from, to, r); + } + + r.push_back(to); if (_waypts[index]->type() == "runway") { // runways get an extra point, at the end. this is particularly @@ -111,6 +137,30 @@ SGGeodVec RoutePath::pathForIndex(int index) const return r; } +void RoutePath::interpolateGreatCircle(const SGGeod& aFrom, const SGGeod& aTo, SGGeodVec& r) const +{ + SGGeoc gcFrom = SGGeoc::fromGeod(aFrom), + gcTo = SGGeoc::fromGeod(aTo); + + double lonDelta = gcTo.getLongitudeRad() - gcFrom.getLongitudeRad(); + if (fabs(lonDelta) < 1e-3) { + return; + } + + lonDelta = SGMiscd::normalizeAngle(lonDelta); + int steps = static_cast(fabs(lonDelta) * SG_RADIANS_TO_DEGREES * 2); + double lonStep = (lonDelta / steps); + + double lon = gcFrom.getLongitudeRad() + lonStep; + for (int s=0; s < (steps - 1); ++s) { + lon = SGMiscd::normalizeAngle(lon); + double lat = latitudeForGCLongitude(gcFrom, gcTo, lon); + r.push_back(SGGeod::fromGeoc(SGGeoc::fromRadM(lon, lat, SGGeodesy::EQURAD))); + //SG_LOG(SG_GENERAL, SG_INFO, "lon:" << lon * SG_RADIANS_TO_DEGREES << " gives lat " << lat * SG_RADIANS_TO_DEGREES); + lon += lonStep; + } +} + SGGeod RoutePath::positionForIndex(int index) const { SGGeod r;