Browse Source

add a function to project the IAF on the current path to have a virtual IAF

Sven Czarnian 3 years ago
parent
commit
4da604af99
2 changed files with 77 additions and 0 deletions
  1. 75 0
      src/PlugIn.cpp
  2. 2 0
      src/PlugIn.h

+ 75 - 0
src/PlugIn.cpp

@@ -19,12 +19,17 @@
 #include <Windows.h>
 
 #include <curl/curl.h>
+#pragma warning(push, 0)
+#include <Eigen/Geometry>
+#pragma warning(pop)
+#include <GeographicLib/Gnomonic.hpp>
 #include <json/json.h>
 
 #include <aman/com/Backend.h>
 #include <aman/config/CommunicationFileFormat.h>
 #include <aman/config/IdentifierFileFormat.h>
 #include <aman/helper/String.h>
+#include <aman/types/GeoCoordinate.h>
 
 #include "com/ZmqContext.h"
 #include "PlugIn.h"
@@ -241,6 +246,76 @@ aman::Aircraft* PlugIn::generateAircraftMessage(const EuroScopePlugIn::CRadarTar
     return retval;
 }
 
+void PlugIn::distanceToPredictedIaf(const EuroScopePlugIn::CRadarTarget& radarTarget, const EuroScopePlugIn::CFlightPlan& flightPlan,
+                                    const EuroScopePlugIn::CPosition& iafPosition, aman::AircraftReport* report) {
+    std::string_view direct(flightPlan.GetControllerAssignedData().GetDirectToPointName());
+
+    if (0 != direct.length()) {
+        GeoCoordinate directCoordinate;
+
+        /* find the coordinate of the direct waypoint */
+        for (int i = 0; i < flightPlan.GetExtractedRoute().GetPointsNumber(); ++i) {
+            if (flightPlan.GetExtractedRoute().GetPointName(i) == direct) {
+                directCoordinate = GeoCoordinate(static_cast<float>(flightPlan.GetExtractedRoute().GetPointPosition(i).m_Longitude) * degree,
+                                                 static_cast<float>(flightPlan.GetExtractedRoute().GetPointPosition(i).m_Latitude) * degree);
+                break;
+            }
+        }
+
+        if (0_m != directCoordinate.distanceTo(GeoCoordinate())) {
+            const GeographicLib::Gnomonic projection(GeographicLib::Geodesic::WGS84());
+            Eigen::Vector2f currentCartesian, iafCartesian, directCartesian;
+
+            /* convert to Cartesian with IAF as the reference */
+            projection.Forward(static_cast<float>(iafPosition.m_Latitude), static_cast<float>(iafPosition.m_Longitude),
+                               static_cast<float>(radarTarget.GetPosition().GetPosition().m_Latitude),
+                               static_cast<float>(radarTarget.GetPosition().GetPosition().m_Longitude),
+                               currentCartesian[0], currentCartesian[1]);
+            projection.Forward(static_cast<float>(iafPosition.m_Latitude), static_cast<float>(iafPosition.m_Longitude),
+                               directCoordinate.latitude().convert(degree),
+                               directCoordinate.longitude().convert(degree),
+                               directCartesian[0], directCartesian[1]);
+            projection.Forward(static_cast<float>(iafPosition.m_Latitude), static_cast<float>(iafPosition.m_Longitude),
+                               static_cast<float>(iafPosition.m_Latitude), static_cast<float>(iafPosition.m_Longitude),
+                               iafCartesian[0], iafCartesian[1]);
+
+            /* project IAF on line between current position and direct */
+            const auto direction = (directCartesian - currentCartesian).normalized();
+            Eigen::ParametrizedLine<float, 2> line(currentCartesian, direction);
+            const auto projectCartesian = line.projection(iafCartesian);
+
+            const auto distanceStart = (currentCartesian - projectCartesian).squaredNorm();
+            const auto distanceEnd = (directCartesian - projectCartesian).squaredNorm();
+            const auto distanceDirect = (currentCartesian - directCartesian).squaredNorm();
+
+            /* projection of IAF in front of aircraft and not behind direct */
+            if (distanceStart <= distanceDirect && distanceEnd <= distanceDirect) {
+                EuroScopePlugIn::CPosition projected;
+                float lat = 0.0f, lon = 0.0f;
+
+                projection.Reverse(static_cast<float>(iafPosition.m_Latitude), static_cast<float>(iafPosition.m_Longitude),
+                                   projectCartesian[0], projectCartesian[1], lat, lon);
+                projected.m_Latitude = lat;
+                projected.m_Longitude = lon;
+
+                const auto distanceToProjected = radarTarget.GetPosition().GetPosition().DistanceTo(projected);
+                report->set_distancetoiaf(static_cast<int>(std::round(distanceToProjected)));
+            }
+            else {
+                report->set_distancetoiaf(0);
+            }
+        }
+        /* did not find the coordinate -> fallback */
+        else {
+            report->set_distancetoiaf(0);
+        }
+    }
+    /* in heading mode and passed IAF */
+    else {
+        report->set_distancetoiaf(0);
+    }
+}
+
 void PlugIn::generateAircraftReportMessage(EuroScopePlugIn::CRadarTarget& radarTarget, aman::AircraftReport* report) {
     const auto flightPlan = radarTarget.GetCorrelatedFlightPlan();
 

+ 2 - 0
src/PlugIn.h

@@ -55,6 +55,8 @@ namespace aman {
         void updateInbound(EuroScopePlugIn::CRadarTarget& radarTarget);
         void updateInbound(EuroScopePlugIn::CFlightPlan& plan);
         void updateSequence(std::shared_ptr<aman::AircraftSequence>& sequence);
+        static void distanceToPredictedIaf(const EuroScopePlugIn::CRadarTarget& radarTarget, const EuroScopePlugIn::CFlightPlan& flightPlan,
+                                           const EuroScopePlugIn::CPosition& iafPosition, aman::AircraftReport* report);
 
         Communication                                 m_configuration;
         std::shared_ptr<RadarScreen>                  m_screen;