- // Part of this flight is in the future.
- if ((*i)->getArrivalTime() > now)
- {
-
- dep = (*i)->getDepartureAirport();
- arr = (*i)->getArrivalAirport ();
- if (!(dep && arr))
- return false;
-
- if (dep != arr) {
- SGVec3d a = SGVec3d::fromGeoc(SGGeoc::fromDegM(dep->getLongitude(),
- dep->getLatitude(), 1));
- SGVec3d b = SGVec3d::fromGeoc(SGGeoc::fromDegM(arr->getLongitude(),
- arr->getLatitude(), 1));
- SGVec3d _cross = cross(b, a);
-
- angle = sgACos(dot(a, b));
-
- // Okay, at this point we have the angle between departure and
- // arrival airport, in degrees. From here we can interpolate the
- // position of the aircraft by calculating the ratio between
- // total time enroute and elapsed time enroute.
-
- totalTimeEnroute = (*i)->getArrivalTime() - (*i)->getDepartureTime();
- if (now > (*i)->getDepartureTime())
- {
- //err << "Lat = " << lat << ", lon = " << lon << endl;
- //cerr << "Time diff: " << now-i->getDepartureTime() << endl;
- elapsedTimeEnroute = now - (*i)->getDepartureTime();
- remainingTimeEnroute = (*i)->getArrivalTime() - now;
- SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic Manager: Flight is in progress.");
- }
- else
- {
- lat = dep->getLatitude();
- lon = dep->getLongitude();
- elapsedTimeEnroute = 0;
- remainingTimeEnroute = totalTimeEnroute;
- SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic Manager: Flight is pending.");
- }
- angle *= ( (double) elapsedTimeEnroute/ (double) totalTimeEnroute);
- //cout << "a = " << a[0] << " " << a[1] << " " << a[2]
- // << "b = " << b[0] << " " << b[1] << " " << b[2] << endl;
- sgdMat4 matrix;
- sgdMakeRotMat4(matrix, angle, _cross.data());
- for(int j = 0; j < 3; j++) {
- for (int k = 0; k<3; k++) {
- newPos[j] += matrix[j][k]*a[k];
- }
- }
- }
- SGGeod current;
- if ((now > (*i)->getDepartureTime() && (dep != arr))) {
- current = SGGeod::fromCart(newPos);
- speed = SGGeodesy::distanceNm(current, arr->geod()) /
- ((double) remainingTimeEnroute/3600.0);
- } else {
- current = dep->geod();
- speed = 450;
- }
- SGGeod user = SGGeod::fromDegM(userLongitude, userLatitude, (*i)->getCruiseAlt());
-
- distanceToUser = SGGeodesy::distanceNm(current, user);
-
- // If distance between user and simulated aircaft is less
- // then 500nm, create this flight. At jet speeds 500 nm is roughly
- // one hour flight time, so that would be a good approximate point
- // to start a more detailed simulation of this aircraft.
- SG_LOG (SG_GENERAL, SG_DEBUG, "Traffic manager: " << registration << " is scheduled for a flight from "
+ // current pos is based on great-circle course between departure/arrival,
+ // with percentage of distance travelled, based upon percentage of time
+ // enroute elapsed.
+ double course, az2, distanceM;
+ SGGeodesy::inverse(dep->geod(), arr->geod(), course, az2, distanceM);
+ double coveredDistance = distanceM * x;
+
+ SGGeodesy::direct(dep->geod(), course, coveredDistance, position, az2);
+
+ SG_LOG (SG_GENERAL, SG_BULK, "Traffic Manager: Flight is in progress, %=" << x);
+ speed = ((distanceM - coveredDistance) * SG_METER_TO_NM) / 3600.0;
+ } else {
+ // not departed yet
+ remainingTimeEnroute = totalTimeEnroute;
+ elapsedTimeEnroute = 0;
+ position = dep->geod();
+ SG_LOG (SG_GENERAL, SG_BULK, "Traffic Manager: Flight is pending, departure in "
+ << flight->getDepartureTime() - now << " seconds ");
+ }
+ } else {
+ // departure / arrival coincident
+ remainingTimeEnroute = totalTimeEnroute = 0.0;
+ elapsedTimeEnroute = 0;
+ position = dep->geod();
+ }
+
+ // cartesian calculations are more numerically stable over the (potentially)
+ // large distances involved here: see bug #80
+ distanceToUser = dist(userCart, SGVec3d::fromGeod(position)) * SG_METER_TO_NM;
+
+ // If distance between user and simulated aircaft is less
+ // then 500nm, create this flight. At jet speeds 500 nm is roughly
+ // one hour flight time, so that would be a good approximate point
+ // to start a more detailed simulation of this aircraft.
+ SG_LOG (SG_GENERAL, SG_BULK, "Traffic manager: " << registration << " is scheduled for a flight from "