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);
}
+