_has_metar(has_metar),
_dynamics(0),
mTowerDataLoaded(false),
+ mHasTower(false),
mRunwaysLoaded(false),
mHelipadsLoaded(false),
mTaxiwaysLoaded(false),
return false;
}
+FGRunwayRef FGAirport::longestRunway() const
+{
+ FGRunwayRef r;
+ loadRunways();
+
+ BOOST_FOREACH(FGRunwayRef rwy, mRunways) {
+ if (!r || (r->lengthFt() < rwy->lengthFt())) {
+ r = rwy;
+ }
+ } // of runways iteration
+
+ return r;
+}
+
//------------------------------------------------------------------------------
FGRunwayList FGAirport::getRunways() const
{
NavDataCache* cache = NavDataCache::instance();
PositionedIDVec towers = cache->airportItemsOfType(guid(), FGPositioned::TOWER);
if (towers.empty()) {
- SG_LOG(SG_GENERAL, SG_ALERT, "No towers defined for:" <<ident());
+ mHasTower = false;
mTowerPosition = geod(); // use airport position
// increase tower elevation by 20 metres above the field elevation
mTowerPosition.setElevationM(geod().getElevationM() + 20.0);
} else {
FGPositionedRef tower = cache->loadById(towers.front());
mTowerPosition = tower->geod();
+ mHasTower = true;
}
SGPath path;
SGPropertyNode_ptr rootNode = new SGPropertyNode;
readProperties(path.str(), rootNode);
const_cast<FGAirport*>(this)->readTowerData(rootNode);
+ mHasTower = true;
} catch (sg_exception& e){
SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading twr XML failed:" << e.getFormattedMessage());
}
}
}
+bool FGAirport::hasTower() const
+{
+ validateTowerData();
+ return mHasTower;
+}
+
void FGAirport::readILSData(SGPropertyNode* aRoot)
{
NavDataCache* cache = NavDataCache::instance();
*/
void validateILSData();
+ bool hasTower() const;
+
SGGeod getTowerLocation() const;
void setMetar(bool value) { _has_metar = value; }
*/
bool hasHardRunwayOfLengthFt(double aLengthFt) const;
+ FGRunwayRef longestRunway() const;
+
unsigned int numTaxiways() const;
FGTaxiwayRef getTaxiwayByIndex(unsigned int aIndex) const;
FGTaxiwayList getTaxiways() const;
void loadProcedures() const;
mutable bool mTowerDataLoaded;
+ mutable bool mHasTower;
mutable SGGeod mTowerPosition;
mutable bool mRunwaysLoaded;
#include <QVector2D>
#include <QMouseEvent>
+#include <Navaids/navrecord.hxx>
+#include <Navaids/positioned.hxx>
+#include <Airports/airport.hxx>
+
/* equatorial and polar earth radius */
const float rec = 6378137; // earth radius, equator (?)
const float rpol = 6356752.314f; // earth radius, polar (?)
return t;
}
+void BaseDiagram::extendRect(QRectF &r, const QPointF &p)
+{
+ if (p.x() < r.left()) {
+ r.setLeft(p.x());
+ } else if (p.x() > r.right()) {
+ r.setRight(p.x());
+ }
+
+ if (p.y() < r.top()) {
+ r.setTop(p.y());
+ } else if (p.y() > r.bottom()) {
+ r.setBottom(p.y());
+ }
+}
+
void BaseDiagram::paintEvent(QPaintEvent* pe)
{
QPainter p(this);
QTransform t(transform());
p.setTransform(t);
+ paintNavaids(&p);
+
paintContents(&p);
}
+class MapFilter : public FGPositioned::TypeFilter
+{
+public:
+ MapFilter()
+ {
+ // addType(FGPositioned::FIX);
+ addType(FGPositioned::AIRPORT);
+ addType(FGPositioned::NDB);
+ addType(FGPositioned::VOR);
+ }
+
+ virtual bool pass(FGPositioned* aPos) const
+ {
+ bool ok = TypeFilter::pass(aPos);
+ if (ok && (aPos->type() == FGPositioned::FIX)) {
+ // ignore fixes which end in digits
+ if (aPos->ident().length() > 4 && isdigit(aPos->ident()[3]) && isdigit(aPos->ident()[4])) {
+ return false;
+ }
+ }
+
+ return ok;
+ }
+};
+
+
+void BaseDiagram::paintNavaids(QPainter* painter)
+{
+ QTransform xf = painter->transform();
+ painter->setTransform(QTransform()); // reset to identity
+ QTransform invT = xf.inverted();
+ SGGeod topLeft = unproject(invT.map(QPointF(0,0)), m_projectionCenter);
+
+ double minRunwayLengthFt = (16 / m_scale) * SG_METER_TO_FEET;
+ // add 10nm fudge factor
+ double drawRangeNm = SGGeodesy::distanceNm(m_projectionCenter, topLeft) + 10.0;
+ //qDebug() << "draw range computed as:" << drawRangeNm;
+
+ MapFilter f;
+ FGPositionedList items = FGPositioned::findWithinRange(m_projectionCenter, drawRangeNm, &f);
+
+ // pass 0 - icons
+
+ FGPositionedList::const_iterator it;
+ for (it = items.begin(); it != items.end(); ++it) {
+ bool drawAsIcon = true;
+
+ if ((*it)->type() == FGPositioned::AIRPORT) {
+ FGAirport* apt = static_cast<FGAirport*>(it->ptr());
+ if (apt->hasHardRunwayOfLengthFt(minRunwayLengthFt)) {
+
+ drawAsIcon = false;
+ painter->setTransform(xf);
+ QVector<QLineF> lines = projectAirportRuwaysWithCenter(apt, m_projectionCenter);
+
+ QPen pen(QColor(0x03, 0x83, 0xbf), 8);
+ pen.setCosmetic(true);
+ painter->setPen(pen);
+ painter->drawLines(lines);
+
+ QPen linePen(Qt::white, 2);
+ linePen.setCosmetic(true);
+ painter->setPen(linePen);
+ painter->drawLines(lines);
+
+ painter->resetTransform();
+ }
+ }
+
+ if (drawAsIcon) {
+ QPixmap pm = iconForPositioned(*it);
+ QPointF loc = xf.map(project((*it)->geod()));
+ loc -= QPointF(pm.width() >> 1, pm.height() >> 1);
+ painter->drawPixmap(loc, pm);
+ }
+ }
+
+ // restore transform
+ painter->setTransform(xf);
+}
+
void BaseDiagram::mousePressEvent(QMouseEvent *me)
{
m_lastMousePos = me->pos();
update();
}
-void BaseDiagram::paintContents(QPainter*)
+void BaseDiagram::paintContents(QPainter* painter)
{
-
}
void BaseDiagram::recomputeBounds(bool resetZoom)
void BaseDiagram::extendBounds(const QPointF& p)
{
- if (p.x() < m_bounds.left()) {
- m_bounds.setLeft(p.x());
- } else if (p.x() > m_bounds.right()) {
- m_bounds.setRight(p.x());
- }
-
- if (p.y() < m_bounds.top()) {
- m_bounds.setTop(p.y());
- } else if (p.y() > m_bounds.bottom()) {
- m_bounds.setBottom(p.y());
- }
+ extendRect(m_bounds, p);
}
-QPointF BaseDiagram::project(const SGGeod& geod) const
+QPointF BaseDiagram::project(const SGGeod& geod, const SGGeod& center)
{
double r = earth_radius_lat(geod.getLatitudeRad());
- double ref_lat = m_projectionCenter.getLatitudeRad(),
- ref_lon = m_projectionCenter.getLongitudeRad(),
+ double ref_lat = center.getLatitudeRad(),
+ ref_lon = center.getLongitudeRad(),
lat = geod.getLatitudeRad(),
lon = geod.getLongitudeRad(),
lonDiff = lon - ref_lon;
return QPointF(x, -y) * r;
}
+
+SGGeod BaseDiagram::unproject(const QPointF& xy, const SGGeod& center)
+{
+ double r = earth_radius_lat(center.getLatitudeRad());
+ double lat = 0,
+ lon = 0,
+ ref_lat = center.getLatitudeRad(),
+ ref_lon = center.getLongitudeRad(),
+ rho = QVector2D(xy).length(),
+ c = rho/r;
+
+ if (rho == 0) {
+ return center;
+ }
+
+ double x = xy.x(), y = xy.y();
+ lat = asin( cos(c) * sin(ref_lat) + (y * sin(c) * cos(ref_lat)) / rho);
+
+ if (ref_lat == (90 * SG_DEGREES_TO_RADIANS)) // north pole
+ {
+ lon = ref_lon + atan(-x/y);
+ }
+ else if (ref_lat == -(90 * SG_DEGREES_TO_RADIANS)) // south pole
+ {
+ lon = ref_lon + atan(x/y);
+ }
+ else
+ {
+ lon = ref_lon + atan(x* sin(c) / (rho * cos(ref_lat) * cos(c) - y * sin(ref_lat) * sin(c)));
+ }
+
+ return SGGeod::fromRad(lon, lat);
+}
+
+QPointF BaseDiagram::project(const SGGeod& geod) const
+{
+ return project(geod, m_projectionCenter);
+}
+
+QPixmap BaseDiagram::iconForPositioned(const FGPositionedRef& pos)
+{
+ // if airport type, check towered or untowered
+
+ bool isTowered = false;
+ if (FGAirport::isAirportType(pos)) {
+ FGAirport* apt = static_cast<FGAirport*>(pos.ptr());
+ isTowered = apt->hasTower();
+ }
+
+ switch (pos->type()) {
+ case FGPositioned::VOR:
+ // check for VORTAC
+
+ if (static_cast<FGNavRecord*>(pos.ptr())->hasDME())
+ return QPixmap(":/vor-dme-icon");
+
+ return QPixmap(":/vor-icon");
+
+ case FGPositioned::AIRPORT:
+ return iconForAirport(static_cast<FGAirport*>(pos.ptr()));
+
+ case FGPositioned::HELIPORT:
+ return QPixmap(":/heliport-icon");
+ case FGPositioned::SEAPORT:
+ return QPixmap(isTowered ? ":/seaport-tower-icon" : ":/seaport-icon");
+ case FGPositioned::NDB:
+ return QPixmap(":/ndb-icon");
+ case FGPositioned::FIX:
+ return QPixmap(":/waypoint-icon");
+
+ default:
+ break;
+ }
+
+ return QPixmap();
+}
+
+QPixmap BaseDiagram::iconForAirport(FGAirport* apt)
+{
+ if (!apt->hasHardRunwayOfLengthFt(1500)) {
+ return QPixmap(apt->hasTower() ? ":/airport-tower-icon" : ":/airport-icon");
+ }
+
+ if (apt->hasHardRunwayOfLengthFt(8500)) {
+ QPixmap result(32, 32);
+ result.fill(Qt::transparent);
+ {
+ QPainter p(&result);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ QRectF b = result.rect().adjusted(4, 4, -4, -4);
+ QVector<QLineF> lines = projectAirportRuwaysIntoRect(apt, b);
+
+ p.setPen(QPen(QColor(0x03, 0x83, 0xbf), 8));
+ p.drawLines(lines);
+
+ p.setPen(QPen(Qt::white, 2));
+ p.drawLines(lines);
+ }
+ return result;
+ }
+
+ QPixmap result(25, 25);
+ result.fill(Qt::transparent);
+
+ {
+ QPainter p(&result);
+ p.setRenderHint(QPainter::Antialiasing, true);
+ p.setPen(Qt::NoPen);
+
+ p.setBrush(apt->hasTower() ? QColor(0x03, 0x83, 0xbf) :
+ QColor(0x9b, 0x5d, 0xa2));
+ p.drawEllipse(QPointF(13, 13), 10, 10);
+
+ FGRunwayRef r = apt->longestRunway();
+
+ p.setPen(QPen(Qt::white, 2));
+ p.translate(13, 13);
+ p.rotate(r->headingDeg());
+ p.drawLine(0, -8, 0, 8);
+ }
+
+ return result;
+}
+
+QVector<QLineF> BaseDiagram::projectAirportRuwaysWithCenter(FGAirportRef apt, const SGGeod& c)
+{
+ QVector<QLineF> r;
+
+ const FGRunwayList& runways(apt->getRunwaysWithoutReciprocals());
+ FGRunwayList::const_iterator it;
+
+ for (it = runways.begin(); it != runways.end(); ++it) {
+ FGRunwayRef rwy = *it;
+ QPointF p1 = project(rwy->geod(), c);
+ QPointF p2 = project(rwy->end(), c);
+ r.append(QLineF(p1, p2));
+ }
+
+ return r;
+}
+
+QVector<QLineF> BaseDiagram::projectAirportRuwaysIntoRect(FGAirportRef apt, const QRectF &bounds)
+{
+ QVector<QLineF> r = projectAirportRuwaysWithCenter(apt, apt->geod());
+
+ QRectF extent;
+ Q_FOREACH(const QLineF& l, r) {
+ extendRect(extent, l.p1());
+ extendRect(extent, l.p2());
+ }
+
+ // find constraining scale factor
+ double ratioInX = bounds.width() / extent.width();
+ double ratioInY = bounds.height() / extent.height();
+
+ QTransform t;
+ t.translate(bounds.left(), bounds.top());
+ t.scale(std::min(ratioInX, ratioInY),
+ std::min(ratioInX, ratioInY));
+ t.translate(-extent.left(), -extent.top()); // move unscaled to 0,0
+
+ for (int i=0; i<r.size(); ++i) {
+ r[i] = t.map(r[i]);
+ }
+
+ return r;
+}
#include <simgear/math/sg_geodesy.hxx>
+#include <Navaids/positioned.hxx>
+#include <Airports/airport.hxx>
+
class BaseDiagram : public QWidget
{
Q_OBJECT
public:
BaseDiagram(QWidget* pr);
+ static QPixmap iconForPositioned(const FGPositionedRef &pos);
+ static QPixmap iconForAirport(FGAirport *apt);
-
+ static QVector<QLineF> projectAirportRuwaysIntoRect(FGAirportRef apt, const QRectF& bounds);
+ static QVector<QLineF> projectAirportRuwaysWithCenter(FGAirportRef apt, const SGGeod &c);
protected:
virtual void paintEvent(QPaintEvent* pe);
QPointF m_panOffset, m_lastMousePos;
int m_wheelAngleDeltaAccumulator;
bool m_didPan;
+
+ static void extendRect(QRectF& r, const QPointF& p);
+
+ static QPointF project(const SGGeod &geod, const SGGeod ¢er);
+
+ static SGGeod unproject(const QPointF &xy, const SGGeod ¢er);
+private:
+ void paintNavaids(QPainter *p);
+
};
#endif // of GUI_BASEDIAGRAM_HXX
#include <QTimer>
#include <QDebug>
#include <QToolButton>
+#include <QMovie>
+#include <QPainter>
#include "AirportDiagram.hxx"
#include "NavaidDiagram.hxx"
}
}
+ if (role == Qt::DecorationRole) {
+ return AirportDiagram::iconForPositioned(pos);
+ }
+
if (role == Qt::EditRole) {
return QString::fromStdString(pos->ident());
}
private:
-
void onSearchResultsPoll()
{
PositionedIDVec newIds = m_search->results();
QIcon historyIcon(":/history-icon");
m_ui->searchHistory->setIcon(historyIcon);
- m_ui->searchIcon->setPixmap(QPixmap(":/search-icon"));
+ QByteArray format;
+ m_ui->searchIcon->setMovie(new QMovie(":/spinner", format, this));
m_searchModel = new NavSearchModel;
m_ui->searchResultsList->setModel(m_searchModel);
this, SLOT(onOffsetDataChanged()));
m_backButton = new QToolButton(this);
- m_backButton->setGeometry(0, 0, 32, 32);
- m_backButton->setIcon(QIcon(":/search-icon"));
+ m_backButton->setGeometry(0, 0, 64, 32);
+ m_backButton->setText("<< Back");
+ //m_backButton->setIcon(QIcon(":/search-icon"));
m_backButton->raise();
connect(m_backButton, &QAbstractButton::clicked,
{
flightgear::Options* opt = flightgear::Options::sharedInstance();
+ std::string altStr = QString::number(m_ui->altitudeSpinbox->value()).toStdString();
+ std::string vcStr = QString::number(m_ui->airspeedSpinbox->value()).toStdString();
+
if (m_locationIsLatLon) {
// bypass the options mechanism because converting to deg:min:sec notation
// just to parse back again is nasty.
fgSetDouble("/position/latitude-deg", m_geodLocation.getLatitudeDeg());
fgSetDouble("/sim/presets/longitude-deg", m_geodLocation.getLongitudeDeg());
fgSetDouble("/position/longitude-deg", m_geodLocation.getLongitudeDeg());
+
+ opt->addOption("altitude", altStr);
+ opt->addOption("vc", vcStr);
return;
}
int index = m_ui->runwayCombo->itemData(m_ui->runwayCombo->currentIndex()).toInt();
if (index >= 0) {
// explicit runway choice
- opt->addOption("runway", apt->getRunwayByIndex(index)->ident());
+ FGRunwayRef runway = apt->getRunwayByIndex(index);
+ opt->addOption("runway", runway->ident());
+
+ // set nav-radio 1 based on selected runway
+ if (runway->ILS()) {
+ double mhz = runway->ILS()->get_freq() / 100.0;
+ QString navOpt = QString("%1:%2").arg(runway->headingDeg()).arg(mhz);
+ opt->addOption("nav1", navOpt.toStdString());
+ }
}
if (m_ui->onFinalCheckbox->isChecked()) {
opt->addOption("glideslope", "3.0");
- opt->addOption("offset-distance", "10.0"); // in nautical miles
+ double offsetNm = m_ui->approachDistanceSpin->value();
+ opt->addOption("offset-distance", QString::number(offsetNm).toStdString());
}
+
} else if (m_ui->parkingRadio->isChecked()) {
// parking selection
opt->addOption("parkpos", m_ui->parkingCombo->currentText().toStdString());
}
// of location is an airport
- }
+ } else {
+ // location is a navaid
+ // note setting the ident here is ambigious, we really only need and
+ // want the 'navaid-id' property. However setting the 'real' option
+ // gives a better UI experience (eg existing Position in Air dialog)
+ FGPositioned::Type ty = m_location->type();
+ switch (ty) {
+ case FGPositioned::VOR:
+ opt->addOption("vor", m_location->ident());
+ setNavRadioOption();
+ break;
+
+ case FGPositioned::NDB:
+ opt->addOption("ndb", m_location->ident());
+ setNavRadioOption();
+ break;
+
+ case FGPositioned::FIX:
+ opt->addOption("fix", m_location->ident());
+ break;
+ default:
+ break;
+ }
+
+ opt->addOption("altitude", altStr);
+ opt->addOption("vc", vcStr);
- FGPositioned::Type ty = m_location->type();
- switch (ty) {
- case FGPositioned::VOR:
- case FGPositioned::NDB:
- case FGPositioned::FIX:
// set disambiguation property
globals->get_props()->setIntValue("/sim/presets/navaid-id",
static_cast<int>(m_location->guid()));
+ }
- // we always set 'fix', but really this is just to force positionInit
- // code to check for the navaid-id value above.
- opt->addOption("fix", m_location->ident());
- break;
- default:
- break;
+}
+
+void LocationWidget::setNavRadioOption()
+{
+ flightgear::Options* opt = flightgear::Options::sharedInstance();
+
+ if (m_location->type() == FGPositioned::VOR) {
+ FGNavRecordRef nav(static_cast<FGNavRecord*>(m_location.ptr()));
+ double mhz = nav->get_freq() / 100.0;
+ int heading = 0; // add heading support
+ QString navOpt = QString("%1:%2").arg(heading).arg(mhz);
+ opt->addOption("nav1", navOpt.toStdString());
+ } else {
+ FGNavRecordRef nav(static_cast<FGNavRecord*>(m_location.ptr()));
+ int khz = nav->get_freq() / 100;
+ int heading = 0;
+ QString adfOpt = QString("%1:%2").arg(heading).arg(khz);
+ qDebug() << "ADF opt is:" << adfOpt;
+ opt->addOption("adf1", adfOpt.toStdString());
}
}
if (m_searchModel->isSearchActive()) {
m_ui->searchStatusText->setText(QString("Searching for '%1'").arg(search));
+ qDebug() << "setting icon visible";
m_ui->searchIcon->setVisible(true);
+ m_ui->searchIcon->movie()->start();
} else if (m_searchModel->rowCount(QModelIndex()) == 1) {
setBaseLocation(m_searchModel->itemAtRow(0));
}
void onOffsetEnabledToggled(bool on);
void onBackToSearch();
+ void setNavRadioOption();
};
#endif // LOCATIONWIDGET_H
<item>
<widget class="QStackedWidget" name="stack">
<property name="currentIndex">
- <number>1</number>
+ <number>2</number>
</property>
<widget class="QWidget" name="airportPage">
<layout class="QGridLayout" name="gridLayout" columnstretch="1,0,0,0">
</widget>
<widget class="QWidget" name="searchPage">
<layout class="QVBoxLayout" name="verticalLayout_2">
+ <property name="spacing">
+ <number>2</number>
+ </property>
<property name="leftMargin">
<number>0</number>
</property>
</layout>
</item>
<item>
- <layout class="QHBoxLayout" name="horizontalLayout">
+ <layout class="QHBoxLayout" name="horizontalLayout" stretch="1,0">
<item>
<widget class="QLabel" name="searchStatusText">
<property name="text">
</item>
<item>
<widget class="QLabel" name="searchIcon">
+ <property name="minimumSize">
+ <size>
+ <width>16</width>
+ <height>16</height>
+ </size>
+ </property>
<property name="text">
<string>TextLabel</string>
</property>
SGGeod offsetGeod = SGGeodesy::direct(m_geod, m_offsetBearingDeg, d);
QPointF offset = project(offsetGeod);
- qDebug() << base << offset;
-
QPen pen(Qt::green);
pen.setCosmetic(true);
painter->setPen(pen);
bool startPaused = m_ui->startPausedCheck->isChecked() ||
m_ui->location->shouldStartPaused();
if (startPaused) {
+ qDebug() << "will start paused";
opt->addOption("enable-freeze", "");
}
<RCC>
<qresource prefix="/">
<file alias="history-icon">history-icon.png</file>
- <file alias="search-icon">large-search-icon.png</file>
<file alias="right-arrow-icon">arrow-right-icon.png</file>
<file alias="left-arrow-icon">arrow-left-icon.png</file>
<file alias="app-icon-large">../../icons/128x128/apps/flightgear.png</file>
+ <file alias="spinner">spinner.gif</file>
+ <file alias="heliport-icon">heliport-icon.png</file>
+ <file alias="seaport-icon">seaport-icon.png</file>
+ <file alias="vor-icon">vor-icon.png</file>
+ <file alias="vortac-icon">vortac-icon.png</file>
+ <file alias="waypoint-icon">waypoint-icon.png</file>
+ <file alias="ndb-icon">ndb-icon.png</file>
+ <file alias="airport-icon">airport-icon.png</file>
+ <file alias="airport-tower-icon">airport-tower-icon.png</file>
+ <file alias="vor-dme-icon">vor-dme-icon.png</file>
+ <file alias="seaport-tower-icon">seaport-tower-icon.png</file>
</qresource>
-</RCC>
\ No newline at end of file
+</RCC>
// Set current_options lon/lat given an airport id and heading (degrees)
-static bool fgSetPosFromNAV( const string& id, const double& freq, FGPositioned::Type type )
+static bool fgSetPosFromNAV( const string& id,
+ const double& freq,
+ FGPositioned::Type type,
+ PositionedID guid)
{
- FGNavList::TypeFilter filter(type);
- const nav_list_type navlist = FGNavList::findByIdentAndFreq( id.c_str(), freq, &filter );
-
- if (navlist.empty()) {
- SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate NAV = "
- << id << ":" << freq );
- return false;
- }
-
- if( navlist.size() > 1 ) {
- std::ostringstream buf;
- buf << "Ambigous NAV-ID: '" << id << "'. Specify id and frequency. Available stations:" << endl;
- for( nav_list_type::const_iterator it = navlist.begin(); it != navlist.end(); ++it ) {
- // NDB stored in kHz, VOR stored in MHz * 100 :-P
- double factor = (*it)->type() == FGPositioned::NDB ? 1.0 : 1/100.0;
- string unit = (*it)->type() == FGPositioned::NDB ? "kHz" : "MHz";
- buf << (*it)->ident() << " "
- << std::setprecision(5) << (double)((*it)->get_freq() * factor) << " "
- << (*it)->get_lat() << "/" << (*it)->get_lon()
- << endl;
+ FGNavRecord* nav = 0;
+
+
+ if (guid != 0) {
+ nav = FGPositioned::loadById<FGNavRecord>(guid);
+ if (!nav)
+ return false;
+ } else {
+ FGNavList::TypeFilter filter(type);
+ const nav_list_type navlist = FGNavList::findByIdentAndFreq( id.c_str(), freq, &filter );
+
+ if (navlist.empty()) {
+ SG_LOG( SG_GENERAL, SG_ALERT, "Failed to locate NAV = "
+ << id << ":" << freq );
+ return false;
+ }
+
+ if( navlist.size() > 1 ) {
+ std::ostringstream buf;
+ buf << "Ambigous NAV-ID: '" << id << "'. Specify id and frequency. Available stations:" << endl;
+ for( nav_list_type::const_iterator it = navlist.begin(); it != navlist.end(); ++it ) {
+ // NDB stored in kHz, VOR stored in MHz * 100 :-P
+ double factor = (*it)->type() == FGPositioned::NDB ? 1.0 : 1/100.0;
+ string unit = (*it)->type() == FGPositioned::NDB ? "kHz" : "MHz";
+ buf << (*it)->ident() << " "
+ << std::setprecision(5) << (double)((*it)->get_freq() * factor) << " "
+ << (*it)->get_lat() << "/" << (*it)->get_lon()
+ << endl;
+ }
+
+ SG_LOG( SG_GENERAL, SG_ALERT, buf.str() );
+ return false;
+ }
+
+ // nav list must be of length 1
+ nav = navlist[0];
}
-
- SG_LOG( SG_GENERAL, SG_ALERT, buf.str() );
- return false;
- }
-
- FGNavRecord *nav = navlist[0];
- fgApplyStartOffset(nav->geod(), fgGetDouble("/sim/presets/heading-deg"));
- return true;
+
+ fgApplyStartOffset(nav->geod(), fgGetDouble("/sim/presets/heading-deg"));
+ return true;
}
// Set current_options lon/lat given an aircraft carrier id
}
}
-// Set current_options lon/lat given an airport id and heading (degrees)
+// Set current_options lon/lat given a fix ident and GUID
static bool fgSetPosFromFix( const string& id, PositionedID guid )
{
FGPositioned* fix = NULL;
if ( !set_pos && !vor.empty() ) {
// a VOR is requested
- if ( fgSetPosFromNAV( vor, vor_freq, FGPositioned::VOR ) ) {
+ if ( fgSetPosFromNAV( vor, vor_freq, FGPositioned::VOR, navaidId ) ) {
set_pos = true;
}
}
if ( !set_pos && !ndb.empty() ) {
// an NDB is requested
- if ( fgSetPosFromNAV( ndb, ndb_freq, FGPositioned::NDB ) ) {
+ if ( fgSetPosFromNAV( ndb, ndb_freq, FGPositioned::NDB, navaidId ) ) {
set_pos = true;
}
}