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
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");
_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);
}
_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 {
_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();
_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();
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);
}
}
}
}
-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);
}
+
#include <vector>
#include <string>
+#include <memory>
+
+#include <Navaids/positioned.hxx>
class FGODGauge;
class FGRouteMgr;
class FGNavRecord;
-class FGPositioned;
class SymbolInstance;
class SymbolDef;
virtual void init();
virtual void update(double dt);
+ void invalidatePositionedCache()
+ {
+ _cachedItemsValid = false;
+ }
protected:
std::string _name;
int _num;
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;
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;
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