From: James Turner Date: Tue, 10 Nov 2015 22:54:57 +0000 (+0000) Subject: Navaid diagram for launcher X-Git-Url: https://git.mxchange.org/?a=commitdiff_plain;h=a39df4877264fc25365f609c41ed86eec66cc944;p=flightgear.git Navaid diagram for launcher - work in progress, needs labels --- diff --git a/src/Airports/airport.cxx b/src/Airports/airport.cxx index 60a711bf5..ce8fd1a39 100644 --- a/src/Airports/airport.cxx +++ b/src/Airports/airport.cxx @@ -76,6 +76,7 @@ FGAirport::FGAirport( PositionedID aGuid, _has_metar(has_metar), _dynamics(0), mTowerDataLoaded(false), + mHasTower(false), mRunwaysLoaded(false), mHelipadsLoaded(false), mTaxiwaysLoaded(false), @@ -314,6 +315,20 @@ bool FGAirport::hasHardRunwayOfLengthFt(double aLengthFt) const 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 { @@ -663,13 +678,14 @@ void FGAirport::validateTowerData() 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:" <loadById(towers.front()); mTowerPosition = tower->geod(); + mHasTower = true; } SGPath path; @@ -681,6 +697,7 @@ void FGAirport::validateTowerData() const SGPropertyNode_ptr rootNode = new SGPropertyNode; readProperties(path.str(), rootNode); const_cast(this)->readTowerData(rootNode); + mHasTower = true; } catch (sg_exception& e){ SG_LOG(SG_NAVAID, SG_WARN, ident() << "loading twr XML failed:" << e.getFormattedMessage()); } @@ -723,6 +740,12 @@ void FGAirport::validateILSData() } } +bool FGAirport::hasTower() const +{ + validateTowerData(); + return mHasTower; +} + void FGAirport::readILSData(SGPropertyNode* aRoot) { NavDataCache* cache = NavDataCache::instance(); diff --git a/src/Airports/airport.hxx b/src/Airports/airport.hxx index b9155d68d..b585d19d8 100644 --- a/src/Airports/airport.hxx +++ b/src/Airports/airport.hxx @@ -73,6 +73,8 @@ class FGAirport : public FGPositioned */ void validateILSData(); + bool hasTower() const; + SGGeod getTowerLocation() const; void setMetar(bool value) { _has_metar = value; } @@ -142,6 +144,8 @@ class FGAirport : public FGPositioned */ bool hasHardRunwayOfLengthFt(double aLengthFt) const; + FGRunwayRef longestRunway() const; + unsigned int numTaxiways() const; FGTaxiwayRef getTaxiwayByIndex(unsigned int aIndex) const; FGTaxiwayList getTaxiways() const; @@ -319,6 +323,7 @@ private: void loadProcedures() const; mutable bool mTowerDataLoaded; + mutable bool mHasTower; mutable SGGeod mTowerPosition; mutable bool mRunwaysLoaded; diff --git a/src/GUI/BaseDiagram.cxx b/src/GUI/BaseDiagram.cxx index ddc59f0ad..1c938a0a0 100644 --- a/src/GUI/BaseDiagram.cxx +++ b/src/GUI/BaseDiagram.cxx @@ -27,6 +27,10 @@ #include #include +#include +#include +#include + /* equatorial and polar earth radius */ const float rec = 6378137; // earth radius, equator (?) const float rpol = 6356752.314f; // earth radius, polar (?) @@ -62,6 +66,21 @@ QTransform BaseDiagram::transform() const 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); @@ -79,9 +98,92 @@ void BaseDiagram::paintEvent(QPaintEvent* pe) 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(it->ptr()); + if (apt->hasHardRunwayOfLengthFt(minRunwayLengthFt)) { + + drawAsIcon = false; + painter->setTransform(xf); + QVector 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(); @@ -132,9 +234,8 @@ void BaseDiagram::wheelEvent(QWheelEvent *we) update(); } -void BaseDiagram::paintContents(QPainter*) +void BaseDiagram::paintContents(QPainter* painter) { - } void BaseDiagram::recomputeBounds(bool resetZoom) @@ -158,24 +259,14 @@ void BaseDiagram::doComputeBounds() 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; @@ -206,3 +297,170 @@ QPointF BaseDiagram::project(const SGGeod& geod) const 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(pos.ptr()); + isTowered = apt->hasTower(); + } + + switch (pos->type()) { + case FGPositioned::VOR: + // check for VORTAC + + if (static_cast(pos.ptr())->hasDME()) + return QPixmap(":/vor-dme-icon"); + + return QPixmap(":/vor-icon"); + + case FGPositioned::AIRPORT: + return iconForAirport(static_cast(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 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 BaseDiagram::projectAirportRuwaysWithCenter(FGAirportRef apt, const SGGeod& c) +{ + QVector 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 BaseDiagram::projectAirportRuwaysIntoRect(FGAirportRef apt, const QRectF &bounds) +{ + QVector 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 +#include +#include + class BaseDiagram : public QWidget { Q_OBJECT public: BaseDiagram(QWidget* pr); + static QPixmap iconForPositioned(const FGPositionedRef &pos); + static QPixmap iconForAirport(FGAirport *apt); - + static QVector projectAirportRuwaysIntoRect(FGAirportRef apt, const QRectF& bounds); + static QVector projectAirportRuwaysWithCenter(FGAirportRef apt, const SGGeod &c); protected: virtual void paintEvent(QPaintEvent* pe); @@ -60,6 +66,15 @@ protected: 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 diff --git a/src/GUI/LocationWidget.cxx b/src/GUI/LocationWidget.cxx index 0136103ba..69723a1b5 100644 --- a/src/GUI/LocationWidget.cxx +++ b/src/GUI/LocationWidget.cxx @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include "AirportDiagram.hxx" #include "NavaidDiagram.hxx" @@ -202,6 +204,10 @@ public: } } + if (role == Qt::DecorationRole) { + return AirportDiagram::iconForPositioned(pos); + } + if (role == Qt::EditRole) { return QString::fromStdString(pos->ident()); } @@ -228,7 +234,6 @@ Q_SIGNALS: private: - void onSearchResultsPoll() { PositionedIDVec newIds = m_search->results(); @@ -267,7 +272,8 @@ LocationWidget::LocationWidget(QWidget *parent) : 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); @@ -310,8 +316,9 @@ LocationWidget::LocationWidget(QWidget *parent) : 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, @@ -374,6 +381,9 @@ void LocationWidget::setLocationOptions() { 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. @@ -381,6 +391,9 @@ void LocationWidget::setLocationOptions() 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; } @@ -396,35 +409,79 @@ void LocationWidget::setLocationOptions() 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(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(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(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()); } } @@ -446,7 +503,9 @@ void LocationWidget::onSearch() 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)); } diff --git a/src/GUI/LocationWidget.hxx b/src/GUI/LocationWidget.hxx index dc9987337..d6910d036 100644 --- a/src/GUI/LocationWidget.hxx +++ b/src/GUI/LocationWidget.hxx @@ -88,6 +88,7 @@ private: void onOffsetEnabledToggled(bool on); void onBackToSearch(); + void setNavRadioOption(); }; #endif // LOCATIONWIDGET_H diff --git a/src/GUI/LocationWidget.ui b/src/GUI/LocationWidget.ui index 719fe1921..f68766eef 100644 --- a/src/GUI/LocationWidget.ui +++ b/src/GUI/LocationWidget.ui @@ -26,7 +26,7 @@ - 1 + 2 @@ -292,6 +292,9 @@ + + 2 + 0 @@ -342,7 +345,7 @@ - + @@ -355,6 +358,12 @@ + + + 16 + 16 + + TextLabel diff --git a/src/GUI/NavaidDiagram.cxx b/src/GUI/NavaidDiagram.cxx index b31e881cd..fa6b78c2c 100644 --- a/src/GUI/NavaidDiagram.cxx +++ b/src/GUI/NavaidDiagram.cxx @@ -82,8 +82,6 @@ void NavaidDiagram::paintContents(QPainter *painter) 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); diff --git a/src/GUI/QtLauncher.cxx b/src/GUI/QtLauncher.cxx index 1cd689d73..57f8be6f3 100644 --- a/src/GUI/QtLauncher.cxx +++ b/src/GUI/QtLauncher.cxx @@ -787,6 +787,7 @@ void QtLauncher::onRun() bool startPaused = m_ui->startPausedCheck->isChecked() || m_ui->location->shouldStartPaused(); if (startPaused) { + qDebug() << "will start paused"; opt->addOption("enable-freeze", ""); } diff --git a/src/GUI/airport-icon.png b/src/GUI/airport-icon.png new file mode 100644 index 000000000..1d23061ae Binary files /dev/null and b/src/GUI/airport-icon.png differ diff --git a/src/GUI/airport-tower-icon.png b/src/GUI/airport-tower-icon.png new file mode 100644 index 000000000..cb0be995c Binary files /dev/null and b/src/GUI/airport-tower-icon.png differ diff --git a/src/GUI/heliport-icon.png b/src/GUI/heliport-icon.png new file mode 100644 index 000000000..16075818c Binary files /dev/null and b/src/GUI/heliport-icon.png differ diff --git a/src/GUI/large-search-icon.png b/src/GUI/large-search-icon.png deleted file mode 100644 index 8ab5253ab..000000000 Binary files a/src/GUI/large-search-icon.png and /dev/null differ diff --git a/src/GUI/ndb-icon.png b/src/GUI/ndb-icon.png new file mode 100644 index 000000000..3d0fd3fdf Binary files /dev/null and b/src/GUI/ndb-icon.png differ diff --git a/src/GUI/resources.qrc b/src/GUI/resources.qrc index 4cbca391d..c48a7d40f 100644 --- a/src/GUI/resources.qrc +++ b/src/GUI/resources.qrc @@ -1,9 +1,19 @@ history-icon.png - large-search-icon.png arrow-right-icon.png arrow-left-icon.png ../../icons/128x128/apps/flightgear.png + spinner.gif + heliport-icon.png + seaport-icon.png + vor-icon.png + vortac-icon.png + waypoint-icon.png + ndb-icon.png + airport-icon.png + airport-tower-icon.png + vor-dme-icon.png + seaport-tower-icon.png - \ No newline at end of file + diff --git a/src/GUI/seaport-icon.png b/src/GUI/seaport-icon.png new file mode 100644 index 000000000..61755fe25 Binary files /dev/null and b/src/GUI/seaport-icon.png differ diff --git a/src/GUI/seaport-tower-icon.png b/src/GUI/seaport-tower-icon.png new file mode 100644 index 000000000..c1c0f76cc Binary files /dev/null and b/src/GUI/seaport-tower-icon.png differ diff --git a/src/GUI/spinner.gif b/src/GUI/spinner.gif new file mode 100644 index 000000000..5b33f7e54 Binary files /dev/null and b/src/GUI/spinner.gif differ diff --git a/src/GUI/vor-dme-icon.png b/src/GUI/vor-dme-icon.png new file mode 100644 index 000000000..e5e5a48f1 Binary files /dev/null and b/src/GUI/vor-dme-icon.png differ diff --git a/src/GUI/vor-icon.png b/src/GUI/vor-icon.png new file mode 100644 index 000000000..111b014cf Binary files /dev/null and b/src/GUI/vor-icon.png differ diff --git a/src/GUI/vortac-icon.png b/src/GUI/vortac-icon.png new file mode 100644 index 000000000..e12642074 Binary files /dev/null and b/src/GUI/vortac-icon.png differ diff --git a/src/GUI/waypoint-icon.png b/src/GUI/waypoint-icon.png new file mode 100644 index 000000000..173dd9614 Binary files /dev/null and b/src/GUI/waypoint-icon.png differ diff --git a/src/Main/positioninit.cxx b/src/Main/positioninit.cxx index 59000c10b..681296687 100644 --- a/src/Main/positioninit.cxx +++ b/src/Main/positioninit.cxx @@ -353,37 +353,51 @@ static void fgSetDistOrAltFromGlideSlope() { // 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(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 @@ -429,7 +443,7 @@ static bool fgSetPosFromCarrier( const string& carrier, const string& posid ) { } } -// 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; @@ -558,14 +572,14 @@ bool initPosition() 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; } }