|
@@ -229,30 +229,46 @@ static __inline Angle __normalize(const Angle& angle) {
|
|
|
}
|
|
|
|
|
|
int Inbound::matchToPredictedPath(const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions, const GeoCoordinate& position,
|
|
|
- Length& trackmiles) {
|
|
|
+ const Velocity& groundspeed, Length& trackmiles) {
|
|
|
trackmiles = 0_m;
|
|
|
|
|
|
- if (0 == predictions.GetPointsNumber())
|
|
|
+ if (1 >= predictions.GetPointsNumber())
|
|
|
return 0;
|
|
|
|
|
|
- GeoCoordinate lastPosition(__convert(predictions.GetPosition(0)));
|
|
|
+ std::vector<Length> distances;
|
|
|
+ distances.reserve(static_cast<std::size_t>(predictions.GetPointsNumber()) - 1);
|
|
|
|
|
|
+ /* calculate the "potential field" for the distances*/
|
|
|
for (int i = 1; i < predictions.GetPointsNumber(); ++i) {
|
|
|
- GeoCoordinate coordinate(__convert(predictions.GetPosition(i)));
|
|
|
-
|
|
|
- const auto prev = lastPosition.bearingTo(position);
|
|
|
- const auto next = coordinate.bearingTo(position);
|
|
|
- const auto delta = __normalize(prev - next);
|
|
|
- if (90_deg <= delta.abs() || 2.0_nm >= lastPosition.distanceTo(position)) {
|
|
|
- trackmiles += lastPosition.distanceTo(position);
|
|
|
- return i - 1;
|
|
|
- }
|
|
|
+ const GeoCoordinate coordinate(__convert(predictions.GetPosition(i)));
|
|
|
+ distances.push_back(coordinate.distanceTo(position));
|
|
|
+ }
|
|
|
+
|
|
|
+ /* get the index of the minimal value*/
|
|
|
+ std::size_t idx = std::min_element(distances.cbegin(), distances.cend()) - distances.cbegin();
|
|
|
+
|
|
|
+ /* calculate the theoretical maximum distance (assuming one minute steps) and validate the distance */
|
|
|
+ const auto& maxDistance = groundspeed * 1_min;
|
|
|
+ if (gsl::at(distances, idx) > maxDistance)
|
|
|
+ return 0;
|
|
|
|
|
|
+ if (idx + 1 < static_cast<std::size_t>(predictions.GetPointsNumber()) && 0 != idx) {
|
|
|
+ const auto bearingCurrent = position.bearingTo(GeoCoordinate(__convert(predictions.GetPosition(idx))));
|
|
|
+ const auto bearingNext = position.bearingTo(GeoCoordinate(__convert(predictions.GetPosition(idx + 1))));
|
|
|
+
|
|
|
+ /* current and next in front of position -> use the previous element */
|
|
|
+ if (90_deg > __normalize(bearingNext - bearingCurrent).abs())
|
|
|
+ idx -= 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ GeoCoordinate lastPosition(__convert(predictions.GetPosition(0)));
|
|
|
+ for (std::size_t i = 1; i <= static_cast<int>(idx + 1); ++i) {
|
|
|
+ const GeoCoordinate coordinate(__convert(predictions.GetPosition(i)));
|
|
|
trackmiles += lastPosition.distanceTo(coordinate);
|
|
|
lastPosition = coordinate;
|
|
|
}
|
|
|
|
|
|
- return predictions.GetPointsNumber();
|
|
|
+ return static_cast<int>(idx);
|
|
|
}
|
|
|
|
|
|
void Inbound::predictETA(const EuroScopePlugIn::CRadarTarget& target, const EuroScopePlugIn::CFlightPlanPositionPredictions& predictions) {
|
|
@@ -261,9 +277,16 @@ void Inbound::predictETA(const EuroScopePlugIn::CRadarTarget& target, const Euro
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
+ /* get the ground speed */
|
|
|
+ Velocity groundspeed;
|
|
|
+ if (0 == target.GetGS())
|
|
|
+ groundspeed = static_cast<double>(target.GetPosition().GetReportedGS()) * knot;
|
|
|
+ else
|
|
|
+ groundspeed = static_cast<double>(target.GetGS()) * knot;
|
|
|
+
|
|
|
const auto& destination = gsl::at(this->m_arrivalRoute, this->m_nextStarWaypoint);
|
|
|
Length distanceToNextWaypoint = 0_m;
|
|
|
- Inbound::matchToPredictedPath(predictions, destination.position(), distanceToNextWaypoint);
|
|
|
+ Inbound::matchToPredictedPath(predictions, destination.position(), groundspeed, distanceToNextWaypoint);
|
|
|
this->m_trackmiles = distanceToNextWaypoint;
|
|
|
|
|
|
/* predict the flight and the descend */
|