From 17bdbb0fbb4e54564c2ca5bea6bb95a2fca3d292 Mon Sep 17 00:00:00 2001 From: Folke Will Date: Sat, 25 Dec 2021 21:57:52 +0100 Subject: [PATCH] Show runway elevation --- CMakeLists.txt | 2 +- src/avitab/apps/AirportApp.cpp | 6 ++++- src/libxdata/parsers/CIFPParser.cpp | 23 ++++++++++++++++++++ src/libxdata/parsers/CIFPParser.h | 1 + src/libxdata/parsers/objects/CIFPData.h | 10 ++++++++- src/libxdata/world/loaders/CIFPLoader.cpp | 17 ++++++++++----- src/libxdata/world/loaders/CIFPLoader.h | 1 + src/libxdata/world/models/airport/Runway.cpp | 8 +++++++ src/libxdata/world/models/airport/Runway.h | 3 +++ 9 files changed, 62 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 413219d5..2d0ab8cc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,5 +1,5 @@ cmake_minimum_required(VERSION 3.9) -project(AviTab VERSION 0.4.7 DESCRIPTION "AviTab X-Plane plugin") +project(AviTab VERSION 0.4.8 DESCRIPTION "AviTab X-Plane plugin") if (NOT "$ENV{NAVIGRAPH_SECRET}" STREQUAL "") set(NAVIGRAPH_SECRET "$ENV{NAVIGRAPH_SECRET}" CACHE INTERNAL "Copied from environment variable") diff --git a/src/avitab/apps/AirportApp.cpp b/src/avitab/apps/AirportApp.cpp index 081b6605..eb4d8d1c 100644 --- a/src/avitab/apps/AirportApp.cpp +++ b/src/avitab/apps/AirportApp.cpp @@ -216,10 +216,11 @@ std::string AirportApp::toRunwayInfo(std::shared_ptr airport) { auto aptLoc = airport->getLocation(); auto magneticVariation = api().getMagneticVariation(aptLoc.latitude, aptLoc.longitude); - str << "Runways (Length in X-Plane might differ from real length):\n"; + str << "Runways:\n"; airport->forEachRunway([this, &str, &magneticVariation] (const std::shared_ptr rwy) { str << " " + rwy->getID(); auto ils = rwy->getILSData(); + auto elevation = rwy->getElevation(); int rwHeading = (int)(rwy->getHeading() + magneticVariation + 0.5 + 360.0) % 360; if (ils) { int ilsHeading = (int)(ils->getILSLocalizer()->getRunwayHeading() + magneticVariation + 0.5 + 360.0) % 360; @@ -237,6 +238,9 @@ std::string AirportApp::toRunwayInfo(std::shared_ptr airport) { if (!std::isnan(rwHeading)) { str << ", CRS " << rwHeading << "° mag"; } + if (!std::isnan(elevation)) { + str << ", " << (int) elevation << " ft MSL"; + } float length = rwy->getLength(); if (!std::isnan(length)) { str << ", " << std::to_string((int) (length * xdata::M_TO_FT + 0.5)) << " ft"; diff --git a/src/libxdata/parsers/CIFPParser.cpp b/src/libxdata/parsers/CIFPParser.cpp index df06f67c..ac2a0656 100644 --- a/src/libxdata/parsers/CIFPParser.cpp +++ b/src/libxdata/parsers/CIFPParser.cpp @@ -48,6 +48,9 @@ void CIFPParser::parseLine() { case RecordType::APPROACH: parseProcedure(); break; + case RecordType::RWY: + parseRunway(); + break; default: // silently ignore other types for now return; @@ -82,6 +85,26 @@ CIFPParser::RecordType CIFPParser::parseRecordType() { } } +void CIFPParser::parseRunway() { + finishAndRestart(); + + curData.type = CIFPData::ProcedureType::RUNWAY; + curData.id = parser.nextDelimitedWord(','); // runway identifier + parser.nextDelimitedWord(','); // gradient + parser.nextDelimitedWord(','); // ellipsoid height + auto elevationStr = parser.nextDelimitedWord(','); // landing threshold elevation + parser.nextDelimitedWord(','); // TCH value + parser.nextDelimitedWord(','); // localizer identifier + auto ilsCatStr = parser.nextDelimitedWord(','); // ILS category + parser.nextDelimitedWord(';'); // threshold crossing height + parser.nextDelimitedWord(','); // latitude + parser.nextDelimitedWord(','); // longitude + parser.nextDelimitedWord(';'); // displacement distance + + curData.rwyInfo.elevation = std::strtoul(elevationStr.c_str(), nullptr, 10); + curData.rwyInfo.ilsCategory = std::strtoul(ilsCatStr.c_str(), nullptr, 10); +} + void CIFPParser::parseProcedure() { parser.nextDelimitedWord(','); // sequence number std::string type = parser.nextDelimitedWord(','); // type diff --git a/src/libxdata/parsers/CIFPParser.h b/src/libxdata/parsers/CIFPParser.h index 67fa4b99..7b5f4a0e 100644 --- a/src/libxdata/parsers/CIFPParser.h +++ b/src/libxdata/parsers/CIFPParser.h @@ -48,6 +48,7 @@ class CIFPParser { void finishAndRestart(); RecordType parseRecordType(); + void parseRunway(); void parseProcedure(); void parseRunwayTransition(); void parseCommonRoute(); diff --git a/src/libxdata/parsers/objects/CIFPData.h b/src/libxdata/parsers/objects/CIFPData.h index 01e03fee..6966949a 100644 --- a/src/libxdata/parsers/objects/CIFPData.h +++ b/src/libxdata/parsers/objects/CIFPData.h @@ -88,7 +88,8 @@ struct CIFPData { NONE, SID, STAR, - APPROACH + APPROACH, + RUNWAY, }; struct FixInRegion { @@ -121,6 +122,12 @@ struct CIFPData { std::vector fixes; }; + // For type = runway + struct RunwayInfo { + int elevation = 0; + int ilsCategory = 0; + }; + ProcedureType type = ProcedureType::NONE; std::string id; @@ -129,6 +136,7 @@ struct CIFPData { std::map enrouteTransitions; // key is destination fix, e.g. "COREZ" std::map approachTransitions; // key is approach name, e.g. "RAR25" std::vector approach; + RunwayInfo rwyInfo{}; }; } /* namespace xdata */ diff --git a/src/libxdata/world/loaders/CIFPLoader.cpp b/src/libxdata/world/loaders/CIFPLoader.cpp index fda4ecbf..cf25cfb3 100644 --- a/src/libxdata/world/loaders/CIFPLoader.cpp +++ b/src/libxdata/world/loaders/CIFPLoader.cpp @@ -43,23 +43,28 @@ void CIFPLoader::load(std::shared_ptr airport, const std::string& file) void CIFPLoader::onProcedureLoaded(std::shared_ptr airport, const CIFPData& procedure) { switch (procedure.type) { - case CIFPData::ProcedureType::SID: { + case CIFPData::ProcedureType::RUNWAY: + loadRunway(airport, procedure); + case CIFPData::ProcedureType::SID: loadSID(airport, procedure); break; - } - case CIFPData::ProcedureType::STAR: { + case CIFPData::ProcedureType::STAR: loadSTAR(airport, procedure); break; - } - case CIFPData::ProcedureType::APPROACH: { + case CIFPData::ProcedureType::APPROACH: loadApproach(airport, procedure); break; - } default: return; } } +void CIFPLoader::loadRunway(std::shared_ptr airport, const CIFPData& procedure) { + forEveryMatchingRunway(procedure.id, airport, [&procedure] (std::shared_ptr rwy) { + rwy->setElevation(procedure.rwyInfo.elevation); + }); +} + void CIFPLoader::loadSID(std::shared_ptr airport, const CIFPData& procedure) { auto sid = std::make_shared(procedure.id); diff --git a/src/libxdata/world/loaders/CIFPLoader.h b/src/libxdata/world/loaders/CIFPLoader.h index dca0f27a..838415f2 100644 --- a/src/libxdata/world/loaders/CIFPLoader.h +++ b/src/libxdata/world/loaders/CIFPLoader.h @@ -34,6 +34,7 @@ class CIFPLoader { void onProcedureLoaded(std::shared_ptr airport, const CIFPData &procedure); + void loadRunway(std::shared_ptr airport, const CIFPData &procedure); void loadSID(std::shared_ptr airport, const CIFPData &procedure); void loadSTAR(std::shared_ptr airport, const CIFPData &procedure); void loadApproach(std::shared_ptr airport, const CIFPData &procedure); diff --git a/src/libxdata/world/models/airport/Runway.cpp b/src/libxdata/world/models/airport/Runway.cpp index b28dfef3..7a63d5c8 100644 --- a/src/libxdata/world/models/airport/Runway.cpp +++ b/src/libxdata/world/models/airport/Runway.cpp @@ -42,6 +42,10 @@ void Runway::setLength(float l) { this->length = l; } +void Runway::setElevation(float e) { + this->elevation = e; +} + void Runway::setLocation(const Location &loc) { this->location = loc; } @@ -91,6 +95,10 @@ float xdata::Runway::getLength() const { return length; } +float xdata::Runway::getElevation() const { + return elevation; +} + xdata::Runway::SurfaceType xdata::Runway::getSurfaceType() const{ return surfaceType; } diff --git a/src/libxdata/world/models/airport/Runway.h b/src/libxdata/world/models/airport/Runway.h index 171fe896..2ae837bb 100644 --- a/src/libxdata/world/models/airport/Runway.h +++ b/src/libxdata/world/models/airport/Runway.h @@ -50,8 +50,10 @@ class Runway: public NavNode { void setLength(float l); void setLocation(const Location &loc); void setSurfaceType(SurfaceType surfaceType); + void setElevation(float elevation); float getHeading() const; // can be NaN float getLength() const; // can be NaN + float getElevation() const; // can be NaN const std::string &getID() const override; const Location &getLocation() const override; @@ -68,6 +70,7 @@ class Runway: public NavNode { private: std::string name; Location location; + float elevation = std::numeric_limits::quiet_NaN(); // feet MSL float width = std::numeric_limits::quiet_NaN(); // meters float heading = std::numeric_limits::quiet_NaN(); // degrees float length = std::numeric_limits::quiet_NaN(); // meters