X-Git-Url: https://git.mxchange.org/?a=blobdiff_plain;f=src%2FInstrumentation%2FKLN89%2Fkln89_page_apt.cxx;h=52a0778c319d202a75279171ae4ca1b15b3de47b;hb=1eb8ae1fbf43359eec09b99885a9280f529c86fb;hp=e4212151940376169d77a3cd299fbf610c405f90;hpb=e2bf85e67ebe9d53a6d9b3664988d263b3cc412a;p=flightgear.git diff --git a/src/Instrumentation/KLN89/kln89_page_apt.cxx b/src/Instrumentation/KLN89/kln89_page_apt.cxx index e42121519..52a0778c3 100644 --- a/src/Instrumentation/KLN89/kln89_page_apt.cxx +++ b/src/Instrumentation/KLN89/kln89_page_apt.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -26,55 +26,17 @@ #endif #include "kln89_page_apt.hxx" -#include "ATCDCL/commlist.hxx" -#include "Main/globals.hxx" -#include "Airports/runways.hxx" -#include "Airports/simple.hxx" -// This function is copied from Airports/runways.cxx -// TODO - Make the original properly available and remove this instance!!!! -// Return reverse rwy number -// eg 01 -> 19 -// 03L -> 21R -static string GetReverseRunwayNo(string rwyno) { - // cout << "Original rwyno = " << rwyNo << '\n'; - - // standardize input number - string tmp = rwyno.substr(1, 1); - if (( tmp == "L" || tmp == "R" || tmp == "C" ) || (rwyno.size() == 1)) { - tmp = rwyno; - rwyno = "0" + tmp; - SG_LOG( SG_GENERAL, SG_INFO, - "Standardising rwy number from " << tmp << " to " << rwyno ); - } - - char buf[4]; - int rn = atoi(rwyno.substr(0,2).c_str()); - rn += 18; - while(rn > 36) { - rn -= 36; - } - sprintf(buf, "%02i", rn); - if(rwyno.size() == 3) { - if(rwyno.substr(2,1) == "L") { - buf[2] = 'R'; - buf[3] = '\0'; - } else if (rwyno.substr(2,1) == "R") { - buf[2] = 'L'; - buf[3] = '\0'; - } else if (rwyno.substr(2,1) == "C") { - buf[2] = 'C'; - buf[3] = '\0'; - } else if (rwyno.substr(2,1) == "T") { - buf[2] = 'T'; - buf[3] = '\0'; - } else { - SG_LOG(SG_GENERAL, SG_ALERT, "Unknown runway code " - << rwyno << " passed to GetReverseRunwayNo(...)"); - } - } - return(buf); -} +#include +#include +#include + +#include +#include
+#include +#include + +using std::string; KLN89AptPage::KLN89AptPage(KLN89* parent) : KLN89Page(parent) { @@ -182,7 +144,6 @@ void KLN89AptPage::Update(double dt) { 2, 0, 0, _to_flag, (_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 5 ? true : false)); } else if(_subPage == 2) { // Try and calculate a realistic difference from UTC based on longitude - float degLonPerHr = 360.0 / 24.0; // 15 degrees per hour difference. // Since 0 longitude is the middle of UTC, the boundaries will be at 7.5, 22.5, 37.5 etc. int hrDiff = ((int)((fabs(ap->getLongitude())) + 7.5)) / 15; _kln89->DrawText("UTC", 2, 0, 2); @@ -204,7 +165,7 @@ void KLN89AptPage::Update(double dt) { // I guess we can make a heuristic guess as to fuel availability from the runway sizes // For now assume that airports with asphalt or concrete runways will have at least 100L, // and that runways over 4000ft will have JET. - if(_aptRwys[0]->_surface_code <= 2) { + if(_aptRwys[0]->surface() <= 2) { if(_aptRwys[0]->lengthFt() >= 4000) { _kln89->DrawText("JET 100L", 2, 0, 1); } else { @@ -228,14 +189,15 @@ void KLN89AptPage::Update(double dt) { string s = _aptRwys[i]->ident(); _kln89->DrawText(s, 2, 9, 3); _kln89->DrawText("/", 2, 12, 3); - _kln89->DrawText(GetReverseRunwayNo(s), 2, 13, 3); + string recipIdent = _aptRwys[i]->reciprocalRunway()->ident(); + _kln89->DrawText(recipIdent, 2, 13, 3); // Length s = GPSitoa(int(float(_aptRwys[i]->lengthFt()) * (_kln89->_altUnits == GPS_ALT_UNITS_FT ? 1.0 : SG_FEET_TO_METER) + 0.5)); _kln89->DrawText(s, 2, 5 - s.size(), 2); _kln89->DrawText((_kln89->_altUnits == GPS_ALT_UNITS_FT ? "ft" : "m"), 2, 5, 2); // Surface // TODO - why not store these strings as an array? - switch(_aptRwys[i]->_surface_code) { + switch(_aptRwys[i]->surface()) { case 1: // Asphalt - fall through case 2: @@ -276,14 +238,15 @@ void KLN89AptPage::Update(double dt) { string s = _aptRwys[i]->ident(); _kln89->DrawText(s, 2, 9, 1); _kln89->DrawText("/", 2, 12, 1); - _kln89->DrawText(GetReverseRunwayNo(s), 2, 13, 1); + string recip = _aptRwys[i]->reciprocalRunway()->ident(); + _kln89->DrawText(recip, 2, 13, 1); // Length s = GPSitoa(int(float(_aptRwys[i]->lengthFt()) * (_kln89->_altUnits == GPS_ALT_UNITS_FT ? 1.0 : SG_FEET_TO_METER) + 0.5)); _kln89->DrawText(s, 2, 5 - s.size(), 0); _kln89->DrawText((_kln89->_altUnits == GPS_ALT_UNITS_FT ? "ft" : "m"), 2, 5, 0); // Surface // TODO - why not store these strings as an array? - switch(_aptRwys[i]->_surface_code) { + switch(_aptRwys[i]->surface()) { case 1: // Asphalt - fall through case 2: @@ -354,19 +317,19 @@ void KLN89AptPage::Update(double dt) { _kln89->DrawText("For This Airport", 2, 0, 0); } else { if(_iafDialog) { - _kln89->DrawText(_iaps[_curIap]->_abbrev, 2, 1, 3); + _kln89->DrawText(_iaps[_curIap]->_ident, 2, 1, 3); _kln89->DrawText(_iaps[_curIap]->_rwyStr, 2, 7, 3); - _kln89->DrawText(_iaps[_curIap]->_id, 2, 12, 3); + _kln89->DrawText(_iaps[_curIap]->_aptIdent, 2, 12, 3); _kln89->DrawText("IAF", 2, 2, 2); - int line = 0; - for(unsigned int i=_iafStart; i<_IAF.size(); ++i) { + unsigned int line = 0; + for(unsigned int i=_iafStart; i<_approachRoutes.size(); ++i) { if(line == 2) { - i = _IAF.size() - 1; + i = _approachRoutes.size() - 1; } // Assume that the IAF number is always single digit! _kln89->DrawText(GPSitoa(i+1), 2, 6, 2-line); if(!(_kln89->_mode == KLN89_MODE_CRSR && _kln89->_blink && _uLinePos == (line + 1))) { - _kln89->DrawText(_IAF[i]->id, 2, 8, 2-line); + _kln89->DrawText(_approachRoutes[i]->waypoints[0]->id, 2, 8, 2-line); } if(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (line + 1) && !(_kln89->_blink )) { _kln89->Underline(2, 8, 2-line, 5); @@ -377,9 +340,9 @@ void KLN89AptPage::Update(double dt) { _kln89->DrawEnt(); } } else if(_addDialog) { - _kln89->DrawText(_iaps[_curIap]->_abbrev, 2, 1, 3); + _kln89->DrawText(_iaps[_curIap]->_ident, 2, 1, 3); _kln89->DrawText(_iaps[_curIap]->_rwyStr, 2, 7, 3); - _kln89->DrawText(_iaps[_curIap]->_id, 2, 12, 3); + _kln89->DrawText(_iaps[_curIap]->_aptIdent, 2, 12, 3); string s = GPSitoa(_fStart + 1); _kln89->DrawText(s, 2, 2-s.size(), 2); s = GPSitoa(_kln89->_approachFP->waypoints.size()); @@ -400,9 +363,9 @@ void KLN89AptPage::Update(double dt) { } } } else if(_replaceDialog) { - _kln89->DrawText(_iaps[_curIap]->_abbrev, 2, 1, 3); + _kln89->DrawText(_iaps[_curIap]->_ident, 2, 1, 3); _kln89->DrawText(_iaps[_curIap]->_rwyStr, 2, 7, 3); - _kln89->DrawText(_iaps[_curIap]->_id, 2, 12, 3); + _kln89->DrawText(_iaps[_curIap]->_aptIdent, 2, 12, 3); _kln89->DrawText("Replace Existing", 2, 0, 2); _kln89->DrawText("Approach", 2, 4, 1); if(_uLinePos > 0 && !(_kln89->_blink)) { @@ -412,24 +375,35 @@ void KLN89AptPage::Update(double dt) { } } else { _kln89->DrawText("IAP", 2, 11, 3); - int check = 0; bool selApp = false; if(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos > 4) { selApp = true; if(!_kln89->_blink) _kln89->DrawEnt(); } - for(unsigned int i=0; i<_iaps.size(); ++i) { // TODO - do this properly when > 3 IAPs - string s = GPSitoa(i+1); - _kln89->DrawText(s, 2, 2 - s.size(), 2-i); - if(!(selApp && _uLinePos == 5+i && _kln89->_blink)) { - _kln89->DrawText(_iaps[i]->_abbrev, 2, 3, 2-i); - _kln89->DrawText(_iaps[i]->_rwyStr, 2, 9, 2-i); - } - if(selApp && _uLinePos == 5+i && !_kln89->_blink) { - _kln89->Underline(2, 3, 2-i, 9); + // _maxULine pos should be 4 + iaps.size() at this point. + // Draw a maximum of 3 IAPs. + // If there are more than 3 IAPs for this airport, then we need to offset the start + // of the list if _uLinePos is pointing at the 4th or later IAP. + unsigned int offset = 0; + unsigned int index; + if(_uLinePos > 7) { + offset = _uLinePos - 7; + } + for(unsigned int i=0; i<3; ++i) { + index = offset + i; + if(index < _iaps.size()) { + string s = GPSitoa(index+1); + _kln89->DrawText(s, 2, 2 - s.size(), 2-i); + if(!(selApp && _uLinePos == index+5 && _kln89->_blink)) { + _kln89->DrawText(_iaps[index]->_ident, 2, 3, 2-i); + _kln89->DrawText(_iaps[index]->_rwyStr, 2, 9, 2-i); + } + if(selApp && _uLinePos == index+5 && !_kln89->_blink) { + _kln89->Underline(2, 3, 2-i, 9); + } + } else { + break; } - check++; - if(check > 2) break; } } } @@ -486,38 +460,35 @@ void KLN89AptPage::SetId(const string& s) { // Update the cached airport details void KLN89AptPage::UpdateAirport(const string& id) { // Frequencies - _aptFreqs.clear(); - ATCData ad; - AptFreq aq; - //cout << "UpdateAirport called, id = " << id << '\n'; - // TODO - the logic below only returns one service per type per airport - they can be on more than one freq though. - if(current_commlist->FindByCode(id, ad, ATIS)) { - //cout << "Found ATIS\n"; - aq.service = "ATIS*"; - aq.freq = ad.freq; - _aptFreqs.push_back(aq); - } - if(current_commlist->FindByCode(id, ad, GROUND)) { - aq.service = "GRND*"; - aq.freq = ad.freq; - _aptFreqs.push_back(aq); - } - if(current_commlist->FindByCode(id, ad, TOWER)) { - aq.service = "TWR *"; - aq.freq = ad.freq; - _aptFreqs.push_back(aq); - } - if(current_commlist->FindByCode(id, ad, APPROACH)) { - aq.service = "APR"; - aq.freq = ad.freq; - _aptFreqs.push_back(aq); - } + _aptFreqs.clear(); + + const FGAirport* apt = fgFindAirportID(id); + if (!apt) { + throw sg_exception("UpdateAirport: unknown airport id " + id); + } + + for (unsigned int c=0; ccommStations().size(); ++c) { + flightgear::CommStation* comm = apt->commStations()[c]; + AptFreq aq; + aq.freq = comm->freqKHz(); + switch (comm->type()) { + case FGPositioned::FREQ_ATIS: + aq.service = "ATIS*"; break; + case FGPositioned::FREQ_GROUND: + aq.service = "GRND*"; break; + case FGPositioned::FREQ_TOWER: + aq.service = "TWR *"; break; + case FGPositioned::FREQ_APP_DEP: + aq.service = "APR *"; break; + default: + continue; + } + } + _nFreqPages = (unsigned int)ceil((float(_aptFreqs.size())) / 3.0f); // Runways _aptRwys.clear(); - const FGAirport* apt = fgFindAirportID(id); - assert(apt); // build local array, longest runway first for (unsigned int r=0; rnumRunways(); ++r) { @@ -572,7 +543,7 @@ void KLN89AptPage::CrsrPressed() { } else if(_subPage == 7) { // Don't *think* we need some of this since some of it we can only get to by pressing ENT, not CRSR. if(_iafDialog) { - _maxULinePos = _IAF.size(); + _maxULinePos = _approachRoutes.size(); _uLinePos = 1; } else if(_addDialog) { _maxULinePos = 1; @@ -608,7 +579,7 @@ void KLN89AptPage::ClrPressed() { } } else if(_addDialog) { _addDialog = false; - if(_IAF.size() > 1) { + if(_approachRoutes.size() > 1) { _iafDialog = true; _maxULinePos = 1; // Don't reset _curIaf since it is remembed. @@ -633,15 +604,19 @@ void KLN89AptPage::ClrPressed() { void KLN89AptPage::EntPressed() { if(_entInvert) { _entInvert = false; - _last_apt_id = _apt_id; - _apt_id = _save_apt_id; + if(_kln89->_dtoReview) { + _kln89->DtoInitiate(_apt_id); + } else { + _last_apt_id = _apt_id; + _apt_id = _save_apt_id; + } } else if(_subPage == 7 && _kln89->_mode == KLN89_MODE_CRSR && _uLinePos > 0) { // We are selecting an approach if(_iafDialog) { if(_uLinePos > 0) { // Record the IAF that was picked if(_uLinePos == 3) { - _curIaf = _IAF.size() - 1; + _curIaf = _approachRoutes.size() - 1; } else { _curIaf = _uLinePos - 1 + _iafStart; } @@ -649,9 +624,8 @@ void KLN89AptPage::EntPressed() { // TODO - delete the waypoints inside _approachFP before clearing them!!!!!!! _kln89->_approachFP->waypoints.clear(); GPSWaypoint* wp = new GPSWaypoint; - *wp = *_IAF[_curIaf]; // Need to make copies here since we're going to alter ID and type sometimes + *wp = *(_approachRoutes[_curIaf]->waypoints[0]); // Need to make copies here since we're going to alter ID and type sometimes string iafid = wp->id; - //wp->id += 'i'; _kln89->_approachFP->waypoints.push_back(wp); for(unsigned int i=0; i<_IAP.size(); ++i) { if(_IAP[i]->id != iafid) { // Don't duplicate waypoints that are part of the initial fix list and the approach procedure list. @@ -667,11 +641,6 @@ void KLN89AptPage::EntPressed() { _kln89->_approachFP->waypoints.push_back(wp); } } - // Only add 1 missed approach procedure waypoint for now. I think this might be standard always anyway. - wp = new GPSWaypoint; - *wp = *_MAP[0]; - //wp->id += 'h'; - _kln89->_approachFP->waypoints.push_back(wp); _iafDialog = false; _addDialog = true; _maxULinePos = _kln89->_approachFP->waypoints.size() + 1; @@ -703,7 +672,7 @@ void KLN89AptPage::EntPressed() { _kln89->_activeFP->waypoints.insert(_kln89->_activeFP->waypoints.end(), _kln89->_approachFP->waypoints.begin(), _kln89->_approachFP->waypoints.end()); } _kln89->_approachID = _apt_id; - _kln89->_approachAbbrev = _iaps[_curIap]->_abbrev; + _kln89->_approachAbbrev = _iaps[_curIap]->_ident; _kln89->_approachRwyStr = _iaps[_curIap]->_rwyStr; _kln89->_approachLoaded = true; //_kln89->_messageStack.push_back("*Press ALT To Set Baro"); @@ -718,20 +687,36 @@ void KLN89AptPage::EntPressed() { } else if(_replaceDialog) { // TODO - load the approach! } else if(_uLinePos > 4) { - _IAF.clear(); + _approachRoutes.clear(); _IAP.clear(); - _MAP.clear(); _curIaf = 0; - _IAF = ((FGNPIAP*)(_iaps[_uLinePos-5]))->_IAF; + _approachRoutes = ((FGNPIAP*)(_iaps[_uLinePos-5]))->_approachRoutes; _IAP = ((FGNPIAP*)(_iaps[_uLinePos-5]))->_IAP; - _MAP = ((FGNPIAP*)(_iaps[_uLinePos-5]))->_MAP; _curIap = _uLinePos - 5; // TODO - handle the start of list ! no. 1, and the end of list not sequential! _uLinePos = 1; - if(_IAF.size() > 1) { + if(_approachRoutes.size() > 1) { // More than 1 IAF - display the selection dialog _iafDialog = true; - _maxULinePos = _IAF.size(); + _maxULinePos = _approachRoutes.size(); } else { + // There is only 1 IAF, so load the waypoints into the approach flightplan here. + // TODO - there is nasty code duplication loading the approach FP between the case here where we have only one + // IAF and the case where we must choose the IAF from a list. Try to tidy this after it is all working properly. + _kln89->_approachFP->waypoints.clear(); + GPSWaypoint* wp = new GPSWaypoint; + *wp = *(_approachRoutes[0]->waypoints[0]); // Need to make copies here since we're going to alter ID and type sometimes + string iafid = wp->id; + _kln89->_approachFP->waypoints.push_back(wp); + for(unsigned int i=0; i<_IAP.size(); ++i) { + if(_IAP[i]->id != iafid) { // Don't duplicate waypoints that are part of the initial fix list and the approach procedure list. + // FIXME - allow the same waypoint to be both the IAF and the FAF in some + // approaches that have a procedure turn eg. KDLL + // Also allow MAF to be the same as IAF! + wp = new GPSWaypoint; + *wp = *_IAP[i]; + _kln89->_approachFP->waypoints.push_back(wp); + } + } _addDialog = true; _maxULinePos = 1; } @@ -803,6 +788,15 @@ void KLN89AptPage::Knob2Left1() { } else { _curRwyPage--; } + } else if(_subPage == 0) { + _subPage = 7; + // We have to set _uLinePos here even though the cursor isn't pressed, to + // ensure that the list displays properly. + if(_iaps.empty()) { + _uLinePos = 1; + } else { + _uLinePos = 5; + } } else { KLN89Page::Knob2Left1(); } @@ -846,6 +840,15 @@ void KLN89AptPage::Knob2Right1() { } else { _curFreqPage++; } + } else if(_subPage == 6) { + _subPage = 7; + // We have to set _uLinePos here even though the cursor isn't pressed, to + // ensure that the list displays properly. + if(_iaps.empty()) { + _uLinePos = 1; + } else { + _uLinePos = 5; + } } else { KLN89Page::Knob2Right1(); }