diff --git a/projects/VC90/fgadmin/fgadmin.vcproj b/projects/VC90/fgadmin/fgadmin.vcproj
index cf34dc845..a7d8f4e09 100644
--- a/projects/VC90/fgadmin/fgadmin.vcproj
+++ b/projects/VC90/fgadmin/fgadmin.vcproj
@@ -65,7 +65,7 @@
/>
+#include
+
#include
#include
#include
+#include
+#include
+#include
+
#include
-#if defined(ENABLE_THREADS)
-#include
-#include
-#endif
using simgear::PropertyList;
@@ -110,6 +112,7 @@ protected:
simgear::TiedPropertyList _tiedProperties;
typedef std::vector MetarPropertiesList;
MetarPropertiesList _metarProperties;
+
};
/* -------------------------------------------------------------------------------- */
@@ -195,86 +198,95 @@ public:
virtual void update (bool first, double delta_time_sec);
virtual void shutdown ();
- class MetarLoadRequest {
- public:
- MetarLoadRequest( const string & stationId ) :
- _stationId(stationId),
- _proxyHost(fgGetNode("/sim/presets/proxy/host", true)->getStringValue()),
- _proxyPort(fgGetNode("/sim/presets/proxy/port", true)->getStringValue()),
- _proxyAuth(fgGetNode("/sim/presets/proxy/authentication", true)->getStringValue())
- {}
- MetarLoadRequest( const MetarLoadRequest & other ) :
- _stationId(other._stationId),
- _proxyHost(other._proxyAuth),
- _proxyPort(other._proxyPort),
- _proxyAuth(other._proxyAuth)
- {}
- string _stationId;
- string _proxyHost;
- string _proxyPort;
- string _proxyAuth;
- private:
- };
-
- class MetarLoadResponse {
- public:
- MetarLoadResponse( const string & stationId, const string metar ) {
- _stationId = stationId;
- _metar = metar;
- }
- MetarLoadResponse( const MetarLoadResponse & other ) {
- _stationId = other._stationId;
- _metar = other._metar;
- }
- string _stationId;
- string _metar;
- };
+ /**
+ * callback from MetarGetRequest when a download succeeds
+ */
+ void gotMetar(const string& stationId, const string& metar);
private:
double _positionTimeToLive;
double _requestTimer;
-#if defined(ENABLE_THREADS)
- class MetarLoadThread : public OpenThreads::Thread {
- public:
- MetarLoadThread( long maxAge );
- virtual ~MetarLoadThread( ) { stop(); }
- void requestMetar( const MetarLoadRequest & metarRequest, bool background = true );
- bool hasMetar() { return _responseQueue.size() > 0; }
- MetarLoadResponse getMetar() { return _responseQueue.pop(); }
- virtual void run();
- void stop();
- private:
- void fetch( const MetarLoadRequest & );
- long _maxAge;
- long _minRequestInterval;
- volatile bool _stop;
- SGBlockingQueue _requestQueue;
- SGBlockingQueue _responseQueue;
- };
-
- MetarLoadThread * _metarLoadThread;
-#endif
+ simgear::HTTP::Client _http;
};
+class MetarGetRequest : public simgear::HTTP::Request
+{
+public:
+ MetarGetRequest(NoaaMetarRealWxController* con, const string& s) :
+ Request(""),
+ stationId(s),
+ fromProxy(false),
+ wxController(con)
+ {
+ setUrl("http://weather.noaa.gov/pub/data/observations/metar/stations/" + stationId + ".TXT");
+ }
+
+ virtual string_list requestHeaders() const
+ {
+ string_list r;
+ r.push_back("X-Time");
+ return r;
+ }
+
+ virtual string header(const string& name) const
+ {
+ if (name == "X-Time") {
+ char buf[16];
+ snprintf(buf, 16, "%ld", globals->get_time_params()->get_cur_time());
+ return buf;
+ }
+
+ return Request::header(name);
+ }
+
+ virtual void responseHeader(const string& key, const string& value)
+ {
+ if (key == "x-metarproxy") {
+ fromProxy = true;
+ }
+ }
+
+ virtual void gotBodyData(const char* s, int n)
+ {
+ metar += string(s, n);
+ }
+
+ virtual void responseComplete()
+ {
+ if (responseCode() == 200) {
+ wxController->gotMetar(stationId, metar);
+ } else {
+ SG_LOG(SG_IO, SG_WARN, "metar download failed:" << url() << ": reason:" << responseReason());
+ }
+ }
+
+ bool fromMetarProxy() const
+ { return fromProxy; }
+private:
+ string stationId;
+ string metar;
+ bool fromProxy;
+ NoaaMetarRealWxController* wxController;
+};
+
+
+
NoaaMetarRealWxController::NoaaMetarRealWxController( SGPropertyNode_ptr rootNode ) :
BasicRealWxController(rootNode),
_positionTimeToLive(0.0),
_requestTimer(0.0)
{
-#if defined(ENABLE_THREADS)
- _metarLoadThread = new MetarLoadThread(getMetarMaxAgeMin());
- _metarLoadThread->start();
-#endif
+ string proxyHost(fgGetString("/sim/presets/proxy/host"));
+ int proxyPort(fgGetInt("/sim/presets/proxy/port"));
+ string proxyAuth(fgGetString("/sim/presets/proxy/auth"));
+
+ if (!proxyHost.empty()) {
+ _http.setProxy(proxyHost, proxyPort, proxyAuth);
+ }
}
void NoaaMetarRealWxController::shutdown()
{
-#if defined(ENABLE_THREADS)
- if( _metarLoadThread ) {
- delete _metarLoadThread;
- _metarLoadThread = NULL;
- }
-#endif // ENABLE_THREADS
}
NoaaMetarRealWxController::~NoaaMetarRealWxController()
@@ -283,6 +295,8 @@ NoaaMetarRealWxController::~NoaaMetarRealWxController()
void NoaaMetarRealWxController::update( bool first, double dt )
{
+ _http.update();
+
_positionTimeToLive -= dt;
_requestTimer -= dt;
@@ -315,143 +329,32 @@ void NoaaMetarRealWxController::update( bool first, double dt )
if( _requestTimer <= 0.0 ) {
_requestTimer = 10.0;
+
+ BOOST_FOREACH(LiveMetarProperties* p, _metarProperties) {
+ if( p->getTimeToLive() > 0.0 ) continue;
+ const std::string & stationId = p->getStationId();
+ if( stationId.empty() ) continue;
- for( MetarPropertiesList::iterator it = _metarProperties.begin();
- it != _metarProperties.end(); it++ ) {
-
- if( (*it)->getTimeToLive() > 0.0 ) continue;
- const std::string & stationId = (*it)->getStationId();
- if( stationId.empty() ) continue;
-
- SG_LOG(SG_ALL, SG_INFO,
- "NoaaMetarRealWxController::update(): spawning load request for station-id '" << stationId << "'" );
+ SG_LOG(SG_ALL, SG_INFO,
+ "NoaaMetarRealWxController::update(): spawning load request for station-id '" << stationId << "'" );
- MetarLoadRequest request( stationId );
- // load the metar for the nearest airport in the foreground if the fdm is uninitialized
- // to make sure a metar is received
- // before the automatic runway selection code runs. All subsequent calls
- // run in the background
- bool background = fgGetBool("/sim/fdm-initialized", false ) || it != _metarProperties.begin();
- _metarLoadThread->requestMetar( request, background );
- }
- }
-
- // pick all the received responses from the result queue and update the associated
- // property tree
- while( _metarLoadThread->hasMetar() ) {
- MetarLoadResponse metar = _metarLoadThread->getMetar();
- SG_LOG( SG_ALL, SG_INFO, "NoaaMetarRwalWxController::update() received METAR for " << metar._stationId << ": " << metar._metar );
- for( MetarPropertiesList::iterator it = _metarProperties.begin();
- it != _metarProperties.end(); it++ ) {
- if( (*it)->getStationId() != metar._stationId )
- continue;
- (*it)->setTimeToLive(900);
- (*it)->setMetar( metar._metar );
- }
+ _http.makeRequest(new MetarGetRequest(this, stationId));
+ } // of MetarProperties iteration
}
}
-/* -------------------------------------------------------------------------------- */
-
-#if defined(ENABLE_THREADS)
-NoaaMetarRealWxController::MetarLoadThread::MetarLoadThread( long maxAge ) :
- _maxAge(maxAge),
- _minRequestInterval(2000),
- _stop(false)
+void NoaaMetarRealWxController::gotMetar(const string& stationId, const string& metar)
{
-}
-
-void NoaaMetarRealWxController::MetarLoadThread::requestMetar( const MetarLoadRequest & metarRequest, bool background )
-{
- if( background ) {
- if( _requestQueue.size() > 10 ) {
- SG_LOG(SG_ALL,SG_ALERT,
- "NoaaMetarRealWxController::MetarLoadThread::requestMetar() more than 10 outstanding METAR requests, dropping "
- << metarRequest._stationId );
- return;
- }
-
- _requestQueue.push( metarRequest );
- } else {
- fetch( metarRequest );
+ SG_LOG( SG_ALL, SG_INFO, "NoaaMetarRwalWxController::update() received METAR for " << stationId << ": " << metar );
+ BOOST_FOREACH(LiveMetarProperties* p, _metarProperties) {
+ if (p->getStationId() != stationId)
+ continue;
+
+ p->setTimeToLive(900);
+ p->setMetar( metar );
}
}
-void NoaaMetarRealWxController::MetarLoadThread::stop()
-{
- // set stop flag and wake up the thread with an empty request
- _stop = true;
- MetarLoadRequest request("");
- requestMetar(request);
- join();
-}
-
-void NoaaMetarRealWxController::MetarLoadThread::run()
-{
- SGTimeStamp lastRun = SGTimeStamp::fromSec(0);
- for( ;; ) {
- SGTimeStamp dt = SGTimeStamp::now() - lastRun;
-
- long delayMs = _minRequestInterval - dt.getSeconds() * 1000;
- while (( delayMs > 0 ) && !_stop)
- {
- // sleep no more than 3 seconds at a time, otherwise shutdown response is too slow
- long sleepMs = (delayMs>3000) ? 3000 : delayMs;
- microSleep( sleepMs * 1000 );
- delayMs -= sleepMs;
- }
-
- if (_stop)
- break;
-
- lastRun = SGTimeStamp::now();
-
- const MetarLoadRequest request = _requestQueue.pop();
-
- if (( request._stationId.size() == 0 ) || _stop)
- break;
-
- fetch( request );
- }
-}
-
-void NoaaMetarRealWxController::MetarLoadThread::fetch( const MetarLoadRequest & request )
-{
- SGSharedPtr result = NULL;
-
- try {
- result = new FGMetar( request._stationId, request._proxyHost, request._proxyPort, request._proxyAuth );
- _minRequestInterval = 2000;
- } catch (const sg_io_exception& e) {
- SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): can't get METAR for "
- << request._stationId << ":" << e.getFormattedMessage().c_str() );
- _minRequestInterval += _minRequestInterval/2;
- if( _minRequestInterval > 30000 )
- _minRequestInterval = 30000;
- return;
- }
-
- string reply = result->getData();
- std::replace(reply.begin(), reply.end(), '\n', ' ');
- string metar = simgear::strutils::strip( reply );
-
- if( metar.empty() ) {
- SG_LOG( SG_GENERAL, SG_WARN, "NoaaMetarRealWxController::fetchMetar(): dropping empty METAR for "
- << request._stationId );
- return;
- }
-
- if( _maxAge && result->getAge_min() > _maxAge ) {
- SG_LOG( SG_GENERAL, SG_ALERT, "NoaaMetarRealWxController::fetchMetar(): dropping outdated METAR "
- << metar );
- return;
- }
-
- MetarLoadResponse response( request._stationId, metar );
- _responseQueue.push( response );
-}
-#endif
-
/* -------------------------------------------------------------------------------- */
RealWxController * RealWxController::createInstance( SGPropertyNode_ptr rootNode )
diff --git a/src/Main/FGEventHandler.cxx b/src/Main/FGEventHandler.cxx
index d6be62054..5599723fa 100644
--- a/src/Main/FGEventHandler.cxx
+++ b/src/Main/FGEventHandler.cxx
@@ -60,6 +60,20 @@ FGEventHandler::FGEventHandler() :
numlockKeyMap[GUIEventAdapter::KEY_KP_Home] = '7';
numlockKeyMap[GUIEventAdapter::KEY_KP_Up] = '8';
numlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = '9';
+ numlockKeyMap[GUIEventAdapter::KEY_KP_Delete] = '.';
+
+ // mapping when NumLock is off
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Insert] = PU_KEY_INSERT;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_End] = PU_KEY_END;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Down] = PU_KEY_DOWN;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Page_Down] = PU_KEY_PAGE_DOWN;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Left] = PU_KEY_LEFT;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Begin] = '5';
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Right] = PU_KEY_RIGHT;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Home] = PU_KEY_HOME;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Up] = PU_KEY_UP;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Page_Up] = PU_KEY_PAGE_UP;
+ noNumlockKeyMap[GUIEventAdapter::KEY_KP_Delete] = 127;
for (int i = 0; i < 128; i++)
release_keys[i] = i;
@@ -259,7 +273,6 @@ void FGEventHandler::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
case GUIEventAdapter::KEY_F10: key = PU_KEY_F10; break;
case GUIEventAdapter::KEY_F11: key = PU_KEY_F11; break;
case GUIEventAdapter::KEY_F12: key = PU_KEY_F12; break;
- case GUIEventAdapter::KEY_KP_Delete: key = '.'; break;
case GUIEventAdapter::KEY_KP_Enter: key = '\r'; break;
case GUIEventAdapter::KEY_KP_Add: key = '+'; break;
case GUIEventAdapter::KEY_KP_Divide: key = '/'; break;
@@ -268,18 +281,30 @@ void FGEventHandler::handleKey(const osgGA::GUIEventAdapter& ea, int& key,
}
osgGA::GUIEventAdapter::EventType eventType = ea.getEventType();
- std::map::iterator numPadIter = numlockKeyMap.find(key);
-
- if (numPadIter != numlockKeyMap.end()) {
#ifdef __APPLE__
- // Num Lock is always true on Mac
+ // Num Lock is always true on Mac
+ std::map::iterator numPadIter = numlockKeyMap.find(key);
+ if (numPadIter != numlockKeyMap.end()) {
key = numPadIter->second;
+ }
#else
- if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_NUM_LOCK) {
+ if (ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_NUM_LOCK)
+ {
+ // NumLock on: map to numeric keys
+ std::map::iterator numPadIter = numlockKeyMap.find(key);
+ if (numPadIter != numlockKeyMap.end()) {
key = numPadIter->second;
}
-#endif
}
+ else
+ {
+ // NumLock off: map to PU arrow keys
+ std::map::iterator numPadIter = noNumlockKeyMap.find(key);
+ if (numPadIter != noNumlockKeyMap.end()) {
+ key = numPadIter->second;
+ }
+ }
+#endif
modifiers = osgToFGModifiers(ea.getModKeyMask());
currentModifiers = modifiers;
diff --git a/src/Main/FGEventHandler.hxx b/src/Main/FGEventHandler.hxx
index 080d5afa1..652b2b74d 100644
--- a/src/Main/FGEventHandler.hxx
+++ b/src/Main/FGEventHandler.hxx
@@ -113,6 +113,7 @@ protected:
int statsType;
int currentModifiers;
std::map numlockKeyMap;
+ std::map noNumlockKeyMap;
void handleKey(const osgGA::GUIEventAdapter& ea, int& key, int& modifiers);
bool resizable;
bool mouseWarped;
diff --git a/src/Scenery/scenery.cxx b/src/Scenery/scenery.cxx
index 58bd4db56..12c3ebb69 100644
--- a/src/Scenery/scenery.cxx
+++ b/src/Scenery/scenery.cxx
@@ -28,8 +28,12 @@
#include
#include
+#include
+#include
+#include
+#include
+#include
#include
-#include
#include
#include
@@ -38,6 +42,8 @@
#include
#include
#include
+#include
+#include
#include
#include
@@ -70,6 +76,138 @@ public:
}
};
+class FGSceneryIntersect : public osg::NodeVisitor {
+public:
+ FGSceneryIntersect(const SGLineSegmentd& lineSegment,
+ const osg::Node* skipNode) :
+ osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN),
+ _lineSegment(lineSegment),
+ _skipNode(skipNode),
+ _material(0),
+ _haveHit(false)
+ { }
+
+ bool getHaveHit() const
+ { return _haveHit; }
+ const SGLineSegmentd& getLineSegment() const
+ { return _lineSegment; }
+ const SGMaterial* getMaterial() const
+ { return _material; }
+
+ virtual void apply(osg::Node& node)
+ {
+ if (&node == _skipNode)
+ return;
+ if (!testBoundingSphere(node.getBound()))
+ return;
+
+ addBoundingVolume(node);
+ }
+
+ virtual void apply(osg::Group& group)
+ {
+ if (&group == _skipNode)
+ return;
+ if (!testBoundingSphere(group.getBound()))
+ return;
+
+ traverse(group);
+ addBoundingVolume(group);
+ }
+
+ virtual void apply(osg::Transform& transform)
+ { handleTransform(transform); }
+ virtual void apply(osg::Camera& camera)
+ {
+ if (camera.getRenderOrder() != osg::Camera::NESTED_RENDER)
+ return;
+ handleTransform(camera);
+ }
+ virtual void apply(osg::CameraView& transform)
+ { handleTransform(transform); }
+ virtual void apply(osg::MatrixTransform& transform)
+ { handleTransform(transform); }
+ virtual void apply(osg::PositionAttitudeTransform& transform)
+ { handleTransform(transform); }
+
+private:
+ void handleTransform(osg::Transform& transform)
+ {
+ if (&transform == _skipNode)
+ return;
+ // Hmm, may be this needs to be refined somehow ...
+ if (transform.getReferenceFrame() != osg::Transform::RELATIVE_RF)
+ return;
+
+ if (!testBoundingSphere(transform.getBound()))
+ return;
+
+ osg::Matrix inverseMatrix;
+ if (!transform.computeWorldToLocalMatrix(inverseMatrix, this))
+ return;
+ osg::Matrix matrix;
+ if (!transform.computeLocalToWorldMatrix(matrix, this))
+ return;
+
+ SGLineSegmentd lineSegment = _lineSegment;
+ bool haveHit = _haveHit;
+ const SGMaterial* material = _material;
+
+ _haveHit = false;
+ _lineSegment = lineSegment.transform(SGMatrixd(inverseMatrix.ptr()));
+
+ addBoundingVolume(transform);
+ traverse(transform);
+
+ if (_haveHit) {
+ _lineSegment = _lineSegment.transform(SGMatrixd(matrix.ptr()));
+ } else {
+ _lineSegment = lineSegment;
+ _material = material;
+ _haveHit = haveHit;
+ }
+ }
+
+ simgear::BVHNode* getNodeBoundingVolume(osg::Node& node)
+ {
+ SGSceneUserData* userData = SGSceneUserData::getSceneUserData(&node);
+ if (!userData)
+ return 0;
+ return userData->getBVHNode();
+ }
+ void addBoundingVolume(osg::Node& node)
+ {
+ simgear::BVHNode* bvNode = getNodeBoundingVolume(node);
+ if (!bvNode)
+ return;
+
+ // Find ground intersection on the bvh nodes
+ simgear::BVHLineSegmentVisitor lineSegmentVisitor(_lineSegment,
+ 0/*startTime*/);
+ bvNode->accept(lineSegmentVisitor);
+ if (!lineSegmentVisitor.empty()) {
+ _lineSegment = lineSegmentVisitor.getLineSegment();
+ _material = lineSegmentVisitor.getMaterial();
+ _haveHit = true;
+ }
+ }
+
+ bool testBoundingSphere(const osg::BoundingSphere& bound) const
+ {
+ if (!bound.valid())
+ return false;
+
+ SGSphered sphere(toVec3d(toSG(bound._center)), bound._radius);
+ return intersects(_lineSegment, sphere);
+ }
+
+ SGLineSegmentd _lineSegment;
+ const osg::Node* _skipNode;
+
+ const SGMaterial* _material;
+ bool _haveHit;
+};
+
// Scenery Management system
FGScenery::FGScenery()
{
@@ -138,43 +276,20 @@ FGScenery::get_elevation_m(const SGGeod& geod, double& alt,
SGGeod geodEnd = geod;
geodEnd.setElevationM(SGMiscd::min(geod.getElevationM() - 10, -10000));
SGVec3d end = SGVec3d::fromGeod(geodEnd);
-
- osgUtil::IntersectVisitor intersectVisitor;
+
+ FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom);
intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
- osg::ref_ptr lineSegment;
- lineSegment = new osg::LineSegment(toOsg(start), toOsg(end));
- intersectVisitor.addLineSegment(lineSegment.get());
get_scene_graph()->accept(intersectVisitor);
- bool hits = false;
- if (intersectVisitor.hits()) {
- int nHits = intersectVisitor.getNumHits(lineSegment.get());
- alt = -SGLimitsd::max();
- for (int i = 0; i < nHits; ++i) {
- const osgUtil::Hit& hit
- = intersectVisitor.getHitList(lineSegment.get())[i];
- if (butNotFrom &&
- std::find(hit.getNodePath().begin(), hit.getNodePath().end(),
- butNotFrom) != hit.getNodePath().end())
- continue;
- // We might need the double variant of the intersection point.
- // Thus we cannot use the float variant delivered by
- // hit.getWorldIntersectPoint() but we have to redo that with osg::Vec3d.
- osg::Vec3d point = hit.getLocalIntersectPoint();
- if (hit.getMatrix())
- point = point*(*hit.getMatrix());
- SGGeod geod = SGGeod::fromCart(toSG(point));
- double elevation = geod.getElevationM();
- if (alt < elevation) {
- alt = elevation;
- hits = true;
- if (material)
- *material = SGMaterialLib::findMaterial(hit.getGeode());
- }
- }
- }
+ if (!intersectVisitor.getHaveHit())
+ return false;
- return hits;
+ geodEnd = SGGeod::fromCart(intersectVisitor.getLineSegment().getEnd());
+ alt = geodEnd.getElevationM();
+ if (material)
+ *material = intersectVisitor.getMaterial();
+
+ return true;
}
bool
@@ -190,40 +305,16 @@ FGScenery::get_cart_ground_intersection(const SGVec3d& pos, const SGVec3d& dir,
// computation of ground intersection.
SGVec3d start = pos;
SGVec3d end = start + 1e5*normalize(dir); // FIXME visibility ???
-
- osgUtil::IntersectVisitor intersectVisitor;
- intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
- osg::ref_ptr lineSegment;
- lineSegment = new osg::LineSegment(toOsg(start), toOsg(end));
- intersectVisitor.addLineSegment(lineSegment.get());
- get_scene_graph()->accept(intersectVisitor);
- bool hits = false;
- if (intersectVisitor.hits()) {
- int nHits = intersectVisitor.getNumHits(lineSegment.get());
- double dist = SGLimitsd::max();
- for (int i = 0; i < nHits; ++i) {
- const osgUtil::Hit& hit
- = intersectVisitor.getHitList(lineSegment.get())[i];
- if (butNotFrom &&
- std::find(hit.getNodePath().begin(), hit.getNodePath().end(),
- butNotFrom) != hit.getNodePath().end())
- continue;
- // We might need the double variant of the intersection point.
- // Thus we cannot use the float variant delivered by
- // hit.getWorldIntersectPoint() but we have to redo that with osg::Vec3d.
- osg::Vec3d point = hit.getLocalIntersectPoint();
- if (hit.getMatrix())
- point = point*(*hit.getMatrix());
- double newdist = length(start - toSG(point));
- if (newdist < dist) {
- dist = newdist;
- nearestHit = toSG(point);
- hits = true;
- }
- }
- }
- return hits;
+ FGSceneryIntersect intersectVisitor(SGLineSegmentd(start, end), butNotFrom);
+ intersectVisitor.setTraversalMask(SG_NODEMASK_TERRAIN_BIT);
+ get_scene_graph()->accept(intersectVisitor);
+
+ if (!intersectVisitor.getHaveHit())
+ return false;
+
+ nearestHit = intersectVisitor.getLineSegment().getEnd();
+ return true;
}
bool FGScenery::scenery_available(const SGGeod& position, double range_m)
diff --git a/utils/fgadmin/src/fgadmin_funcs.cxx b/utils/fgadmin/src/fgadmin_funcs.cxx
index e8d2c9a0c..c05b9e929 100644
--- a/utils/fgadmin/src/fgadmin_funcs.cxx
+++ b/utils/fgadmin/src/fgadmin_funcs.cxx
@@ -24,14 +24,12 @@
#include
#include
#include
-#include
#ifdef _WIN32
# include
#endif
#include
-#include
#include
@@ -142,11 +140,12 @@ void FGAdminUI::update_install_box() {
install_box->clear();
if ( source.length() ) {
- ulDir *dir = ulOpenDir( source.c_str() ) ;
- ulDirEnt *ent;
- while ( dir != 0 && ( ent = ulReadDir( dir ) ) ) {
+ struct dirent **list;
+ int nb = fl_filename_list( source.c_str(), &list );
+ for ( int i = 0; i < nb; ++i ) {
// find base name of archive file
char base[FL_PATH_MAX];
+ dirent *ent = list[i];
strncpy( base, ent->d_name, FL_PATH_MAX );
const char *p = fl_filename_ext( base );
int offset, expected_length = 0;
@@ -186,9 +185,10 @@ void FGAdminUI::update_install_box() {
// cout << install.str() << " exists." << endl;
}
}
+ free( ent );
}
+ free( list );
- ulCloseDir( dir );
for ( set::iterator it = file_list.begin(); it != file_list.end(); ++it ) {
install_box->add( it->c_str() );
}
@@ -217,16 +217,18 @@ void FGAdminUI::update_remove_box() {
set dir_list;
for ( int i = 0; i < 2; i++ ) {
if ( !path[i].empty() ) {
- ulDir *dir = ulOpenDir( path[i].c_str() ) ;
- ulDirEnt *ent;
- while ( dir != 0 && ( ent = ulReadDir( dir ) ) ) {
+ dirent **list;
+ int nb = fl_filename_list( path[i].c_str(), &list );
+ for ( int i = 0; i < nb; ++i ) {
+ dirent *ent = list[i];
if ( strlen(ent->d_name) == 7 &&
( ent->d_name[0] == 'e' || ent->d_name[0] == 'w' ) &&
( ent->d_name[4] == 'n' || ent->d_name[4] == 's' ) ) {
dir_list.insert( ent->d_name );
}
+ free( ent );
}
- ulCloseDir( dir );
+ free( list );
}
}
@@ -254,7 +256,7 @@ void FGAdminUI::install_selected() {
SGPath file( source );
file.append( f );
struct stat info;
- stat( file.str().c_str(), &info );
+ fl_stat( file.str().c_str(), &info );
float old_max = progress->maximum();
progress->maximum( info.st_size );
progress_label = "Installing ";
@@ -279,23 +281,25 @@ void FGAdminUI::install_selected() {
static unsigned long count_dir( const char *dir_name, bool top = true ) {
unsigned long cnt = 0L;
- ulDir *dir = ulOpenDir( dir_name ) ;
- if ( dir ) {
- ulDirEnt *ent;
- while ( ent = ulReadDir( dir ) ) {
+ dirent **list;
+ int nb = fl_filename_list( dir_name, &list );
+ if ( nb != 0 ) {
+ for ( int i = 0; i < nb; ++i ) {
+ dirent *ent = list[i];
if ( strcmp( ent->d_name, "." ) == 0 ) {
// ignore "."
} else if ( strcmp( ent->d_name, ".." ) == 0 ) {
// ignore ".."
- } else if ( ent->d_isdir ) {
+ } else if ( fl_filename_isdir( ent->d_name ) ) {
SGPath child( dir_name );
child.append( ent->d_name );
cnt += count_dir( child.c_str(), false );
} else {
cnt += 1;
}
+ free( ent );
}
- ulCloseDir( dir );
+ free( list );
} else if ( top ) {
string base = dir_name;
size_t pos = base.rfind('/');
@@ -310,15 +314,16 @@ static unsigned long count_dir( const char *dir_name, bool top = true ) {
}
static void remove_dir( const char *dir_name, void (*step)(void*,int), void *data, bool top = true ) {
- ulDir *dir = ulOpenDir( dir_name ) ;
- if ( dir ) {
- ulDirEnt *ent;
- while ( ent = ulReadDir( dir ) ) {
+ dirent **list;
+ int nb = fl_filename_list( dir_name, &list );
+ if ( nb != 0 ) {
+ for ( int i = 0; i < nb; ++i ) {
+ dirent *ent = list[i];
if ( strcmp( ent->d_name, "." ) == 0 ) {
// ignore "."
} else if ( strcmp( ent->d_name, ".." ) == 0 ) {
// ignore ".."
- } else if ( ent->d_isdir ) {
+ } else if ( fl_filename_isdir( ent->d_name ) ) {
SGPath child( dir_name );
child.append( ent->d_name );
remove_dir( child.c_str(), step, data, false );
@@ -328,8 +333,9 @@ static void remove_dir( const char *dir_name, void (*step)(void*,int), void *dat
unlink( child.c_str() );
if (step) step( data, 1 );
}
+ free( ent );
}
- ulCloseDir( dir );
+ free( list );
rmdir( dir_name );
} else if ( top ) {
string base = dir_name;
diff --git a/utils/metarproxy/metarproxy b/utils/metarproxy/metarproxy
index ba03eb377..88320881f 100755
--- a/utils/metarproxy/metarproxy
+++ b/utils/metarproxy/metarproxy
@@ -441,6 +441,8 @@ sub serve()
$metar .= sprintf "$icao %02d%02d%02dZ ", $day, $hour, $min;
$metar .= $last_metar{$addr} || $METAR_DEFAULT;
}
+
+ print $client "HTTP/1.0 200 OK\015\012";
print $client "Content-Type: text/plain\015\012"
. "X-MetarProxy: nasse Maus\015\012"
. "\015\012"