Merge branch 'jmt/gps' into next
Conflicts: src/Instrumentation/navradio.cxx
This commit is contained in:
commit
ebdeb3eed3
13 changed files with 1798 additions and 48 deletions
|
@ -1828,6 +1828,8 @@
|
|||
</File>
|
||||
<File RelativePath="..\..\..\src\GUI\WaypointList.cxx"></File>
|
||||
<File RelativePath="..\..\..\src\GUI\WaypointList.hxx"></File>
|
||||
<File RelativePath="..\..\..\src\GUI\MapWidget.cxx"></File>
|
||||
<File RelativePath="..\..\..\src\GUI\MapWidget.hxx"></File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Lib_Input"
|
||||
|
|
|
@ -2647,6 +2647,8 @@
|
|||
</File>
|
||||
<File RelativePath="..\..\..\src\GUI\WaypointList.cxx"></File>
|
||||
<File RelativePath="..\..\..\src\GUI\WaypointList.hxx"></File>
|
||||
<File RelativePath="..\..\..\src\GUI\MapWidget.cxx"></File>
|
||||
<File RelativePath="..\..\..\src\GUI\MapWidget.hxx"></File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Lib_Input"
|
||||
|
|
|
@ -597,6 +597,7 @@ void FGRouteMgr::jumpToIndex(int index)
|
|||
|
||||
_route->set_current(index);
|
||||
currentWaypointChanged();
|
||||
_currentWpt->fireValueChanged();
|
||||
}
|
||||
|
||||
void FGRouteMgr::currentWaypointChanged()
|
||||
|
|
|
@ -23,7 +23,8 @@ libGUI_a_SOURCES = \
|
|||
property_list.cxx property_list.hxx \
|
||||
layout.cxx layout-props.cxx layout.hxx \
|
||||
SafeTexFont.cxx SafeTexFont.hxx \
|
||||
WaypointList.cxx WaypointList.hxx
|
||||
WaypointList.cxx WaypointList.hxx \
|
||||
MapWidget.cxx MapWidget.hxx
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src
|
||||
|
||||
|
|
1613
src/GUI/MapWidget.cxx
Normal file
1613
src/GUI/MapWidget.cxx
Normal file
File diff suppressed because it is too large
Load diff
109
src/GUI/MapWidget.hxx
Normal file
109
src/GUI/MapWidget.hxx
Normal file
|
@ -0,0 +1,109 @@
|
|||
#ifndef GUI_MAPWIDGET_HXX
|
||||
#define GUI_MAPWIDGET_HXX
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
#include <plib/pu.h>
|
||||
|
||||
#include "dialog.hxx" // for GUI_ID
|
||||
|
||||
// forward decls
|
||||
class FGRouteMgr;
|
||||
class FGRunway;
|
||||
class FGAirport;
|
||||
class FGNavRecord;
|
||||
class FGFix;
|
||||
class MapData;
|
||||
class SGMagVar;
|
||||
|
||||
class MapWidget : public puObject
|
||||
{
|
||||
public:
|
||||
MapWidget(int x, int y, int width, int height);
|
||||
virtual ~MapWidget();
|
||||
|
||||
virtual void setSize(int width, int height);
|
||||
virtual void doHit( int button, int updown, int x, int y ) ;
|
||||
virtual void draw( int dx, int dy ) ;
|
||||
virtual int checkKey(int key, int updown);
|
||||
|
||||
void setProperty(SGPropertyNode_ptr prop);
|
||||
private:
|
||||
void handlePan(int x, int y);
|
||||
|
||||
void pan(const SGVec2d& delta);
|
||||
void zoomIn();
|
||||
void zoomOut();
|
||||
|
||||
void paintAircraftLocation(const SGGeod& aircraftPos);
|
||||
void paintRoute();
|
||||
void paintRuler();
|
||||
|
||||
void drawGPSData();
|
||||
void drawNavRadio(SGPropertyNode_ptr radio);
|
||||
void drawTunedLocalizer(SGPropertyNode_ptr radio);
|
||||
|
||||
void drawLatLonGrid();
|
||||
SGVec2d gridPoint(int ix, int iy);
|
||||
bool drawLineClipped(const SGVec2d& a, const SGVec2d& b);
|
||||
|
||||
void drawAirports();
|
||||
void drawAirport(FGAirport* apt);
|
||||
int scoreAirportRunways(FGAirport* apt);
|
||||
void drawRunwayPre(FGRunway* rwy);
|
||||
void drawRunway(FGRunway* rwy);
|
||||
void drawILS(bool tuned, FGRunway* rwy);
|
||||
|
||||
void drawNavaids();
|
||||
void drawNDB(bool tuned, FGNavRecord* nav);
|
||||
void drawVOR(bool tuned, FGNavRecord* nav);
|
||||
void drawFix(FGFix* fix);
|
||||
|
||||
void drawTraffic();
|
||||
void drawAIAircraft(const SGPropertyNode* model, const SGGeod& pos, double hdg);
|
||||
void drawAIShip(const SGPropertyNode* model, const SGGeod& pos, double hdg);
|
||||
|
||||
void drawData();
|
||||
bool validDataForKey(void* key);
|
||||
MapData* getOrCreateDataForKey(void* key);
|
||||
MapData* createDataForKey(void* key);
|
||||
void setAnchorForKey(void* key, const SGVec2d& anchor);
|
||||
|
||||
SGVec2d project(const SGGeod& geod) const;
|
||||
SGGeod unproject(const SGVec2d& p) const;
|
||||
double currentScale() const;
|
||||
|
||||
void circleAt(const SGVec2d& center, int nSides, double r);
|
||||
void circleAtAlt(const SGVec2d& center, int nSides, double r, double r2);
|
||||
void drawLine(const SGVec2d& p1, const SGVec2d& p2);
|
||||
void drawLegendBox(const SGVec2d& pos, const std::string& t);
|
||||
|
||||
int _width, _height;
|
||||
int _zoom;
|
||||
double _drawRangeNm;
|
||||
double _upHeading; // true heading corresponding to +ve y-axis
|
||||
bool _magneticHeadings;
|
||||
|
||||
SGGeod _projectionCenter;
|
||||
SGGeod _aircraft;
|
||||
SGGeod _clickGeod;
|
||||
SGVec2d _hitLocation;
|
||||
FGRouteMgr* _route;
|
||||
SGPropertyNode_ptr _root;
|
||||
SGPropertyNode_ptr _gps;
|
||||
|
||||
typedef std::map<void*, MapData*> KeyDataMap;
|
||||
KeyDataMap _mapData;
|
||||
std::vector<MapData*> _dataQueue;
|
||||
|
||||
SGMagVar* _magVar;
|
||||
|
||||
typedef std::map<int, SGVec2d> GridPointCache;
|
||||
GridPointCache _gridCache;
|
||||
double _gridSpacing;
|
||||
SGGeod _gridCenter;
|
||||
};
|
||||
|
||||
#endif // of GUI_MAPWIDGET_HXX
|
|
@ -14,6 +14,7 @@
|
|||
#include "property_list.hxx"
|
||||
#include "layout.hxx"
|
||||
#include "WaypointList.hxx"
|
||||
#include "MapWidget.hxx"
|
||||
|
||||
enum format_type { f_INVALID, f_INT, f_LONG, f_FLOAT, f_DOUBLE, f_STRING };
|
||||
static const int FORMAT_BUFSIZE = 255;
|
||||
|
@ -815,7 +816,10 @@ FGDialog::makeObject (SGPropertyNode *props, int parentWidth, int parentHeight)
|
|||
setupObject(obj, props);
|
||||
setColor(obj, props);
|
||||
return obj;
|
||||
|
||||
} else if (type == "map") {
|
||||
MapWidget* mapWidget = new MapWidget(x, y, x + width, y + height);
|
||||
setupObject(mapWidget, props);
|
||||
return mapWidget;
|
||||
} else if (type == "combo") {
|
||||
fgComboBox *obj = new fgComboBox(x, y, x + width, y + height, props,
|
||||
props->getBoolValue("editable", false));
|
||||
|
@ -953,12 +957,21 @@ FGDialog::setupObject (puObject *object, SGPropertyNode *props)
|
|||
name = "";
|
||||
const char *propname = props->getStringValue("property");
|
||||
SGPropertyNode_ptr node = fgGetNode(propname, true);
|
||||
copy_to_pui(node, object);
|
||||
if (type == "map") {
|
||||
// mapWidget binds to a sub-tree of properties, and
|
||||
// ignroes the puValue mechanism, so special case things here
|
||||
MapWidget* mw = static_cast<MapWidget*>(object);
|
||||
mw->setProperty(node);
|
||||
} else {
|
||||
// normal widget, creating PropertyObject
|
||||
copy_to_pui(node, object);
|
||||
PropertyObject *po = new PropertyObject(name, object, node);
|
||||
_propertyObjects.push_back(po);
|
||||
if (props->getBoolValue("live"))
|
||||
_liveObjects.push_back(po);
|
||||
}
|
||||
|
||||
|
||||
PropertyObject *po = new PropertyObject(name, object, node);
|
||||
_propertyObjects.push_back(po);
|
||||
if (props->getBoolValue("live"))
|
||||
_liveObjects.push_back(po);
|
||||
}
|
||||
|
||||
SGPropertyNode *dest = fgGetNode("/sim/bindings/gui", true);
|
||||
|
|
|
@ -220,7 +220,8 @@ GPS::GPS ( SGPropertyNode *node) :
|
|||
_num(node->getIntValue("number", 0)),
|
||||
_computeTurnData(false),
|
||||
_anticipateTurn(false),
|
||||
_inTurn(false)
|
||||
_inTurn(false),
|
||||
_desiredCourse(0.0)
|
||||
{
|
||||
string branch = "/instrumentation/" + _name;
|
||||
_gpsNode = fgGetNode(branch.c_str(), _num, true );
|
||||
|
@ -303,6 +304,7 @@ GPS::init ()
|
|||
fromFlag->alias(wp1_node->getChild("from-flag"));
|
||||
|
||||
// autopilot drive properties
|
||||
_apDrivingFlag = fgGetNode("/autopilot/settings/gps-driving-true-heading", true);
|
||||
_apTrueHeading = fgGetNode("/autopilot/settings/true-heading-deg",true);
|
||||
_apTargetAltitudeFt = fgGetNode("/autopilot/settings/target-altitude-ft", true);
|
||||
_apAltitudeLock = fgGetNode("/autopilot/locks/altitude", true);
|
||||
|
@ -958,12 +960,17 @@ void GPS::updateRouteData()
|
|||
void GPS::driveAutopilot()
|
||||
{
|
||||
if (!_config.driveAutopilot() || !_realismSimpleGps->getBoolValue()) {
|
||||
_apDrivingFlag->setBoolValue(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// compatability feature - allow the route-manager / GPS to drive the
|
||||
// generic autopilot heading hold *in leg mode only*
|
||||
if (_mode == "leg") {
|
||||
|
||||
bool drive = _mode == "leg";
|
||||
_apDrivingFlag->setBoolValue(drive);
|
||||
|
||||
if (drive) {
|
||||
// FIXME: we want to set desired track, not heading, here
|
||||
_apTrueHeading->setDoubleValue(getWP1Bearing());
|
||||
}
|
||||
|
|
|
@ -413,6 +413,7 @@ private:
|
|||
SGPropertyNode_ptr _realismSimpleGps; ///< should the GPS be simple or realistic?
|
||||
|
||||
// autopilot drive properties
|
||||
SGPropertyNode_ptr _apDrivingFlag;
|
||||
SGPropertyNode_ptr _apTrueHeading;
|
||||
SGPropertyNode_ptr _apTargetAltitudeFt;
|
||||
SGPropertyNode_ptr _apAltitudeLock;
|
||||
|
|
|
@ -891,7 +891,7 @@ void FGNavRadio::search()
|
|||
} else { // ILS or LOC
|
||||
_gs = globals->get_gslist()->findByFreq(freq, pos);
|
||||
has_gs_node->setBoolValue(_gs != NULL);
|
||||
_localizerWidth = localizerWidth(nav);
|
||||
_localizerWidth = nav->localizerWidth();
|
||||
twist = 0.0;
|
||||
effective_range = nav->get_range();
|
||||
|
||||
|
@ -941,39 +941,6 @@ void FGNavRadio::search()
|
|||
id_c4_node->setIntValue( (int)identBuffer[3] );
|
||||
}
|
||||
|
||||
double FGNavRadio::localizerWidth(FGNavRecord* aLOC)
|
||||
{
|
||||
FGRunway* rwy = aLOC->runway();
|
||||
if (!rwy) {
|
||||
return 6.0; // no runway associated, return default value
|
||||
}
|
||||
|
||||
|
||||
SGVec3d thresholdCart(SGVec3d::fromGeod(rwy->threshold()));
|
||||
double axisLength = dist(aLOC->cart(), thresholdCart);
|
||||
double landingLength = dist(thresholdCart, SGVec3d::fromGeod(rwy->end()));
|
||||
|
||||
// Reference: http://dcaa.slv.dk:8000/icaodocs/
|
||||
// ICAO standard width at threshold is 210 m = 689 feet = approx 700 feet.
|
||||
// ICAO 3.1.1 half course = DDM = 0.0775
|
||||
// ICAO 3.1.3.7.1 Sensitivity 0.00145 DDM/m at threshold
|
||||
// implies peg-to-peg of 214 m ... we will stick with 210.
|
||||
// ICAO 3.1.3.7.1 "Course sector angle shall not exceed 6 degrees."
|
||||
|
||||
// Very short runway: less than 1200 m (4000 ft) landing length:
|
||||
if (landingLength < 1200.0) {
|
||||
// ICAO fudges localizer sensitivity for very short runways.
|
||||
// This produces a non-monotonic sensitivity-versus length relation.
|
||||
axisLength += 1050.0;
|
||||
}
|
||||
|
||||
// Example: very short: San Diego KMYF (Montgomery Field) ILS RWY 28R
|
||||
// Example: short: Tom's River KMJX (Robert J. Miller) ILS RWY 6
|
||||
// Example: very long: Denver KDEN (Denver) ILS RWY 16R
|
||||
double raw_width = 210.0 / axisLength * SGD_RADIANS_TO_DEGREES;
|
||||
return raw_width < 6.0? raw_width : 6.0;
|
||||
}
|
||||
|
||||
void FGNavRadio::audioNavidChanged()
|
||||
{
|
||||
if (_sgr->exists(nav_fx_name)) {
|
||||
|
|
|
@ -191,11 +191,6 @@ class FGNavRadio : public SGSubsystem, public SGPropertyChangeListener
|
|||
|
||||
void clearOutputs();
|
||||
|
||||
/**
|
||||
* Compute the localizer width in degrees - see implementation for
|
||||
* more information on the relevant standards and formulae.
|
||||
*/
|
||||
double localizerWidth(FGNavRecord* aLOC);
|
||||
FGNavRecord* findPrimaryNavaid(const SGGeod& aPos, double aFreqMHz);
|
||||
|
||||
/// accessor for tied, read-only 'operable' property
|
||||
|
|
|
@ -181,6 +181,38 @@ void FGNavRecord::alignLocaliserWithRunway(double aThreshold)
|
|||
}
|
||||
}
|
||||
|
||||
double FGNavRecord::localizerWidth() const
|
||||
{
|
||||
if (!mRunway) {
|
||||
return 6.0;
|
||||
}
|
||||
|
||||
SGVec3d thresholdCart(SGVec3d::fromGeod(mRunway->threshold()));
|
||||
double axisLength = dist(cart(), thresholdCart);
|
||||
double landingLength = dist(thresholdCart, SGVec3d::fromGeod(mRunway->end()));
|
||||
|
||||
// Reference: http://dcaa.slv.dk:8000/icaodocs/
|
||||
// ICAO standard width at threshold is 210 m = 689 feet = approx 700 feet.
|
||||
// ICAO 3.1.1 half course = DDM = 0.0775
|
||||
// ICAO 3.1.3.7.1 Sensitivity 0.00145 DDM/m at threshold
|
||||
// implies peg-to-peg of 214 m ... we will stick with 210.
|
||||
// ICAO 3.1.3.7.1 "Course sector angle shall not exceed 6 degrees."
|
||||
|
||||
// Very short runway: less than 1200 m (4000 ft) landing length:
|
||||
if (landingLength < 1200.0) {
|
||||
// ICAO fudges localizer sensitivity for very short runways.
|
||||
// This produces a non-monotonic sensitivity-versus length relation.
|
||||
axisLength += 1050.0;
|
||||
}
|
||||
|
||||
// Example: very short: San Diego KMYF (Montgomery Field) ILS RWY 28R
|
||||
// Example: short: Tom's River KMJX (Robert J. Miller) ILS RWY 6
|
||||
// Example: very long: Denver KDEN (Denver) ILS RWY 16R
|
||||
double raw_width = 210.0 / axisLength * SGD_RADIANS_TO_DEGREES;
|
||||
return raw_width < 6.0? raw_width : 6.0;
|
||||
|
||||
}
|
||||
|
||||
FGTACANRecord::FGTACANRecord(void) :
|
||||
channel(""),
|
||||
freq(0)
|
||||
|
|
|
@ -96,6 +96,13 @@ public:
|
|||
* Retrieve the runway this navaid is associated with (for ILS/LOC/GS)
|
||||
*/
|
||||
FGRunway* runway() const { return mRunway; }
|
||||
|
||||
/**
|
||||
* return the localizer width, in degrees
|
||||
* computation is based up ICAO stdandard width at the runway threshold
|
||||
* see implementation for further details.
|
||||
*/
|
||||
double localizerWidth() const;
|
||||
};
|
||||
|
||||
class FGTACANRecord : public SGReferenced {
|
||||
|
|
Loading…
Reference in a new issue