diff --git a/src/Instrumentation/NavDisplay.cxx b/src/Instrumentation/NavDisplay.cxx index e27c04361..4cc9d5b3b 100644 --- a/src/Instrumentation/NavDisplay.cxx +++ b/src/Instrumentation/NavDisplay.cxx @@ -145,6 +145,22 @@ static osg::Vec2 mult(const osg::Vec2& v, const osg::Matrixf& m) return osg::Vec2(r.x(), r.y()); } +class NavDisplay::CacheListener : public SGPropertyChangeListener +{ +public: + CacheListener(NavDisplay *nd) : + _nd(nd) + {} + + virtual void valueChanged (SGPropertyNode * prop) + { + _nd->invalidatePositionedCache(); + SG_LOG(SG_INSTR, SG_INFO, "invalidating NavDisplay cache"); + } +private: + NavDisplay* _nd; +}; + /////////////////////////////////////////////////////////////////// class SymbolDef @@ -381,8 +397,14 @@ NavDisplay::~NavDisplay() void NavDisplay::init () { + _cachedItemsValid = false; + _cacheListener.reset(new CacheListener(this)); + _serviceable_node = _Instrument->getNode("serviceable", true); - + _rangeNode = _Instrument->getNode("range", true); + _rangeNode->setDoubleValue(40.0); + _rangeNode->addChangeListener(_cacheListener.get()); + // texture name to use in 2D and 3D instruments _texture_path = _Instrument->getStringValue("radar-texture-path", "Aircraft/Instruments/Textures/od_wxradar.rgb"); @@ -402,11 +424,6 @@ NavDisplay::init () _odg = (FGODGauge *)imgr->get_subsystem("od_gauge"); _odg->setSize(_Instrument->getIntValue("texture-size", 512)); - - _user_lat_node = fgGetNode("/position/latitude-deg", true); - _user_lon_node = fgGetNode("/position/longitude-deg", true); - _user_alt_node = fgGetNode("/position/altitude-ft", true); - _route = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager")); _navRadio1Node = fgGetNode("/instrumentation/nav[0]", true); @@ -508,7 +525,7 @@ NavDisplay::update (double delta_time_sec) } _time -= _updateInterval; - _rangeNm = _Instrument->getFloatValue("range", 40.0); + _rangeNm = _rangeNode->getFloatValue(); if (_Instrument->getBoolValue("aircraft-heading-up", true)) { _view_heading = fgGetDouble("/orientation/heading-deg"); } else { @@ -527,9 +544,17 @@ NavDisplay::update (double delta_time_sec) _projectMat = osg::Matrixf::scale(_scale, _scale, 1.0) * degRotation(-_view_heading) * _centerTrans; - _pos = SGGeod::fromDegFt(_user_lon_node->getDoubleValue(), - _user_lat_node->getDoubleValue(), - _user_alt_node->getDoubleValue()); + _pos = globals->get_aircraft_position(); + + // invalidate the cache of positioned items, if we travelled more than 1nm + if (_cachedItemsValid) { + SGVec3d cartNow(SGVec3d::fromGeod(_pos)); + double movedNm = dist(_cachedPos, cartNow) * SG_METER_TO_NM; + _cachedItemsValid = (movedNm < 1.0); + if (!_cachedItemsValid) { + SG_LOG(SG_INSTR, SG_INFO, "invalidating NavDisplay cache due to moving: " << movedNm); + } + } _vertices->clear(); _lineVertices->clear(); @@ -538,6 +563,11 @@ NavDisplay::update (double delta_time_sec) _texCoords->clear(); _textGeode->removeDrawables(0, _textGeode->getNumDrawables()); + BOOST_FOREACH(SymbolInstance* si, _symbols) { + delete si; + } + _symbols.clear(); + BOOST_FOREACH(SymbolDef* def, _rules) { if (def->enable) { def->enabled = def->enable->test(); @@ -787,15 +817,17 @@ public: void NavDisplay::findItems() { - Filter filt; - filt.minRunwayLengthFt = 2000; - - FGPositioned::List items = - FGPositioned::findWithinRange(_pos, _rangeNm, &filt); - - FGPositioned::List::const_iterator it; - for (it = items.begin(); it != items.end(); ++it) { - foundPositionedItem(*it); + if (!_cachedItemsValid) { + SG_LOG(SG_INSTR, SG_INFO, "re-validating NavDisplay cache"); + Filter filt; + filt.minRunwayLengthFt = 2000; + _itemsInRange = FGPositioned::findWithinRange(_pos, _rangeNm, &filt); + _cachedItemsValid = true; + _cachedPos = SGVec3d::fromGeod(_pos); + } + + BOOST_FOREACH(FGPositioned* pos, _itemsInRange) { + foundPositionedItem(pos); } } @@ -1118,11 +1150,26 @@ void NavDisplay::computeAIStates(const SGPropertyNode* ai, string_set& states) } } -void NavDisplay::addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars) +bool NavDisplay::addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars) { + if (isProjectedClipped(proj)) { + return false; + } + SymbolInstance* sym = new SymbolInstance(proj, heading, def, vars); _symbols.push_back(sym); + return true; +} + +bool NavDisplay::isProjectedClipped(const osg::Vec2& projected) const +{ + double size = _odg->size(); + return (projected.x() < 0.0) || + (projected.y() < 0.0) || + (projected.x() >= size) || + (projected.y() >= size); } + diff --git a/src/Instrumentation/NavDisplay.hxx b/src/Instrumentation/NavDisplay.hxx index 7f4b0f283..00725e082 100644 --- a/src/Instrumentation/NavDisplay.hxx +++ b/src/Instrumentation/NavDisplay.hxx @@ -34,11 +34,13 @@ #include <vector> #include <string> +#include <memory> + +#include <Navaids/positioned.hxx> class FGODGauge; class FGRouteMgr; class FGNavRecord; -class FGPositioned; class SymbolInstance; class SymbolDef; @@ -61,6 +63,10 @@ public: virtual void init(); virtual void update(double dt); + void invalidatePositionedCache() + { + _cachedItemsValid = false; + } protected: std::string _name; int _num; @@ -70,11 +76,7 @@ protected: SGPropertyNode_ptr _serviceable_node; SGPropertyNode_ptr _Instrument; SGPropertyNode_ptr _radar_mode_control_node; - - SGPropertyNode_ptr _user_lat_node; - SGPropertyNode_ptr _user_lon_node; SGPropertyNode_ptr _user_heading_node; - SGPropertyNode_ptr _user_alt_node; FGODGauge *_odg; @@ -103,11 +105,11 @@ private: bool anyRuleMatches(const std::string& type, const string_set& states) const; void findRules(const std::string& type, const string_set& states, SymbolDefVector& rules); - void addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars); + bool addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars); void addLine(osg::Vec2 a, osg::Vec2 b, const osg::Vec4& color); osg::Vec2 projectBearingRange(double bearingDeg, double rangeNm) const; osg::Vec2 projectGeod(const SGGeod& geod) const; - + bool isProjectedClipped(const osg::Vec2& projected) const; void updateFont(); std::string _texture_path; @@ -154,13 +156,21 @@ private: FGRouteMgr* _route; SGGeod _pos; double _rangeNm; - + SGPropertyNode_ptr _rangeNode; + SymbolDefVector _rules; FGNavRecord* _nav1Station; FGNavRecord* _nav2Station; std::vector<SymbolInstance*> _symbols; std::set<FGPositioned*> _routeSources; + + bool _cachedItemsValid; + SGVec3d _cachedPos; + FGPositioned::List _itemsInRange; SGPropertyNode_ptr _excessDataNode; + + class CacheListener; + std::auto_ptr<CacheListener> _cacheListener; }; #endif // _INST_ND_HXX